summaryrefslogtreecommitdiff
path: root/lib/dbwrap/dbwrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dbwrap/dbwrap.c')
-rw-r--r--lib/dbwrap/dbwrap.c112
1 files changed, 112 insertions, 0 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) {