TDB_DATA data;
int32_t res;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_STATUS, 0, data,
+ CTDB_CONTROL_STATUS, 0, tdb_null,
ctdb, &data, &res, NULL, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for status failed\n"));
int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
{
int ret;
- TDB_DATA data;
int32_t res;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_SHUTDOWN, CTDB_CTRL_FLAG_NOREPLY, data,
- ctdb, &data, &res, &timeout, NULL);
+ CTDB_CONTROL_SHUTDOWN, CTDB_CTRL_FLAG_NOREPLY, tdb_null,
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0) {
DEBUG(0,(__location__ " ctdb_control for shutdown failed\n"));
return -1;
int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
{
int ret;
- TDB_DATA data, outdata;
+ TDB_DATA outdata;
int32_t res;
struct ctdb_vnn_map_wire *map;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_GETVNNMAP, 0, data,
+ CTDB_CONTROL_GETVNNMAP, 0, tdb_null,
mem_ctx, &outdata, &res, &timeout, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for getvnnmap failed\n"));
CTDB_NO_MEMORY(ctdb, (*vnnmap)->map);
memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size);
+ talloc_free(outdata.dptr);
return 0;
}
int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, struct timeval timeout, 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_GET_RECMODE, 0, data,
- ctdb, &outdata, &res, &timeout, NULL);
+ CTDB_CONTROL_GET_RECMODE, 0, tdb_null,
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0) {
DEBUG(0,(__location__ " ctdb_control for getrecmode failed\n"));
return -1;
int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode)
{
int ret;
- TDB_DATA data, outdata;
+ TDB_DATA data;
int32_t res;
data.dsize = sizeof(uint32_t);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_SET_RECMODE, 0, data,
- ctdb, &outdata, &res, &timeout, NULL);
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for setrecmode failed\n"));
return -1;
int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *recmaster)
{
int ret;
- TDB_DATA data, outdata;
int32_t res;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_GET_RECMASTER, 0, data,
- ctdb, &outdata, &res, &timeout, NULL);
+ CTDB_CONTROL_GET_RECMASTER, 0, tdb_null,
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0) {
DEBUG(0,(__location__ " ctdb_control for getrecmaster failed\n"));
return -1;
int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster)
{
int ret;
- TDB_DATA data, outdata;
+ TDB_DATA data;
int32_t res;
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_SET_RECMASTER, 0, data,
- ctdb, &outdata, &res, &timeout, NULL);
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for setrecmaster failed\n"));
return -1;
/*
get a list of databases off a remote node
*/
-int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_dbid_map **dbmap)
+int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
+ TALLOC_CTX *mem_ctx, struct ctdb_dbid_map **dbmap)
{
int ret;
- TDB_DATA data, outdata;
+ TDB_DATA outdata;
int32_t res;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_GET_DBMAP, 0, data,
+ CTDB_CONTROL_GET_DBMAP, 0, tdb_null,
mem_ctx, &outdata, &res, &timeout, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for getdbmap failed\n"));
}
*dbmap = (struct ctdb_dbid_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
+ talloc_free(outdata.dptr);
return 0;
}
TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
{
int ret;
- TDB_DATA data, outdata;
+ TDB_DATA outdata;
int32_t res;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_GET_NODEMAP, 0, data,
+ CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,
mem_ctx, &outdata, &res, &timeout, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for getnodes failed\n"));
}
*nodemap = (struct ctdb_node_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
+ talloc_free(outdata.dptr);
return 0;
}
/*
set vnn map on a node
*/
-int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
+int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
+ TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
{
int ret;
- TDB_DATA data, outdata;
+ TDB_DATA data;
int32_t res;
struct ctdb_vnn_map_wire *map;
size_t len;
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_SETVNNMAP, 0, data,
- mem_ctx, &outdata, &res, &timeout, NULL);
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for setvnnmap failed\n"));
return -1;
/*
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 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;
rec = (struct ctdb_rec_data *)(rec->length + (uint8_t *)rec);
}
+ talloc_free(outdata.dptr);
+
return 0;
}
/*
copy a tdb from one node to another node
*/
-int ctdb_ctrl_copydb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t sourcenode, uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx)
+int ctdb_ctrl_copydb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t sourcenode,
+ uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx)
{
int ret;
TDB_DATA indata, outdata;
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_PUSH_DB, 0, outdata,
mem_ctx, NULL, &res, &timeout, NULL);
+ talloc_free(outdata.dptr);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for pushdb failed\n"));
return -1;
/*
change dmaster for all keys in the database to the new value
*/
-int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
+int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
+ TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
{
int ret;
- TDB_DATA indata, outdata;
+ TDB_DATA indata;
int32_t res;
indata.dsize = 2*sizeof(uint32_t);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_SET_DMASTER, 0, indata,
- mem_ctx, &outdata, &res, &timeout, NULL);
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for setdmaster failed\n"));
return -1;
int ctdb_ctrl_cleardb(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid)
{
int ret;
- TDB_DATA indata, outdata;
+ TDB_DATA indata;
int32_t res;
indata.dsize = sizeof(uint32_t);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_CLEAR_DB, 0, indata,
- mem_ctx, &outdata, &res, NULL, NULL);
+ NULL, NULL, &res, NULL, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for cleardb failed\n"));
return -1;
{
int ret;
int32_t res;
- TDB_DATA data;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
- data, NULL, NULL, &res, NULL, NULL);
+ tdb_null, NULL, NULL, &res, NULL, NULL);
if (ret != 0) {
return -1;
}
int32_t res;
TDB_DATA data;
- ZERO_STRUCT(data);
- ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, data,
+ ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null,
ctdb, &data, &res, NULL, NULL);
if (ret != 0 || res != 0) {
return -1;
int ctdb_status_reset(struct ctdb_context *ctdb, uint32_t destnode)
{
int ret;
- TDB_DATA data;
int32_t res;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_STATUS_RESET, 0, data,
+ CTDB_CONTROL_STATUS_RESET, 0, tdb_null,
NULL, NULL, &res, NULL, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for reset status failed\n"));
}
ctdb_db->db_id = *(uint32_t *)data.dptr;
+ talloc_free(data.dptr);
ret = ctdb_ctrl_getdbpath(ctdb, timeval_current_ofs(1, 0), CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
if (ret != 0) {
int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid)
{
int ret;
- TDB_DATA data, outdata;
int32_t res;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_GET_PID, 0, data,
- ctdb, &outdata, &res, &timeout, NULL);
+ CTDB_CONTROL_GET_PID, 0, tdb_null,
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0) {
DEBUG(0,(__location__ " ctdb_control for getpid failed\n"));
return -1;
int ctdb_ctrl_setmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t monmode)
{
int ret;
- TDB_DATA data, outdata;
+ TDB_DATA data;
int32_t res;
data.dsize = sizeof(uint32_t);
- data.dptr = (unsigned char *)&monmode;
+ data.dptr = (uint8_t *)&monmode;
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_SET_MONMODE, 0, data,
- ctdb, &outdata, &res, &timeout, NULL);
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for setmonmode failed\n"));
return -1;
int ctdb_ctrl_getmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *monmode)
{
int ret;
- TDB_DATA data, outdata;
int32_t res;
- ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
- CTDB_CONTROL_GET_MONMODE, 0, data,
- ctdb, &outdata, &res, &timeout, NULL);
+ CTDB_CONTROL_GET_MONMODE, 0, tdb_null,
+ NULL, NULL, &res, &timeout, NULL);
if (ret != 0) {
DEBUG(0,(__location__ " ctdb_control for getrecmode failed\n"));
return -1;
return 0;
}
+
+
+/*
+ get maximum rsn for a db on a node
+ */
+int ctdb_ctrl_get_max_rsn(struct ctdb_context *ctdb, struct timeval timeout,
+ uint32_t destnode, uint32_t db_id, uint64_t *max_rsn)
+{
+ TDB_DATA data, outdata;
+ int ret;
+ int32_t res;
+
+ data.dptr = (uint8_t *)&db_id;
+ data.dsize = sizeof(db_id);
+
+ ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_MAX_RSN, 0, data, ctdb,
+ &outdata, &res, &timeout, NULL);
+ if (ret != 0 || res != 0 || outdata.dsize != sizeof(uint64_t)) {
+ DEBUG(0,(__location__ " ctdb_control for get_max_rsn failed\n"));
+ return -1;
+ }
+
+ *max_rsn = *(uint64_t *)outdata.dptr;
+ talloc_free(outdata.dptr);
+
+ return 0;
+}
+
+/*
+ set the rsn on non-empty records to the given rsn
+ */
+int ctdb_ctrl_set_rsn_nonempty(struct ctdb_context *ctdb, struct timeval timeout,
+ uint32_t destnode, uint32_t db_id, uint64_t rsn)
+{
+ TDB_DATA data;
+ int ret;
+ int32_t res;
+ struct ctdb_control_set_rsn_nonempty p;
+
+ p.db_id = db_id;
+ p.rsn = rsn;
+
+ data.dptr = (uint8_t *)&p;
+ data.dsize = sizeof(p);
+
+ ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_RSN_NONEMPTY, 0, data, NULL,
+ NULL, &res, &timeout, NULL);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for set_rsn_nonempty failed\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ delete records which have a rsn below the given rsn
+ */
+int ctdb_ctrl_delete_low_rsn(struct ctdb_context *ctdb, struct timeval timeout,
+ uint32_t destnode, uint32_t db_id, uint64_t rsn)
+{
+ TDB_DATA data;
+ int ret;
+ int32_t res;
+ struct ctdb_control_delete_low_rsn p;
+
+ p.db_id = db_id;
+ p.rsn = rsn;
+
+ data.dptr = (uint8_t *)&p;
+ data.dsize = sizeof(p);
+
+ ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DELETE_LOW_RSN, 0, data, NULL,
+ NULL, &res, &timeout, NULL);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for delete_low_rsn failed\n"));
+ return -1;
+ }
+
+ return 0;
+}
return 0;
}
+/*
+ callback for ctdb_control_max_rsn
+ */
+static int traverse_max_rsn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p)
+{
+ struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
+ uint64_t *max_rsn = (uint64_t *)p;
+
+ if (data.dsize >= sizeof(*h)) {
+ (*max_rsn) = MAX(*max_rsn, h->rsn);
+ }
+ return 0;
+}
+
+/*
+ get max rsn across an entire db
+ */
+int32_t ctdb_control_max_rsn(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata)
+{
+ struct ctdb_db_context *ctdb_db;
+ uint32_t db_id = *(uint32_t *)indata.dptr;
+ uint64_t max_rsn = 0;
+ int ret;
+
+ if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
+ DEBUG(0,("rejecting ctdb_control_max_rsn when not frozen\n"));
+ return -1;
+ }
+
+ ctdb_db = find_ctdb_db(ctdb, db_id);
+ if (!ctdb_db) {
+ DEBUG(0,(__location__ " Unknown db\n"));
+ return -1;
+ }
+
+ if (ctdb_lock_all_databases_mark(ctdb) != 0) {
+ DEBUG(0,(__location__ " Failed to get lock on entired db - failing\n"));
+ return -1;
+ }
+
+ ret = tdb_traverse_read(ctdb_db->ltdb->tdb, traverse_max_rsn, &max_rsn);
+ if (ret < 0) {
+ DEBUG(0,(__location__ " traverse failed in ctdb_control_max_rsn\n"));
+ return -1;
+ }
+
+ ctdb_lock_all_databases_unmark(ctdb);
+
+ outdata->dptr = (uint8_t *)talloc(outdata, uint64_t);
+ if (!outdata->dptr) {
+ return -1;
+ }
+ (*(uint64_t *)outdata->dptr) = max_rsn;
+ outdata->dsize = sizeof(uint64_t);
+
+ return 0;
+}
+
+
+/*
+ callback for ctdb_control_set_rsn_nonempty
+ */
+static int traverse_set_rsn_nonempty(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p)
+{
+ struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
+ uint64_t *rsn = (uint64_t *)p;
+
+ if (data.dsize > sizeof(*h)) {
+ h->rsn = *rsn;
+ if (tdb_store(tdb, key, data, TDB_REPLACE) != 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ set rsn for all non-empty records in a database to a given rsn
+ */
+int32_t ctdb_control_set_rsn_nonempty(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata)
+{
+ struct ctdb_control_set_rsn_nonempty *p = (struct ctdb_control_set_rsn_nonempty *)indata.dptr;
+ struct ctdb_db_context *ctdb_db;
+ int ret;
+
+ if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
+ DEBUG(0,("rejecting ctdb_control_set_rsn_nonempty when not frozen\n"));
+ return -1;
+ }
+
+ ctdb_db = find_ctdb_db(ctdb, p->db_id);
+ if (!ctdb_db) {
+ DEBUG(0,(__location__ " Unknown db\n"));
+ return -1;
+ }
+
+ if (ctdb_lock_all_databases_mark(ctdb) != 0) {
+ DEBUG(0,(__location__ " Failed to get lock on entired db - failing\n"));
+ return -1;
+ }
+
+ ret = tdb_traverse(ctdb_db->ltdb->tdb, traverse_set_rsn_nonempty, &p->rsn);
+ if (ret < 0) {
+ DEBUG(0,(__location__ " traverse failed in ctdb_control_set_rsn_nonempty\n"));
+ return -1;
+ }
+
+ ctdb_lock_all_databases_unmark(ctdb);
+
+ return 0;
+}
+
+
+/*
+ callback for ctdb_control_delete_low_rsn
+ */
+static int traverse_delete_low_rsn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p)
+{
+ struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
+ uint64_t *rsn = (uint64_t *)p;
+
+ if (data.dsize < sizeof(*h) || h->rsn < *rsn) {
+ if (tdb_delete(tdb, key) != 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ delete any records with a rsn < the given rsn
+ */
+int32_t ctdb_control_delete_low_rsn(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata)
+{
+ struct ctdb_control_delete_low_rsn *p = (struct ctdb_control_delete_low_rsn *)indata.dptr;
+ struct ctdb_db_context *ctdb_db;
+ int ret;
+
+ if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
+ DEBUG(0,("rejecting ctdb_control_delete_low_rsn when not frozen\n"));
+ return -1;
+ }
+
+ ctdb_db = find_ctdb_db(ctdb, p->db_id);
+ if (!ctdb_db) {
+ DEBUG(0,(__location__ " Unknown db\n"));
+ return -1;
+ }
+
+ if (ctdb_lock_all_databases_mark(ctdb) != 0) {
+ DEBUG(0,(__location__ " Failed to get lock on entired db - failing\n"));
+ return -1;
+ }
+
+ ret = tdb_traverse(ctdb_db->ltdb->tdb, traverse_delete_low_rsn, &p->rsn);
+ if (ret < 0) {
+ DEBUG(0,(__location__ " traverse failed in ctdb_control_delete_low_rsn\n"));
+ return -1;
+ }
+
+ ctdb_lock_all_databases_unmark(ctdb);
+
+ return 0;
+}