summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2020-04-27 10:44:31 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2020-04-27 10:44:31 (GMT)
commit9dff021e31a300dcd5eda941d9e4992a6a8e465a (patch) (side-by-side diff)
tree9ba56aa2ccbd7c24b1d1e8535c8e3eeef25f27cf
parente19cf8e1303700b5b2e4f3e525285f63a3c7b51f (diff)
downloadwydawca-9dff021e31a300dcd5eda941d9e4992a6a8e465a.tar.gz
wydawca-9dff021e31a300dcd5eda941d9e4992a6a8e465a.tar.bz2
Use BSD queue macros to implement queues and linked lists.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--modules/mailutils/mod_mailutils.c2
-rw-r--r--src/Makefile.am13
-rw-r--r--src/config.c18
-rw-r--r--src/directive.c14
-rw-r--r--src/event.c43
-rw-r--r--src/gpg.c5
-rw-r--r--src/module.c30
-rw-r--r--src/net.c49
-rw-r--r--src/queue.h574
-rw-r--r--src/spool.c (renamed from src/process.c)84
-rw-r--r--src/sql.c10
-rw-r--r--src/triplet.c99
-rw-r--r--src/watcher.c44
-rw-r--r--src/wydawca.h66
-rw-r--r--tests/mailnotify.at12
15 files changed, 777 insertions, 286 deletions
diff --git a/modules/mailutils/mod_mailutils.c b/modules/mailutils/mod_mailutils.c
index 00ea697..759fa14 100644
--- a/modules/mailutils/mod_mailutils.c
+++ b/modules/mailutils/mod_mailutils.c
@@ -603,7 +603,7 @@ wy_config(grecs_node_t *node)
}
void
-wy_flush()
+wy_flush(void)
{
if (mailer_opened) {
mu_mailer_close(mailer);
diff --git a/src/Makefile.am b/src/Makefile.am
index 5af4c2c..5b70f5e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,10 +16,6 @@
sbin_PROGRAMS=wydawca
-if COND_INOTIFY
- WATCHER_C=watcher.c
-endif
-
wydawca_SOURCES=\
backup.c\
builtin.c\
@@ -30,13 +26,12 @@ wydawca_SOURCES=\
directive.c\
diskio.c\
exec.c\
- event.c\
gpg.c\
interval.c\
module.c\
net.c\
pidfile.c\
- process.c\
+ spool.c\
sql.c\
sql.h\
tcpwrap.c\
@@ -49,7 +44,11 @@ wydawca_SOURCES=\
null.c\
timer.c\
thread_name.c\
- $(WATCHER_C)
+ queue.h
+
+if COND_INOTIFY
+ wydawca_SOURCES += watcher.c
+endif
BUILT_SOURCES=cmdline.h
EXTRA_DIST=cmdline.opt
diff --git a/src/config.c b/src/config.c
index a7ceb92..ee9f0c3 100644
--- a/src/config.c
+++ b/src/config.c
@@ -125,7 +125,7 @@ static struct archive_descr default_archive_descr = {
};
static struct dictionary *default_dictionary[dictionary_count];
-struct notification *default_notification = NULL;
+NOTIFYQ default_notification = NOTIFYQ_INITIALIZER(default_notification);
/* safe_file_name: convert a file name possibly containig relative
specs (../) into a safer form using only direct descendence.
@@ -879,9 +879,7 @@ cb_notify_event(enum grecs_callback_command cmd, grecs_node_t * node,
else {
/* FIXME: Check if the module is defined. Better yet,
delay this check until config_finish */
- struct notification **p = (struct notification **) varptr;
- ntf->next = *p;
- *p = ntf;
+ NOTIFYQ_APPEND((NOTIFYQ*)varptr, ntf);
/* FIXME: check ev and tgt? */
}
break;
@@ -1135,7 +1133,7 @@ static struct grecs_keyword spool_kw[] = {
{ "notify-event", NULL,
N_("Configure notification"),
grecs_type_section, GRECS_MULT,
- NULL, offsetof(struct spool, notification),
+ NULL, offsetof(struct spool, notification_queue),
cb_notify_event, NULL, notify_event_kw },
{ "check-script", NULL,
N_("A /bin/sh script to verify the tarball"),
@@ -1207,14 +1205,16 @@ cb_spool(enum grecs_callback_command cmd, grecs_node_t * node,
return 1;
}
- if (rc)
+ if (rc) {
+ //FIXME: free spool */
return rc;
+ }
- if (!spool->notification)
- spool->notification = default_notification;
+ //FIXME
+ if (NOTIFYQ_EMPTY(&spool->notification_queue))
+ spool->notification_queue = default_notification;
spool->dest_dir = wy_url_printable(spool->dest_url);
register_spool(spool);
- free(spool);
*pdata = NULL;
break;
diff --git a/src/directive.c b/src/directive.c
index 8e7afeb..bb5ce4b 100644
--- a/src/directive.c
+++ b/src/directive.c
@@ -58,10 +58,12 @@ str_dirname_sig(char const *a, char const *b)
while (*a && *b) {
if (*a != *b) {
if (arg2) {
- if (ISSPACE(*a) && strncmp(b, ".sig", 4) == 0) {
+ if (ISSPACE(*a)
+ && strncmp(b, SUF_SIG, SUF_SIG_LEN) == 0) {
arg2 = 1;
b += 4;
- } else if (ISSPACE(*b) && strncmp(a, ".sig", 4) == 0) {
+ } else if (ISSPACE(*b)
+ && strncmp(a, SUF_SIG, SUF_SIG_LEN) == 0) {
arg2 = -1;
a += 4;
} else
@@ -77,10 +79,10 @@ str_dirname_sig(char const *a, char const *b)
b++;
}
- if (*a == 0 && strcmp(b, ".sig") == 0)
+ if (*a == 0 && strcmp(b, SUF_SIG) == 0)
return (arg2 == 0 || arg2 == 1) ? 1 : 0;
- if (*b == 0 && strcmp(a, ".sig") == 0)
+ if (*b == 0 && strcmp(a, SUF_SIG) == 0)
return (arg2 == 0 || arg2 == -1) ? -1 : 0;
return 0;
@@ -649,7 +651,7 @@ external_check(struct wy_triplet *trp)
if (rc) {
wydawca_stat_incr(WY_STAT_CHECK_FAIL);
- notify(spool->notification, trp, wy_ev_check_fail);
+ notify(&spool->notification_queue, trp, wy_ev_check_fail);
}
return rc;
@@ -759,6 +761,6 @@ process_directives(struct wy_triplet *trp)
wydawca_stat_incr(WY_STAT_TRIPLET_SUCCESS);
triplet_report_finish(trp);
timer_stop(WY_TIMER_TRIPLET);
- notify(spool->notification, trp, wy_ev_success);
+ notify(&spool->notification_queue, trp, wy_ev_success);
return 0;
}
diff --git a/src/event.c b/src/event.c
deleted file mode 100644
index da26a30..0000000
--- a/src/event.c
+++ b/dev/null
@@ -1,43 +0,0 @@
-/* wydawca - automatic release submission daemon
- Copyright (C) 2007-2020 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"
-
-void
-notify(struct notification *n, struct wy_triplet *t, enum wy_event e)
-{
- for (; n; n = n->next)
- if (n->ev == e) {
- if (n->modname)
- module_notify(n->modname, n->modcfg, e, t);
- }
-}
-
-void
-notify_finish(void)
-{
- notify(default_notification, NULL, wy_ev_finish);
-}
-
-void
-notify_flush(struct spool *sp)
-{
- struct notification *n;
-
- for (n = sp->notification; n; n = n->next)
- if (n->modcfg)
- module_flush(n->modname, n->modcfg);
-}
diff --git a/src/gpg.c b/src/gpg.c
index 41ac723..1aafb11 100644
--- a/src/gpg.c
+++ b/src/gpg.c
@@ -328,7 +328,7 @@ verify_directive_signature(struct wy_triplet *trp)
result = gpgme_op_verify_result(ctx);
if (!gpg_verify_signature(ctx, result->signatures, trp)) {
wydawca_stat_incr(WY_STAT_BAD_SIGNATURE);
- notify(trp->spool->notification, trp,
+ notify(&trp->spool->notification_queue, trp,
wy_ev_bad_directive_signature);
rc = 1;
} else
@@ -376,7 +376,8 @@ verify_detached_signature(struct wy_triplet *trp)
} else {
wydawca_stat_incr(WY_STAT_BAD_SIGNATURE);
wy_log(LOG_ERR, _("BAD detached signature for %s"), trp->name);
- notify(trp->spool->notification, trp, wy_ev_bad_detached_signature);
+ notify(&trp->spool->notification_queue, trp,
+ wy_ev_bad_detached_signature);
rc = 1;
}
diff --git a/src/module.c b/src/module.c
index 22a9c6e..2b47ba0 100644
--- a/src/module.c
+++ b/src/module.c
@@ -17,17 +17,17 @@
#include "wydawca.h"
#include <ltdl.h>
-static struct module *mod_head, *mod_tail;
+static STAILQ_HEAD(,module) mod_head = STAILQ_HEAD_INITIALIZER(mod_head);
struct grecs_list *module_load_path, *module_prepend_load_path;
static struct module *
modlookup(const char *name)
{
struct module *p;
-
- for (p = mod_head; p; p = p->next)
+ STAILQ_FOREACH(p, &mod_head, link) {
if (strcmp(p->name, name) == 0)
- return p;;
+ return p;
+ }
return NULL;
}
@@ -53,11 +53,7 @@ modinstall(const char *name, const char *path, grecs_locus_t * loc)
p->locus.end.line = loc->end.line;
p->locus.end.col = loc->end.col;
- if (mod_tail)
- mod_tail->next = p;
- else
- mod_head = p;
- mod_tail = p;
+ STAILQ_INSERT_TAIL(&mod_head, p, link);
return p;
}
@@ -135,9 +131,10 @@ modload(struct module *mod, lt_dladvise advise)
}
static int
-conf_notification_modules(struct notification *np)
+conf_notification_modules(NOTIFYQ *nq)
{
- for (; np; np = np->next) {
+ struct notification *np;
+ NOTIFYQ_FOREACH(np, nq) {
if (np->modname) {
struct module *mod = modlookup(np->modname);
if (!mod) {
@@ -160,7 +157,7 @@ conf_notification_modules(struct notification *np)
static int
spoolmodcfg(struct spool *spool, void *unused)
{
- return conf_notification_modules(spool->notification);
+ return conf_notification_modules(&spool->notification_queue);
}
void
@@ -194,7 +191,7 @@ modules_load()
wy_log(LOG_ERR, "lt_dladvise_global: %s", lt_dlerror());
}
- for (mod = mod_head; mod; mod = mod->next) {
+ STAILQ_FOREACH(mod, &mod_head, link) {
if (modload(mod, advise))
exit(EX_UNAVAILABLE);
}
@@ -204,18 +201,19 @@ modules_load()
wy_log(LOG_CRIT, _("some modules failed to configure, exiting"));
exit(EX_UNAVAILABLE);
}
- conf_notification_modules(default_notification);
+ conf_notification_modules(&default_notification);
}
void
-modules_close()
+modules_close(void)
{
struct module *mod;
- for (mod = mod_head; mod; mod = mod->next) {
+ while ((mod = STAILQ_FIRST(&mod_head)) != NULL) {
if (mod->close)
mod->close();
lt_dlclose(mod->handle);
+ STAILQ_REMOVE_HEAD(&mod_head, link);
}
}
diff --git a/src/net.c b/src/net.c
index eccd078..400585c 100644
--- a/src/net.c
+++ b/src/net.c
@@ -89,43 +89,28 @@ struct wydawca_connection {
struct timespec ts;
pthread_t tid;
FILE *fp;
- struct wydawca_connection *next, *prev;
+ TAILQ_ENTRY(wydawca_connection) link;
};
-struct wydawca_connection_queue {
- struct wydawca_connection *head, *tail;
-};
+typedef TAILQ_HEAD(,wydawca_connection) WYDAWCA_CONNECTION_QUEUE;
static inline void
-wydawca_connection_enqueue(struct wydawca_connection_queue *q,
+wydawca_connection_enqueue(WYDAWCA_CONNECTION_QUEUE *q,
struct wydawca_connection *conn)
{
- conn->next = NULL;
- conn->prev = q->tail;
- if (q->tail)
- q->tail->next = conn;
- else
- q->head = conn;
- q->tail = conn;
+ TAILQ_INSERT_TAIL(q, conn, link);
}
static inline void
-wydawca_connection_dequeue(struct wydawca_connection_queue *q,
+wydawca_connection_dequeue(WYDAWCA_CONNECTION_QUEUE *q,
struct wydawca_connection *conn)
{
- if (conn->prev)
- conn->prev->next = conn->next;
- else
- q->head = conn->next;
- if (conn->next)
- conn->next->prev = conn->prev;
- else
- q->tail = conn->prev;
- conn->prev = conn->next = NULL;
+ TAILQ_REMOVE(q, conn, link);
}
static struct wydawca_connection *conn_table;
-static struct wydawca_connection_queue conn_avail, conn_idle;
+static WYDAWCA_CONNECTION_QUEUE conn_avail = TAILQ_HEAD_INITIALIZER(conn_avail),
+ conn_idle = TAILQ_HEAD_INITIALIZER(conn_idle);
static pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t conn_cond = PTHREAD_COND_INITIALIZER;
@@ -146,8 +131,7 @@ connection_start(int fd)
struct wydawca_connection *conn;
pthread_mutex_lock(&conn_mutex);
- if (conn_avail.head) {
- conn = conn_avail.head;
+ if ((conn = TAILQ_FIRST(&conn_avail)) != NULL) {
wydawca_connection_dequeue(&conn_avail, conn);
clock_gettime(CLOCK_REALTIME, &conn->ts);
conn->ts.tv_sec += idle_timeout;
@@ -155,7 +139,7 @@ connection_start(int fd)
pthread_create(&conn->tid, NULL, wy_thr_tcpmux, conn);
wydawca_connection_enqueue(&conn_idle, conn);
pthread_cond_broadcast(&conn_cond);
- } else {
+ } else {
wy_log(LOG_ERR, "connection table is full");
close(fd);
}
@@ -263,16 +247,17 @@ wy_thr_connection_watcher(void *ptr)
wy_set_cur_thread_name("connwatch");
pthread_mutex_lock(&conn_mutex);
while (1) {
- if (conn_idle.head) {
+ struct wydawca_connection *conn;
+
+ if ((conn = TAILQ_FIRST(&conn_idle)) != NULL) {
struct timespec ts;
- pthread_cond_timedwait(&conn_cond, &conn_mutex,
- &conn_idle.head->ts);
- if (conn_idle.head) {
+ pthread_cond_timedwait(&conn_cond, &conn_mutex, &conn->ts);
+ if ((conn = TAILQ_FIRST(&conn_idle)) != NULL) {
clock_gettime(CLOCK_REALTIME, &ts);
- if (timespec_cmp(&ts, &conn_idle.head->ts) >= 0) {
+ if (timespec_cmp(&ts, &conn->ts) >= 0) {
void *ret;
- pthread_t tid = conn_idle.head->tid;
+ pthread_t tid = conn->tid;
pthread_cancel(tid);
pthread_mutex_unlock(&conn_mutex);
pthread_join(tid, &ret);
diff --git a/src/queue.h b/src/queue.h
new file mode 100644
index 0000000..daf4553
--- a/dev/null
+++ b/src/queue.h
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list. Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction. Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ (head)->lh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = ((head)->lh_first); \
+ (var); \
+ (var) = ((var)->field.le_next))
+
+/*
+ * List access methods.
+ */
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) do { \
+ (head)->slh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while(curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first; /* first element */ \
+ struct type **stqh_last; /* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_INIT(head) do { \
+ (head)->stqh_first = NULL; \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (head)->stqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.stqe_next = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (listelm)->field.stqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->stqh_first == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->stqh_first; \
+ while (curelm->field.stqe_next != (elm)) \
+ curelm = curelm->field.stqe_next; \
+ if ((curelm->field.stqe_next = \
+ curelm->field.stqe_next->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(curelm)->field.stqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->stqh_first); \
+ (var); \
+ (var) = ((var)->field.stqe_next))
+
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->sqh_first == (elm)) { \
+ SIMPLEQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->sqh_first; \
+ while (curelm->field.sqe_next != (elm)) \
+ curelm = curelm->field.sqe_next; \
+ if ((curelm->field.sqe_next = \
+ curelm->field.sqe_next->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(curelm)->field.sqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->sqh_first); \
+ (var); \
+ (var) = ((var)->field.sqe_next))
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define _TAILQ_HEAD(name, type, qual) \
+struct name { \
+ qual type *tqh_first; /* first element */ \
+ qual type *qual *tqh_last; /* addr of last next element */ \
+}
+#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define _TAILQ_ENTRY(type, qual) \
+struct { \
+ qual type *tqe_next; /* next element */ \
+ qual type *qual *tqe_prev; /* address of previous next element */\
+}
+#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); \
+ (var); \
+ (var) = ((var)->field.tqe_next))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
+ (var); \
+ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { (void *)&head, (void *)&head }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = (void *)(head); \
+ (head)->cqh_last = (void *)(head); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = (void *)(head); \
+ if ((head)->cqh_last == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.cqe_next = (void *)(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ if ((elm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->cqh_first); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_next))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for ((var) = ((head)->cqh_last); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
+ (((elm)->field.cqe_next == (void *)(head)) \
+ ? ((head)->cqh_first) \
+ : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field) \
+ (((elm)->field.cqe_prev == (void *)(head)) \
+ ? ((head)->cqh_last) \
+ : (elm->field.cqe_prev))
+
+#endif /* sys/queue.h */
diff --git a/src/process.c b/src/spool.c
index 323dbfe..39ddc7b 100644
--- a/src/process.c
+++ b/src/spool.c
@@ -16,21 +16,16 @@
#include "wydawca.h"
-struct spool_list {
- struct spool_list *next;
- struct spool spool;
-};
-
-static struct spool_list *spool_head, *spool_tail;
+static STAILQ_HEAD(,spool) spool_list = STAILQ_HEAD_INITIALIZER(spool_list);
size_t spool_count;
int
for_each_spool(int (*fun) (struct spool *, void *), void *data)
{
- struct spool_list *sp;
+ struct spool *sp;
- for (sp = spool_head; sp; sp = sp->next) {
- int rc = fun(&sp->spool, data);
+ STAILQ_FOREACH(sp, &spool_list, link) {
+ int rc = fun(sp, data);
if (rc)
return rc;
}
@@ -40,15 +35,8 @@ for_each_spool(int (*fun) (struct spool *, void *), void *data)
void
register_spool(struct spool *spool)
{
- struct spool_list *sp = grecs_malloc(sizeof *sp);
- sp->spool = *spool;
- sp->next = NULL;
- if (spool_tail)
- spool_tail->next = sp;
- else
- spool_head = sp;
- spool_tail = sp;
- sp->spool.timer_id = spool_count++ + MY_TIMER_SPOOL_FIRST;
+ spool->timer_id = spool_count++ + MY_TIMER_SPOOL_FIRST;
+ STAILQ_INSERT_TAIL(&spool_list, spool, link);
}
static int
@@ -62,14 +50,13 @@ spool_check_alias(struct spool *spool, const char *name)
struct spool *
wydawca_find_spool(const char *name)
{
- struct spool_list *sp;
+ struct spool *sp;
- for (sp = spool_head; sp; sp = sp->next) {
- if (strcmp(sp->spool.tag, name) == 0 ||
- spool_check_alias(&sp->spool, name))
- return &sp->spool;
+ STAILQ_FOREACH(sp, &spool_list, link) {
+ if (strcmp(sp->tag, name) == 0 || spool_check_alias(sp, name))
+ break;
}
- return NULL;
+ return sp;
}
/* Return true if NAME is a directory. If stat fails, return the error
@@ -235,29 +222,58 @@ spool_close_dictionaries(struct spool *spool)
void
dictionaries_close(void)
{
- struct spool_list *sp;
- for (sp = spool_head; sp; sp = sp->next)
- spool_close_dictionaries(&sp->spool);
+ struct spool *sp;
+ STAILQ_FOREACH(sp, &spool_list, link)
+ spool_close_dictionaries(sp);
}
/* Scan all configured update directories */
void
scan_all_spools(void)
{
- struct spool_list *sp;
- for (sp = spool_head; sp; sp = sp->next)
- scan_spool(&sp->spool);
+ struct spool *sp;
+ STAILQ_FOREACH(sp, &spool_list, link)
+ scan_spool(sp);
}
int
spool_timer_id(char *name)
{
- struct spool_list *sp;
- for (sp = spool_head; sp; sp = sp->next) {
- if (strcmp(sp->spool.tag, name) == 0)
- return sp->spool.timer_id;
+ struct spool *sp;
+ STAILQ_FOREACH(sp, &spool_list, link) {
+ if (strcmp(sp->tag, name) == 0)
+ return sp->timer_id;
}
return -1;
}
+
+void
+notify(const NOTIFYQ *nq, struct wy_triplet *t, enum wy_event e)
+{
+ struct notification *n;
+ NOTIFYQ_FOREACH(n, nq) {
+ if (n->ev == e) {
+ if (n->modname)
+ module_notify(n->modname, n->modcfg, e, t);
+ }
+ }
+}
+
+void
+notify_finish(void)
+{
+ notify(&default_notification, NULL, wy_ev_finish);
+}
+
+void
+spool_notify_flush(struct spool *spool)
+{
+ struct notification *n;
+ NOTIFYQ_FOREACH(n, &spool->notification_queue) {
+ if (n->modcfg)
+ module_flush(n->modname, n->modcfg);
+ }
+}
+
diff --git a/src/sql.c b/src/sql.c
index 1381ff2..65cc5df 100644
--- a/src/sql.c
+++ b/src/sql.c
@@ -19,11 +19,11 @@
/* Singly-linked list of configured MySQL connections. */
struct sql_list {
- struct sql_list *next;
+ SLIST_ENTRY(sql_list) link;
struct sqlconn conn;
};
-static struct sql_list *sql_list;
+static SLIST_HEAD(,sql_list) sql_head = SLIST_HEAD_INITIALIZER(sql_head);
/* Append CONN to the end of sql_list */
void
@@ -31,8 +31,7 @@ sql_register_conn(struct sqlconn *conn)
{
struct sql_list *ent = grecs_malloc(sizeof *ent);
ent->conn = *conn;
- ent->next = sql_list;
- sql_list = ent;
+ SLIST_INSERT_HEAD(&sql_head, ent, link);
}
/* Find a configured connection that has the given IDENT */
@@ -40,9 +39,10 @@ struct sqlconn *
sql_find_connection(const char *ident)
{
struct sql_list *p;
- for (p = sql_list; p; p = p->next)
+ SLIST_FOREACH(p, &sql_head, link) {
if (strcmp(p->conn.ident, ident) == 0)
return &p->conn;
+ }
return NULL;
}
diff --git a/src/triplet.c b/src/triplet.c
index 9998046..840ecce 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -24,22 +24,26 @@ static pthread_mutex_t triplet_table_mutex = PTHREAD_MUTEX_INITIALIZER;
/* ... and are organized into a doubly-linked list, using the prev and
next members of struct wy_triplet: */
struct triplet_list {
- struct wy_triplet *head, *tail;
+ TAILQ_HEAD(, wy_triplet) head;
pthread_mutex_t mutex;
pthread_cond_t cond;
};
-#define TRIPLET_LIST_INITIALIZER \
- { NULL, NULL, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER }
+#define TRIPLET_LIST_INITIALIZER(t) \
+ { TAILQ_HEAD_INITIALIZER(t.head), \
+ PTHREAD_MUTEX_INITIALIZER, \
+ PTHREAD_COND_INITIALIZER }
/* Two such lists are maintained. The pending list is ordered so that
prev points to a triplet older than this one, and next points to a
newer triplet. Its head member points to the oldest triplet available. */
-static struct triplet_list triplet_pending_list = TRIPLET_LIST_INITIALIZER;
+static struct triplet_list triplet_pending_list =
+ TRIPLET_LIST_INITIALIZER(triplet_pending_list);
/* The running list contains triplets which are processed by running
threads */
-static struct triplet_list triplet_running_list = TRIPLET_LIST_INITIALIZER;
+static struct triplet_list triplet_running_list =
+ TRIPLET_LIST_INITIALIZER(triplet_running_list);
/* Functions for building the ordered doubly-linked list of triplets */
@@ -60,24 +64,13 @@ triplet_list_unlock(struct triplet_list *list)
void
triplet_list_unlink(struct triplet_list *list, struct wy_triplet *tp)
{
- int head_changed = 0;
-
- if (tp->prev)
- tp->prev->next = tp->next;
- else if (tp == list->head) {
- list->head = tp->next;
- head_changed = 1;
+ if (list) {
+ int head_changed = tp == TAILQ_FIRST(&list->head);
+ TAILQ_REMOVE(&list->head, tp, link);
+ if (head_changed)
+ pthread_cond_broadcast(&list->cond);
+ tp->list = NULL;
}
-
- if (tp->next)
- tp->next->prev = tp->prev;
- else
- list->tail = tp->prev;
-
- tp->next = tp->prev = NULL;
- if (head_changed)
- pthread_cond_broadcast(&list->cond);
- tp->list = NULL;
}
static void
@@ -85,36 +78,23 @@ triplet_list_insert(struct triplet_list *list,
struct wy_triplet *newp, struct wy_triplet *anchor,
int after)
{
- int head_changed = 0;
+ int head_changed = TAILQ_EMPTY(&list->head);
- if (!anchor) {
- newp->prev = NULL;
- newp->next = list->head;
- if (list->head)
- list->head->prev = newp;
+ if (after) {
+ if (!anchor)
+ TAILQ_INSERT_TAIL(&list->head, newp, link);
else
- list->tail = newp;
- list->head = newp;
- head_changed = 1;
- } else if (after) {
- if (anchor->next)
- anchor->next->prev = newp;
- else
- list->tail = newp;
- newp->prev = anchor;
- newp->next = anchor->next;
- anchor->next = newp;
+ TAILQ_INSERT_AFTER(&list->head, anchor, newp, link);
} else {
- if (anchor->prev)
- anchor->prev->next = newp;
- else {
- list->head = newp;
+ if (!anchor) {
head_changed = 1;
+ TAILQ_INSERT_HEAD(&list->head, newp, link);
+ } else {
+ head_changed = anchor == TAILQ_FIRST(&list->head);
+ TAILQ_INSERT_BEFORE(anchor, newp, link);
}
- newp->prev = anchor->prev;
- newp->next = anchor;
- anchor->prev = newp;
}
+
newp->list = list;
if (head_changed)
pthread_cond_broadcast(&list->cond);
@@ -158,14 +138,16 @@ void
triplet_list_ordered_insert(struct triplet_list *list, struct wy_triplet *tp)
{
time_t t = triplet_timestamp(tp);
- struct wy_triplet *p, *prev = NULL;
+ struct wy_triplet *p;
- for (p = list->head; p && triplet_timestamp(p) < t;
- prev = p, p = p->next);
+ TAILQ_FOREACH(p, &list->head, link) {
+ if (triplet_timestamp(p) >= t)
+ break;
+ }
if (p)
triplet_list_insert(list, tp, p, 0);
- else
- triplet_list_insert(list, tp, prev ? prev->next : NULL, 1);
+ else
+ triplet_list_insert(list, tp, NULL, 1);
}
static struct wy_user *
@@ -281,7 +263,7 @@ register_file(struct file_info *finfo, struct spool *spool)
ret->spool = spool;
ret->acc = grecs_txtacc_create();
ret->report_acc = grecs_txtacc_create();
- } else if (ret->list)
+ } else
triplet_list_unlink(ret->list, ret);
triplet_list_ordered_insert(&triplet_pending_list, ret);
triplet_list_unlock(&triplet_pending_list);
@@ -372,8 +354,7 @@ triplet_enqueue(struct wy_triplet *trp)
triplet_list_unlock(&triplet_pending_list);
triplet_list_lock(&triplet_running_list);
- triplet_list_insert(&triplet_running_list, trp,
- triplet_running_list.tail, 1);
+ triplet_list_insert(&triplet_running_list, trp, NULL, 1);
triplet_list_unlock(&triplet_running_list);
trp->in_processing = 1;
pthread_create(&tid, NULL, wy_thr_triplet, trp);
@@ -497,17 +478,17 @@ wy_thr_cleaner(void *ptr)
wy_set_cur_thread_name("tricleaner");
triplet_list_lock(&triplet_pending_list);
while (1) {
- if (triplet_pending_list.head) {
+ if (!TAILQ_EMPTY(&triplet_pending_list.head)) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
- triplet_ttl(triplet_pending_list.head, &ts);
+ triplet_ttl(TAILQ_FIRST(&triplet_pending_list.head), &ts);
pthread_cond_timedwait(&triplet_pending_list.cond,
&triplet_pending_list.mutex, &ts);
} else
pthread_cond_wait(&triplet_pending_list.cond,
&triplet_pending_list.mutex);
- if (triplet_expired_p(triplet_pending_list.head))
- remove_triplet_unlocked(triplet_pending_list.head);
+ if (triplet_expired_p(TAILQ_FIRST(&triplet_pending_list.head)))
+ remove_triplet_unlocked(TAILQ_FIRST(&triplet_pending_list.head));
}
}
@@ -517,7 +498,7 @@ wy_triplet_wait(void)
size_t n;
triplet_list_lock(&triplet_running_list);
- while (triplet_running_list.head) {
+ while (TAILQ_FIRST(&triplet_running_list.head)) {
pthread_cond_wait(&triplet_running_list.cond,
&triplet_running_list.mutex);
}
diff --git a/src/watcher.c b/src/watcher.c
index aa02439..121f825 100644
--- a/src/watcher.c
+++ b/src/watcher.c
@@ -20,43 +20,12 @@
/* A directory watcher is described by the following structure */
struct dirwatcher {
- struct dirwatcher *next, *prev;
+ LIST_ENTRY(dirwatcher) link;
struct spool *spool;
int wd; /* Watch descriptor */
};
-static struct dirwatcher *dirwatcher_list;
-
-struct dirwatcher *
-dirwatcher_unlink(struct dirwatcher **root, struct dirwatcher *p)
-{
- if (p->prev)
- p->prev->next = p->next;
- else
- *root = p->next;
- if (p->next)
- p->next->prev = p->prev;
- p->next = p->prev = NULL;
- return p;
-}
-
-struct dirwatcher *
-dirwatcher_pop(struct dirwatcher **pp)
-{
- if (*pp)
- return dirwatcher_unlink(pp, *pp);
- return NULL;
-}
-
-static void
-dirwatcher_push(struct dirwatcher **pp, struct dirwatcher *p)
-{
- p->prev = NULL;
- p->next = *pp;
- if (*pp)
- (*pp)->prev = p;
- *pp = p;
-}
+static LIST_HEAD(,dirwatcher) dirwatcher_list;
/* Find a watcher with the given descriptor */
static struct dirwatcher *
@@ -64,9 +33,10 @@ dirwatcher_find_wd(int wd)
{
struct dirwatcher *dwp;
- for (dwp = dirwatcher_list; dwp; dwp = dwp->next)
+ LIST_FOREACH(dwp, &dirwatcher_list, link) {
if (dwp->wd == wd)
break;
+ }
return dwp;
}
@@ -105,12 +75,12 @@ create_watcher(struct spool *sp, void *data)
}
dwp->wd = wd;
- dirwatcher_push(&dirwatcher_list, dwp);
+ LIST_INSERT_HEAD(&dirwatcher_list, dwp, link);
return 0;
}
int
-watcher_init()
+watcher_init(void)
{
int ifd, rc;
@@ -129,7 +99,7 @@ watcher_init()
rc = for_each_spool(create_watcher, &ifd);
if (rc)
exit(EX_OSERR);
- if (!dirwatcher_list) {
+ if (LIST_EMPTY(&dirwatcher_list)) {
wy_debug(2, ("inotify: nothing to watch"));
close(ifd);
ifd = -1;
diff --git a/src/wydawca.h b/src/wydawca.h
index 044c036..7fd8a02 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -53,6 +53,7 @@
#include "grecs.h"
#include "wordsplit.h"
+#include "queue.h"
#ifndef O_SEARCH
# define O_SEARCH 0
@@ -200,7 +201,7 @@ struct wy_triplet {
/* Triplets are joined in a doubly-linked list in chronological order.
The prev member points to a triplet older than this one, and next
points to a triplet newer than it: */
- struct wy_triplet *prev, *next;
+ TAILQ_ENTRY(wy_triplet) link;
struct triplet_list *list;
int in_processing; /* True if the triplet is being processed */
/* User data */
@@ -232,17 +233,33 @@ const char *wy_url_printable(wy_url_t url);
int wy_url_is_local(wy_url_t url);
struct virt_tab {
- int (*test_url) (wy_url_t url, grecs_locus_t * loc);
- int (*move_file) (struct wy_triplet * trp, enum file_type file_id);
- int (*archive_file) (struct wy_triplet * trp, const char *file_name);
- int (*symlink_file) (struct wy_triplet * trp,
+ int (*test_url) (wy_url_t url, grecs_locus_t *loc);
+ int (*move_file) (struct wy_triplet *trp, enum file_type file_id);
+ int (*archive_file) (struct wy_triplet *trp, const char *file_name);
+ int (*symlink_file) (struct wy_triplet *trp,
const char *wanted_src, const char *wanted_dst);
- int (*rmsymlink_file) (struct wy_triplet * trp, const char *file_name);
+ int (*rmsymlink_file) (struct wy_triplet *trp, const char *file_name);
};
+
+struct notification {
+ STAILQ_ENTRY(notification) link;
+ enum wy_event ev;
+ char *modname;
+ void *modcfg;
+ grecs_node_t *modnode;
+};
+
+typedef STAILQ_HEAD(,notification) NOTIFYQ;
+#define NOTIFYQ_INITIALIZER(name) STAILQ_HEAD_INITIALIZER(name)
+#define NOTIFYQ_EMPTY(q) STAILQ_EMPTY(q)
+#define NOTIFYQ_FOREACH(var, queue) STAILQ_FOREACH(var, queue, link)
+#define NOTIFYQ_APPEND(queue, ntf) STAILQ_INSERT_TAIL(queue, ntf, link)
+#define NOTIFYQ_INIT(queue) STAILQ_INIT(queue)
/* An upload spool. This structure contains all data necessary for releasing
files from source to destination */
struct spool {
+ STAILQ_ENTRY(spool) link;
char *tag;
int timer_id;
struct grecs_list *aliases;
@@ -261,28 +278,19 @@ struct spool {
struct dictionary *dictionary[dictionary_count];
int dict_inited;
struct archive_descr archive; /* Archivation data */
- struct notification *notification;
+ NOTIFYQ notification_queue;
char *check_script;
};
-struct notification {
- struct notification *next;
- enum wy_event ev;
- char *modname;
- void *modcfg;
- grecs_node_t *modnode;
-};
-
-void notify(struct notification *, struct wy_triplet *, enum wy_event);
-void notify_stats(void);
-void notify_flush(struct spool *sp);
+void notify(const NOTIFYQ *, struct wy_triplet *, enum wy_event);
+void spool_notify_flush(struct spool *sp);
void notify_finish(void);
/* Modules */
struct module {
- struct module *next;
+ STAILQ_ENTRY(module) link;
char *name;
char *path;
grecs_locus_t locus;
@@ -295,13 +303,13 @@ struct module {
void (*close) (void);
};
-int cb_module(enum grecs_callback_command cmd, grecs_node_t * node,
+int cb_module(enum grecs_callback_command cmd, grecs_node_t *node,
void *varptr, void *cb_data);
void modules_load(void);
void modules_close(void);
void modules_help(void);
-int module_set_init(const char *name, grecs_node_t * node);
+int module_set_init(const char *name, grecs_node_t *node);
extern struct grecs_list *module_load_path, *module_prepend_load_path;
void module_notify(const char *name, void *modcfg,
@@ -350,7 +358,7 @@ extern unsigned max_directive_version;
extern int inotify_enable;
-extern struct notification *default_notification;
+extern NOTIFYQ default_notification;
extern size_t spool_count;
@@ -378,7 +386,7 @@ int test_dir(const char *name, int *ec);
char *create_directory(const char *base, const char *name);
int create_hierarchy(int dirfd, char const *dir);
void parse_config(void);
-void log_output(int prio, const char *prog, FILE * fp);
+void log_output(int prio, const char *prog, FILE *fp);
enum exec_result {
exec_success, /* Command executed and returned 0 */
@@ -432,7 +440,7 @@ const char *dictionary_result(struct dictionary *dict, void *handle,
unsigned nrow, unsigned ncol);
int dictionary_quote_string(struct dictionary *dict, void *handle,
const char *input, char **poutput,
- size_t * psize);
+ size_t *psize);
unsigned dictionary_num_rows(struct dictionary *dict);
unsigned dictionary_num_cols(struct dictionary *dict);
@@ -452,7 +460,7 @@ int directive_get_value(struct wy_triplet const *trp, const char *key,
const char **pval);
int directive_pack_version(const char *val, unsigned *pversion);
int directive_unpack_version(unsigned version, char **pbuf,
- size_t * psize);
+ size_t *psize);
int directive_version_in_range_p(struct wy_triplet *trp,
unsigned from, unsigned to);
@@ -468,7 +476,7 @@ int selected_spools(void);
char *triplet_strdup(struct wy_triplet *tp, const char *str);
-int parse_time_interval(const char *str, time_t * pint, const char **endp);
+int parse_time_interval(const char *str, time_t *pint, const char **endp);
/* config.c */
void config_init(void);
@@ -476,7 +484,7 @@ void config_finish(struct grecs_node *);
void config_help(void);
int wy_assert_string_arg(grecs_locus_t *, enum grecs_callback_command,
const grecs_value_t *);
-grecs_value_t *get_arg(grecs_value_t * value, unsigned n, int type);
+grecs_value_t *get_arg(grecs_value_t *value, unsigned n, int type);
int wy_strtofac(const char *str);
int wy_strtopri(const char *str);
@@ -498,7 +506,7 @@ char *concat_file(char const *dir, ...);
int copy_file(int src_dirfd, const char *src_file,
int dst_dirfd, const char *dst_file);
-int dir_test_url(wy_url_t url, grecs_locus_t * locus);
+int dir_test_url(wy_url_t url, grecs_locus_t *locus);
int dir_move_file(struct wy_triplet *trp, enum file_type file_id);
int dir_archive_file(struct wy_triplet *trp, const char *reldir);
int dir_symlink_file(struct wy_triplet *trp,
@@ -548,7 +556,7 @@ extern struct grecs_keyword tcpwrapper_kw[];
int tcpwrap_access(int fd);
/* userprivs.c */
-int wydawca_userprivs(uid_t uid, gid_t gid, gid_t * grplist, size_t ngrp);
+int wydawca_userprivs(uid_t uid, gid_t gid, gid_t *grplist, size_t ngrp);
#ifdef WITH_INOTIFY
int watcher_init(void);
diff --git a/tests/mailnotify.at b/tests/mailnotify.at
index 6ac8c0b..18e8681 100644
--- a/tests/mailnotify.at
+++ b/tests/mailnotify.at
@@ -44,11 +44,11 @@ sed -e 's,^-[[rwx-]]\{9\} '${USER}'.* \([[^ ][^ ]]*\)$,listing of \1,' mail.out
[0],
[From wydawca-noreply@localhost
From: wydawca-noreply@localhost
-To: "Jeannot de Chevigny" <jeannot@example.com>
+To: "Wydawca tester for the Conversion project" <jeannot@example.com>
Subject: Upload of conversion successful
-Wydawca tester for the Conversion project (jeannot@example.com) successfully uploaded files
-for conversion to ftp://wydawca.test/conversion. Files uploaded:
+Upload of conversion to ftp://wydawca.test/conversion finished successfully.
+Files uploaded:
listing of conversion-1.1.tar
listing of conversion-1.1.tar.sig
@@ -58,11 +58,11 @@ Wydawca
The Project Submission Robot
From wydawca-noreply@localhost
From: wydawca-noreply@localhost
-To: "Wydawca tester for the Conversion project" <jeannot@example.com>
+To: "Jeannot de Chevigny" <jeannot@example.com>
Subject: Upload of conversion successful
-Upload of conversion to ftp://wydawca.test/conversion finished successfully.
-Files uploaded:
+Wydawca tester for the Conversion project (jeannot@example.com) successfully uploaded files
+for conversion to ftp://wydawca.test/conversion. Files uploaded:
listing of conversion-1.1.tar
listing of conversion-1.1.tar.sig

Return to:

Send suggestions and report system problems to the System administrator.