diff options
author | Stefan Metzmacher <metze@samba.org> | 2022-06-26 12:57:06 +0000 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2022-07-26 13:40:34 +0000 |
commit | 50163da3096d71c08e9c3ff13dd3ecb252a60f4e (patch) | |
tree | 087ed476a41b75a06e152c7a376bf8541c891113 | |
parent | 2eb6a209493e228e433a565154c7c4cd076c0a4a (diff) | |
download | samba-50163da3096d71c08e9c3ff13dd3ecb252a60f4e.tar.gz |
s3:dbwrap_watch: remove a watcher via db_watched_record_fini()
The new dbwrap_watched_watch_remove_instance() will just remove ourself
from the in memory array and let db_watched_record_fini() call
dbwrap_watched_record_storev() in order to write the modified version
into the low level backend record.
For now there's no change in behavior, but it allows us to change it
soon....
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15125
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
-rw-r--r-- | source3/lib/dbwrap/dbwrap_watch.c | 174 |
1 files changed, 89 insertions, 85 deletions
diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c index b3fde2dba75..8f4b792fa63 100644 --- a/source3/lib/dbwrap/dbwrap_watch.c +++ b/source3/lib/dbwrap/dbwrap_watch.c @@ -905,6 +905,86 @@ static uint64_t dbwrap_watched_watch_add_instance(struct db_record *rec) return wrec->added.instance; } +static void dbwrap_watched_watch_remove_instance(struct db_record *rec, uint64_t instance) +{ + struct db_watched_record *wrec = db_record_get_watched_record(rec); + struct dbwrap_watcher clear_watcher = { + .pid = wrec->self, + .instance = instance, + }; + size_t i; + struct server_id_buf buf; + + if (instance == 0) { + return; + } + + if (wrec->added.instance == instance) { + SMB_ASSERT(server_id_equal(&wrec->added.pid, &wrec->self)); + DBG_DEBUG("Watcher %s:%"PRIu64" reverted from adding\n", + server_id_str_buf(clear_watcher.pid, &buf), + clear_watcher.instance); + ZERO_STRUCT(wrec->added); + } + + for (i=0; i < wrec->watchers.count; i++) { + struct dbwrap_watcher watcher; + size_t off = i*DBWRAP_WATCHER_BUF_LENGTH; + size_t next_off; + size_t full_len; + size_t move_len; + + dbwrap_watcher_get(&watcher, wrec->watchers.first + off); + + if (clear_watcher.instance != watcher.instance) { + continue; + } + if (!server_id_equal(&clear_watcher.pid, &watcher.pid)) { + continue; + } + + wrec->force_fini_store = true; + + if (i == 0) { + DBG_DEBUG("Watcher %s:%"PRIu64" removed from first position of %zu\n", + server_id_str_buf(clear_watcher.pid, &buf), + clear_watcher.instance, + wrec->watchers.count); + wrec->watchers.first += DBWRAP_WATCHER_BUF_LENGTH; + wrec->watchers.count -= 1; + return; + } + if (i == (wrec->watchers.count-1)) { + DBG_DEBUG("Watcher %s:%"PRIu64" removed from last position of %zu\n", + server_id_str_buf(clear_watcher.pid, &buf), + clear_watcher.instance, + wrec->watchers.count); + wrec->watchers.count -= 1; + return; + } + + DBG_DEBUG("Watcher %s:%"PRIu64" cleared at position %zu from %zu\n", + server_id_str_buf(clear_watcher.pid, &buf), + clear_watcher.instance, i+1, + wrec->watchers.count); + + next_off = off + DBWRAP_WATCHER_BUF_LENGTH; + full_len = wrec->watchers.count * DBWRAP_WATCHER_BUF_LENGTH; + move_len = full_len - next_off; + memmove(wrec->watchers.first + off, + wrec->watchers.first + next_off, + move_len); + wrec->watchers.count -= 1; + return; + } + + DBG_DEBUG("Watcher %s:%"PRIu64" not found in %zu watchers\n", + server_id_str_buf(clear_watcher.pid, &buf), + clear_watcher.instance, + wrec->watchers.count); + return; +} + static void dbwrap_watched_watch_skip_alerting(struct db_record *rec) { struct db_watched_record *wrec = db_record_get_watched_record(rec); @@ -1019,100 +1099,24 @@ static void dbwrap_watched_watch_state_destructor_fn( { struct dbwrap_watched_watch_state *state = talloc_get_type_abort( private_data, struct dbwrap_watched_watch_state); - uint8_t *watchers; - size_t num_watchers = 0; - size_t i; - bool ok; - NTSTATUS status; - - uint8_t num_watchers_buf[4]; - - TDB_DATA dbufs[4] = { - { - .dptr = num_watchers_buf, - .dsize = sizeof(num_watchers_buf), - }, - { 0 }, /* watchers "before" state->w */ - { 0 }, /* watchers "behind" state->w */ - { 0 }, /* filled in with data */ - }; - ok = dbwrap_watch_rec_parse( - value, &watchers, &num_watchers, &dbufs[3]); - if (!ok) { - status = dbwrap_record_delete(rec); - if (!NT_STATUS_IS_OK(status)) { - DBG_DEBUG("dbwrap_record_delete failed: %s\n", - nt_errstr(status)); - } - return; - } - - for (i=0; i<num_watchers; i++) { - struct dbwrap_watcher watcher; - - dbwrap_watcher_get( - &watcher, watchers + i*DBWRAP_WATCHER_BUF_LENGTH); - - if ((state->watcher.instance == watcher.instance) && - server_id_equal(&state->watcher.pid, &watcher.pid)) { - break; - } - } - - if (i == num_watchers) { - struct server_id_buf buf; - DBG_DEBUG("Watcher %s:%"PRIu64" not found\n", - server_id_str_buf(state->watcher.pid, &buf), - state->watcher.instance); - return; - } - - if (i > 0) { - dbufs[1] = (TDB_DATA) { - .dptr = watchers, - .dsize = i * DBWRAP_WATCHER_BUF_LENGTH, - }; - } - - if (i < (num_watchers - 1)) { - size_t behind = (num_watchers - 1 - i); - - dbufs[2] = (TDB_DATA) { - .dptr = watchers + (i+1) * DBWRAP_WATCHER_BUF_LENGTH, - .dsize = behind * DBWRAP_WATCHER_BUF_LENGTH, - }; - } - - num_watchers -= 1; - - if ((num_watchers == 0) && (dbufs[3].dsize == 0)) { - status = dbwrap_record_delete(rec); - if (!NT_STATUS_IS_OK(status)) { - DBG_DEBUG("dbwrap_record_delete() failed: %s\n", - nt_errstr(status)); - } - return; - } - - SIVAL(num_watchers_buf, 0, num_watchers); - - status = dbwrap_record_storev(rec, dbufs, ARRAY_SIZE(dbufs), 0); - if (!NT_STATUS_IS_OK(status)) { - DBG_DEBUG("dbwrap_record_storev() failed: %s\n", - nt_errstr(status)); - } + /* + * Here we just remove ourself from the in memory + * watchers array and let db_watched_record_fini() + * call dbwrap_watched_record_storev() to do the magic + * of writing back the modified in memory copy. + */ + dbwrap_watched_watch_remove_instance(rec, state->watcher.instance); + return; } static int dbwrap_watched_watch_state_destructor( struct dbwrap_watched_watch_state *state) { - struct db_watched_ctx *ctx = talloc_get_type_abort( - state->db->private_data, struct db_watched_ctx); NTSTATUS status; status = dbwrap_do_locked( - ctx->backend, + state->db, state->key, dbwrap_watched_watch_state_destructor_fn, state); |