diff options
-rw-r--r-- | source3/include/ctdbd_conn.h | 5 | ||||
-rw-r--r-- | source3/lib/ctdbd_conn.c | 71 |
2 files changed, 76 insertions, 0 deletions
diff --git a/source3/include/ctdbd_conn.h b/source3/include/ctdbd_conn.h index 5778a9291d..295d41e6b6 100644 --- a/source3/include/ctdbd_conn.h +++ b/source3/include/ctdbd_conn.h @@ -65,6 +65,11 @@ NTSTATUS ctdbd_migrate(struct ctdbd_connection *conn, uint32_t db_id, NTSTATUS ctdbd_fetch(struct ctdbd_connection *conn, uint32_t db_id, TDB_DATA key, TALLOC_CTX *mem_ctx, TDB_DATA *data, bool local_copy); +NTSTATUS ctdbd_parse(struct ctdbd_connection *conn, uint32_t db_id, + TDB_DATA key, bool local_copy, + void (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data); NTSTATUS ctdbd_traverse(uint32_t db_id, void (*fn)(TDB_DATA key, TDB_DATA data, diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index 2cf5e472b0..d77b03dc0a 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -1494,6 +1494,77 @@ NTSTATUS ctdbd_fetch(struct ctdbd_connection *conn, uint32_t db_id, return status; } +/* + * Fetch a record and parse it + */ +NTSTATUS ctdbd_parse(struct ctdbd_connection *conn, uint32_t db_id, + TDB_DATA key, bool local_copy, + void (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data) +{ + struct ctdb_req_call req; + struct ctdb_reply_call *reply; + NTSTATUS status; + uint32_t flags; + +#ifdef HAVE_CTDB_WANT_READONLY_DECL + flags = local_copy ? CTDB_WANT_READONLY : 0; +#else + flags = 0; +#endif + + ZERO_STRUCT(req); + + req.hdr.length = offsetof(struct ctdb_req_call, data) + key.dsize; + req.hdr.ctdb_magic = CTDB_MAGIC; + req.hdr.ctdb_version = CTDB_VERSION; + req.hdr.operation = CTDB_REQ_CALL; + req.hdr.reqid = ctdbd_next_reqid(conn); + req.flags = flags; + req.callid = CTDB_FETCH_FUNC; + req.db_id = db_id; + req.keylen = key.dsize; + + status = ctdb_packet_send( + conn->pkt, 2, + data_blob_const(&req, offsetof(struct ctdb_req_call, data)), + data_blob_const(key.dptr, key.dsize)); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("ctdb_packet_send failed: %s\n", nt_errstr(status))); + return status; + } + + status = ctdb_packet_flush(conn->pkt); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("write to ctdbd failed: %s\n", nt_errstr(status))); + cluster_fatal("cluster dispatch daemon control write error\n"); + } + + status = ctdb_read_req(conn, req.hdr.reqid, NULL, (void *)&reply); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("ctdb_read_req failed: %s\n", nt_errstr(status))); + goto fail; + } + + if (reply->hdr.operation != CTDB_REPLY_CALL) { + DEBUG(0, ("received invalid reply\n")); + status = NT_STATUS_INTERNAL_ERROR; + goto fail; + } + + parser(key, make_tdb_data(&reply->data[0], reply->datalen), + private_data); + + status = NT_STATUS_OK; + fail: + TALLOC_FREE(reply); + return status; +} + struct ctdbd_traverse_state { void (*fn)(TDB_DATA key, TDB_DATA data, void *private_data); void *private_data; |