From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id C750B138334 for ; Sun, 27 Oct 2019 12:22:33 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 160B0E0828; Sun, 27 Oct 2019 12:22:33 +0000 (UTC) Received: from smtp.gentoo.org (mail.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id E6BFEE0828 for ; Sun, 27 Oct 2019 12:22:32 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id CC21534C4D0 for ; Sun, 27 Oct 2019 12:22:29 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 509C1897 for ; Sun, 27 Oct 2019 12:22:28 +0000 (UTC) From: "Fabian Groffen" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Fabian Groffen" Message-ID: <1572178746.c9d7b9de78f1488827cb516bf61a54df28a750ab.grobian@gentoo> Subject: [gentoo-commits] proj/portage-utils:master commit in: /, man/ X-VCS-Repository: proj/portage-utils X-VCS-Files: main.c man/qlop.1 qlop.c X-VCS-Directories: / man/ X-VCS-Committer: grobian X-VCS-Committer-Name: Fabian Groffen X-VCS-Revision: c9d7b9de78f1488827cb516bf61a54df28a750ab X-VCS-Branch: master Date: Sun, 27 Oct 2019 12:22:28 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 193c1095-a58b-47b6-9795-27e80aa5a9e8 X-Archives-Hash: e87877c8a19e529b7d010aeba7fa8aca commit: c9d7b9de78f1488827cb516bf61a54df28a750ab Author: Fabian Groffen gentoo org> AuthorDate: Sun Oct 27 12:19:06 2019 +0000 Commit: Fabian Groffen gentoo org> CommitDate: Sun Oct 27 12:19:06 2019 +0000 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=c9d7b9de qlop: take two at implementing currently running merges Probe /proc filesystem for running merges, and use the atoms found there to select the packages to list. In addition, prune any operations that started > 10 days ago so there will be some sort of convergence. Bug: https://bugs.gentoo.org/698196 Signed-off-by: Fabian Groffen gentoo.org> main.c | 3 +- man/qlop.1 | 4 +- qlop.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 173 insertions(+), 9 deletions(-) diff --git a/main.c b/main.c index 5d4c4cd..0b827fc 100644 --- a/main.c +++ b/main.c @@ -501,7 +501,8 @@ read_portage_env_file(const char *configroot, const char *file, env_vars vars[]) source_len = strlen(sfile); if (buflen <= source_len + file_path_len) - buf = xrealloc(buf, buflen = source_len + file_path_len + 1); + buf = xrealloc(buf, + buflen = source_len + file_path_len + 1); memmove(buf + file_path_len, buf + 7, source_len + 1); memcpy(buf, file, file_path_len); sfile = buf; diff --git a/man/qlop.1 b/man/qlop.1 index de1e525..58efd09 100644 --- a/man/qlop.1 +++ b/man/qlop.1 @@ -1,5 +1,5 @@ .\" generated by mkman.py, please do NOT edit! -.TH qlop "1" "Sep 2019" "Gentoo Foundation" "qlop" +.TH qlop "1" "Oct 2019" "Gentoo Foundation" "qlop" .SH NAME qlop \- emerge log analyzer .SH SYNOPSIS @@ -51,7 +51,7 @@ Print elapssed time in human readable format. This form uses minutes, hours and days instead of just seconds. .TP \fB\-M\fR, \fB\-\-machine\fR -Print elapsed time as seconds with no formatting. +Print start/elapsed time as seconds with no formatting. .TP \fB\-m\fR, \fB\-\-merge\fR Show merge history. diff --git a/qlop.c b/qlop.c index 7a93656..6cb2c04 100644 --- a/qlop.c +++ b/qlop.c @@ -16,9 +16,11 @@ #include #include #include +#include #include "atom.h" #include "eat_file.h" +#include "scandirat.h" #include "set.h" #include "xarray.h" #include "xasprintf.h" @@ -51,7 +53,7 @@ static const char * const qlop_opts_help[] = { "Print time taken to complete action", "Print average time taken to complete action", "Print elapsed time in human readable format (use with -t or -a)", - "Print elapsed time as seconds with no formatting", + "Print start/elapsed time as seconds with no formatting", "Show merge history", "Show unmerge history", "Show autoclean unmerge history", @@ -201,10 +203,15 @@ parse_date(const char *sdate, time_t *t) static char _date_buf[48]; static char *fmt_date(struct qlop_mode *flags, time_t ts, time_t te) { - time_t t; + time_t t = flags->do_endtime ? te : ts; + + if (flags->do_machine) + snprintf(_date_buf, sizeof(_date_buf), + "%zd", (size_t)t); + else + strftime(_date_buf, sizeof(_date_buf), + "%Y-%m-%dT%H:%M:%S", localtime(&t)); - t = flags->do_endtime ? te : ts; - strftime(_date_buf, sizeof(_date_buf), "%Y-%m-%dT%H:%M:%S", localtime(&t)); return _date_buf; } @@ -336,6 +343,21 @@ New format: 1550953125: >>> unmerge success: app-admin/pwgen-2.08 1550953125: *** exiting successfully. 1550953125: *** terminating. + + +Currently running merges can be found in the /proc filesystem: +- Linux: readlink(/proc//fd/X) +- Solaris: readlink(/proc//path/X) +from here a file should be there that points to the build.log file +$CAT/$P/work/build.log. If so, it's running for $CAT/$P. +This requires being the portage user though, or root. + +Should there be no /proc, we can deduce from the log whether a package +is being emerged, if and only if, there are no parallel merges, and +portage never got interrupted in a way where it could not write its +interruption to the log. Unfortunately these scenarios happen a lot. +As such, we can try to remedy this somewhat by using a rule of thumb +that currently merging packages need to be withinin the last 10 days. */ static int do_emerge_log( const char *log, @@ -463,6 +485,7 @@ static int do_emerge_log( tbegin = last_merge; tend = tstart; } + /* loop over lines searching for atoms */ while (fgets(buf, sizeof(buf), fp) != NULL) { if ((p = strchr(buf, ':')) == NULL) @@ -821,11 +844,19 @@ static int do_emerge_log( } fclose(fp); if (flags->do_running) { + time_t cutofftime; + + /* emerge.log can be interrupted, incorrect and hopelessly lost, + * so to eliminate some unfinished crap from there, we just + * ignore anything that's > cutofftime, 10 days for now. */ + cutofftime = 10 * 24 * 60 * 60; /* when we consider entries stale */ + /* can't report endtime for non-finished operations */ flags->do_endtime = 0; tstart = time(NULL); sync_time /= sync_cnt; - if (sync_start > 0) { + if (sync_start >= tstart - cutofftime) { + elapsed = tstart - sync_start; if (elapsed >= sync_time) sync_time = 0; if (flags->do_time) { @@ -847,6 +878,9 @@ static int do_emerge_log( time_t maxtime = 0; bool isMax = false; + if (pkgw->tbegin < tstart - cutofftime) + continue; + snprintf(afmt, sizeof(afmt), "%s/%s", pkgw->atom->CATEGORY, pkgw->atom->PN); @@ -891,6 +925,9 @@ static int do_emerge_log( time_t maxtime = 0; bool isMax = false; + if (pkgw->tbegin < tstart - cutofftime) + continue; + snprintf(afmt, sizeof(afmt), "%s/%s", pkgw->atom->CATEGORY, pkgw->atom->PN); @@ -978,6 +1015,118 @@ static int do_emerge_log( return 0; } +/* scan through /proc for running merges, this requires portage user + * or root */ +static array_t *probe_proc(array_t *atoms) +{ + struct dirent **procs; + int procslen; + int pi; + struct dirent **links; + int linkslen; + int li; + struct dirent *d; + char npath[_Q_PATH_MAX * 2]; + char rpath[_Q_PATH_MAX]; + const char *subdir = NULL; + const char *pid; + ssize_t rpathlen; + char *p; + depend_atom *atom; + DECLARE_ARRAY(ret_atoms); + size_t i; + + /* /proc//path/<[0-9]+link> + * /proc//fd/<[0-9]+link> */ + if ((procslen = scandir("/proc", &procs, NULL, NULL)) > 0) { + for (pi = 0; pi < procslen; pi++) { + d = procs[pi]; + /* must be [0-9]+ */ + if (d->d_name[0] < '0' || d->d_name[0] > '9') + continue; + + if (subdir == NULL) { + struct stat st; + + snprintf(npath, sizeof(npath), "/proc/%s/path", d->d_name); + if (stat(npath, &st) < 0) + subdir = "fd"; + else + subdir = "path"; + } + + pid = d->d_name; + snprintf(npath, sizeof(npath), "/proc/%s/%s", pid, subdir); + if ((linkslen = scandir(npath, &links, NULL, NULL)) > 0) { + for (li = 0; li < linkslen; li++) { + d = links[li]; + /* must be [0-9]+ */ + if (d->d_name[0] < '0' || d->d_name[0] > '9') + continue; + snprintf(npath, sizeof(npath), "/proc/%s/%s/%s", + pid, subdir, d->d_name); + rpathlen = readlink(npath, rpath, sizeof(rpath)); + if (rpathlen <= 0) + continue; + rpath[rpathlen] = '\0'; + /* check if this points to a portage build: + * /portage///temp/build.log */ + if (strcmp(rpath + rpathlen - + (sizeof("/temp/build.log") - 1), + "/temp/build.log") == 0 && + (p = strstr(rpath, "/portage/")) != NULL) + { + p += sizeof("/portage/") - 1; + rpath[rpathlen - (sizeof("/temp/build.log") - 1)] = + '\0'; + atom = atom_explode(p); + if (atom == NULL || + atom->CATEGORY == NULL || atom->P == NULL) + { + if (atom != NULL) + atom_implode(atom); + continue; + } + xarraypush_ptr(ret_atoms, atom); + } + } + scandir_free(links, linkslen); + } + } + scandir_free(procs, procslen); + } else { + /* flag /proc doesn't exist */ + return NULL; + } + + if (array_cnt(atoms) > 0) { + size_t j; + depend_atom *atomr; + + /* calculate intersection */ + array_for_each(atoms, i, atom) { + array_for_each(ret_atoms, j, atomr) { + if (atom_compare(atomr, atom) != EQUAL) { + xarraydelete_ptr(ret_atoms, j); + atom_implode(atomr); + break; + } + } + atom_implode(atom); + } + xarrayfree_int(atoms); + } + + /* ret_atoms is allocated on the stack, so copy into atoms which is + * empty at this point */ + array_for_each(ret_atoms, i, atom) + xarraypush_ptr(atoms, atom); + + xarrayfree_int(ret_atoms); + + return atoms; +} + int qlop_main(int argc, char **argv) { size_t i; @@ -1160,7 +1309,21 @@ int qlop_main(int argc, char **argv) m.fmt = "%[CATEGORY]%[PN]"; } - do_emerge_log(logfile, &m, atoms, start_time, end_time); + if (m.do_running) { + array_t *new_atoms = probe_proc(atoms); + + if (new_atoms != NULL && array_cnt(new_atoms) == 0) { + /* proc supported, found nothing running */ + start_time = LONG_MAX; + } else { + warn("/proc not available, deducing running " + "merges from emerge.log"); + } + + } + + if (start_time < LONG_MAX) + do_emerge_log(logfile, &m, atoms, start_time, end_time); array_for_each(atoms, i, atom) atom_implode(atom);