hdr->generation));
break;
}
+ /* if we are in recovery mode we discard all traffic
+ until the cluster has recovered.
+ */
+ if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
+ DEBUG(0,(__location__ " ctdb request %d of type"
+ " %d length %d from node %d to %d"
+ " while we are in recovery mode\n",
+ hdr->reqid, hdr->operation, hdr->length,
+ hdr->srcnode, hdr->destnode));
+ break;
+ }
+
ctdb->status.count.req_call++;
ctdb_request_call(ctdb, hdr);
break;
ctdb = talloc_zero(ev, struct ctdb_context);
ctdb->ev = ev;
+ ctdb->recovery_mode = CTDB_RECOVERY_NORMAL;
ctdb->upcalls = &ctdb_upcalls;
ctdb->idr = idr_init(ctdb);
ctdb->max_lacount = CTDB_DEFAULT_MAX_LACOUNT;
return 0;
}
+/*
+ get the recovery mode of a remote node
+ */
+int ctdb_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_GET_RECMODE, 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_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, 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;
}
+ case CTDB_CONTROL_SET_RECMODE: {
+ ctdb->recovery_mode = ((uint32_t *)(&indata.dptr[0]))[0];
+
+ return 0;
+ }
+
+ case CTDB_CONTROL_GET_RECMODE: {
+ outdata->dsize = sizeof(uint32_t);
+ outdata->dptr = (unsigned char *)talloc_array(outdata, uint32_t, 1);
+ *((uint32_t *)(&outdata->dptr[0])) = ctdb->recovery_mode;
+
+ return 0;
+ }
+
case CTDB_CONTROL_CONFIG: {
CHECK_CONTROL_DATA_SIZE(0);
outdata->dptr = (uint8_t *)ctdb;
*/
int ctdb_pulldb(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t from_vnn);
+
+#define CTDB_RECOVERY_NORMAL 0
+#define CTDB_RECOVERY_ACTIVE 1
+/*
+ get the recovery mode of a remote node
+ */
+int ctdb_getrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *recmode);
+/*
+ set the recovery mode of a remote node
+ */
+int ctdb_setrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t recmode);
+
#endif
/* main state of the ctdb daemon */
struct ctdb_context {
struct event_context *ev;
+ uint32_t recovery_mode;
struct ctdb_address address;
const char *name;
const char *db_directory;
CTDB_CONTROL_GET_KEYS,
CTDB_CONTROL_SET_DMASTER,
CTDB_CONTROL_CLEAR_DB,
- CTDB_CONTROL_PULL_DB};
+ CTDB_CONTROL_PULL_DB,
+ CTDB_CONTROL_GET_RECMODE,
+ CTDB_CONTROL_SET_RECMODE};
enum call_state {CTDB_CALL_WAIT, CTDB_CALL_DONE, CTDB_CALL_ERROR};
printf(" setdmaster <vnn> <dbid> <dmaster> sets new dmaster for all records in the database\n");
printf(" cleardb <vnn> <dbid> deletes all records in a db\n");
printf(" pulldb <vnn> <dbid> <from vnn> pull a db from a remote node\n");
+ printf(" getrecmode <vnn> get recovery mode\n");
+ printf(" setrecmode <vnn> <mode> set recovery mode\n");
exit(1);
}
return 0;
}
+/*
+ display recovery mode of a remote node
+ */
+static int control_getrecmode(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+ uint32_t vnn, recmode;
+ int ret;
+
+
+ if (argc < 1) {
+ usage();
+ }
+
+ vnn = strtoul(argv[0], NULL, 0);
+
+ ret = ctdb_getrecmode(ctdb, vnn, &recmode);
+ if (ret != 0) {
+ printf("Unable to get recmode from node %u\n", vnn);
+ return ret;
+ }
+ printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
+
+ return 0;
+}
+
+/*
+ set recovery mode of a remote node
+ */
+static int control_setrecmode(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+ uint32_t vnn, recmode;
+ int ret;
+
+
+ if (argc < 2) {
+ usage();
+ }
+
+ vnn = strtoul(argv[0], NULL, 0);
+ recmode = strtoul(argv[0], NULL, 0);
+
+ ret = ctdb_setrecmode(ctdb, vnn, recmode);
+ if (ret != 0) {
+ printf("Unable to set recmode on node %u\n", vnn);
+ return ret;
+ }
+
+ return 0;
+}
+
/*
display remote list of keys for a tdb
*/
ret = control_cleardb(ctdb, extra_argc-1, extra_argv+1);
} else if (strcmp(control, "pulldb") == 0) {
ret = control_pulldb(ctdb, extra_argc-1, extra_argv+1);
+ } else if (strcmp(control, "getrecmode") == 0) {
+ ret = control_getrecmode(ctdb, extra_argc-1, extra_argv+1);
+ } else if (strcmp(control, "setrecmode") == 0) {
+ ret = control_setrecmode(ctdb, extra_argc-1, extra_argv+1);
} else if (strcmp(control, "ping") == 0) {
ret = control_ping(ctdb, extra_argc-1, extra_argv+1);
} else if (strcmp(control, "debug") == 0) {