From c7196d16e8e03bb2a64be164d15a7502300eae0e Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Wed, 20 Jul 2011 11:27:05 +1000 Subject: [PATCH] ReadOnly records: Add a new RPC function FETCH_WITH_HEADER. This function differs from the old FETCH in that this function will also fetch the record header and not just the record data --- client/ctdb_client.c | 23 +++++++++++++++++++++++ include/ctdb_protocol.h | 6 ++++-- server/ctdb_ltdb_server.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/client/ctdb_client.c b/client/ctdb_client.c index 55c32735..d5c2f559 100644 --- a/client/ctdb_client.c +++ b/client/ctdb_client.c @@ -89,6 +89,7 @@ int ctdb_call_local(struct ctdb_db_context *ctdb_db, struct ctdb_call *call, c->new_data = NULL; c->reply_data = NULL; c->status = 0; + c->header = header; for (fn=ctdb_db->calls;fn;fn=fn->next) { if (fn->id == call->call_id) break; @@ -1693,6 +1694,27 @@ static int ctdb_fetch_func(struct ctdb_call_info *call) return 0; } +/* + this is a plain fetch procedure that all databases support + this returns the full record including the ltdb header +*/ +static int ctdb_fetch_with_header_func(struct ctdb_call_info *call) +{ + call->reply_data = talloc(call, TDB_DATA); + if (call->reply_data == NULL) { + return -1; + } + call->reply_data->dsize = sizeof(struct ctdb_ltdb_header) + call->record_data.dsize; + call->reply_data->dptr = talloc_size(call->reply_data, call->reply_data->dsize); + if (call->reply_data->dptr == NULL) { + return -1; + } + memcpy(call->reply_data->dptr, call->header, sizeof(struct ctdb_ltdb_header)); + memcpy(&call->reply_data->dptr[sizeof(struct ctdb_ltdb_header)], call->record_data.dptr, call->record_data.dsize); + + return 0; +} + /* attach to a specific database - client call */ @@ -1758,6 +1780,7 @@ struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb, const char *name, /* add well known functions */ ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC); ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC); + ctdb_set_call(ctdb_db, ctdb_fetch_with_header_func, CTDB_FETCH_WITH_HEADER_FUNC); return ctdb_db; } diff --git a/include/ctdb_protocol.h b/include/ctdb_protocol.h index 0422afeb..b805182b 100644 --- a/include/ctdb_protocol.h +++ b/include/ctdb_protocol.h @@ -30,8 +30,9 @@ #define CTDB_DS_ALIGNMENT 8 -#define CTDB_NULL_FUNC 0xFF000001 -#define CTDB_FETCH_FUNC 0xFF000002 +#define CTDB_NULL_FUNC 0xFF000001 +#define CTDB_FETCH_FUNC 0xFF000002 +#define CTDB_FETCH_WITH_HEADER_FUNC 0xFF000003 struct ctdb_call { @@ -50,6 +51,7 @@ struct ctdb_call { */ struct ctdb_call_info { TDB_DATA key; /* record key */ + struct ctdb_ltdb_header *header; TDB_DATA record_data; /* current data in the record */ TDB_DATA *new_data; /* optionally updated record data */ TDB_DATA *call_data; /* optionally passed from caller */ diff --git a/server/ctdb_ltdb_server.c b/server/ctdb_ltdb_server.c index a93e2fa0..f04b7de4 100644 --- a/server/ctdb_ltdb_server.c +++ b/server/ctdb_ltdb_server.c @@ -49,6 +49,27 @@ static int ctdb_fetch_func(struct ctdb_call_info *call) return 0; } +/* + this is a plain fetch procedure that all databases support + this returns the full record including the ltdb header +*/ +static int ctdb_fetch_with_header_func(struct ctdb_call_info *call) +{ + call->reply_data = talloc(call, TDB_DATA); + if (call->reply_data == NULL) { + return -1; + } + call->reply_data->dsize = sizeof(struct ctdb_ltdb_header) + call->record_data.dsize; + call->reply_data->dptr = talloc_size(call->reply_data, call->reply_data->dsize); + if (call->reply_data->dptr == NULL) { + return -1; + } + memcpy(call->reply_data->dptr, call->header, sizeof(struct ctdb_ltdb_header)); + memcpy(&call->reply_data->dptr[sizeof(struct ctdb_ltdb_header)], call->record_data.dptr, call->record_data.dsize); + + return 0; +} + /** * write a record to a normal database @@ -932,6 +953,17 @@ again: return -1; } + /* + all databases support the "fetch_with_header" function. we need this + for efficient readonly record fetches + */ + ret = ctdb_daemon_set_call(ctdb, ctdb_db->db_id, ctdb_fetch_with_header_func, CTDB_FETCH_WITH_HEADER_FUNC); + if (ret != 0) { + DEBUG(DEBUG_CRIT,("Failed to setup fetch function for '%s'\n", ctdb_db->db_name)); + talloc_free(ctdb_db); + return -1; + } + ret = ctdb_vacuum_init(ctdb_db); if (ret != 0) { DEBUG(DEBUG_CRIT,("Failed to setup vacuuming for " -- 2.34.1