diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-12-24 08:50:18 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-12-24 08:50:18 +0200 |
commit | 633512c033c129a80a11a86ec85037fb2d2babf5 (patch) | |
tree | 7f1c0810110518f530237636dda7d9f2f39ba818 /src/triplet.c | |
parent | 0077bc419d34a0341f978fc0e2d5cba8d35d4b28 (diff) | |
download | wydawca-633512c033c129a80a11a86ec85037fb2d2babf5.tar.gz wydawca-633512c033c129a80a11a86ec85037fb2d2babf5.tar.bz2 |
Improve triplet queue handling.
Remove the expired and invalid triplets in the master process.
* src/job.c (job_queue_runner): Take estimated minimal
interval as an argument. Set timer even if no wake-up
is scheduled.
* src/net.c: Call triplet_sweep to sweep off expired
triplets and estimate minimal timeout for job_queue_runner.
* src/triplet.c: Link all registered triplets into a doubly-
linked list ordered by the triplet age, in descending order.
Use that list to estimate minimal timeout.
(triplet_list): New variable.
(triplet_timestamp, triplet_ttl)
(triplet_list_unlink,triplet_list_insert_before)
(triplet_list_ordered_insert): New static functions.
(register_file): Insert triplet into the list.
(triplet_expired_p): Take one argument. Obtain the ttl
from the associated spool. Fix condition.
(remove_triplet): Remove triplet from the list and symtab.
(triplet_sweep): New function.
(triplet_counter): Remove bad and expired triplets.
(triplet_remove_file): Call remove_triplet.
* src/wydawca.h (file_triplet) <next,prev>: New members.
(triplet_sweep): New proto.
(job_queue_runner): Change signature.
Diffstat (limited to 'src/triplet.c')
-rw-r--r-- | src/triplet.c | 138 |
1 files changed, 127 insertions, 11 deletions
diff --git a/src/triplet.c b/src/triplet.c index aa74de0..14182be 100644 --- a/src/triplet.c +++ b/src/triplet.c @@ -17,8 +17,106 @@ #include "wydawca.h" #include <time.h> +/* Triplets are stored in a symtab: */ static struct grecs_symtab *triplet_table; +/* ... and are organized into a doubly-linked list, using the prev and + next members of struct file_triplet. The list is ordered so that + prev points to a triplet older than this one, and next points to a + newer triplet. The triplet_list variable points to the root of the + list, i.e. the oldest triplet available. */ +static struct file_triplet *triplet_list; + +/* Functions for building the ordered doubly-linked list of triplets */ +static time_t +triplet_timestamp (struct file_triplet *tp) +{ + int i; + time_t t = 0; + + if (!tp) + return 0; + + for (i = 0; i < FILE_TYPE_COUNT; i++) + { + if (tp->file[i].name && + (t == 0 || t > tp->file[i].sb.st_mtime)) + t = tp->file[i].sb.st_mtime; + } + return t; +} + +static time_t +triplet_ttl (struct file_triplet *tp) +{ + time_t t; + if (!tp) + return 0; + t = time (NULL) - triplet_timestamp (tp); + if (t < tp->spool->file_sweep_time) + return tp->spool->file_sweep_time - t; + return 0; +} + +void +triplet_list_unlink (struct file_triplet *tp) +{ + if (tp->prev) + tp->prev->next = tp->next; + else + triplet_list = tp->next; + + if (tp->next) + tp->next->prev = tp->prev; + + tp->next = tp->prev = NULL; +} + +static void +triplet_list_insert_before (struct file_triplet *newp, + struct file_triplet *anchor) +{ + if (!anchor) + { + triplet_list = newp; + return; + } + + if (anchor->prev) + anchor->prev->next = newp; + else + triplet_list = newp; + newp->prev = anchor->prev; + + anchor->prev = newp; + newp->next = anchor; +} + +void +triplet_list_ordered_insert (struct file_triplet *tp) +{ + time_t t = triplet_timestamp (tp); + struct file_triplet *p, *prev = NULL; + + for (p = triplet_list; p && triplet_timestamp (p) < t; prev = p, p = p->next) + ; + if (p) + triplet_list_insert_before (tp, p); + else if (prev) + { + prev->next = tp; + tp->prev = prev; + tp->next = NULL; + } + else + { + tp->next = tp->prev = NULL; + triplet_list = tp; + } +} + + +/* Functions for operation on a symtab of triplets. */ static unsigned hash_triplet_hasher (void *data, unsigned long n_buckets) { @@ -110,6 +208,8 @@ register_file (struct file_info *finfo, const struct spool *spool) ret->acc = txtacc_create (); } ret->file[finfo->type] = *finfo; + triplet_list_unlink (ret); + triplet_list_ordered_insert (ret); } struct file_triplet * @@ -138,18 +238,19 @@ triplet_lookup (struct spool *spool, const char *name) /* Return true if any part of the triplet TRP was modified more than TTL seconds ago */ static int -triplet_expired_p (struct file_triplet *trp, time_t ttl) +triplet_expired_p (struct file_triplet *trp) { int i; time_t now = time (NULL); - + time_t ttl = trp->spool->file_sweep_time; + if (ttl == 0) return 0; for (i = 0; i < FILE_TYPE_COUNT; i++) { if (trp->file[i].name - && (now - trp->file[i].sb.st_mtime) > ttl) + && (now - trp->file[i].sb.st_mtime) >= ttl) { if (debug_level) logmsg (LOG_DEBUG, _("file %s expired"), trp->file[i].name); @@ -220,6 +321,19 @@ remove_triplet (struct file_triplet *trp) trp->file[i].name, strerror (errno)); } } + triplet_list_unlink (trp); + grecs_symtab_remove (triplet_table, trp); +} + +time_t +triplet_sweep (void) +{ + struct file_triplet const *tp; + + while (triplet_list && triplet_expired_p (triplet_list)) + remove_triplet (triplet_list); + + return triplet_ttl (triplet_list); } /* Process a single triplet from the table */ @@ -258,7 +372,7 @@ triplet_processor (void *data, void *proc_data) return 0; } - if (triplet_expired_p (trp, trp->spool->file_sweep_time)) + if (triplet_expired_p (trp)) { UPDATE_STATS (STAT_EXPIRED_TRIPLETS); remove_triplet (trp); @@ -306,15 +420,17 @@ triplet_counter (void *data, void *proc_data) { case triplet_directive: case triplet_complete: - case triplet_bad: - ++*cp; + if (triplet_expired_p (trp)) + remove_triplet (trp); + else + ++*cp; + break; case triplet_incomplete: - return 0; + break; + case triplet_bad: + remove_triplet (trp); } - if (triplet_expired_p (trp, trp->spool->file_sweep_time)) - ++*cp;//FIXME - return 0; } @@ -351,7 +467,7 @@ triplet_remove_file (struct spool *spool, const char *name) if (debug_level > 0) logmsg (LOG_DEBUG, "deleting empty triplet (%s/%s)", spool->source_dir, name); - grecs_symtab_remove (triplet_table, tp); + remove_triplet (tp); } } |