along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "includes.h"
+#include "replace.h"
+#include "lib/util/debug.h"
+#include "lib/util/fault.h"
+#include "lib/util/talloc_stack.h"
#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
NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags)
{
NTSTATUS status;
- struct db_context *db;
status = rec->store(rec, data, flags);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- db = rec->db;
- if (db->stored_callback != NULL) {
- db->stored_callback(db, rec,
- db->stored_callback_private_data);
- }
return NT_STATUS_OK;
}
-void dbwrap_set_stored_callback(
- struct db_context *db,
- void (*cb)(struct db_context *db, struct db_record *rec,
- void *private_data),
- void *private_data)
-{
- db->stored_callback = cb;
- db->stored_callback_private_data = private_data;
-}
-
NTSTATUS dbwrap_record_delete(struct db_record *rec)
{
NTSTATUS status;
- struct db_context *db;
status = rec->delete_rec(rec);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- db = rec->db;
- if (db->stored_callback != NULL) {
- db->stored_callback(db, rec,
- db->stored_callback_private_data);
- }
return NT_STATUS_OK;
}
static struct db_context *locked_dbs[DBWRAP_LOCK_ORDER_MAX];
struct dbwrap_lock_order_state *state = NULL;
- if (db->lock_order == 0) {
- /*
- * lock order 0 is for example for dbwrap_rbt without
- * real locking. Return state nevertheless to avoid
- * special cases.
- */
- return talloc_zero(mem_ctx, struct dbwrap_lock_order_state);
- }
-
- if (db->lock_order > DBWRAP_LOCK_ORDER_MAX) {
+ if (!DBWRAP_LOCK_ORDER_VALID(db->lock_order)) {
DEBUG(0,("Invalid lock order %d of %s\n",
(int)db->lock_order, db->name));
smb_panic("invalid lock_order\n");
TDB_DATA key))
{
struct db_record *rec;
- struct dbwrap_lock_order_state *lock_order;
- TALLOC_CTX *frame = talloc_stackframe();
+ struct dbwrap_lock_order_state *lock_order = NULL;
- lock_order = dbwrap_check_lock_order(db, frame);
- if (lock_order == NULL) {
- TALLOC_FREE(frame);
- return NULL;
+ if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
+ lock_order = dbwrap_check_lock_order(db, mem_ctx);
+ if (lock_order == NULL) {
+ return NULL;
+ }
}
rec = db_fn(db, mem_ctx, key);
if (rec == NULL) {
- TALLOC_FREE(frame);
+ TALLOC_FREE(lock_order);
return NULL;
}
(void)talloc_steal(rec, lock_order);
rec->db = db;
- TALLOC_FREE(frame);
return rec;
}
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) {
return db->wipe(db);
}
-int dbwrap_hash_size(struct db_context *db)
-{
- return db->hash_size;
-}
-
int dbwrap_check(struct db_context *db)
{
if (db->check == NULL) {
return db->transaction_cancel(db);
}
-void dbwrap_db_id(struct db_context *db, const uint8_t **id, size_t *idlen)
+size_t dbwrap_db_id(struct db_context *db, uint8_t *id, size_t idlen)
{
- db->id(db, id, idlen);
+ return db->id(db, id, idlen);
}
bool dbwrap_is_persistent(struct db_context *db)