aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-04-20 11:41:18 +0300
committerSergey Poznyakoff <gray@gnu.org>2020-04-20 11:41:18 +0300
commitce2bded4521255e3a0f7d2926d4198e75743af1d (patch)
treeb97924438f3309a172c0dd09aa1d1ba9e51819c6 /src
parent84838fa69592cf37f97aaa918ad4e69b8bd4d62a (diff)
downloadwydawca-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.c4
-rw-r--r--src/process.c42
-rw-r--r--src/timer.c108
-rw-r--r--src/triplet.c64
-rw-r--r--src/wydawca.c4
-rw-r--r--src/wydawca.h28
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, ...);

Return to:

Send suggestions and report system problems to the System administrator.