summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2009-01-04 11:28:40 +0100
committerVolker Lendecke <vl@samba.org>2009-01-04 16:42:40 +0100
commit611f0d7ee607bad65b7a40ba2f0195ba987f1cab (patch)
tree68c46c261710cbd1e102c59029d5f50107be4963
parentebacce2efe6dbb27a9e7962597da8ef783473f6a (diff)
downloadsamba-611f0d7ee607bad65b7a40ba2f0195ba987f1cab.tar.gz
samba-611f0d7ee607bad65b7a40ba2f0195ba987f1cab.tar.bz2
samba-611f0d7ee607bad65b7a40ba2f0195ba987f1cab.zip
Add an async queueing mechanism
-rw-r--r--source3/include/async_req.h8
-rw-r--r--source3/lib/async_req.c78
2 files changed, 86 insertions, 0 deletions
diff --git a/source3/include/async_req.h b/source3/include/async_req.h
index bbe52da723..1b8dbf3346 100644
--- a/source3/include/async_req.h
+++ b/source3/include/async_req.h
@@ -141,5 +141,13 @@ struct async_req *async_wait_send(TALLOC_CTX *mem_ctx,
NTSTATUS async_wait_recv(struct async_req *req);
+struct async_req_queue;
+
+struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx);
+
+bool async_req_enqueue(struct async_req_queue *queue,
+ struct event_context *ev,
+ struct async_req *req,
+ void (*trigger)(struct async_req *req));
#endif
diff --git a/source3/lib/async_req.c b/source3/lib/async_req.c
index 0653ff62a7..ac06df65a3 100644
--- a/source3/lib/async_req.c
+++ b/source3/lib/async_req.c
@@ -236,3 +236,81 @@ NTSTATUS async_wait_recv(struct async_req *req)
{
return NT_STATUS_OK;
}
+
+struct async_queue_entry {
+ struct async_queue_entry *prev, *next;
+ struct async_req_queue *queue;
+ struct async_req *req;
+ void (*trigger)(struct async_req *req);
+};
+
+struct async_req_queue {
+ struct async_queue_entry *queue;
+};
+
+struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx)
+{
+ return TALLOC_ZERO_P(mem_ctx, struct async_req_queue);
+}
+
+static int async_queue_entry_destructor(struct async_queue_entry *e)
+{
+ struct async_req_queue *queue = e->queue;
+
+ DLIST_REMOVE(queue->queue, e);
+
+ if (queue->queue != NULL) {
+ queue->queue->trigger(queue->queue->req);
+ }
+
+ return 0;
+}
+
+static void async_req_immediate_trigger(struct event_context *ev,
+ struct timed_event *te,
+ const struct timeval *now,
+ void *priv)
+{
+ struct async_queue_entry *e = talloc_get_type_abort(
+ priv, struct async_queue_entry);
+
+ TALLOC_FREE(te);
+ e->trigger(e->req);
+}
+
+bool async_req_enqueue(struct async_req_queue *queue, struct event_context *ev,
+ struct async_req *req,
+ void (*trigger)(struct async_req *req))
+{
+ struct async_queue_entry *e;
+ bool busy;
+
+ busy = (queue->queue != NULL);
+
+ e = talloc(req, struct async_queue_entry);
+ if (e == NULL) {
+ return false;
+ }
+
+ e->req = req;
+ e->trigger = trigger;
+ e->queue = queue;
+
+ DLIST_ADD_END(queue->queue, e, struct async_queue_entry *);
+ talloc_set_destructor(e, async_queue_entry_destructor);
+
+ if (!busy) {
+ struct timed_event *te;
+
+ te = event_add_timed(ev, e, timeval_zero(),
+ "async_req_immediate_trigger",
+ async_req_immediate_trigger,
+ e);
+ if (te == NULL) {
+ TALLOC_FREE(e);
+ return false;
+ }
+ }
+
+ return true;
+}