summaryrefslogtreecommitdiffabout
path: root/src/timer.c
authorSergey Poznyakoff <gray@gnu.org.ua>2009-02-21 16:26:51 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2009-02-21 16:26:51 (GMT)
commit0b63c31eadfe5d4e94c7014bd0f3bd4370783d19 (patch) (side-by-side diff)
tree9feb30a2c64d785d5e59fecd06429413e9f4d398 /src/timer.c
parent1213cf065e9b3a5fb45d00276b3d168462838c17 (diff)
downloadwydawca-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') (more/less context) (ignore whitespace changes)
-rw-r--r--src/timer.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/timer.c b/src/timer.c
new file mode 100644
index 0000000..7078f4f
--- a/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++;
+ }
+}

Return to:

Send suggestions and report system problems to the System administrator.