summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2013-05-31 22:00:17 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-06-04 17:24:13 +0200
commit044aff9bd41e0126b89f1ad672e196c3aa1654b7 (patch)
tree4f0a0fd4e401d9b4742c7c8d9ab7e7f197e9af00 /src
parent909a86af4eb99f5d311d7136cab78dca535ae304 (diff)
downloadsssd-044aff9bd41e0126b89f1ad672e196c3aa1654b7.tar.gz
sssd-044aff9bd41e0126b89f1ad672e196c3aa1654b7.tar.bz2
sssd-044aff9bd41e0126b89f1ad672e196c3aa1654b7.zip
Add be request queue
For some backend targets it might be not desirable to run requests in parallel but to serialize them. To avoid that each provider has to implement a queue for this target this patch implements a generic queue which collects incoming requests before they are send to the target.
Diffstat (limited to 'src')
-rw-r--r--src/providers/data_provider_be.c119
-rw-r--r--src/providers/dp_backend.h11
2 files changed, 130 insertions, 0 deletions
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index cd671568..1d61a88b 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -301,6 +301,125 @@ static errno_t be_file_request(TALLOC_CTX *mem_ctx,
return EOK;
}
+static errno_t be_queue_request(TALLOC_CTX *queue_mem_ctx,
+ struct bet_queue_item **req_queue,
+ TALLOC_CTX *req_mem_ctx,
+ struct be_req *be_req,
+ be_req_fn_t fn)
+{
+ struct bet_queue_item *item;
+ int ret;
+
+ if (*req_queue == NULL) {
+ DEBUG(SSSDBG_TRACE_ALL, ("Queue is empty, " \
+ "running request immediately.\n"));
+ ret = be_file_request(req_mem_ctx, be_req, fn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("be_file_request failed.\n"));
+ return ret;
+ }
+ }
+
+ item = talloc_zero(queue_mem_ctx, struct bet_queue_item);
+ if (item == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed, cannot add item to " \
+ "request queue.\n"));
+ } else {
+ DEBUG(SSSDBG_TRACE_ALL, ("Adding request to queue.\n"));
+ item->mem_ctx = req_mem_ctx;
+ item->be_req = be_req;
+ item->fn = fn;
+
+ DLIST_ADD_END(*req_queue, item, struct bet_queue_item *);
+ }
+
+ return EOK;
+}
+
+static void be_queue_next_request(struct be_req *be_req, enum bet_type type)
+{
+ struct bet_queue_item *item;
+ struct bet_queue_item *current = NULL;
+ struct bet_queue_item **req_queue;
+ int ret;
+ DBusMessage *reply;
+ uint16_t err_maj;
+ uint32_t err_min;
+ const char *err_msg = "Cannot file back end request";
+ struct be_req *next_be_req = NULL;
+ dbus_bool_t dbret;
+ DBusConnection *dbus_conn;
+
+ req_queue = &be_req->becli->bectx->bet_info[type].req_queue;
+
+ if (*req_queue == NULL) {
+ DEBUG(SSSDBG_TRACE_ALL, ("Queue is empty, nothing to do.\n"));
+ return;
+ }
+
+ DLIST_FOR_EACH(item, *req_queue) {
+ if (item->be_req == be_req) {
+ current = item;
+ break;
+ }
+ }
+
+ if (current != NULL) {
+ DLIST_REMOVE(*req_queue, current);
+ }
+
+ if (*req_queue == NULL) {
+ DEBUG(SSSDBG_TRACE_ALL, ("Request queue is empty.\n"));
+ return;
+ }
+
+ next_be_req = (*req_queue)->be_req;
+
+ ret = be_file_request((*req_queue)->mem_ctx, next_be_req, (*req_queue)->fn);
+ if (ret == EOK) {
+ DEBUG(SSSDBG_TRACE_ALL, ("Queued request filed successfully.\n"));
+ return;
+ }
+
+ DEBUG(SSSDBG_OP_FAILURE, ("be_file_request failed.\n"));
+
+ be_queue_next_request(next_be_req, type);
+
+ reply = (DBusMessage *) next_be_req->pvt;
+
+ if (reply) {
+ /* Return a reply if one was requested
+ * There may not be one if this request began
+ * while we were offline
+ */
+ err_maj = DP_ERR_FATAL;
+ err_min = ret;
+
+ dbret = dbus_message_append_args(reply,
+ DBUS_TYPE_UINT16, &err_maj,
+ DBUS_TYPE_UINT32, &err_min,
+ DBUS_TYPE_STRING, &err_msg,
+ DBUS_TYPE_INVALID);
+
+ if (!dbret) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to generate dbus reply\n"));
+ dbus_message_unref(reply);
+ goto done;
+ }
+
+ dbus_conn = sbus_get_connection(next_be_req->becli->conn);
+ if (dbus_conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("D-BUS not connected\n"));
+ goto done;
+ }
+ dbus_connection_send(dbus_conn, reply, NULL);
+ dbus_message_unref(reply);
+ }
+
+done:
+ talloc_free(next_be_req);
+}
+
bool be_is_offline(struct be_ctx *ctx)
{
time_t now = time(NULL);
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index e0e2210c..9a8df4cd 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -68,11 +68,22 @@ struct loaded_be {
void *handle;
};
+struct bet_queue_item {
+ struct bet_queue_item *prev;
+ struct bet_queue_item *next;
+
+ TALLOC_CTX *mem_ctx;
+ struct be_req *be_req;
+ be_req_fn_t fn;
+
+};
+
struct bet_info {
enum bet_type bet_type;
struct bet_ops *bet_ops;
void *pvt_bet_data;
char *mod_name;
+ struct bet_queue_item *req_queue;
};
struct be_offline_status {