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 | |
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.
-rw-r--r-- | gconf/gconf-gram.y | 19 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/config.c | 93 | ||||
-rw-r--r-- | src/directive.c | 2 | ||||
-rw-r--r-- | src/diskio.c | 43 | ||||
-rw-r--r-- | src/mail.c | 11 | ||||
-rw-r--r-- | src/null.c | 58 | ||||
-rw-r--r-- | src/process.c | 11 | ||||
-rw-r--r-- | src/timer.c | 255 | ||||
-rw-r--r-- | src/triplet.c | 26 | ||||
-rw-r--r-- | src/vtab.c | 80 | ||||
-rw-r--r-- | src/wydawca.c | 24 | ||||
-rw-r--r-- | src/wydawca.h | 140 | ||||
-rw-r--r-- | tests/upload-dry.at | 2 |
14 files changed, 681 insertions, 88 deletions
diff --git a/gconf/gconf-gram.y b/gconf/gconf-gram.y index ed685d0..a1d9f2a 100644 --- a/gconf/gconf-gram.y +++ b/gconf/gconf-gram.y @@ -377,17 +377,26 @@ stmt_begin (struct gconf_keyword *kwp, gconf_value_t tag) static void stmt_end (struct gconf_keyword *kwp) { + gconf_callback_fn callback = NULL; + void *dataptr = NULL; + if (cursect && cursect->callback) - cursect->callback (gconf_callback_section_end, - &gconf_current_locus, /* FIXME */ - kwp ? target_ptr(kwp) : NULL, - NULL, - &cursect->callback_data); + { + callback = cursect->callback; + dataptr = &cursect->callback_data; + } if (gl_list_size (sections) == 0) abort (); cursect = (struct gconf_keyword *) gl_list_get_at (sections, 0); gl_list_remove_at (sections, 0); + if (callback) + callback (gconf_callback_section_end, + &gconf_current_locus, /* FIXME */ + kwp ? target_ptr(kwp) : NULL, + NULL, + dataptr); + } static struct gconf_keyword * diff --git a/src/Makefile.am b/src/Makefile.am index b5e5040..110bd07 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,7 +35,10 @@ wydawca_SOURCES=\ wydawca.c\ wydawca.h\ mail.h\ - mail.c + mail.c\ + vtab.c\ + null.c\ + timer.c BUILT_SOURCES=cmdline.h EXTRA_DIST=cmdline.opt getopt.m4 pp-setup diff --git a/src/config.c b/src/config.c index c22074f..b8c31f7 100644 --- a/src/config.c +++ b/src/config.c @@ -268,11 +268,6 @@ cb_mailer (enum gconf_callback_command cmd, gconf_error (locus, 0, _("Unexpected block statement")); return 1; } - if (!value || value->type != GCONF_TYPE_STRING) - { - gconf_error (locus, 0, _("expected scalar value")); - return 1; - } rc = mu_mailer_create (&mailer, value->v.string); if (rc) gconf_error (locus, 0, _("cannot create mailer `%s': %s"), @@ -1089,13 +1084,49 @@ cb_access_method (enum gconf_callback_command cmd, return 0; } +static int +cb_destination_url (enum gconf_callback_command cmd, + gconf_locus_t *locus, + void *varptr, + gconf_value_t *value, + void *cb_data) +{ + mu_url_t *purl = varptr, url; + int rc; + + if (assert_string_arg (locus, cmd, value)) + return 1; + if (cmd != gconf_callback_set_value) + { + gconf_error (locus, 0, _("Unexpected block statement")); + return 1; + } + rc = mu_url_create (&url, value->v.string); + if (rc) + { + gconf_error (locus, 0, _("cannot create URL `%s': %s"), + value->v.string, mu_strerror (rc)); + return rc; + } + rc = mu_url_parse (url); + if (rc) + { + gconf_error (locus, 0, _("cannot parse URL `%s': %s"), + value->v.string, mu_strerror (rc)); + mu_url_destroy (&url); + return rc; + } + *purl = url; + return 0; +} static struct gconf_keyword directory_kw[] = { { "source", N_("dir"), N_("Source directory"), gconf_type_string, NULL, offsetof(struct directory_pair, source_dir) }, { "destination", N_("dir"), N_("Destination directory"), - gconf_type_string, NULL, offsetof(struct directory_pair, dest_dir) }, + gconf_type_string, NULL, offsetof(struct directory_pair, dest_url), + cb_destination_url }, { "file-sweep-time", N_("interval"), N_("Define file sweep time"), gconf_type_string, NULL, offsetof(struct directory_pair, file_sweep_time), cb_interval }, @@ -1121,7 +1152,8 @@ cb_directory (enum gconf_callback_command cmd, { struct directory_pair *dpair; void **pdata = cb_data; - int ec, i; + int rc, ec, i; + const char *ep = NULL; switch (cmd) { @@ -1141,11 +1173,13 @@ cb_directory (enum gconf_callback_command cmd, break; case gconf_callback_section_end: + rc = 0; dpair = *pdata; if (!dpair->source_dir) - gconf_error (locus, 0, _("source is not given")); - else if (!dpair->dest_dir) - gconf_error (locus, 0, _("destination is not given")); + { + gconf_error (locus, 0, _("source is not given")); + rc = 1; + } else if (test_dir (dpair->source_dir, &ec)) { if (ec) @@ -1153,29 +1187,38 @@ cb_directory (enum gconf_callback_command cmd, else gconf_error (locus, 0, _("%s is not a directory"), dpair->source_dir); + rc = 1; } - else if (test_dir (dpair->dest_dir, &ec)) + + if (!dpair->dest_url) { - if (ec) - gconf_error (locus, ec, _("cannot access %s"), dpair->dest_dir); - else - gconf_error (locus, ec, _("%s is not a directory"), - dpair->dest_dir); + gconf_error (locus, 0, _("destination is not given")); + rc = 1; } - else if (dpair->access_method[verify_method]->type != method_none - && dpair->access_method[gpg_key_method]->type != method_none) + else if (url_to_vtab (dpair->dest_url, &dpair->vtab)) { - int i; - - for (i = 0; i < access_method_count; i++) - if (dpair->access_method[i]->type == method_external) - gconf_error (locus, 0, - _("Sorry, method type `external' is not yet supported")); + gconf_error (locus, 0, _("unsupported url: %s"), + mu_url_to_string (dpair->dest_url)); + rc = 1; } + else if (dpair->vtab.test_url + && dpair->vtab.test_url (dpair->dest_url, locus)) + rc = 1; + for (i = 0; i < access_method_count; i++) + if (dpair->access_method[i]->type == method_external) + { + gconf_error (locus, 0, + _("Sorry, method type `external' is not yet supported")); + rc = 1; + } + + if (rc) + return rc; + if (!dpair->notification) dpair->notification = default_notification; - + mu_url_sget_path (dpair->dest_url, &dpair->dest_dir); register_directory_pair (dpair); free (dpair); *pdata = NULL; diff --git a/src/directive.c b/src/directive.c index d99f65b..b050ffb 100644 --- a/src/directive.c +++ b/src/directive.c @@ -308,6 +308,7 @@ process_directives (struct file_triplet *trp, struct directory_pair *dpair) const char *key, *val; char *relative_dir; + timer_start ("triplet"); UPDATE_STATS (STAT_COMPLETE_TRIPLETS); for (n = directive_first (trp, &key, &val); n; n = directive_next (trp, n, &key, &val)) @@ -400,6 +401,7 @@ process_directives (struct file_triplet *trp, struct directory_pair *dpair) free (relative_dir); UPDATE_STATS (STAT_TRIPLET_SUCCESS); + timer_stop ("triplet"); notify (dpair->notification, trp, ev_success); return 0; } diff --git a/src/diskio.c b/src/diskio.c index e30b215..0548972 100644 --- a/src/diskio.c +++ b/src/diskio.c @@ -26,7 +26,7 @@ /* Return true if ARG is NULL or is a sub-directory of DIR */ int -sub_dir_p (char *arg, char *dir) +sub_dir_p (const char *arg, const char *dir) { int dlen; @@ -441,8 +441,8 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file, Do nothing if dry_run_mode is set. */ int -move_file (struct file_triplet *trp, struct directory_pair *dpair, - enum file_type file_id, const char *reldir) +dir_move_file (struct file_triplet *trp, struct directory_pair *dpair, + enum file_type file_id, const char *reldir) { char *dst_file; int rc = 0; @@ -548,8 +548,8 @@ make_signame (const char *file_name) Do nothing if dry_run_mode is set. */ int -archive_file (struct file_triplet *trp, struct directory_pair *dpair, - const char *reldir, const char *file_name) +dir_archive_file (struct file_triplet *trp, struct directory_pair *dpair, + const char *reldir, const char *file_name) { int rc; char *signame; @@ -568,9 +568,9 @@ archive_file (struct file_triplet *trp, struct directory_pair *dpair, Do nothing if dry_run_mode is set. */ int -symlink_file (struct file_triplet *trp, struct directory_pair *dpair, - const char *reldir, - const char *wanted_src, const char *wanted_dst) +dir_symlink_file (struct file_triplet *trp, struct directory_pair *dpair, + const char *reldir, + const char *wanted_src, const char *wanted_dst) { int rc = 0; struct saved_cwd cwd; @@ -728,8 +728,8 @@ do_rmsymlink_file (const char *dst_file, int noentok) Do nothing if dry_run_mode is set. */ int -rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair, - const char *reldir, const char *file_name) +dir_rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair, + const char *reldir, const char *file_name) { char *dst_file; int rc = 0; @@ -763,3 +763,26 @@ rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair, return rc; } +int +dir_test_url (mu_url_t url, gconf_locus_t *locus) +{ + int rc; + const char *dest_dir; + + rc = mu_url_sget_path (url, &dest_dir); + if (rc) + { + gconf_error (locus, 0, _("cannot extract directory part from URL: %s"), + mu_strerror (rc)); + return rc; + } + if (test_dir (dest_dir, &rc)) + { + if (rc) + gconf_error (locus, rc, _("cannot access %s"), dest_dir); + else + gconf_error (locus, 0, _("%s is not a directory"), dest_dir); + return 1; + } + return 0; +} @@ -202,10 +202,11 @@ resolve_message_template (const char *name) void mail_stats () { - struct metadef exp[MAX_STAT + 2]; + struct metadef *exp; time_t t; const char *tmpl; char *text; + size_t tc; if (!admin_stat_message || !stat_mask_p (mail_admin_mask) || !mailer) return; @@ -230,13 +231,13 @@ mail_stats () if (dry_run_mode) return; + tc = timer_get_count () * 3; + exp = make_stat_expansion (tc + 1); time (&t); - memset (exp, 0, sizeof (exp)); exp[0].kw = "date"; exp[0].value = exp[0].storage = xstrdup (ctime (&t)); exp[0].value [strlen (exp[0].value) - 1] = 0; - - make_stat_expansion (exp + 1); + timer_fill_meta (exp + 1, tc); tmpl = resolve_message_template (admin_stat_message); if (!tmpl) @@ -251,6 +252,8 @@ mail_stats () free (text); meta_free (exp); + timer_free_meta (exp + 1, tc); + free (exp); } mu_address_t diff --git a/src/null.c b/src/null.c new file mode 100644 index 0000000..3c17361 --- /dev/null +++ b/src/null.c @@ -0,0 +1,58 @@ +/* wydawca - automatic release submission daemon + Copyright (C) 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" + +int +null_move_file (struct file_triplet *trp, struct directory_pair *dpair, + enum file_type file_id, const char *reldir) +{ + if (debug_level) + logmsg (LOG_DEBUG, "%s: installing file `%s/%s'", + dpair->url, reldir, trp->file[file_id].name); + return 0; +} + +int +null_archive_file (struct file_triplet *trp, struct directory_pair *dpair, + const char *file_name, const char *reldir) +{ + if (debug_level) + logmsg (LOG_DEBUG, "%s: archiving `%s'", dpair->url, file_name); + return 0; +} + +int +null_symlink_file (struct file_triplet *trp, struct directory_pair *dpair, + const char *reldir, + const char *wanted_src, const char *wanted_dst) +{ + if (debug_level) + logmsg (LOG_DEBUG, "%s: symlinking `%s' to `%s'", + dpair->url, wanted_src, wanted_dst); + return 0; +} + +int +null_rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair, + const char *reldir, const char *file_name) +{ + if (debug_level) + logmsg (LOG_DEBUG, "%s: removing symlink `%s/%s'", + dpair->url, reldir, file_name); + return 0; +} + diff --git a/src/process.c b/src/process.c index 645d987..dd499bd 100644 --- a/src/process.c +++ b/src/process.c @@ -109,7 +109,8 @@ scan_directory_pair (struct directory_pair *dpair) struct dirent *ent; if (debug_level) - logmsg (LOG_DEBUG, "%s -> %s", dpair->source_dir, dpair->dest_dir); + logmsg (LOG_DEBUG, "%s -> %s", dpair->source_dir, + mu_url_to_string (dpair->dest_url)); if (chdir (dpair->source_dir)) { @@ -126,6 +127,8 @@ scan_directory_pair (struct directory_pair *dpair) return; } + timer_start ("directory"); + timer_start (dpair->url); while ((ent = readdir (dir))) { struct stat st; @@ -179,6 +182,8 @@ scan_directory_pair (struct directory_pair *dpair) } enumerate_triplets (dpair); } + timer_stop (dpair->url); + timer_stop ("directory"); } static void @@ -194,10 +199,14 @@ void scan_directories () { struct directory_list *dp; + + timer_start ("wydawca"); + for (dp = dlist; dp; dp = dp->next) scan_directory_pair (&dp->pair); for (dp = dlist; dp; dp = dp->next) close_methods (&dp->pair); + timer_stop ("wydawca"); } 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++; + } +} diff --git a/src/triplet.c b/src/triplet.c index 03aa4cc..6ebc142 100644 --- a/src/triplet.c +++ b/src/triplet.c @@ -229,7 +229,8 @@ void enumerate_triplets (struct directory_pair *dpair) { if (debug_level) - logmsg (LOG_DEBUG, "Processing files for %s", dpair->dest_dir); + logmsg (LOG_DEBUG, "Processing files for %s (%s)", + dpair->url, mu_url_to_string (dpair->dest_url)); if (triplet_table) { hash_do_for_each (triplet_table, triplet_processor, dpair); @@ -542,6 +543,26 @@ expand_user_email (struct metadef *def, void *data) return def->value; } +#define DECL_EXPAND_TIMER(what) \ +static const char * \ +__cat2__(expand_timer_,what) (struct metadef *def, void *data) \ +{ \ + wydawca_timer_t t = timer_stop ((char*)def->data); \ + def->storage = timer_format_time (__cat2__(timer_get_,what) (t)); \ + def->value = def->storage; \ +} + +DECL_EXPAND_TIMER(real) +DECL_EXPAND_TIMER(user) +DECL_EXPAND_TIMER(system) + +#define DECL_TIMER(name,t) \ + { "timer:" #name ":" #t, NULL, __cat2__(expand_timer_,t), NULL, #name } +#define DECL_FULL_TIMER(name) \ + DECL_TIMER(name, real), \ + DECL_TIMER(name, user), \ + DECL_TIMER(name, system) + struct metadef triplet_meta[] = { { "project", NULL, expand_project_base, NULL }, { "url", NULL, expand_url, NULL }, @@ -557,6 +578,9 @@ struct metadef triplet_meta[] = { { "user:name", NULL, expand_user_name, NULL }, { "user:real-name", NULL, expand_user_real_name, NULL }, { "user:email", NULL, expand_user_email, NULL }, + DECL_FULL_TIMER(wydawca), + DECL_FULL_TIMER(triplet), + DECL_FULL_TIMER(directory), { NULL } }; diff --git a/src/vtab.c b/src/vtab.c new file mode 100644 index 0000000..66d8ecd --- /dev/null +++ b/src/vtab.c @@ -0,0 +1,80 @@ +/* wydawca - automatic release submission daemon + Copyright (C) 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" + +struct virt_tab_reg +{ + char *scheme; + struct virt_tab vtab; +}; + +static struct virt_tab_reg reg[] = { + { "file", + { dir_test_url, dir_move_file, dir_archive_file, dir_symlink_file, + dir_rmsymlink_file } }, + { "null", + { NULL, null_move_file, null_archive_file, null_symlink_file, + null_rmsymlink_file } }, + { NULL } +}; + +int +url_to_vtab (mu_url_t url, struct virt_tab *vtab) +{ + const char *scheme; + int i; + + if (mu_url_sget_scheme (url, &scheme)) + return 1; + for (i = 0; reg[i].scheme; i++) + if (strcmp (reg[i].scheme, scheme) == 0) + { + *vtab = reg[i].vtab; + return 0; + } + return 1; +} + + +int +move_file (struct file_triplet *trp, struct directory_pair *dpair, + enum file_type file_id, const char *reldir) +{ + return dpair->vtab.move_file (trp, dpair, file_id, reldir); +} + +int +archive_file (struct file_triplet *trp, struct directory_pair *dpair, + const char *reldir, const char *file_name) +{ + return dpair->vtab.archive_file (trp, dpair, reldir, file_name); +} + +int +symlink_file (struct file_triplet *trp, struct directory_pair *dpair, + const char *reldir, + const char *wanted_src, const char *wanted_dst) +{ + return dpair->vtab.symlink_file (trp, dpair, reldir, wanted_src, wanted_dst); +} + +int +rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair, + const char *reldir, const char *file_name) +{ + return dpair->vtab.rmsymlink_file (trp, dpair, reldir, file_name); +} diff --git a/src/wydawca.c b/src/wydawca.c index 1d953b9..5df2638 100644 --- a/src/wydawca.c +++ b/src/wydawca.c @@ -215,19 +215,23 @@ stat_expand (struct metadef *def, void *data) return def->value; } -void -make_stat_expansion (struct metadef *def) +struct metadef * +make_stat_expansion (size_t count) { int i; - for (i = 0; i < MAX_STAT; i++) + struct metadef *def, *p; + def = xcalloc (MAX_STAT + count + 1, sizeof (def[0])); + p = def + count; + for (i = 0; i < MAX_STAT; i++, p++) { - def[i].kw = stat_kwname[i]; - def[i].value = NULL; - def[i].storage = NULL; - def[i].expand = stat_expand; - def[i].data = (void*) i; + p->kw = stat_kwname[i]; + p->value = NULL; + p->storage = NULL; + p->expand = stat_expand; + p->data = (void*) i; } - def[i].kw = NULL; + p->kw = NULL; + return def; } void @@ -308,7 +312,7 @@ main (int argc, char **argv) logmsg (LOG_NOTICE, "wydawca (%s) finished", PACKAGE_STRING); logstats (); - + mail_finish (); exit (0); diff --git a/src/wydawca.h b/src/wydawca.h index d990a97..2e00f65 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -33,6 +33,11 @@ #include <dirent.h> #include <sys/stat.h> #include <fcntl.h> + +#include <mailutils/types.h> +#include <mailutils/url.h> +#include <mailutils/errno.h> + #include "error.h" #include "xalloc.h" #include "progname.h" @@ -60,6 +65,8 @@ #define SUF_DIR ".directive.asc" #define SUF_DIR_LEN (sizeof (SUF_DIR) - 1) +#define __cat2__(a,b) a ## b +#define __cat3__(a,b,c) a ## b ## c #define NITEMS(a) (sizeof(a)/sizeof((a)[0])) enum access_method_id { @@ -122,22 +129,6 @@ struct archive_descr }; - -/* A source/destination directory pair. This structure contains all the - data necessary for releasing files from source to destination */ -struct directory_pair -{ - char *url; /* Download URL */ - char *source_dir; /* Source directory */ - char *dest_dir; /* Destination directory */ - time_t file_sweep_time; /* Remove invalid/unprocessed files - after this amount of time */ - struct access_method *access_method[access_method_count]; - struct archive_descr archive; /* Archivation data */ - struct notification *notification; -}; - - /* Type of file in a triplet */ enum file_type { @@ -179,6 +170,48 @@ struct file_triplet /* GID is filled in after the triplet is finalized and verified */ #define TRIPLET_GID(t) ((t)->gid) + + +struct virt_tab +{ + int (*test_url) (mu_url_t url, gconf_locus_t *loc); + int (*move_file) (struct file_triplet *trp, + struct directory_pair *dpair, + enum file_type file_id, + const char *reldir); + int (*archive_file) (struct file_triplet *trp, + struct directory_pair *dpair, + const char *reldir, + const char *file_name); + int (*symlink_file) (struct file_triplet *trp, + struct directory_pair *dpair, + const char *reldir, + const char *wanted_src, + const char *wanted_dst); + int (*rmsymlink_file)(struct file_triplet *trp, + struct directory_pair *dpair, + const char *reldir, + const char *file_name); +}; + +/* A source/destination directory pair. This structure contains all the + data necessary for releasing files from source to destination */ +struct directory_pair +{ + char *url; /* Download URL */ + char *source_dir; /* Source directory */ + mu_url_t dest_url; /* Destination URL */ + const char *dest_dir; /* Directory part of the above */ + struct virt_tab vtab; /* Virtual method table */ + + time_t file_sweep_time; /* Remove invalid/unprocessed files + after this amount of time */ + struct access_method *access_method[access_method_count]; + struct archive_descr archive; /* Archivation data */ + struct notification *notification; +}; + + enum wydawca_stat { STAT_ERRORS, @@ -280,7 +313,7 @@ extern char *admin_stat_message; while (0) int stat_mask_p (unsigned long mask); -void make_stat_expansion (struct metadef *def); +struct metadef *make_stat_expansion (size_t count); /* Utility functions */ @@ -358,22 +391,69 @@ int process_directives (struct file_triplet *trp, struct directory_pair *dpair); -/* Actions */ - -int move_file (struct file_triplet *trp, struct directory_pair *dpair, - enum file_type file_id, const char *reldir); -int archive_file (struct file_triplet *trp, struct directory_pair *dpair, - const char *file_name, const char *reldir); -int symlink_file (struct file_triplet *trp, struct directory_pair *dpair, - const char *reldir, - const char *wanted_src, const char *wanted_dst); -int rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair, - const char *reldir, const char *file_name); - - int parse_time_interval (const char *str, time_t *pint, const char **endp); /* config.c */ void config_init (void); void config_help (void); + + +/* vtab.c */ +int url_to_vtab (mu_url_t url, struct virt_tab *vtab); + +int +move_file (struct file_triplet *trp, struct direc |