From: "Fabian Groffen" <grobian@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/portage-utils:master commit in: /, man/
Date: Sun, 27 Oct 2019 12:22:28 +0000 (UTC) [thread overview]
Message-ID: <1572178746.c9d7b9de78f1488827cb516bf61a54df28a750ab.grobian@gentoo> (raw)
commit: c9d7b9de78f1488827cb516bf61a54df28a750ab
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sun Oct 27 12:19:06 2019 +0000
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> 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 <grobian <AT> 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 <stdlib.h>
#include <ctype.h>
#include <limits.h>
+#include <sys/stat.h>
#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/<pid>/fd/X)
+- Solaris: readlink(/proc/<pid>/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/<pid>/path/<[0-9]+link>
+ * /proc/<pid>/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:
+ * <somepath>/portage/<cat>/<pf>/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);
next reply other threads:[~2019-10-27 12:22 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-27 12:22 Fabian Groffen [this message]
-- strict thread matches above, loose matches on Subject: below --
2020-05-02 8:45 [gentoo-commits] proj/portage-utils:master commit in: /, man/ Fabian Groffen
2020-01-06 15:03 Fabian Groffen
2019-12-14 17:01 Fabian Groffen
2019-11-24 12:29 Fabian Groffen
2019-11-09 10:13 Fabian Groffen
2019-09-28 13:19 Fabian Groffen
2019-09-10 18:25 Fabian Groffen
2019-07-14 13:09 Fabian Groffen
2019-07-14 10:21 Fabian Groffen
2019-07-14 10:21 Fabian Groffen
2019-07-14 10:21 Fabian Groffen
2019-07-14 10:21 Fabian Groffen
2019-05-20 10:46 Fabian Groffen
2016-03-28 4:53 Mike Frysinger
2016-02-22 20:37 Mike Frysinger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1572178746.c9d7b9de78f1488827cb516bf61a54df28a750ab.grobian@gentoo \
--to=grobian@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox