struct dbwrap_watch_rec wrec;
};
+static NTSTATUS dbwrap_watched_subrec_storev(
+ struct db_record *rec, struct db_watched_subrec *subrec,
+ const TDB_DATA *dbufs, int num_dbufs, int flags);
+static NTSTATUS dbwrap_watched_subrec_delete(
+ struct db_record *rec, struct db_watched_subrec *subrec);
static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
const TDB_DATA *dbufs, int num_dbufs,
- int flag);
+ int flags);
static NTSTATUS dbwrap_watched_delete(struct db_record *rec);
+static void dbwrap_watched_wakeup(struct db_record *rec,
+ struct dbwrap_watch_rec *wrec);
+static NTSTATUS dbwrap_watched_save(struct db_record *rec,
+ struct dbwrap_watch_rec *wrec,
+ struct server_id *addwatch,
+ const TDB_DATA *databufs,
+ size_t num_databufs,
+ int flags);
static struct db_record *dbwrap_watched_fetch_locked(
struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
return rec;
}
+struct dbwrap_watched_do_locked_state {
+ TALLOC_CTX *mem_ctx;
+ struct db_context *db;
+ void (*fn)(struct db_record *rec, void *private_data);
+ void *private_data;
+
+ struct db_watched_subrec subrec;
+
+ NTSTATUS status;
+};
+
+static NTSTATUS dbwrap_watched_do_locked_storev(
+ struct db_record *rec, const TDB_DATA *dbufs, int num_dbufs,
+ int flags)
+{
+ struct dbwrap_watched_do_locked_state *state = rec->private_data;
+ struct db_watched_subrec *subrec = &state->subrec;
+ NTSTATUS status;
+
+ status = dbwrap_watched_subrec_storev(rec, subrec, dbufs, num_dbufs,
+ flags);
+ return status;
+}
+
+static NTSTATUS dbwrap_watched_do_locked_delete(struct db_record *rec)
+{
+ struct dbwrap_watched_do_locked_state *state = rec->private_data;
+ struct db_watched_subrec *subrec = &state->subrec;
+ NTSTATUS status;
+
+ status = dbwrap_watched_subrec_delete(rec, subrec);
+ return status;
+}
+
+static void dbwrap_watched_do_locked_fn(struct db_record *subrec,
+ void *private_data)
+{
+ struct dbwrap_watched_do_locked_state *state =
+ (struct dbwrap_watched_do_locked_state *)private_data;
+ TDB_DATA subrec_value = dbwrap_record_get_value(subrec);
+ struct db_record rec;
+ bool ok;
+
+ rec = (struct db_record) {
+ .db = state->db, .key = dbwrap_record_get_key(subrec),
+ .storev = dbwrap_watched_do_locked_storev,
+ .delete_rec = dbwrap_watched_do_locked_delete,
+ .private_data = state
+ };
+
+ state->subrec = (struct db_watched_subrec) {
+ .subrec = subrec
+ };
+
+ ok = dbwrap_watch_rec_parse(subrec_value, &state->subrec.wrec);
+ if (ok) {
+ rec.value = state->subrec.wrec.data;
+ }
+
+ state->fn(&rec, state->private_data);
+}
+
+static NTSTATUS dbwrap_watched_do_locked(struct db_context *db, TDB_DATA key,
+ void (*fn)(struct db_record *rec,
+ void *private_data),
+ void *private_data)
+{
+ struct db_watched_ctx *ctx = talloc_get_type_abort(
+ db->private_data, struct db_watched_ctx);
+ struct dbwrap_watched_do_locked_state state = {
+ .mem_ctx = talloc_stackframe(),
+ .db = db, .fn = fn, .private_data = private_data
+ };
+ NTSTATUS status;
+
+ status = dbwrap_do_locked(
+ ctx->backend, key, dbwrap_watched_do_locked_fn, &state);
+ TALLOC_FREE(state.mem_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("dbwrap_do_locked returned %s\n", nt_errstr(status));
+ return status;
+ }
+
+ DBG_DEBUG("dbwrap_watched_do_locked_fn returned %s\n",
+ nt_errstr(state.status));
+
+ return state.status;
+}
+
static void dbwrap_watched_wakeup(struct db_record *rec,
struct dbwrap_watch_rec *wrec)
{
return status;
}
-static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
- const TDB_DATA *dbufs, int num_dbufs,
- int flags)
+static NTSTATUS dbwrap_watched_subrec_storev(
+ struct db_record *rec, struct db_watched_subrec *subrec,
+ const TDB_DATA *dbufs, int num_dbufs, int flags)
{
- struct db_watched_subrec *subrec = talloc_get_type_abort(
- rec->private_data, struct db_watched_subrec);
NTSTATUS status;
dbwrap_watched_wakeup(rec, &subrec->wrec);
return status;
}
-static NTSTATUS dbwrap_watched_delete(struct db_record *rec)
+static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
+ const TDB_DATA *dbufs, int num_dbufs,
+ int flags)
{
struct db_watched_subrec *subrec = talloc_get_type_abort(
rec->private_data, struct db_watched_subrec);
+ NTSTATUS status;
+
+ status = dbwrap_watched_subrec_storev(rec, subrec, dbufs, num_dbufs,
+ flags);
+ return status;
+}
+
+static NTSTATUS dbwrap_watched_subrec_delete(
+ struct db_record *rec, struct db_watched_subrec *subrec)
+{
+ NTSTATUS status;
dbwrap_watched_wakeup(rec, &subrec->wrec);
subrec->wrec.deleted = true;
- return dbwrap_watched_save(subrec->subrec, &subrec->wrec,
- NULL, NULL, 0, 0);
+ status = dbwrap_watched_save(subrec->subrec, &subrec->wrec,
+ NULL, NULL, 0, 0);
+ return status;
+}
+
+static NTSTATUS dbwrap_watched_delete(struct db_record *rec)
+{
+ struct db_watched_subrec *subrec = talloc_get_type_abort(
+ rec->private_data, struct db_watched_subrec);
+ NTSTATUS status;
+
+ status = dbwrap_watched_subrec_delete(rec, subrec);
+ return status;
}
struct dbwrap_watched_traverse_state {
ctx->backend = talloc_move(ctx, &backend);
db->fetch_locked = dbwrap_watched_fetch_locked;
+ db->do_locked = dbwrap_watched_do_locked;
db->traverse = dbwrap_watched_traverse;
db->traverse_read = dbwrap_watched_traverse_read;
db->get_seqnum = dbwrap_watched_get_seqnum;
struct db_record *rec,
struct server_id blocker)
{
- struct db_watched_subrec *subrec = talloc_get_type_abort(
- rec->private_data, struct db_watched_subrec);
struct db_context *db = dbwrap_record_get_db(rec);
struct db_watched_ctx *ctx = talloc_get_type_abort(
db->private_data, struct db_watched_ctx);
-
+ struct db_watched_subrec *subrec = NULL;
struct tevent_req *req, *subreq;
struct dbwrap_watched_watch_state *state;
ssize_t needed;
return tevent_req_post(req, ev);
}
+ /*
+ * Figure out whether we're called as part of do_locked. If
+ * so, we can't use talloc_get_type_abort, the
+ * db_watched_subrec is stack-allocated in that case.
+ */
+
+ if (rec->storev == dbwrap_watched_storev) {
+ subrec = talloc_get_type_abort(rec->private_data,
+ struct db_watched_subrec);
+ }
+ if (rec->storev == dbwrap_watched_do_locked_storev) {
+ struct dbwrap_watched_do_locked_state *do_locked_state;
+ do_locked_state = rec->private_data;
+ subrec = &do_locked_state->subrec;
+ }
+ if (subrec == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
state->me = messaging_server_id(ctx->msg);
needed = dbwrap_record_watchers_key(db, rec, NULL, 0);
bool run_dbwrap_do_locked1(int dummy)
{
+ struct tevent_context *ev;
+ struct messaging_context *msg;
+ struct db_context *backend;
struct db_context *db;
const char *dbname = "test_do_locked.tdb";
const char *keystr = "key";
int ret = false;
NTSTATUS status;
- db = db_open(talloc_tos(), dbname, 0, TDB_CLEAR_IF_FIRST,
- O_CREAT|O_RDWR, 0644, DBWRAP_LOCK_ORDER_1,
- DBWRAP_FLAG_NONE);
- if (db == NULL) {
+ ev = server_event_context();
+ if (ev == NULL) {
+ fprintf(stderr, "server_event_context() failed\n");
+ return false;
+ }
+ msg = server_messaging_context();
+ if (msg == NULL) {
+ fprintf(stderr, "server_messaging_context() failed\n");
+ return false;
+ }
+
+ backend = db_open(talloc_tos(), dbname, 0,
+ TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0644,
+ DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
+ if (backend == NULL) {
fprintf(stderr, "db_open failed: %s\n", strerror(errno));
return false;
}
+ db = db_open_watched(talloc_tos(), backend, msg);
+ if (db == NULL) {
+ fprintf(stderr, "db_open_watched failed: %s\n",
+ strerror(errno));
+ return false;
+ }
+
status = dbwrap_do_locked(db, key, do_locked1_cb, &state);
if (!NT_STATUS_IS_OK(status)) {
fprintf(stderr, "dbwrap_do_locked failed: %s\n",
goto fail;
}
if (!NT_STATUS_IS_OK(state.status)) {
- fprintf(stderr, "store returned %s\n", nt_errstr(status));
+ fprintf(stderr, "store returned %s\n",
+ nt_errstr(state.status));
goto fail;
}