return 0;
}
- CTDB_CONTROL_GET_RECMODE, data,
+/*
+ get the recovery mode of a remote node
+ */
+int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *recmode)
+{
+ int ret;
+ TDB_DATA data, outdata;
+ int32_t res;
+
+ ZERO_STRUCT(data);
+ ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_SET_RECMODE, data,
++ CTDB_CONTROL_GET_RECMODE, 0, data,
+ ctdb, &outdata, &res);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for getrecmode failed\n"));
+ return -1;
+ }
+
+ *recmode = ((uint32_t *)outdata.dptr)[0];
+
+ return 0;
+}
+
+/*
+ set the recovery mode of a remote node
+ */
+int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t recmode)
+{
+ int ret;
+ TDB_DATA data, outdata;
+ int32_t res;
+
+ ZERO_STRUCT(data);
+ data.dsize = sizeof(uint32_t);
+ data.dptr = (unsigned char *)&recmode;
+
+ ret = ctdb_control(ctdb, destnode, 0,
++ CTDB_CONTROL_SET_RECMODE, 0, data,
+ ctdb, &outdata, &res);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for getrecmode failed\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
/*
get a list of databases off a remote node
*/
return 0;
}
- CTDB_CONTROL_PULL_DB, indata,
+/*
+ get all keys and records for a specific database
+ */
+int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx, struct ctdb_key_list *keys)
+{
+ int i, ret;
+ TDB_DATA indata, outdata;
+ int32_t res;
+ unsigned char *ptr;
+
+ indata.dsize = 2*sizeof(uint32_t);
+ indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
+
+ ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
+ ((uint32_t *)(&indata.dptr[0]))[1] = lmaster;
+
+ ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_PULL_DB, indata,
++ CTDB_CONTROL_PULL_DB, 0, indata,
+ mem_ctx, &outdata, &res);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for pulldb failed\n"));
+ return -1;
+ }
+
+
+ keys->dbid = ((uint32_t *)(&outdata.dptr[0]))[0];
+ keys->num = ((uint32_t *)(&outdata.dptr[0]))[1];
+ 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[8];
+ for(i=0;i<keys->num;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;
+}
+
+/*
+ copy a tdb from one node to another node
+ */
+int ctdb_ctrl_copydb(struct ctdb_context *ctdb, uint32_t sourcenode, uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx)
+{
+ int ret;
+ TDB_DATA indata, outdata;
+ int32_t res;
+
+ indata.dsize = 2*sizeof(uint32_t);
+ indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
+
+ ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
+ ((uint32_t *)(&indata.dptr[0]))[1] = lmaster;
+
+ ret = ctdb_control(ctdb, sourcenode, 0,
- CTDB_CONTROL_SET_DMASTER, indata,
++ CTDB_CONTROL_PULL_DB, 0, indata,
+ mem_ctx, &outdata, &res);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for pulldb failed\n"));
+ return -1;
+ }
+
+ ret = ctdb_control(ctdb, destnode, 0,
+ CTDB_CONTROL_PUSH_DB, outdata,
+ mem_ctx, NULL, &res);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for pushdb failed\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ change dmaster for all keys in the database to the new value
+ */
+int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
+{
+ int ret;
+ TDB_DATA indata, outdata;
+ int32_t res;
+
+ indata.dsize = 2*sizeof(uint32_t);
+ indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
+
+ ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
+ ((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
+
+ ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_CLEAR_DB, indata,
++ CTDB_CONTROL_SET_DMASTER, 0, indata,
+ mem_ctx, &outdata, &res);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for setdmaster failed\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ delete all records from a tdb
+ */
+int ctdb_ctrl_cleardb(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid)
+{
+ int ret;
+ TDB_DATA indata, outdata;
+ int32_t res;
+
+ indata.dsize = sizeof(uint32_t);
+ indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 1);
+
+ ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
+
+ ret = ctdb_control(ctdb, destnode, 0,
++ CTDB_CONTROL_CLEAR_DB, 0, indata,
+ mem_ctx, &outdata, &res);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for cleardb failed\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
/*
ping a node, return number of clients connected
*/
} \
} while (0)
-
+static int traverse_cleardb(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p)
+{
+ int ret;
+
+
+ ret = tdb_delete(tdb, key);
+ if (ret) {
+ DEBUG(0,(__location__ "failed to delete tdb record\n"));
+ return ret;
+ }
+ return 0;
+}
+
+static int traverse_setdmaster(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p)
+{
+ uint32_t *dmaster = (uint32_t *)p;
+ struct ctdb_ltdb_header *header = (struct ctdb_ltdb_header *)data.dptr;
+ int ret;
+
+ header->dmaster = *dmaster;
+
+ ret = tdb_store(tdb, key, data, TDB_REPLACE);
+ if (ret) {
+ DEBUG(0,(__location__ "failed to write tdb data back ret:%d\n",ret));
+ return ret;
+ }
+ return 0;
+}
+
+struct getkeys_params {
+ struct ctdb_db_context *ctdb_db;
+ TDB_DATA *outdata;
+ uint32_t lmaster;
+};
+
+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;
+ uint32_t lmaster;
+
+ lmaster = ctdb_lmaster(ctdb_db->ctdb, &key);
+
+ /* only include this record if the lmaster matches or if
+ the wildcard lmaster (-1) was specified.
+ */
+ if((lmaster!=CTDB_LMASTER_ANY)
+ && (lmaster!=params->lmaster) ){
+ return 0;
+ }
+
+ 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 second 4 bytes */
+ ((uint32_t *)(&outdata->dptr[0]))[1]++;
+
+ *((uint32_t *)ptr)=lmaster;
+ 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