2 Unix SMB/CIFS implementation.
3 Watch dbwrap record changes
4 Copyright (C) Volker Lendecke 2012
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/filesys.h"
22 #include "lib/util/server_id.h"
23 #include "dbwrap/dbwrap.h"
24 #include "dbwrap_watch.h"
25 #include "dbwrap_open.h"
26 #include "lib/util/util_tdb.h"
27 #include "lib/util/tevent_ntstatus.h"
28 #include "server_id_watch.h"
29 #include "lib/dbwrap/dbwrap_private.h"
31 static ssize_t dbwrap_record_watchers_key(struct db_context *db,
32 struct db_record *rec,
33 uint8_t *wkey, size_t wkey_len)
35 size_t db_id_len = dbwrap_db_id(db, NULL, 0);
36 uint8_t db_id[db_id_len];
40 dbwrap_db_id(db, db_id, db_id_len);
42 key = dbwrap_record_get_key(rec);
44 needed = sizeof(uint32_t) + db_id_len;
45 if (needed < sizeof(uint32_t)) {
50 if (needed < key.dsize) {
54 if (wkey_len >= needed) {
55 SIVAL(wkey, 0, db_id_len);
56 memcpy(wkey + sizeof(uint32_t), db_id, db_id_len);
57 memcpy(wkey + sizeof(uint32_t) + db_id_len,
64 static bool dbwrap_record_watchers_key_parse(
65 TDB_DATA wkey, uint8_t **p_db_id, size_t *p_db_id_len, TDB_DATA *key)
69 if (wkey.dsize < sizeof(uint32_t)) {
70 DBG_WARNING("Invalid watchers key, dsize=%zu\n", wkey.dsize);
73 db_id_len = IVAL(wkey.dptr, 0);
74 if (db_id_len > (wkey.dsize - sizeof(uint32_t))) {
75 DBG_WARNING("Invalid watchers key, wkey.dsize=%zu, "
76 "db_id_len=%zu\n", wkey.dsize, db_id_len);
79 if (p_db_id != NULL) {
80 *p_db_id = wkey.dptr + sizeof(uint32_t);
82 if (p_db_id_len != NULL) {
83 *p_db_id_len = db_id_len;
86 key->dptr = wkey.dptr + sizeof(uint32_t) + db_id_len;
87 key->dsize = wkey.dsize - sizeof(uint32_t) - db_id_len;
93 * Watched records contain a header of:
95 * [uint32] num_records | deleted bit
96 * 0 [SERVER_ID_BUF_LENGTH] \
97 * 1 [SERVER_ID_BUF_LENGTH] |
98 * .. |- Array of watchers
99 * (num_records-1)[SERVER_ID_BUF_LENGTH] /
101 * [Remainder of record....]
103 * If this header is absent then this is a
104 * fresh record of length zero (no watchers).
106 * Note that a record can be deleted with
107 * watchers present. If so the deleted bit
108 * is set and the watcher server_id's are
109 * woken to allow them to remove themselves
110 * from the watcher array. The record is left
111 * present marked with the deleted bit until all
112 * watchers are removed, then the record itself
116 #define NUM_WATCHERS_DELETED_BIT (1UL<<31)
117 #define NUM_WATCHERS_MASK (NUM_WATCHERS_DELETED_BIT-1)
119 static ssize_t dbwrap_watched_parse(TDB_DATA data, struct server_id *ids,
120 size_t num_ids, bool *pdeleted,
123 size_t i, num_watchers;
126 if (data.dsize < sizeof(uint32_t)) {
127 /* Fresh or invalid record */
131 num_watchers = IVAL(data.dptr, 0);
133 deleted = num_watchers & NUM_WATCHERS_DELETED_BIT;
134 num_watchers &= NUM_WATCHERS_MASK;
136 data.dptr += sizeof(uint32_t);
137 data.dsize -= sizeof(uint32_t);
139 if (num_watchers > data.dsize/SERVER_ID_BUF_LENGTH) {
144 if (num_watchers > num_ids) {
146 * Not enough space to store the watchers server_id's.
147 * Just move past all of them to allow the remaining part
148 * of the record to be returned.
150 data.dptr += num_watchers * SERVER_ID_BUF_LENGTH;
151 data.dsize -= num_watchers * SERVER_ID_BUF_LENGTH;
156 * Note, even if marked deleted we still must
157 * return the id's array to allow awoken
158 * watchers to remove themselves.
161 for (i=0; i<num_watchers; i++) {
162 server_id_get(&ids[i], data.dptr);
163 data.dptr += SERVER_ID_BUF_LENGTH;
164 data.dsize -= SERVER_ID_BUF_LENGTH;
169 data = (TDB_DATA) {0};
174 if (pdeleted != NULL) {
181 static ssize_t dbwrap_watched_unparse(const struct server_id *watchers,
182 size_t num_watchers, bool deleted,
184 uint8_t *buf, size_t buflen)
187 uint32_t num_watchers_buf;
189 if (num_watchers > UINT32_MAX/SERVER_ID_BUF_LENGTH) {
193 len = num_watchers * SERVER_ID_BUF_LENGTH;
195 len += sizeof(uint32_t);
196 if (len < sizeof(uint32_t)) {
201 if (len < data.dsize) {
209 num_watchers_buf = num_watchers;
211 num_watchers_buf |= NUM_WATCHERS_DELETED_BIT;
215 SIVAL(buf, ofs, num_watchers_buf);
218 for (i=0; i<num_watchers; i++) {
219 server_id_put(buf+ofs, watchers[i]);
220 ofs += SERVER_ID_BUF_LENGTH;
223 if ((data.dptr != NULL) && (data.dsize != 0)) {
224 memcpy(buf + ofs, data.dptr, data.dsize);
230 struct db_watched_ctx {
231 struct db_context *backend;
232 struct messaging_context *msg;
235 struct db_watched_subrec {
236 struct db_record *subrec;
237 struct server_id *watchers;
241 static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
242 const TDB_DATA *dbufs, int num_dbufs,
244 static NTSTATUS dbwrap_watched_delete(struct db_record *rec);
246 static struct db_record *dbwrap_watched_fetch_locked(
247 struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
249 struct db_watched_ctx *ctx = talloc_get_type_abort(
250 db->private_data, struct db_watched_ctx);
251 struct db_record *rec;
252 struct db_watched_subrec *subrec;
253 TDB_DATA subrec_value;
254 ssize_t num_watchers;
256 rec = talloc_zero(mem_ctx, struct db_record);
260 subrec = talloc_zero(rec, struct db_watched_subrec);
261 if (subrec == NULL) {
265 rec->private_data = subrec;
267 subrec->subrec = dbwrap_fetch_locked(ctx->backend, subrec, key);
268 if (subrec->subrec == NULL) {
274 rec->key = dbwrap_record_get_key(subrec->subrec);
275 rec->storev = dbwrap_watched_storev;
276 rec->delete_rec = dbwrap_watched_delete;
278 subrec_value = dbwrap_record_get_value(subrec->subrec);
280 num_watchers = dbwrap_watched_parse(subrec_value, NULL, 0, NULL, NULL);
281 if (num_watchers == -1) {
282 /* Fresh or invalid record */
283 rec->value = (TDB_DATA) { 0 };
287 subrec->watchers = talloc_array(subrec, struct server_id,
289 if (subrec->watchers == NULL) {
294 dbwrap_watched_parse(subrec_value, subrec->watchers, num_watchers,
295 &subrec->deleted, &rec->value);
300 static void dbwrap_watched_wakeup(struct db_record *rec,
301 struct db_watched_subrec *subrec)
303 struct db_context *db = dbwrap_record_get_db(rec);
304 struct db_watched_ctx *ctx = talloc_get_type_abort(
305 db->private_data, struct db_watched_ctx);
306 size_t i, num_watchers;
307 size_t db_id_len = dbwrap_db_id(db, NULL, 0);
308 uint8_t db_id[db_id_len];
312 SIVAL(len_buf, 0, db_id_len);
314 iov[0] = (struct iovec) { .iov_base = len_buf, .iov_len = 4 };
315 iov[1] = (struct iovec) { .iov_base = db_id, .iov_len = db_id_len };
316 iov[2] = (struct iovec) { .iov_base = rec->key.dptr,
317 .iov_len = rec->key.dsize };
319 dbwrap_db_id(db, db_id, db_id_len);
321 num_watchers = talloc_array_length(subrec->watchers);
325 while (i < num_watchers) {
327 struct server_id_buf tmp;
329 DBG_DEBUG("Alerting %s\n",
330 server_id_str_buf(subrec->watchers[i], &tmp));
332 status = messaging_send_iov(ctx->msg, subrec->watchers[i],
334 iov, ARRAY_SIZE(iov), NULL, 0);
335 if (!NT_STATUS_IS_OK(status)) {
336 DBG_DEBUG("messaging_send_iov to %s failed: %s\n",
337 server_id_str_buf(subrec->watchers[i], &tmp),
340 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
341 subrec->watchers[i] = subrec->watchers[num_watchers-1];
344 subrec->watchers = talloc_realloc(
345 subrec, subrec->watchers, struct server_id,
354 static NTSTATUS dbwrap_watched_save(struct db_watched_subrec *subrec,
355 TDB_DATA data, int flag)
362 num_watchers = talloc_array_length(subrec->watchers);
364 len = dbwrap_watched_unparse(subrec->watchers, num_watchers,
365 subrec->deleted, data, NULL, 0);
367 return NT_STATUS_INSUFFICIENT_RESOURCES;
370 buf = talloc_array(subrec, uint8_t, len);
372 return NT_STATUS_NO_MEMORY;
375 dbwrap_watched_unparse(subrec->watchers, num_watchers,
376 subrec->deleted, data, buf, len);
378 status = dbwrap_record_store(
379 subrec->subrec, (TDB_DATA) { .dptr = buf, .dsize = len },
387 static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
388 const TDB_DATA *dbufs, int num_dbufs,
391 struct db_watched_subrec *subrec = talloc_get_type_abort(
392 rec->private_data, struct db_watched_subrec);
396 data = dbwrap_merge_dbufs(rec, dbufs, num_dbufs);
397 if (data.dptr == NULL) {
398 return NT_STATUS_NO_MEMORY;
401 dbwrap_watched_wakeup(rec, subrec);
403 subrec->deleted = false;
405 status = dbwrap_watched_save(subrec, data, flag);
407 TALLOC_FREE(data.dptr);
412 static NTSTATUS dbwrap_watched_delete(struct db_record *rec)
414 struct db_watched_subrec *subrec = talloc_get_type_abort(
415 rec->private_data, struct db_watched_subrec);
418 dbwrap_watched_wakeup(rec, subrec);
420 num_watchers = talloc_array_length(subrec->watchers);
421 if (num_watchers == 0) {
422 return dbwrap_record_delete(subrec->subrec);
425 subrec->deleted = true;
427 return dbwrap_watched_save(subrec, (TDB_DATA) {0}, 0);
430 struct dbwrap_watched_traverse_state {
431 int (*fn)(struct db_record *rec, void *private_data);
435 static int dbwrap_watched_traverse_fn(struct db_record *rec,
438 struct dbwrap_watched_traverse_state *state = private_data;
439 ssize_t num_watchers;
440 struct db_record prec = *rec;
443 num_watchers = dbwrap_watched_parse(rec->value, NULL, 0, &deleted,
446 if ((num_watchers == -1) || deleted) {
450 return state->fn(&prec, state->private_data);
453 static int dbwrap_watched_traverse(struct db_context *db,
454 int (*fn)(struct db_record *rec,
458 struct db_watched_ctx *ctx = talloc_get_type_abort(
459 db->private_data, struct db_watched_ctx);
460 struct dbwrap_watched_traverse_state state = {
461 .fn = fn, .private_data = private_data };
465 status = dbwrap_traverse(
466 ctx->backend, dbwrap_watched_traverse_fn, &state, &ret);
467 if (!NT_STATUS_IS_OK(status)) {
473 static int dbwrap_watched_traverse_read(struct db_context *db,
474 int (*fn)(struct db_record *rec,
478 struct db_watched_ctx *ctx = talloc_get_type_abort(
479 db->private_data, struct db_watched_ctx);
480 struct dbwrap_watched_traverse_state state = {
481 .fn = fn, .private_data = private_data };
485 status = dbwrap_traverse_read(
486 ctx->backend, dbwrap_watched_traverse_fn, &state, &ret);
487 if (!NT_STATUS_IS_OK(status)) {
493 static int dbwrap_watched_get_seqnum(struct db_context *db)
495 struct db_watched_ctx *ctx = talloc_get_type_abort(
496 db->private_data, struct db_watched_ctx);
497 return dbwrap_get_seqnum(ctx->backend);
500 static int dbwrap_watched_transaction_start(struct db_context *db)
502 struct db_watched_ctx *ctx = talloc_get_type_abort(
503 db->private_data, struct db_watched_ctx);
504 return dbwrap_transaction_start(ctx->backend);
507 static int dbwrap_watched_transaction_commit(struct db_context *db)
509 struct db_watched_ctx *ctx = talloc_get_type_abort(
510 db->private_data, struct db_watched_ctx);
511 return dbwrap_transaction_commit(ctx->backend);
514 static int dbwrap_watched_transaction_cancel(struct db_context *db)
516 struct db_watched_ctx *ctx = talloc_get_type_abort(
517 db->private_data, struct db_watched_ctx);
518 return dbwrap_transaction_cancel(ctx->backend);
521 struct dbwrap_watched_parse_record_state {
522 void (*parser)(TDB_DATA key, TDB_DATA data, void *private_data);
527 static void dbwrap_watched_parse_record_parser(TDB_DATA key, TDB_DATA data,
530 struct dbwrap_watched_parse_record_state *state = private_data;
531 ssize_t num_watchers;
534 num_watchers = dbwrap_watched_parse(data, NULL, 0, &state->deleted,
536 if (num_watchers == -1) {
537 state->deleted = true;
539 if (state->deleted) {
542 state->parser(key, userdata, state->private_data);
545 static NTSTATUS dbwrap_watched_parse_record(
546 struct db_context *db, TDB_DATA key,
547 void (*parser)(TDB_DATA key, TDB_DATA data, void *private_data),
550 struct db_watched_ctx *ctx = talloc_get_type_abort(
551 db->private_data, struct db_watched_ctx);
552 struct dbwrap_watched_parse_record_state state = {
554 .private_data = private_data,
559 status = dbwrap_parse_record(
560 ctx->backend, key, dbwrap_watched_parse_record_parser, &state);
561 if (!NT_STATUS_IS_OK(status)) {
565 return NT_STATUS_NOT_FOUND;
570 static void dbwrap_watched_parse_record_done(struct tevent_req *subreq);
572 static struct tevent_req *dbwrap_watched_parse_record_send(
574 struct tevent_context *ev,
575 struct db_context *db,
577 void (*parser)(TDB_DATA key, TDB_DATA data, void *private_data),
579 enum dbwrap_req_state *req_state)
581 struct db_watched_ctx *ctx = talloc_get_type_abort(
582 db->private_data, struct db_watched_ctx);
583 struct tevent_req *req = NULL;
584 struct tevent_req *subreq = NULL;
585 struct dbwrap_watched_parse_record_state *state = NULL;
587 req = tevent_req_create(mem_ctx, &state,
588 struct dbwrap_watched_parse_record_state);
590 *req_state = DBWRAP_REQ_ERROR;
594 *state = (struct dbwrap_watched_parse_record_state) {
596 .private_data = private_data,
600 subreq = dbwrap_parse_record_send(state,
604 dbwrap_watched_parse_record_parser,
607 if (tevent_req_nomem(subreq, req)) {
608 *req_state = DBWRAP_REQ_ERROR;
609 return tevent_req_post(req, ev);
612 tevent_req_set_callback(subreq, dbwrap_watched_parse_record_done, req);
616 static void dbwrap_watched_parse_record_done(struct tevent_req *subreq)
618 struct tevent_req *req = tevent_req_callback_data(
619 subreq, struct tevent_req);
620 struct dbwrap_watched_parse_record_state *state = tevent_req_data(
621 req, struct dbwrap_watched_parse_record_state);
624 status = dbwrap_parse_record_recv(subreq);
626 if (tevent_req_nterror(req, status)) {
630 if (state->deleted) {
631 tevent_req_nterror(req, NT_STATUS_NOT_FOUND);
635 tevent_req_done(req);
639 static NTSTATUS dbwrap_watched_parse_record_recv(struct tevent_req *req)
643 if (tevent_req_is_nterror(req, &status)) {
644 tevent_req_received(req);
648 tevent_req_received(req);
652 static int dbwrap_watched_exists(struct db_context *db, TDB_DATA key)
654 struct db_watched_ctx *ctx = talloc_get_type_abort(
655 db->private_data, struct db_watched_ctx);
657 return dbwrap_exists(ctx->backend, key);
660 static size_t dbwrap_watched_id(struct db_context *db, uint8_t *id,
663 struct db_watched_ctx *ctx = talloc_get_type_abort(
664 db->private_data, struct db_watched_ctx);
666 return dbwrap_db_id(ctx->backend, id, idlen);
669 struct db_context *db_open_watched(TALLOC_CTX *mem_ctx,
670 struct db_context *backend,
671 struct messaging_context *msg)
673 struct db_context *db;
674 struct db_watched_ctx *ctx;
676 db = talloc_zero(mem_ctx, struct db_context);
680 ctx = talloc_zero(db, struct db_watched_ctx);
685 db->private_data = ctx;
689 db->lock_order = backend->lock_order;
690 backend->lock_order = DBWRAP_LOCK_ORDER_NONE;
691 ctx->backend = talloc_move(ctx, &backend);
693 db->fetch_locked = dbwrap_watched_fetch_locked;
694 db->traverse = dbwrap_watched_traverse;
695 db->traverse_read = dbwrap_watched_traverse_read;
696 db->get_seqnum = dbwrap_watched_get_seqnum;
697 db->transaction_start = dbwrap_watched_transaction_start;
698 db->transaction_commit = dbwrap_watched_transaction_commit;
699 db->transaction_cancel = dbwrap_watched_transaction_cancel;
700 db->parse_record = dbwrap_watched_parse_record;
701 db->parse_record_send = dbwrap_watched_parse_record_send;
702 db->parse_record_recv = dbwrap_watched_parse_record_recv;
703 db->exists = dbwrap_watched_exists;
704 db->id = dbwrap_watched_id;
705 db->name = dbwrap_name(ctx->backend);
710 struct dbwrap_watched_watch_state {
711 struct db_context *db;
714 struct server_id blocker;
718 static bool dbwrap_watched_msg_filter(struct messaging_rec *rec,
720 static void dbwrap_watched_watch_done(struct tevent_req *subreq);
721 static void dbwrap_watched_watch_blocker_died(struct tevent_req *subreq);
722 static int dbwrap_watched_watch_state_destructor(
723 struct dbwrap_watched_watch_state *state);
725 struct tevent_req *dbwrap_watched_watch_send(TALLOC_CTX *mem_ctx,
726 struct tevent_context *ev,
727 struct db_record *rec,
728 struct server_id blocker)
730 struct db_watched_subrec *subrec = talloc_get_type_abort(
731 rec->private_data, struct db_watched_subrec);
732 struct db_context *db = dbwrap_record_get_db(rec);
733 struct db_watched_ctx *ctx = talloc_get_type_abort(
734 db->private_data, struct db_watched_ctx);
736 struct tevent_req *req, *subreq;
737 struct dbwrap_watched_watch_state *state;
740 struct server_id *tmp;
743 req = tevent_req_create(mem_ctx, &state,
744 struct dbwrap_watched_watch_state);
749 state->blocker = blocker;
751 if (ctx->msg == NULL) {
752 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
753 return tevent_req_post(req, ev);
756 state->me = messaging_server_id(ctx->msg);
758 needed = dbwrap_record_watchers_key(db, rec, NULL, 0);
760 tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
761 return tevent_req_post(req, ev);
763 state->w_key.dsize = needed;
765 state->w_key.dptr = talloc_array(state, uint8_t, state->w_key.dsize);
766 if (tevent_req_nomem(state->w_key.dptr, req)) {
767 return tevent_req_post(req, ev);
769 dbwrap_record_watchers_key(db, rec, state->w_key.dptr,
772 subreq = messaging_filtered_read_send(
773 state, ev, ctx->msg, dbwrap_watched_msg_filter, state);
774 if (tevent_req_nomem(subreq, req)) {
775 return tevent_req_post(req, ev);
777 tevent_req_set_callback(subreq, dbwrap_watched_watch_done, req);
779 num_watchers = talloc_array_length(subrec->watchers);
781 tmp = talloc_realloc(subrec, subrec->watchers, struct server_id,
783 if (tevent_req_nomem(tmp, req)) {
784 return tevent_req_post(req, ev);
786 subrec->watchers = tmp;
787 subrec->watchers[num_watchers] = state->me;
789 status = dbwrap_watched_save(subrec, rec->value, 0);
790 if (tevent_req_nterror(req, status)) {
791 return tevent_req_post(req, ev);
794 talloc_set_destructor(state, dbwrap_watched_watch_state_destructor);
796 if (blocker.pid != 0) {
797 subreq = server_id_watch_send(state, ev, ctx->msg, blocker);
798 if (tevent_req_nomem(subreq, req)) {
799 return tevent_req_post(req, ev);
801 tevent_req_set_callback(
802 subreq, dbwrap_watched_watch_blocker_died, req);
808 static void dbwrap_watched_watch_blocker_died(struct tevent_req *subreq)
810 struct tevent_req *req = tevent_req_callback_data(
811 subreq, struct tevent_req);
812 struct dbwrap_watched_watch_state *state = tevent_req_data(
813 req, struct dbwrap_watched_watch_state);
816 ret = server_id_watch_recv(subreq, NULL);
819 tevent_req_nterror(req, map_nt_error_from_unix(ret));
822 state->blockerdead = true;
823 tevent_req_done(req);
826 static bool dbwrap_watched_remove_waiter(struct db_watched_subrec *subrec,
829 size_t i, num_watchers;
831 num_watchers = talloc_array_length(subrec->watchers);
833 for (i=0; i<num_watchers; i++) {
834 if (server_id_equal(&id, &subrec->watchers[i])) {
839 if (i == num_watchers) {
840 struct server_id_buf buf;
841 DBG_WARNING("Did not find %s in state->watchers\n",
842 server_id_str_buf(id, &buf));
846 subrec->watchers[i] = subrec->watchers[num_watchers-1];
847 subrec->watchers = talloc_realloc(subrec, subrec->watchers,
848 struct server_id, num_watchers-1);
853 static int dbwrap_watched_watch_state_destructor(
854 struct dbwrap_watched_watch_state *state)
856 struct db_record *rec;
857 struct db_watched_subrec *subrec;
861 ok = dbwrap_record_watchers_key_parse(state->w_key, NULL, NULL, &key);
863 DBG_WARNING("dbwrap_record_watchers_key_parse failed\n");
867 rec = dbwrap_fetch_locked(state->db, state, key);
869 DBG_WARNING("dbwrap_fetch_locked failed\n");
873 subrec = talloc_get_type_abort(
874 rec->private_data, struct db_watched_subrec);
876 ok = dbwrap_watched_remove_waiter(subrec, state->me);
879 status = dbwrap_watched_save(subrec, rec->value, 0);
880 if (!NT_STATUS_IS_OK(status)) {
881 DBG_WARNING("dbwrap_watched_save failed: %s\n",
890 static bool dbwrap_watched_msg_filter(struct messaging_rec *rec,
893 struct dbwrap_watched_watch_state *state = talloc_get_type_abort(
894 private_data, struct dbwrap_watched_watch_state);
897 if (rec->msg_type != MSG_DBWRAP_MODIFIED) {
900 if (rec->num_fds != 0) {
903 if (rec->buf.length != state->w_key.dsize) {
907 cmp = memcmp(rec->buf.data, state->w_key.dptr, rec->buf.length);
912 static void dbwrap_watched_watch_done(struct tevent_req *subreq)
914 struct tevent_req *req = tevent_req_callback_data(
915 subreq, struct tevent_req);
916 struct messaging_rec *rec;
919 ret = messaging_filtered_read_recv(subreq, talloc_tos(), &rec);
922 tevent_req_nterror(req, map_nt_error_from_unix(ret));
925 tevent_req_done(req);
928 NTSTATUS dbwrap_watched_watch_recv(struct tevent_req *req,
930 struct db_record **prec,
932 struct server_id *blocker)
934 struct dbwrap_watched_watch_state *state = tevent_req_data(
935 req, struct dbwrap_watched_watch_state);
936 struct db_watched_subrec *subrec;
939 struct db_record *rec;
942 if (tevent_req_is_nterror(req, &status)) {
945 if (blockerdead != NULL) {
946 *blockerdead = state->blockerdead;
948 if (blocker != NULL) {
949 *blocker = state->blocker;
955 ok = dbwrap_record_watchers_key_parse(state->w_key, NULL, NULL, &key);
957 return NT_STATUS_INTERNAL_DB_ERROR;
960 rec = dbwrap_fetch_locked(state->db, mem_ctx, key);
962 return NT_STATUS_INTERNAL_DB_ERROR;
965 talloc_set_destructor(state, NULL);
967 subrec = talloc_get_type_abort(
968 rec->private_data, struct db_watched_subrec);
970 ok = dbwrap_watched_remove_waiter(subrec, state->me);
972 status = dbwrap_watched_save(subrec, rec->value, 0);
973 if (!NT_STATUS_IS_OK(status)) {
974 DBG_WARNING("dbwrap_watched_save failed: %s\n",