diff options
author | Volker Lendecke <vl@samba.org> | 2017-06-27 18:40:28 +0200 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2017-07-25 17:43:16 +0200 |
commit | ecb4283f3d3baa5619a55ceeef8acc8d487029f3 (patch) | |
tree | fcafa34432f1149795e8cfe9c801078a97232fbf /source3 | |
parent | faa53616ea6e03c0676c72032d4720f12b4f9340 (diff) | |
download | samba-ecb4283f3d3baa5619a55ceeef8acc8d487029f3.tar.gz |
dbwrap_watch: Implement do_locked
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Diffstat (limited to 'source3')
-rw-r--r-- | source3/lib/dbwrap/dbwrap_watch.c | 167 | ||||
-rw-r--r-- | source3/torture/test_dbwrap_do_locked.c | 32 |
2 files changed, 182 insertions, 17 deletions
diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c index 646106747ee..be0a0d37e0b 100644 --- a/source3/lib/dbwrap/dbwrap_watch.c +++ b/source3/lib/dbwrap/dbwrap_watch.c @@ -198,10 +198,23 @@ struct db_watched_subrec { 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) @@ -245,6 +258,95 @@ static struct db_record *dbwrap_watched_fetch_locked( 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) { @@ -342,12 +444,10 @@ static NTSTATUS dbwrap_watched_save(struct db_record *rec, 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); @@ -359,10 +459,23 @@ static NTSTATUS dbwrap_watched_storev(struct db_record *rec, 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); @@ -372,8 +485,19 @@ static NTSTATUS dbwrap_watched_delete(struct db_record *rec) 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 { @@ -638,6 +762,7 @@ struct db_context *db_open_watched(TALLOC_CTX *mem_ctx, 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; @@ -674,12 +799,10 @@ struct tevent_req *dbwrap_watched_watch_send(TALLOC_CTX *mem_ctx, 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; @@ -698,6 +821,26 @@ struct tevent_req *dbwrap_watched_watch_send(TALLOC_CTX *mem_ctx, 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); diff --git a/source3/torture/test_dbwrap_do_locked.c b/source3/torture/test_dbwrap_do_locked.c index 92dec38ef64..46b326bf163 100644 --- a/source3/torture/test_dbwrap_do_locked.c +++ b/source3/torture/test_dbwrap_do_locked.c @@ -65,6 +65,9 @@ static void do_locked1_del(struct db_record *rec, void *private_data) 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"; @@ -75,14 +78,32 @@ bool run_dbwrap_do_locked1(int dummy) 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", @@ -90,7 +111,8 @@ bool run_dbwrap_do_locked1(int dummy) 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; } |