diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-03-05 15:49:15 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-03-05 15:49:32 +0200 |
commit | 47576447626ac40b61f978836ccb5becbd2b9091 (patch) | |
tree | 8afff1cc0c69b676973a790dfc48bed8face988a | |
parent | 514797c56e431f37de9a00834281f990a7b15c46 (diff) | |
download | wydawca-47576447626ac40b61f978836ccb5becbd2b9091.tar.gz wydawca-47576447626ac40b61f978836ccb5becbd2b9091.tar.bz2 |
Improve locking.
* gconf/gconf-gram.y (string_convert): Rename to gconf_string_convert, make
extern. All uses updated.
* gconf/gconf.h (gconf_string_convert): New proto.
(wydawca_kw): `locking' block statement.
* src/job.c: Introduce a delay before restarting a tempfailed job.
Do not trigger error reporting on tempfail
* src/lock.c: Retry locking attempts, according to configuration.
* src/wydawca.h (lock_retry_attempts, lock_retry_interval): New declarations.
-rw-r--r-- | gconf/gconf-gram.y | 18 | ||||
-rw-r--r-- | gconf/gconf.h | 3 | ||||
-rw-r--r-- | src/config.c | 47 | ||||
-rw-r--r-- | src/job.c | 63 | ||||
-rw-r--r-- | src/lock.c | 23 | ||||
-rw-r--r-- | src/wydawca.h | 2 |
6 files changed, 130 insertions, 26 deletions
diff --git a/gconf/gconf-gram.y b/gconf/gconf-gram.y index 66b5416..c2d833b 100644 --- a/gconf/gconf-gram.y +++ b/gconf/gconf-gram.y @@ -594,8 +594,9 @@ string_to_sockaddr (struct gconf_sockaddr *sp, const char *string) return 0; } -static int -string_convert (void *target, enum gconf_data_type type, const char *string) +int +gconf_string_convert (void *target, enum gconf_data_type type, + const char *string) { uintmax_t uval; intmax_t sval; @@ -699,11 +700,14 @@ string_convert (void *target, enum gconf_data_type type, const char *string) /* FIXME: */ case gconf_type_cidr: - - case gconf_type_section: gconf_error (&gconf_current_locus, 0, _("INTERNAL ERROR at %s:%d"), __FILE__, __LINE__); abort(); + + case gconf_type_section: + gconf_error (&gconf_current_locus, 0, + _("Invalid use of block statement")); + return 1; } return 0; } @@ -828,7 +832,7 @@ process_ident (struct gconf_keyword *kwp, gconf_value_t *value) else { void *ptr = xmalloc (size); - if (string_convert (ptr, type, vp->v.string) == 0) + if (gconf_string_convert (ptr, type, vp->v.string) == 0) gl_list_add_last (list, ptr); else free (ptr); @@ -871,7 +875,7 @@ process_ident (struct gconf_keyword *kwp, gconf_value_t *value) else { ptr = xmalloc (size); - if (string_convert (ptr, type, value->v.string)) + if (gconf_string_convert (ptr, type, value->v.string)) { free (ptr); gl_list_free (list); @@ -882,6 +886,6 @@ process_ident (struct gconf_keyword *kwp, gconf_value_t *value) *(gl_list_t*)target = list; } else - string_convert (target, GCONF_TYPE (kwp->type), value->v.string); + gconf_string_convert (target, GCONF_TYPE (kwp->type), value->v.string); } diff --git a/gconf/gconf.h b/gconf/gconf.h index 56792a0..f3d1bf8 100644 --- a/gconf/gconf.h +++ b/gconf/gconf.h @@ -122,6 +122,9 @@ void gconf_line_begin (void); void gconf_line_add (const char *text, size_t len); char *gconf_line_finish (void); +extern int gconf_string_convert (void *target, enum gconf_data_type type, + const char *string); + extern gconf_locus_t gconf_current_locus; extern int gconf_error_count; extern int gconf_default_port; diff --git a/src/config.c b/src/config.c index 57bd8cb..1cce5fc 100644 --- a/src/config.c +++ b/src/config.c @@ -1301,7 +1301,41 @@ cb_supp_groups (enum gconf_callback_command cmd, } return 0; } - + + +static struct gconf_keyword locking_kw[] = { + { "enable", NULL, N_("Enable or disable locking"), + gconf_type_bool, &enable_locking }, + { "directory", N_("dir"), N_("Set directory for lock files"), + gconf_type_string, &lockdir }, + { "expire-time", N_("interval"), N_("Define lock expiration interval"), + gconf_type_string, &lock_expire_time, 0, cb_interval }, + { "retry-attempts", N_("n"), N_("Number of times to retry locking"), + gconf_type_uint, &lock_retry_attempts }, + { "retry-interval", N_("interval"), N_("Delay between locking attempts"), + gconf_type_string, &lock_retry_interval, 0, cb_interval }, + { NULL } +}; + +static int +cb_locking (enum gconf_callback_command cmd, + gconf_locus_t *locus, + void *varptr, + gconf_value_t *value, + void *cb_data) +{ + if (cmd == gconf_callback_set_value) + { + if (!value || value->type != GCONF_TYPE_STRING) + { + gconf_error (locus, 0, _("expected scalar value as a tag")); + return 1; + } + gconf_string_convert (&enable_locking, gconf_type_bool, value->v.string); + } + return 0; +} + static struct gconf_keyword wydawca_kw[] = { @@ -1321,12 +1355,9 @@ static struct gconf_keyword wydawca_kw[] = { { "group", NULL, N_("Retain these supplementary groups"), gconf_type_string|GCONF_LIST, NULL, 0, cb_supp_groups }, - { "locking", NULL, N_("Enable or disable locking"), - gconf_type_bool, &enable_locking }, - { "lockdir", N_("dir"), N_("Set directory for lock files"), - gconf_type_string, &lockdir }, - { "lock-expire-time", N_("interval"), N_("Define lock expiration interval"), - gconf_type_string, &lock_expire_time, 0, cb_interval }, + { "locking", NULL, N_("Configure locking"), + gconf_type_section, NULL, 0, + cb_locking, NULL, locking_kw }, { "listen", N_("socket"), N_("Listen on this address"), gconf_type_sockaddr, &listen_sockaddr, }, @@ -1416,7 +1447,7 @@ config_init() serv = getservbyname (PACKAGE, "tcp"); if (serv != NULL) gconf_default_port = serv->s_port; - + for (i = 0; i < access_method_count; i++) default_access_method[i] = method_new (i, method_builtin); } @@ -47,6 +47,14 @@ queue_signal (int sig) signal (sig, queue_signal); } +void +set_timer (time_t interval) +{ + wakeup = 0; + if (interval) + alarm (interval); +} + struct job * job_locate (const struct spool *spool, uid_t uid) { @@ -120,6 +128,8 @@ job_start (struct job *job) signal (SIGQUIT, SIG_DFL); signal (SIGINT, SIG_DFL); signal (SIGCHLD, SIG_DFL); + signal (SIGALRM, SIG_DFL); + alarm (0); for (i = getdtablesize (); i > 2; i--) close (i); exit (wydawca_scanner (job) ? WYDAWCA_EX_AGAIN : 0); @@ -214,18 +224,26 @@ print_status (struct job *job, int expect_term) if (WIFEXITED (status)) { - if (WEXITSTATUS (status) == 0) + int exit_code = WEXITSTATUS (status); + if (exit_code == 0) { if (debug_level) logmsg (LOG_DEBUG, _("%lu (%s, %s) exited successfully"), (unsigned long) job->pid, job->spool->tag, pw->pw_name); } + else if (exit_code == WYDAWCA_EX_AGAIN) + { + if (debug_level) + logmsg (LOG_DEBUG, + _("%lu (%s, %s) reported tempfail"), + (unsigned long) job->pid, job->spool->tag, pw->pw_name); + } else logmsg (LOG_ERR, _("%lu (%s, %s) failed with status %d"), (unsigned long) job->pid, job->spool->tag, pw->pw_name, - WEXITSTATUS (status)); + exit_code); } else if (WIFSIGNALED (status)) { @@ -266,7 +284,9 @@ job_queue_runner () { int status; struct job *job; - + time_t now = time (NULL); + time_t min_interval = 0; + if (!wakeup) return; wakeup = 0; @@ -298,21 +318,48 @@ job_queue_runner () { if (WIFEXITED (job->exit_status) && WEXITSTATUS (job->exit_status) == WYDAWCA_EX_AGAIN) - /* Re-queue the job */ - job->state = STATE_QUEUED; + { + time_t interval = lock_retry_attempts * lock_retry_interval; + if (interval == 0) + interval = lock_expire_time; + /* Re-queue the job */ + job->state = STATE_QUEUED; + job->timestamp = now + interval; + } else job_remove (job); } } + if (job->state == STATE_QUEUED) - if (job_start (job)) - pause (); + { + time_t interval; + + if (job->timestamp >= now) + { + if (job_start (job)) + pause (); /* FIXME */ + now = time (NULL); + } + else + { + time_t interval = job->timestamp - now; + if (min_interval == 0 || interval < min_interval) + min_interval = interval; + } + } + job = next; - } + } + + if (debug_level > 1) + logmsg (LOG_DEBUG, _("computed interval: %lu"), min_interval); + set_timer (min_interval); } void job_init () { signal (SIGCHLD, queue_signal); + signal (SIGALRM, queue_signal); } @@ -20,7 +20,9 @@ int enable_locking = 1; char *lockdir; -time_t lock_expire_time; +time_t lock_expire_time = 5*60; +unsigned lock_retry_attempts = 3; +time_t lock_retry_interval = 1; #define LOCKFILE_MODE 0644 @@ -159,7 +161,7 @@ expire_stale_lock (const char *file) stale = 1; /* Corrupted file, remove the lock. */ } - if (!stale) + if (!stale && lock_expire_time > 0) { struct stat stbuf; fstat (fd, &stbuf); @@ -190,7 +192,22 @@ wydawca_lock (const char *lockname) (unsigned long) time (NULL), xgethostname ()); if (!tempname) return LOCK_FAILURE; - rc = _lock_internal (lockname, tempname); + if (lock_retry_attempts) + { + unsigned i; + + for (i = 0; i < lock_retry_attempts; i++) + { + rc = _lock_internal (lockname, tempname); + if (rc == 0) + break; + if (rc == LOCK_RETRY) + sleep (lock_retry_interval); + } + } + else + rc = _lock_internal (lockname, tempname); + free (tempname); return rc; } diff --git a/src/wydawca.h b/src/wydawca.h index 81e6509..1d18ea1 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -328,6 +328,8 @@ extern int force_startup; extern char *lockdir; extern time_t lock_expire_time; +unsigned lock_retry_attempts; +time_t lock_retry_interval; extern int enable_locking; extern int daemon_mode; |