From 35bcd948b00a3c904d5278e06987485ee7c2758e Mon Sep 17 00:00:00 2001 From: Colin Guthrie <colin@mageia.org> Date: Tue, 22 Jul 2014 22:42:07 +0100 Subject: [PATCH] filetriggers: Start filetriggers in priority order. This ensures that filetriggers are started in a more deterministic way whereby they are grouped by priority and executed to completion before moving on to executing the next highest priority. --- doc/manual/filetriggers | 8 ++++++- lib/filetriggers.c | 63 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/doc/manual/filetriggers b/doc/manual/filetriggers index 3bde56c..77d5919 100644 --- a/doc/manual/filetriggers +++ b/doc/manual/filetriggers @@ -64,7 +64,13 @@ some files match, the corresponding {{prog|%_filetriggersdir/<name>.script}} is called, with matching lines passed in stdin. Note that this is done in parallel, so multiple {{prog|<name>.script}} may be running -at the same time. +at the same time. As it may be required to run some filetriggers before others, +a priority mechanism is supported and only those triggers with the same priority +are run in parallel before moving on to the next highest priority. + +To prioritize triggers, simply prefix them with a two digit number followed by a +hyphen, e.g. {{file|00-ldconfig.script}}. Only the range 00 to 99 is supported +and if no numeric prefix is detected then the default priority of 50 is assumed. When it's done, {{file|/var/lib/rpm/files-awaiting-filetriggers}} is removed. diff --git a/lib/filetriggers.c b/lib/filetriggers.c index f5817bf..a1172e0 100644 --- a/lib/filetriggers.c +++ b/lib/filetriggers.c @@ -67,6 +67,8 @@ struct filetrigger_raw { struct filetrigger { regex_t regexp; char *name; + char *matched; + int priority; int command_pipe; int command_pid; }; @@ -146,7 +148,18 @@ static void getFiletriggers(const char *rootDir, regex_t *matches_any, int *nb, *list = calloc(*nb, sizeof(**list)); int i; for (i = 0; i < *nb; i++) { - (*list)[i].name = list_raw[i].name; + char *n = (*list)[i].name = list_raw[i].name; + (*list)[i].matched = NULL; + (*list)[i].priority = 50; + if (strlen(n) > 3 && '-' == n[2]) { + if ('0' == n[0] && '0' == n[1]) + (*list)[i].priority = 0; + else { + int priority = atoi(n); + if (priority > 0 && priority < 100) + (*list)[i].priority = priority; + } + } compileFiletriggersRegexp(list_raw[i].regexp, &(*list)[i].regexp); } free(list_raw); @@ -159,6 +172,8 @@ static void freeFiletriggers(regex_t *matches_any, int nb, struct filetrigger *l for (i = 0; i < nb; i++) { regfree(&list[i].regexp); free(list[i].name); + if (list[i].matched) + free(list[i].matched); } free(list); } @@ -236,6 +251,8 @@ void rpmRunFileTriggers(const char *rootDir) awaiting = fopen(file, "r"); if (awaiting) { char tmp[1024]; + int matched_any = 0; + int matched_priorities[100] = { 0 }; void *oldhandler = signal(SIGPIPE, SIG_IGN); @@ -245,20 +262,44 @@ void rpmRunFileTriggers(const char *rootDir) int i; for (i = 0; i < nb; i++) if (is_regexp_matching(&list[i].regexp, tmp)) { - mayStartFiletrigger(rootDir, &list[i]); - write(list[i].command_pipe, tmp, strlen(tmp)); + int len = strlen(tmp); + matched_any = matched_priorities[list[i].priority] = 1; + if (!list[i].matched) { + list[i].matched = xmalloc(len+1); + strncpy(list[i].matched, tmp, len+1); + } else { + char *oldtmp = list[i].matched; + int oldlen = strlen(oldtmp); + list[i].matched = xmalloc(oldlen+len+1); + strncpy(list[i].matched, oldtmp, oldlen); + strncpy(list[i].matched+oldlen, tmp, len+1); + free(oldtmp); + } } } fclose(awaiting); - int i; - for (i = 0; i < nb; i++) - if (list[i].command_pipe) { - close(list[i].command_pipe); - int status; - rpmlog(RPMLOG_DEBUG, "[filetriggers] waiting for %s to end\n", list[i].name); - waitpid(list[i].command_pid, &status, 0); - } + if (matched_any) { + int i; + for (i = 0; i < 100; ++i) { + int j; + if (!matched_priorities[i]) continue; + + for (j = 0; j < nb; j++) + if (list[j].matched && list[j].priority == i) { + mayStartFiletrigger(rootDir, &list[j]); + write(list[j].command_pipe, list[j].matched, strlen(list[j].matched)); + } + for (j = 0; j < nb; j++) + if (list[j].command_pipe) { + int status; + close(list[j].command_pipe); + list[j].command_pipe = 0; + rpmlog(RPMLOG_DEBUG, "[filetriggers] waiting for %s to end\n", list[j].name); + waitpid(list[j].command_pid, &status, 0); + } + } + } freeFiletriggers(&matches_any, nb, list); signal(SIGPIPE, oldhandler); -- 1.9.2