diff options
Diffstat (limited to 'lib/dbwrap')
-rw-r--r-- | lib/dbwrap/dbwrap.c | 112 | ||||
-rw-r--r-- | lib/dbwrap/dbwrap.h | 33 | ||||
-rw-r--r-- | lib/dbwrap/wscript_build | 2 |
3 files changed, 146 insertions, 1 deletions
diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c index 68e5608608a..025d463b4bd 100644 --- a/lib/dbwrap/dbwrap.c +++ b/lib/dbwrap/dbwrap.c @@ -26,6 +26,7 @@ #include "dbwrap/dbwrap.h" #include "dbwrap/dbwrap_private.h" #include "lib/util/util_tdb.h" +#include "lib/util/tevent_ntstatus.h" /* * Fall back using fetch if no genuine exists operation is provided @@ -368,6 +369,117 @@ NTSTATUS dbwrap_parse_record(struct db_context *db, TDB_DATA key, return db->parse_record(db, key, parser, private_data); } +struct dbwrap_parse_record_state { + struct db_context *db; + TDB_DATA key; + uint8_t _keybuf[64]; +}; + +static void dbwrap_parse_record_done(struct tevent_req *subreq); + +struct tevent_req *dbwrap_parse_record_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct db_context *db, + TDB_DATA key, + void (*parser)(TDB_DATA key, TDB_DATA data, void *private_data), + void *private_data, + enum dbwrap_req_state *req_state) +{ + struct tevent_req *req = NULL; + struct tevent_req *subreq = NULL; + struct dbwrap_parse_record_state *state = NULL; + NTSTATUS status; + + req = tevent_req_create(mem_ctx, &state, struct dbwrap_parse_record_state); + if (req == NULL) { + *req_state = DBWRAP_REQ_ERROR; + return NULL; + } + + *state = (struct dbwrap_parse_record_state) { + .db = db, + }; + + if (parser == NULL) { + parser = dbwrap_null_parser; + } + + *req_state = DBWRAP_REQ_INIT; + + if (db->parse_record_send == NULL) { + /* + * Backend doesn't implement async version, call sync one + */ + status = db->parse_record(db, key, parser, private_data); + if (tevent_req_nterror(req, status)) { + *req_state = DBWRAP_REQ_DONE; + return tevent_req_post(req, ev); + } + + *req_state = DBWRAP_REQ_DONE; + tevent_req_done(req); + return tevent_req_post(req, ev); + } + + /* + * Copy the key into our state ensuring the key data buffer is always + * available to the all dbwrap backend over the entire lifetime of the + * async request. Otherwise the caller might have free'd the key buffer. + */ + if (key.dsize > sizeof(state->_keybuf)) { + state->key.dptr = talloc_memdup(state, key.dptr, key.dsize); + if (tevent_req_nomem(state->key.dptr, req)) { + return tevent_req_post(req, ev); + } + } else { + memcpy(state->_keybuf, key.dptr, key.dsize); + state->key.dptr = state->_keybuf; + } + state->key.dsize = key.dsize; + + subreq = db->parse_record_send(state, + ev, + db, + state->key, + parser, + private_data, + req_state); + if (tevent_req_nomem(subreq, req)) { + *req_state = DBWRAP_REQ_ERROR; + return tevent_req_post(req, ev); + } + + tevent_req_set_callback(subreq, + dbwrap_parse_record_done, + req); + return req; +} + +static void dbwrap_parse_record_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct dbwrap_parse_record_state *state = tevent_req_data( + req, struct dbwrap_parse_record_state); + NTSTATUS status; + + status = state->db->parse_record_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + + tevent_req_done(req); + return; +} + +NTSTATUS dbwrap_parse_record_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} + int dbwrap_wipe(struct db_context *db) { if (db->wipe == NULL) { diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h index 936e66247d7..fac65ee6cfe 100644 --- a/lib/dbwrap/dbwrap.h +++ b/lib/dbwrap/dbwrap.h @@ -22,6 +22,7 @@ #include "replace.h" #include <talloc.h> +#include <tevent.h> #include "libcli/util/ntstatus.h" #include "tdb.h" #include "lib/param/loadparm.h" @@ -98,6 +99,38 @@ NTSTATUS dbwrap_parse_record(struct db_context *db, TDB_DATA key, void (*parser)(TDB_DATA key, TDB_DATA data, void *private_data), void *private_data); +/** + * Async implementation of dbwrap_parse_record + * + * @param[in] mem_ctx talloc memory context to use. + * + * @param[in] ev tevent context to use + * + * @param[in] db Database to query + * + * @param[in] key Record key, the function makes a copy of this + * + * @param[in] parser Parser callback function + * + * @param[in] private_data Private data for the callback function + * + * @param[out] req_state Pointer to a enum dbwrap_req_state variable + * + * @note req_state is updated in the send function. To determine the final + * result of the request the caller should therefor not rely on req_state. The + * primary use case is to give the caller an indication whether the request is + * already sent to ctdb (DBWRAP_REQ_DISPATCHED) or if it's still stuck in the + * sendqueue (DBWRAP_REQ_QUEUED). + **/ +struct tevent_req *dbwrap_parse_record_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct db_context *db, + TDB_DATA key, + void (*parser)(TDB_DATA key, TDB_DATA data, void *private_data), + void *private_data, + enum dbwrap_req_state *req_state); +NTSTATUS dbwrap_parse_record_recv(struct tevent_req *req); int dbwrap_wipe(struct db_context *db); int dbwrap_check(struct db_context *db); int dbwrap_get_seqnum(struct db_context *db); diff --git a/lib/dbwrap/wscript_build b/lib/dbwrap/wscript_build index b719a606e18..83e5895a7b1 100644 --- a/lib/dbwrap/wscript_build +++ b/lib/dbwrap/wscript_build @@ -1,6 +1,6 @@ SRC = '''dbwrap.c dbwrap_util.c dbwrap_rbt.c dbwrap_cache.c dbwrap_tdb.c dbwrap_local_open.c''' -DEPS= '''samba-util util_tdb samba-errors tdb tdb-wrap samba-hostconfig''' +DEPS= '''samba-util util_tdb samba-errors tdb tdb-wrap samba-hostconfig tevent tevent-util''' bld.SAMBA_LIBRARY('dbwrap', source=SRC, |