diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-02-21 18:26:51 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-02-21 18:26:51 +0200 |
commit | 0b63c31eadfe5d4e94c7014bd0f3bd4370783d19 (patch) | |
tree | 9feb30a2c64d785d5e59fecd06429413e9f4d398 /src/timer.c | |
parent | 1213cf065e9b3a5fb45d00276b3d168462838c17 (diff) | |
download | wydawca-0b63c31eadfe5d4e94c7014bd0f3bd4370783d19.tar.gz wydawca-0b63c31eadfe5d4e94c7014bd0f3bd4370783d19.tar.bz2 |
Implement timers and destination URLs.
* gconf/gconf-gram.y (stmt_end): Make sure end callback is called in the
same environment as the begin one.
* src/vtab.c, src/null.c, src/timer.c: New files.
* src/Makefile.am (wydawca_SOURCES): Add new files.
* src/config.c (cb_mailer): Remove useless check.
(cb_destination_url): New function.
(directory_kw): Change handling of the destination keyword.
(cb_directory): Rewrite final checks.
* src/directive.c, /src/process.c, src/triplet.c: Add timers.
* src/diskio.c (move_file, archive_file, symlink_file, rmsymlink_file): Prefix
with dir_.
* src/mail.c (mail_stats): Add timer meta-variables.
* src/wydawca.c (make_stat_expansion): Change definition.
* src/wydawca.h (struct virt_tab): New data type.
(struct directory_pair.dest_url): New member.
* tests/upload-dry.at: Update expected output.
Diffstat (limited to 'src/timer.c')
-rw-r--r-- | src/timer.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/src/timer.c b/src/timer.c new file mode 100644 index 0000000..7078f4f --- /dev/null +++ b/src/timer.c @@ -0,0 +1,255 @@ +/* wydawca - automatic release submission daemon + Copyright (C) 2008, 2009 Sergey Poznyakoff + + Wydawca is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or (at your + option) any later version. + + Wydawca is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with wydawca. If not, see <http://www.gnu.org/licenses/>. */ + +#include <wydawca.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <unistd.h> +#include <string.h> +#include <hash.h> +#include <ctype.h> +#include <xalloc.h> + +struct timer_slot +{ + char *name; + double real; + double self_user; /* user time in sec */ + double self_system; /* system time in sec */ + double children_user; /* user time in sec */ + double children_system; /* system time in sec */ + struct timeval real_mark; + struct rusage self_mark; + struct rusage children_mark; +}; + +static Hash_table *timer_table; +static size_t _timer_count; + +static size_t +hash_string_ci (const char *string, size_t n_buckets) +{ + size_t value = 0; + unsigned char ch; + + for (; (ch = *string); string++) + value = (value * 31 + tolower (ch)) % n_buckets; + return value; +} + +/* Calculate the hash of a string. */ +static size_t +timer_hasher (void const *data, unsigned n_buckets) +{ + const struct timer_slot *t = data; + return hash_string_ci (t->name, n_buckets); +} + +/* Compare two strings for equality. */ +static bool +timer_compare (void const *data1, void const *data2) +{ + const struct timer_slot *t1 = data1; + const struct timer_slot *t2 = data2; + return strcasecmp (t1->name, t2->name) == 0; +} + +/* Allocate a timer structure */ +static wydawca_timer_t +timer_alloc (const char *name) +{ + wydawca_timer_t t = xmalloc (sizeof (*t) + strlen (name) + 1); + memset (t, 0, sizeof (*t)); + t->name = (char *) (t + 1); + strcpy (t->name, name); + return t; +} + +/* Lookup a timer by its name. If it does not exist, create it. */ +wydawca_timer_t +timer_get (const char *name) +{ + wydawca_timer_t tp, ret; + + tp = timer_alloc (name); + + if (!((timer_table + || (timer_table = hash_initialize (0, 0, + timer_hasher, + timer_compare, 0))) + && (ret = hash_insert (timer_table, tp)))) + xalloc_die (); + + if (ret != tp) + free (tp); + else + _timer_count++; + return ret; +} + +wydawca_timer_t +timer_start (const char *name) +{ + wydawca_timer_t t = timer_get (name); + + gettimeofday (&t->real_mark, NULL); + getrusage (RUSAGE_SELF, &t->self_mark); + getrusage (RUSAGE_CHILDREN, &t->children_mark); + return t; +} + +#define DIFFTIME(now,then)\ + (((now).tv_sec - (then).tv_sec) \ + + ((double)((now).tv_usec - (then).tv_usec))/1000000) + +static void +_timer_compute (wydawca_timer_t t) +{ + struct timeval real; + struct rusage rusage; + + gettimeofday (&real, NULL); + t->real = DIFFTIME (real, t->real_mark); + getrusage (RUSAGE_SELF, &rusage); + t->self_user = DIFFTIME (rusage.ru_utime, t->self_mark.ru_utime); + t->self_system = DIFFTIME (rusage.ru_stime, t->self_mark.ru_stime); + + getrusage (RUSAGE_CHILDREN, &rusage); + t->children_user = DIFFTIME (rusage.ru_utime, t->children_mark.ru_utime); + t->children_system = DIFFTIME (rusage.ru_stime, t->children_mark.ru_stime); +} + +wydawca_timer_t +timer_stop (const char *name) +{ + wydawca_timer_t t = timer_get (name); + _timer_compute (t); + return t; +} + +wydawca_timer_t +timer_reset (const char *name) +{ + wydawca_timer_t t = timer_get (name); + t->real = 0.0; + t->self_user = 0.0; + t->self_system = 0.0; + t->children_user = 0.0; + t->children_system = 0.0; + return t; +} + +double +timer_get_real (wydawca_timer_t t) +{ + return t->real; +} + +double +timer_get_user (wydawca_timer_t t) +{ + return t->self_user + t->children_user; +} + +double +timer_get_system (wydawca_timer_t t) +{ + return t->self_system + t->children_system; +} + +char * +timer_format_time (double t) +{ + char *str = NULL; + if (t < 600) + asprintf (&str, "%0.3f", t); + else + { + long int s, m, h, d; + + s = (long int) t; + d = s / (3600 * 24); + s -= d * 3600 * 24; + h = s / 3600; + s -= h * 3600; + m = s / 60; + s -= m * 60; + + if (d) + asprintf (&str, "%ld+%02ld:%02ld:%02ld", d, h, m, s); + else if (h) + asprintf (&str, "%02ld:%02ld:%02ld", h, m, s); + else + asprintf (&str, "%02ld:%02ld", m, s); + } + return str; +} + +size_t +timer_get_count () +{ + return _timer_count; +} + +struct timer_data +{ + struct metadef *def; + size_t num; +}; + +bool +_fill_meta (void *data, void *proc_data) +{ + struct timer_slot *slot = data; + struct timer_data *tp = proc_data; +#define CREATE_DEF(arg) \ + if (tp->num) \ + { \ + asprintf (&tp->def->kw, "timer:%s:%s", slot->name, #arg); \ + tp->def->storage = timer_format_time (__cat2__(timer_get_,arg) (slot)); \ + tp->def->value = tp->def->storage; \ + tp->def->expand = NULL; \ + tp->def++; \ + tp->num--; \ + } + + CREATE_DEF(system); + CREATE_DEF(real); + CREATE_DEF(user); + + return tp->num > 0; +} + +void +timer_fill_meta (struct metadef *def, size_t num) +{ + struct timer_data td; + if (!timer_table) + return; + td.def = def; + td.num = num; + hash_do_for_each (timer_table, _fill_meta, &td); +} + +void +timer_free_meta (struct metadef *def, size_t num) +{ + while (num--) + { + free (def->kw); + def++; + } +} |