From: Ronnie Sahlberg Date: Sat, 28 Apr 2007 19:47:13 +0000 (+1000) Subject: add a control to read an entire tdb from a node including X-Git-Tag: tevent-0.9.20~348^2~2800^2~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=097037a05562f828480603fe4d3010b0e4d6bcf7;p=thirdparty%2Fsamba.git add a control to read an entire tdb from a node including key/lmaster/header and data (This used to be ctdb commit ac00d6271ba6356c1edf804df44d0d2600791610) --- diff --git a/ctdb/common/ctdb_client.c b/ctdb/common/ctdb_client.c index 415d38b0fce..178624bce22 100644 --- a/ctdb/common/ctdb_client.c +++ b/ctdb/common/ctdb_client.c @@ -896,6 +896,68 @@ int ctdb_setvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn return 0; } +/* + get all keys for a specific database + */ +int ctdb_getkeys(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx, struct ctdb_key_list *keys) +{ + int i, ret; + TDB_DATA indata, outdata; + int32_t res; + unsigned char *ptr; + + indata.dsize = sizeof(uint32_t); + indata.dptr = (unsigned char *)&dbid; + + ret = ctdb_control(ctdb, destnode, 0, + CTDB_CONTROL_GET_KEYS, indata, + mem_ctx, &outdata, &res); + if (ret != 0 || res != 0) { + DEBUG(0,(__location__ " ctdb_control for getkeys failed\n")); + return -1; + } + + + keys->num= *((uint32_t *)(&outdata.dptr[0])); + keys->keys=talloc_array(mem_ctx, TDB_DATA, keys->num); + keys->headers=talloc_array(mem_ctx, struct ctdb_ltdb_header, keys->num); + keys->lmasters=talloc_array(mem_ctx, uint32_t, keys->num); + keys->data=talloc_array(mem_ctx, TDB_DATA, keys->num); + + /* loop over all key/data pairs */ + ptr=&outdata.dptr[4]; + for(i=0;inum;i++){ + uint32_t len; + TDB_DATA *key, *data; + + keys->lmasters[i]= *((uint32_t *)ptr); + ptr+=4; + + key=&keys->keys[i]; + key->dsize= *((uint32_t *)ptr); + ptr+=4; + key->dptr=talloc_size(mem_ctx, key->dsize); + memcpy(key->dptr, ptr, key->dsize); + len = (key->dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1); + ptr+=len; + + memcpy(&keys->headers[i], ptr, sizeof(struct ctdb_ltdb_header)); + len = (sizeof(struct ctdb_ltdb_header)+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1); + ptr+=len; + + data=&keys->data[i]; + data->dsize= *((uint32_t *)ptr); + ptr+=4; + data->dptr=talloc_size(mem_ctx, data->dsize); + memcpy(data->dptr, ptr, data->dsize); + len = (data->dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1); + ptr+=len; + + } + + return 0; +} + /* ping a node */ diff --git a/ctdb/common/ctdb_control.c b/ctdb/common/ctdb_control.c index 83bac958e06..7141d20ae8c 100644 --- a/ctdb/common/ctdb_control.c +++ b/ctdb/common/ctdb_control.c @@ -25,6 +25,7 @@ #include "system/wait.h" #include "../include/ctdb_private.h" #include "lib/util/dlinklist.h" +#include "db_wrap.h" struct ctdb_control_state { struct ctdb_context *ctdb; @@ -41,6 +42,56 @@ struct ctdb_control_state { } \ } while (0) + +struct getkeys_params { + struct ctdb_db_context *ctdb_db; + TDB_DATA *outdata; +}; + +static int traverse_getkeys(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p) +{ + struct getkeys_params *params = (struct getkeys_params *)p; + TDB_DATA *outdata = talloc_get_type(params->outdata, TDB_DATA); + struct ctdb_db_context *ctdb_db = talloc_get_type(params->ctdb_db, struct ctdb_db_context); + unsigned char *ptr; + int len, ret; + + len=outdata->dsize; + len+=4; /*lmaster*/ + len+=4; /*key len*/ + len+=key.dsize; + len=(len+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1); + len+=sizeof(struct ctdb_ltdb_header); + len=(len+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1); + len+=4; /*data len */ + len+=data.dsize; + len=(len+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1); + + ptr=outdata->dptr=talloc_realloc_size(outdata, outdata->dptr, len); + ptr+=outdata->dsize; + outdata->dsize=len; + /* number of records is stored as the first 4 bytes */ + (*((uint32_t *)(&outdata->dptr[0])))++; + + *((uint32_t *)ptr)=ctdb_lmaster(ctdb_db->ctdb, &key); + ptr+=4; + + *((uint32_t *)ptr)=key.dsize; + ptr+=4; + memcpy(ptr, key.dptr, key.dsize); + ptr+= (key.dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1); + + memcpy(ptr, data.dptr, sizeof(struct ctdb_ltdb_header)); + ptr+=(sizeof(struct ctdb_ltdb_header)+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1); + + *((uint32_t *)ptr)=data.dsize-sizeof(struct ctdb_ltdb_header); + ptr+=4; + memcpy(ptr, data.dptr+sizeof(struct ctdb_ltdb_header), data.dsize-sizeof(struct ctdb_ltdb_header)); + ptr+= (data.dsize-sizeof(struct ctdb_ltdb_header)+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1); + + return 0; +} + /* process a control request */ @@ -167,6 +218,38 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, return 0; } + case CTDB_CONTROL_GET_KEYS: { + uint32_t dbid; + struct ctdb_db_context *ctdb_db; + struct tdb_wrap *db; + struct getkeys_params params; + + dbid = *((uint32_t *)(&indata.dptr[0])); + ctdb_db = find_ctdb_db(ctdb, dbid); + if (!ctdb_db) { + DEBUG(0,(__location__ " Unknown db\n")); + return -1; + } + + outdata->dsize = sizeof(uint32_t); + outdata->dptr = (unsigned char *)talloc_array(outdata, uint32_t, 1); + *((uint32_t *)(&outdata->dptr[0]))=0; + + db = tdb_wrap_open(NULL, ctdb_db->db_path, 0, TDB_DEFAULT, O_RDONLY, 0); + if (db == NULL) { + DEBUG(0,(__location__ " failed to open db\n")); + return -1; + } + + params.ctdb_db = ctdb_db; + params.outdata = outdata; + tdb_traverse(db->tdb, traverse_getkeys, ¶ms); + + talloc_free(db); + + return 0; + } + case CTDB_CONTROL_CONFIG: { CHECK_CONTROL_DATA_SIZE(0); outdata->dptr = (uint8_t *)ctdb; diff --git a/ctdb/include/ctdb.h b/ctdb/include/ctdb.h index 7dba352a46f..3e666de06bb 100644 --- a/ctdb/include/ctdb.h +++ b/ctdb/include/ctdb.h @@ -241,6 +241,15 @@ struct ctdb_node_map { }; int ctdb_getnodemap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_node_map *nodemap); +struct ctdb_key_list { + uint32_t num; + TDB_DATA *keys; + struct ctdb_ltdb_header *headers; + uint32_t *lmasters; + TDB_DATA *data; +}; +int ctdb_getkeys(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx, struct ctdb_key_list *keys); + int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t dbid, TALLOC_CTX *mem_ctx, const char **path); int ctdb_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid); diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index dbbce30a447..7c6fa8ee238 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -254,7 +254,8 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS, CTDB_CONTROL_GET_DEBUG, CTDB_CONTROL_SET_DEBUG, CTDB_CONTROL_GET_DBMAP, - CTDB_CONTROL_GET_NODEMAP}; + CTDB_CONTROL_GET_NODEMAP, + CTDB_CONTROL_GET_KEYS}; enum call_state {CTDB_CALL_WAIT, CTDB_CALL_DONE, CTDB_CALL_ERROR}; diff --git a/ctdb/tests/ctdb_fetch.c b/ctdb/tests/ctdb_fetch.c index 2af25ed2c18..3d5ace27e95 100644 --- a/ctdb/tests/ctdb_fetch.c +++ b/ctdb/tests/ctdb_fetch.c @@ -247,6 +247,10 @@ int main(int argc, const char *argv[]) printf("DATA:\n%s\n", (char *)call.reply_data.dptr); +#if 1 +/* to keep the cluster up so one can play with it using the controls */ +sleep(9999999); +#endif /* go into a wait loop to allow other nodes to complete */ ctdb_shutdown(ctdb); diff --git a/ctdb/tools/ctdb_control.c b/ctdb/tools/ctdb_control.c index 3a8bb777e90..35cd6ea96f3 100644 --- a/ctdb/tools/ctdb_control.c +++ b/ctdb/tools/ctdb_control.c @@ -42,6 +42,7 @@ static void usage(void) printf(" setvnnmap *\n"); printf(" getdbmap lists databases on a node\n"); printf(" getnodemap lists nodes known to a ctdb daemon\n"); + printf(" getkeys lists all keys in a remote tdb\n"); exit(1); } @@ -156,6 +157,47 @@ static int control_getvnnmap(struct ctdb_context *ctdb, int argc, const char **a return 0; } +/* + display remote list of keys for a tdb + */ +static int control_getkeys(struct ctdb_context *ctdb, int argc, const char **argv) +{ + uint32_t vnn, dbid; + int i, j, ret; + struct ctdb_key_list keys; + TALLOC_CTX *mem_ctx; + + if (argc < 2) { + usage(); + } + + vnn = strtoul(argv[0], NULL, 0); + dbid = strtoul(argv[1], NULL, 0); + + mem_ctx = talloc_new(ctdb); + ret = ctdb_getkeys(ctdb, vnn, dbid, mem_ctx, &keys); + if (ret != 0) { + printf("Unable to get keys from node %u\n", vnn); + return ret; + } + printf("Number of keys:%d\n",keys.num); + for(i=0;i