aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-03-05 15:49:15 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-03-05 15:49:32 +0200
commit47576447626ac40b61f978836ccb5becbd2b9091 (patch)
tree8afff1cc0c69b676973a790dfc48bed8face988a
parent514797c56e431f37de9a00834281f990a7b15c46 (diff)
downloadwydawca-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.y18
-rw-r--r--gconf/gconf.h3
-rw-r--r--src/config.c47
-rw-r--r--src/job.c63
-rw-r--r--src/lock.c23
-rw-r--r--src/wydawca.h2
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
@@ -591,14 +591,15 @@ string_to_sockaddr (struct gconf_sockaddr *sp, const char *string)
sp->sa = xmalloc (sp->len);
memcpy (sp->sa, &sa, sp->len);
}
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;
switch (type)
{
@@ -696,17 +697,20 @@ string_convert (void *target, enum gconf_data_type type, const char *string)
case gconf_type_sockaddr:
return string_to_sockaddr ((struct gconf_sockaddr *)target, 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;
}
struct gconf_prop
{
@@ -825,13 +829,13 @@ process_ident (struct gconf_keyword *kwp, gconf_value_t *value)
kwp->ident, num);
else if (type == gconf_type_string)
gl_list_add_last (list, vp->v.string);
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);
}
}
gl_list_iterator_free (&itr);
@@ -868,20 +872,20 @@ process_ident (struct gconf_keyword *kwp, gconf_value_t *value)
false);
if (type == gconf_type_string)
gl_list_add_last (list, value->v.string);
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);
return;
}
gl_list_add_last (list, ptr);
}
*(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
@@ -119,12 +119,15 @@ void gconf_lex_end(void);
int gconf_parse (const char *name);
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;
extern const char *gconf_preprocessor;
extern bool gconf_log_to_stderr;
diff --git a/src/config.c b/src/config.c
index 57bd8cb..1cce5fc 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1298,13 +1298,47 @@ cb_supp_groups (enum gconf_callback_command cmd,
wydawca_supp_groups[i] = grp->gr_gid;
}
gl_list_iterator_free (&itr);
}
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[] = {
{ "daemon", NULL, N_("Enable daemon mode"),
gconf_type_bool, &daemon_mode },
{ "foreground", NULL, N_("Start in foreground even in daemon mode"),
@@ -1318,18 +1352,15 @@ static struct gconf_keyword wydawca_kw[] = {
{ "user", N_("name"), N_("Run with UID and GID of this user"),
gconf_type_string, NULL, 0, cb_user },
{ "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, },
#ifdef WITH_LIBWRAP
{ "tcp-wrapper", NULL, N_("Configure TCP wrappers"),
@@ -1413,10 +1444,10 @@ config_init()
gconf_preprocessor = DEFAULT_PREPROCESSOR;
gconf_log_to_stderr = true;
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);
}
diff --git a/src/job.c b/src/job.c
index 1baa0af..6d88add 100644
--- a/src/job.c
+++ b/src/job.c
@@ -44,12 +44,20 @@ RETSIGTYPE
queue_signal (int sig)
{
wakeup = 1;
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)
{
struct job *p;
for (p = queue; p; p = p->next)
if (p->spool == spool && p->uid == uid)
@@ -117,12 +125,14 @@ job_start (struct job *job)
int i;
signal (SIGHUP, SIG_DFL);
signal (SIGTERM, SIG_DFL);
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);
}
else if (pid == -1)
{
@@ -211,24 +221,32 @@ print_status (struct job *job, int expect_term)
{
struct passwd *pw = getpwuid (job->uid);
int status = job->exit_status;
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))
{
int prio;
if (expect_term && WTERMSIG (status) == SIGTERM)
{
@@ -263,13 +281,15 @@ print_status (struct job *job, int expect_term)
void
job_queue_runner ()
{
int status;
struct job *job;
-
+ time_t now = time (NULL);
+ time_t min_interval = 0;
+
if (!wakeup)
return;
wakeup = 0;
for (;;)
{
@@ -295,24 +315,51 @@ job_queue_runner ()
{
print_status (job, 0);
if ((job->state &= ~STATE_FINISHED) == 0)
{
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);
}
diff --git a/src/lock.c b/src/lock.c
index 3b8787d..b9ea0dc 100644
--- a/src/lock.c
+++ b/src/lock.c
@@ -17,13 +17,15 @@
#include "wydawca.h"
#include "c-ctype.h"
#include "xgethostname.h"
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
static int
stat_check (const char *file, int fd, int links)
{
@@ -156,13 +158,13 @@ expire_stale_lock (const char *file)
stale = 1;
}
else
stale = 1; /* Corrupted file, remove the lock. */
}
- if (!stale)
+ if (!stale && lock_expire_time > 0)
{
struct stat stbuf;
fstat (fd, &stbuf);
/* The lock has expired. */
if ((time (NULL) - stbuf.st_mtime) > lock_expire_time)
stale = 1;
@@ -187,13 +189,28 @@ wydawca_lock (const char *lockname)
asprintf (&tempname, "%s.%lu.%lu.%s",
lockname,
(unsigned long) getpid (),
(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;
}
void
wydawca_unlock (const char *lockfile)
diff --git a/src/wydawca.h b/src/wydawca.h
index 81e6509..1d18ea1 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -325,12 +325,14 @@ extern char *admin_stat_message;
extern char *pidfile;
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;
extern time_t wakeup_interval;
extern int foreground;
extern int single_process;

Return to:

Send suggestions and report system problems to the System administrator.