diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-04-20 11:41:18 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-04-20 11:41:18 +0300 |
commit | ce2bded4521255e3a0f7d2926d4198e75743af1d (patch) | |
tree | b97924438f3309a172c0dd09aa1d1ba9e51819c6 /src | |
parent | 84838fa69592cf37f97aaa918ad4e69b8bd4d62a (diff) | |
download | wydawca-ce2bded4521255e3a0f7d2926d4198e75743af1d.tar.gz wydawca-ce2bded4521255e3a0f7d2926d4198e75743af1d.tar.bz2 |
Rewrite the timer support.
Timers are kept in a thread-specific array variable. Spool timers are
referenced in expansion strings by their fully qualified names, e.g.
${timer:spool:release:system}.
* NEWS: Update.
* doc/wydawca.texi: Document new syntax for the spool timer variables.
* src/directive.c
* src/wydawca.h (struct spool): New member: timer_id.
* tests/upload-dry.at: Filter out certain messages, that can appear
* src/process.c (spool_count): New global.
(register_spool): Build spool list in the same order as listed in the
configuration file.
(spool_timer_id): New function.
* src/timer.c: Rewrite using array of struct timer_slot, instead of the
hash table.
* src/triplet.c (try_timer_var): Rewrite.
* src/wydawca.c (stderr_printer): Protect stderr by a mutex.
in unpredictable order.
Diffstat (limited to 'src')
-rw-r--r-- | src/directive.c | 4 | ||||
-rw-r--r-- | src/process.c | 42 | ||||
-rw-r--r-- | src/timer.c | 108 | ||||
-rw-r--r-- | src/triplet.c | 64 | ||||
-rw-r--r-- | src/wydawca.c | 4 | ||||
-rw-r--r-- | src/wydawca.h | 28 |
6 files changed, 119 insertions, 131 deletions
diff --git a/src/directive.c b/src/directive.c index b1b5a79..5067f00 100644 --- a/src/directive.c +++ b/src/directive.c @@ -597,7 +597,7 @@ process_directives(struct wy_triplet *trp) struct spool *spool = trp->spool; increase_stat_counter(WY_STAT_COMPLETE_TRIPLETS); - timer_start("triplet"); + timer_start(WY_TIMER_TRIPLET); report_init(); for (n = directive_first(trp, &key, &val); n; n = directive_next(trp, n, &key, &val)) { @@ -670,7 +670,7 @@ process_directives(struct wy_triplet *trp) increase_stat_counter(WY_STAT_TRIPLET_SUCCESS); report_finish(); - timer_stop("triplet"); + timer_stop(WY_TIMER_TRIPLET); notify(spool->notification, trp, wy_ev_success); return 0; } diff --git a/src/process.c b/src/process.c index beb0d72..323dbfe 100644 --- a/src/process.c +++ b/src/process.c @@ -21,14 +21,15 @@ struct spool_list { struct spool spool; }; -static struct spool_list *spool_list; +static struct spool_list *spool_head, *spool_tail; +size_t spool_count; int for_each_spool(int (*fun) (struct spool *, void *), void *data) { struct spool_list *sp; - for (sp = spool_list; sp; sp = sp->next) { + for (sp = spool_head; sp; sp = sp->next) { int rc = fun(&sp->spool, data); if (rc) return rc; @@ -41,8 +42,13 @@ register_spool(struct spool *spool) { struct spool_list *sp = grecs_malloc(sizeof *sp); sp->spool = *spool; - sp->next = spool_list; - spool_list = sp; + sp->next = NULL; + if (spool_tail) + spool_tail->next = sp; + else + spool_head = sp; + spool_tail = sp; + sp->spool.timer_id = spool_count++ + MY_TIMER_SPOOL_FIRST; } static int @@ -58,7 +64,7 @@ wydawca_find_spool(const char *name) { struct spool_list *sp; - for (sp = spool_list; sp; sp = sp->next) { + for (sp = spool_head; sp; sp = sp->next) { if (strcmp(sp->spool.tag, name) == 0 || spool_check_alias(&sp->spool, name)) return &sp->spool; @@ -183,9 +189,8 @@ scan_spool(struct spool *spool) return -1; } - timer_start("spool"); - /* FIXME: prefix spool tag with something */ - timer_start(spool->tag); + timer_start(WY_TIMER_SPOOL); + timer_start(spool->timer_id); while ((ent = readdir(dir))) { if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) @@ -195,8 +200,8 @@ scan_spool(struct spool *spool) closedir(dir); - timer_stop(spool->tag); - timer_stop("spool"); + timer_stop(spool->timer_id); + timer_stop(WY_TIMER_SPOOL); return 0; } @@ -231,7 +236,7 @@ void dictionaries_close(void) { struct spool_list *sp; - for (sp = spool_list; sp; sp = sp->next) + for (sp = spool_head; sp; sp = sp->next) spool_close_dictionaries(&sp->spool); } @@ -240,6 +245,19 @@ void scan_all_spools(void) { struct spool_list *sp; - for (sp = spool_list; sp; sp = sp->next) + for (sp = spool_head; sp; sp = sp->next) scan_spool(&sp->spool); } + +int +spool_timer_id(char *name) +{ + struct spool_list *sp; + for (sp = spool_head; sp; sp = sp->next) { + if (strcmp(sp->spool.tag, name) == 0) + return sp->spool.timer_id; + } + return -1; +} + + diff --git a/src/timer.c b/src/timer.c index a0b54e0..80917b6 100644 --- a/src/timer.c +++ b/src/timer.c @@ -21,8 +21,7 @@ #include <string.h> #include <ctype.h> -struct timer_slot { - char *name; +typedef struct timer_slot { size_t refcnt; double real; double self_user; /* user time in sec */ @@ -32,25 +31,7 @@ struct timer_slot { struct timeval real_mark; struct rusage self_mark; struct rusage children_mark; -}; - -static unsigned -hash_string_ci(const char *string, unsigned long n_buckets) -{ - size_t value = 0; - unsigned char ch; - - for (; (ch = *string); string++) - value = (value * 31 + tolower(ch)) % n_buckets; - return value; -} - -static unsigned -timer_hasher(void *ptr, unsigned long n_buckets) -{ - struct timer_slot *tp = ptr; - return hash_string_ci(tp->name, n_buckets); -} +} WY_TIMER; static pthread_key_t key; static pthread_once_t key_once = PTHREAD_ONCE_INIT; @@ -58,7 +39,7 @@ static pthread_once_t key_once = PTHREAD_ONCE_INIT; static void timer_free(void *f) { - grecs_symtab_free(f); + free(f); } static void @@ -67,42 +48,34 @@ make_key(void) pthread_key_create(&key, timer_free); } -struct grecs_symtab * +#define MAX_TIMERS (MY_TIMER_SPOOL_FIRST + spool_count) + +WY_TIMER * get_thread_timer_table(void) { - struct grecs_symtab *timer_table; + WY_TIMER *timer_table; pthread_once(&key_once, make_key); if ((timer_table = pthread_getspecific(key)) == NULL) { - timer_table = grecs_symtab_create(sizeof(struct timer_slot), - timer_hasher, - NULL, NULL, NULL, NULL); - if (!timer_table) - grecs_alloc_die(); + timer_table = grecs_calloc(MAX_TIMERS, + sizeof(timer_table[0])); pthread_setspecific(key, timer_table); } return timer_table; } -/* Lookup a timer by its name. If it does not exist, create it. */ -struct timer_slot * -timer_slot_lookup(const char *name) +wydawca_timer_t +get_thread_timer(int n) { - struct timer_slot slot, *ret; - int install = 1; - - slot.name = (char *)name; - ret = grecs_symtab_lookup_or_install(get_thread_timer_table(), - &slot, &install); - if (!ret) - grecs_alloc_die(); - return ret; + if (n < 0 || n >= MAX_TIMERS) + abort(); + return get_thread_timer_table() + n; } wydawca_timer_t -timer_start(const char *name) +timer_start(int idx) { - wydawca_timer_t t = timer_slot_lookup(name); + wydawca_timer_t t = get_thread_timer(idx); if (t->refcnt++ == 0) { gettimeofday(&t->real_mark, NULL); @@ -136,27 +109,27 @@ _timer_compute(wydawca_timer_t t) } wydawca_timer_t -timer_get(const char *name) +timer_get(int idx) { - wydawca_timer_t t = timer_slot_lookup(name); + wydawca_timer_t t = get_thread_timer(idx); if (t->refcnt) _timer_compute(t); return t; } wydawca_timer_t -timer_stop(const char *name) +timer_stop(int idx) { - wydawca_timer_t t = timer_get(name); + wydawca_timer_t t = get_thread_timer(idx); if (t->refcnt) --t->refcnt; return t; } wydawca_timer_t -timer_reset(const char *name) +timer_reset(int idx) { - wydawca_timer_t t = timer_get(name); + wydawca_timer_t t = get_thread_timer(idx); t->real = 0.0; t->self_user = 0.0; t->self_system = 0.0; @@ -216,7 +189,7 @@ timer_format_time(double t) /* Cumulative statistic counters and timers */ WY_STAT_COUNTER *wydawca_global_stats; -static struct grecs_symtab *wydawca_global_timer_table; +WY_TIMER *wydawca_global_timer_table; pthread_mutex_t global_stats_mutex = PTHREAD_MUTEX_INITIALIZER; /* wydawca_stats_export must be called from the main thread in order to @@ -229,26 +202,6 @@ wydawca_stats_export(void) wydawca_global_timer_table = get_thread_timer_table(); } -static int -timer_copy(void *sym, void *data) -{ - struct timer_slot *ts = sym, *ret; - int install; - - ret = grecs_symtab_lookup_or_install(wydawca_global_timer_table, - ts, &install); - if (!ret) - grecs_alloc_die(); - - ret->real += ts->real; - ret->self_user += ts->self_user; - ret->self_system += ts->self_system; - ret->children_user += ts->children_user; - ret->children_system += ts->children_system; - - return 0; -} - /* When running in cron mode, this function is called by the triplet processing thread when it has finished processing. The function incorporates the thread-specific statistics into the cumulative @@ -258,10 +211,21 @@ wydawca_stats_update(void) { int i; WY_STAT_COUNTER *ctr = wy_get_stat_array(); - struct grecs_symtab *thread_timers = get_thread_timer_table(); + WY_TIMER *thread_timers = get_thread_timer_table(); pthread_mutex_lock(&global_stats_mutex); for (i = 0; i < WY_MAX_STAT; i++) wydawca_global_stats[i] += ctr[i]; - grecs_symtab_foreach(thread_timers, timer_copy, NULL); + for (i = 0; i < MAX_TIMERS; i++) { + wydawca_global_timer_table[i].real + += thread_timers[i].real; + wydawca_global_timer_table[i].self_user + += thread_timers[i].self_user; + wydawca_global_timer_table[i].self_system + += thread_timers[i].self_system; + wydawca_global_timer_table[i].children_user + += thread_timers[i].children_user; + wydawca_global_timer_table[i].children_system + += thread_timers[i].children_system; + } pthread_mutex_unlock(&global_stats_mutex); } diff --git a/src/triplet.c b/src/triplet.c index 8c81ad8..2ad4e1d 100644 --- a/src/triplet.c +++ b/src/triplet.c @@ -357,8 +357,8 @@ triplet_enqueue(struct wy_triplet *trp) struct spool *spool = trp->spool; if (!trp) return; - timer_start("spool"); - timer_start(spool->tag); + timer_start(WY_TIMER_SPOOL); + timer_start(spool->timer_id); if (spool_open_dictionaries(spool) == 0) { switch (check_triplet_state(trp)) { case triplet_directive: @@ -380,8 +380,8 @@ triplet_enqueue(struct wy_triplet *trp) remove_triplet(trp); } } - timer_stop(spool->tag); - timer_stop("spool"); + timer_stop(spool->timer_id); + timer_stop(WY_TIMER_SPOOL); } /* Unlink all parts of the triplet TRP */ @@ -429,14 +429,14 @@ remove_triplet(struct wy_triplet *trp) void triplet_commit(struct wy_triplet *trp) { - timer_start("spool"); + timer_start(WY_TIMER_SPOOL); if (spool_open_dictionaries(trp->spool) == 0) { - timer_start(trp->spool->tag); + timer_start(trp->spool->timer_id); wy_debug(1, (_("processing triplet `%s'"), trp->name)); process_directives(trp); - timer_stop(trp->spool->tag); + timer_stop(trp->spool->timer_id); } - timer_stop("spool"); + timer_stop(WY_TIMER_SPOOL); } void @@ -570,28 +570,14 @@ struct wy_varexp { int flags; struct wy_triplet *triplet; struct wy_vardef **def; - char **timers; struct dictionary *dict; void *handle; }; -static int -member(char **a, char const *s) -{ - if (!a) - return 1; - while (*a) { - if (strcmp(*a, s) == 0) - return 1; - ++a; - } - return 0; -} - static void wy_ws_error(const char *fmt, ...); static int -try_timer_var(char **retval, char const *var, size_t len, char **timers) +try_timer_var(char **retval, char const *var, size_t len) { struct wordsplit ws; int rc = WRDSE_UNDEF; @@ -608,23 +594,31 @@ try_timer_var(char **retval, char const *var, size_t len, char **timers) (int) len, (int) len, var); exit(EX_UNAVAILABLE); } - if (ws.ws_wordc == 3 && strcmp(ws.ws_wordv[0], "timer") == 0) { - wydawca_timer_t t = NULL; - - if (member(timers, ws.ws_wordv[1])) - t = timer_get(ws.ws_wordv[1]); - if (t) { + if (strcmp(ws.ws_wordv[0], "timer") == 0) { + int n = -1; + + if (ws.ws_wordc == 3) { + if (strcmp(ws.ws_wordv[1], "wydawca") == 0) + n = WY_TIMER_WYDAWCA; + else if (strcmp(ws.ws_wordv[1], "triplet") == 0) + n = WY_TIMER_TRIPLET; + else if (strcmp(ws.ws_wordv[1], "spool") == 0) + n = WY_TIMER_SPOOL; + } else if (ws.ws_wordc == 4 && strcmp(ws.ws_wordv[1], "spool") == 0) + n = spool_timer_id(ws.ws_wordv[1] + 6); + + if (n >= 0) { double (*tfn) (wydawca_timer_t) = NULL; - if (strcmp(ws.ws_wordv[2], "real") == 0) + if (strcmp(ws.ws_wordv[ws.ws_wordc-1], "real") == 0) tfn = timer_get_real; - else if (strcmp(ws.ws_wordv[2], "user") == 0) + else if (strcmp(ws.ws_wordv[ws.ws_wordc-1], "user") == 0) tfn = timer_get_user; - else if (strcmp(ws.ws_wordv[2], "system") == 0) + else if (strcmp(ws.ws_wordv[ws.ws_wordc-1], "system") == 0) tfn = timer_get_system; if (tfn) { - *retval = timer_format_time(tfn(t)); + *retval = timer_format_time(tfn(get_thread_timer(n))); rc = WRDSE_OK; } } @@ -672,7 +666,7 @@ wy_varexp_lookup(char **retval, const char *var, size_t len, void *clos) rc = wy_varexp_lookup_triplet(&res, var, len, exp->def, exp->triplet); if (rc != WRDSE_OK && (exp->flags & WY_EXP_TIMERS)) - rc = try_timer_var(&res, var, len, exp->timers); + rc = try_timer_var(&res, var, len); if (rc != WRDSE_OK && (exp->flags & WY_EXP_STATS)) rc = wy_stat_expansion(&res, var, len); if (rc == WRDSE_OK) { @@ -1087,12 +1081,10 @@ wy_triplet_expand_param(const char *tmpl, struct wy_triplet *trp, { struct wy_vardef *vd[] = { triplet_query_def, triplet_def, extra, NULL }; - static char *timers[] = { "wydawca", "triplet", "spool", NULL }; struct wy_varexp varexp = { .flags = WY_EXP_TIMERS, .triplet = trp, .def = vd, - .timers = timers }; return wy_expand_string(tmpl, &varexp); } diff --git a/src/wydawca.c b/src/wydawca.c index d07ebdf..58f87ce 100644 --- a/src/wydawca.c +++ b/src/wydawca.c @@ -84,10 +84,13 @@ syslog_printer(int prio, const char *fmt, va_list ap) #endif } +static pthread_mutex_t stderr_mutex = PTHREAD_MUTEX_INITIALIZER; + void stderr_printer(int prio, const char *fmt, va_list ap) { const char *p = wy_pritostr(prio); + pthread_mutex_lock(&stderr_mutex); fprintf(stderr, "%s: ", program_name); if (p) @@ -95,6 +98,7 @@ stderr_printer(int prio, const char *fmt, va_list ap) vfprintf(stderr, fmt, ap); fputc('\n', stderr); + pthread_mutex_unlock(&stderr_mutex); } static void (*log_printer) (int prio, const char *fmt, va_list ap) = diff --git a/src/wydawca.h b/src/wydawca.h index c48ea30..467daa0 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -231,6 +231,7 @@ struct virt_tab { files from source to destination */ struct spool { char *tag; + int timer_id; struct grecs_list *aliases; char *url; /* Download URL */ char *source_dir; /* Source directory */ @@ -313,11 +314,6 @@ extern int archive_signatures; extern char *pidfile; extern int force_startup; -extern char *lockdir; -extern time_t lock_expire_time; -extern time_t lock_timeout; -extern int enable_locking; - enum { WY_MODE_NORMAL, WY_MODE_CRON, @@ -343,6 +339,8 @@ extern int inotify_enable; extern struct notification *default_notification; +extern size_t spool_count; + typedef unsigned WY_STAT_COUNTER; WY_STAT_COUNTER *wy_get_stat_array(void); @@ -514,14 +512,26 @@ int null_rmsymlink_file(struct wy_triplet *trp, const char *file_name); /* timer.c */ typedef struct timer_slot *wydawca_timer_t; -wydawca_timer_t timer_get(const char *name); -wydawca_timer_t timer_start(const char *name); -wydawca_timer_t timer_stop(const char *name); -wydawca_timer_t timer_reset(const char *name); +enum { + WY_TIMER_WYDAWCA, + WY_TIMER_TRIPLET, + WY_TIMER_SPOOL, + MY_TIMER_SPOOL_FIRST +}; + +wydawca_timer_t get_thread_timer_table(void); +wydawca_timer_t get_thread_timer(int n); + +wydawca_timer_t timer_get(int); +wydawca_timer_t timer_start(int); +wydawca_timer_t timer_stop(int); +wydawca_timer_t timer_reset(int); double timer_get_real(wydawca_timer_t t); double timer_get_user(wydawca_timer_t t); double timer_get_system(wydawca_timer_t t); char *timer_format_time(double t); +int spool_timer_id(char *name); + void report_init(void); void report_add(const char *fmt, ...); |