summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/ctdbd_conn.h5
-rw-r--r--source3/lib/ctdbd_conn.c71
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;