}
-/*
- perform a samba3 style recovery
- */
-static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
-{
- uint32_t vnn, num_nodes, generation, dmaster;
- struct ctdb_vnn_map *vnnmap;
- struct ctdb_node_map *nodemap=NULL;
- int i, j, ret;
- struct ctdb_dbid_map *dbmap=NULL;
-
- if (argc < 1) {
- usage();
- }
-
-
- vnn = strtoul(argv[0], NULL, 0);
-
- printf("recover ctdb from node %d\n", vnn);
-
- /* 1: find a list of all nodes */
- printf("\n1: fetching list of nodes\n");
- ret = ctdb_ctrl_getnodemap(ctdb, timeval_current_ofs(1, 0), vnn, ctdb, &nodemap);
- if (ret != 0) {
- printf("Unable to get nodemap from node %u\n", vnn);
- return ret;
- }
-
- /* 2: count the active nodes */
- printf("\n2: count number of active nodes\n");
- num_nodes = 0;
- for (i=0; i<nodemap->num; i++) {
- if (nodemap->nodes[i].flags&NODE_FLAGS_CONNECTED) {
- num_nodes++;
- }
- }
- printf("number of active nodes:%d\n",num_nodes);
-
- /* 3: go to all active nodes and activate recovery mode */
- printf("\n3: set recovery mode for all active nodes\n");
- for (j=0; j<nodemap->num; j++) {
- /* dont change it for nodes that are unavailable */
- if (!(nodemap->nodes[j].flags&NODE_FLAGS_CONNECTED)) {
- continue;
- }
-
- printf("setting node %d to recovery mode\n",nodemap->nodes[j].vnn);
- ret = ctdb_ctrl_setrecmode(ctdb, timeval_current_ofs(1, 0), nodemap->nodes[j].vnn, CTDB_RECOVERY_ACTIVE);
- if (ret != 0) {
- printf("Unable to set recmode on node %u\n", nodemap->nodes[j].vnn);
- return ret;
- }
- }
-
- /* 4: get a list of all databases */
- printf("\n4: getting list of databases to recover\n");
- ret = ctdb_ctrl_getdbmap(ctdb, timeval_current_ofs(1, 0), vnn, ctdb, &dbmap);
- if (ret != 0) {
- printf("Unable to get dbids from node %u\n", vnn);
- return ret;
- }
- for (i=0;i<dbmap->num;i++) {
- const char *path;
- const char *name;
-
- ctdb_ctrl_getdbpath(ctdb, timeval_current_ofs(1, 0), CTDB_CURRENT_NODE, dbmap->dbids[i], ctdb, &path);
- ctdb_ctrl_getdbname(ctdb, timeval_current_ofs(1, 0), CTDB_CURRENT_NODE, dbmap->dbids[i], ctdb, &name);
- printf("dbid:0x%08x name:%s path:%s\n", dbmap->dbids[i], name, path);
- }
-
- /* 5: pull all records from all other nodes across to this node
- (this merges based on rsn internally)
- */
- printf("\n5: merge all records from remote nodes\n");
- for (i=0;i<dbmap->num;i++) {
- printf("recovering database 0x%08x\n",dbmap->dbids[i]);
- for (j=0; j<nodemap->num; j++) {
- /* we dont need to merge with ourselves */
- if (nodemap->nodes[j].vnn == vnn) {
- continue;
- }
- /* dont merge from nodes that are unavailable */
- if (!(nodemap->nodes[j].flags&NODE_FLAGS_CONNECTED)) {
- continue;
- }
-
- printf("merging all records from node %d for database 0x%08x\n", nodemap->nodes[j].vnn, dbmap->dbids[i]);
- ret = ctdb_ctrl_copydb(ctdb, timeval_current_ofs(1, 0), nodemap->nodes[j].vnn, vnn, dbmap->dbids[i], CTDB_LMASTER_ANY, ctdb);
- if (ret != 0) {
- printf("Unable to copy db from node %u to node %u\n", nodemap->nodes[j].vnn, vnn);
- return ret;
- }
- }
- }
-
- /* 6: update dmaster to point to this node for all databases/nodes */
- printf("\n6: repoint dmaster to the recovery node\n");
- dmaster = vnn;
- printf("new dmaster is %d\n", dmaster);
- for (i=0;i<dbmap->num;i++) {
- for (j=0; j<nodemap->num; j++) {
- /* dont repoint nodes that are unavailable */
- if (!(nodemap->nodes[j].flags&NODE_FLAGS_CONNECTED)) {
- continue;
- }
-
- printf("setting dmaster to %d for node %d db 0x%08x\n",dmaster,nodemap->nodes[j].vnn,dbmap->dbids[i]);
- ret = ctdb_ctrl_setdmaster(ctdb, timeval_current_ofs(1, 0), nodemap->nodes[j].vnn, ctdb, dbmap->dbids[i], dmaster);
- if (ret != 0) {
- printf("Unable to set dmaster for node %u db:0x%08x\n", nodemap->nodes[j].vnn, dbmap->dbids[i]);
- return ret;
- }
- }
- }
-
- /* 7: push all records out to the nodes again */
- printf("\n7: push all records to remote nodes\n");
- for (i=0;i<dbmap->num;i++) {
- printf("distributing new database 0x%08x\n",dbmap->dbids[i]);
- for (j=0; j<nodemap->num; j++) {
- /* we dont need to push to ourselves */
- if (nodemap->nodes[j].vnn == vnn) {
- continue;
- }
- /* dont push to nodes that are unavailable */
- if (!(nodemap->nodes[j].flags&NODE_FLAGS_CONNECTED)) {
- continue;
- }
-
- printf("pushing all records to node %d for database 0x%08x\n", nodemap->nodes[j].vnn, dbmap->dbids[i]);
- ret = ctdb_ctrl_copydb(ctdb, timeval_current_ofs(1, 0), vnn, nodemap->nodes[j].vnn, dbmap->dbids[i], CTDB_LMASTER_ANY, ctdb);
- if (ret != 0) {
- printf("Unable to copy db from node %u to node %u\n", vnn, nodemap->nodes[j].vnn);
- return ret;
- }
- }
- }
-
- /* 8: build a new vnn map */
- printf("\n8: build a new vnn map with a new generation id\n");
-
- vnnmap = talloc_zero_size(ctdb, offsetof(struct ctdb_vnn_map, map) + 4*num_nodes);
- if (vnnmap == NULL) {
- DEBUG(0,(__location__ " Unable to allocate vnn_map structure\n"));
- exit(1);
- }
- generation = random();
- vnnmap->generation = generation;
- vnnmap->size = num_nodes;
- for (i=j=0;i<nodemap->num;i++) {
- if (nodemap->nodes[i].flags&NODE_FLAGS_CONNECTED) {
- vnnmap->map[j++]=nodemap->nodes[i].vnn;
- }
- }
- printf("Generation:%d\n",vnnmap->generation);
- printf("Size:%d\n",vnnmap->size);
- for(i=0;i<vnnmap->size;i++){
- printf("hash:%d lmaster:%d\n",i,vnnmap->map[i]);
- }
-
- /* 9: push the new vnn map out to all the nodes */
- printf("\n9: distribute the new vnn map\n");
- for (j=0; j<nodemap->num; j++) {
- /* dont push to nodes that are unavailable */
- if (!(nodemap->nodes[j].flags&NODE_FLAGS_CONNECTED)) {
- continue;
- }
-
- printf("setting new vnn map on node %d\n",nodemap->nodes[j].vnn);
- ret = ctdb_ctrl_setvnnmap(ctdb, timeval_current_ofs(1, 0), nodemap->nodes[j].vnn, ctdb, vnnmap);
- if (ret != 0) {
- printf("Unable to set vnnmap for node %u\n", vnn);
- return ret;
- }
- }
-
- /* 10: disable recovery mode */
- printf("\n10: restore recovery mode back to normal\n");
- for (j=0; j<nodemap->num; j++) {
- /* dont push to nodes that are unavailable */
- if (!(nodemap->nodes[j].flags&NODE_FLAGS_CONNECTED)) {
- continue;
- }
-
- printf("changing recovery mode back to normal for node %d\n",nodemap->nodes[j].vnn);
- ret = ctdb_ctrl_setrecmode(ctdb, timeval_current_ofs(1, 0), nodemap->nodes[j].vnn, CTDB_RECOVERY_NORMAL);
- if (ret != 0) {
- printf("Unable to set recmode on node %u\n", nodemap->nodes[j].vnn);
- return ret;
- }
- }
-
- return 0;
-}
-
/*
display remote ctdb vnn map
*/
{ "ping", control_ping },
{ "debug", control_debug },
{ "debuglevel", control_debuglevel },
- { "recover", control_recover },
{ "writerecord", control_writerecord },
{ "attach", control_attach },
{ "dumpmemory", control_dumpmemory },