along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "includes.h"
+#include "replace.h"
#include "system/time.h"
#include "system/filesys.h"
#include "system/network.h"
#include "system/locale.h"
-#include "popt.h"
-#include "cmdline.h"
-#include "../include/ctdb_version.h"
-#include "../include/ctdb_client.h"
-#include "../include/ctdb_private.h"
-#include "../common/rb_tree.h"
-#include "db_wrap.h"
+
+#include <popt.h>
+#include <talloc.h>
+/* Allow use of deprecated function tevent_loop_allow_nesting() */
+#define TEVENT_DEPRECATED
+#include <tevent.h>
+#include <tdb.h>
+
+#include "lib/tdb_wrap/tdb_wrap.h"
#include "lib/util/dlinklist.h"
+#include "lib/util/debug.h"
+#include "lib/util/substitute.h"
+#include "lib/util/time.h"
+
+#include "ctdb_version.h"
+#include "ctdb_private.h"
+#include "ctdb_client.h"
+
+#include "common/cmdline.h"
+#include "common/rb_tree.h"
+#include "common/system.h"
+#include "common/common.h"
+#include "common/logging.h"
#define ERR_TIMEOUT 20 /* timed out trying to reach node */
#define ERR_NONODE 21 /* node does not exist */
uint32_t pnn;
uint32_t *nodes;
int machinereadable;
+ const char *machineseparator;
int verbose;
int maxruntime;
int printemptyrecords;
#define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
#define LONGTIMELIMIT() timeval_current_ofs(LONGTIMEOUT, 0)
+static double timeval_delta(struct timeval *tv2, struct timeval *tv)
+{
+ return (tv2->tv_sec - tv->tv_sec) +
+ (tv2->tv_usec - tv->tv_usec)*1.0e-6;
+}
+
static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
{
printf("CTDB version: %s\n", CTDB_VERSION_STRING);
return 0;
}
+/* Like printf(3) but substitute for separator in format */
+static int printm(const char *format, ...) PRINTF_ATTRIBUTE(1,2);
+static int printm(const char *format, ...)
+{
+ va_list ap;
+ int ret;
+ size_t len = strlen(format);
+ char new_format[len+1];
+
+ strcpy(new_format, format);
+
+ if (options.machineseparator[0] != ':') {
+ all_string_sub(new_format,
+ ":", options.machineseparator, len + 1);
+ }
+
+ va_start(ap, format);
+ ret = vprintf(new_format, ap);
+ va_end(ap);
+
+ return ret;
+}
+
#define CTDB_NOMEM_ABORT(p) do { if (!(p)) { \
DEBUG(DEBUG_ALERT,("ctdb fatal error: %s\n", \
"Out of memory in " __location__ )); \
}
}
+static void assert_current_node_only(struct ctdb_context *ctdb)
+{
+ if (options.pnn != ctdb_get_pnn(ctdb)) {
+ DEBUG(DEBUG_ERR,
+ ("This control can only be applied to the current node\n"));
+ exit(1);
+ }
+}
+
/* Pretty print the flags to a static buffer in human-readable format.
* This never returns NULL!
*/
return h - '0';
}
-static TDB_DATA hextodata(TALLOC_CTX *mem_ctx, const char *str)
+static TDB_DATA hextodata(TALLOC_CTX *mem_ctx, const char *str, size_t len)
{
- int i, len;
+ int i;
TDB_DATA key = {NULL, 0};
- len = strlen(str);
if (len & 0x01) {
DEBUG(DEBUG_ERR,("Key specified with odd number of hexadecimal digits\n"));
return key;
return key;
}
+static TDB_DATA strtodata(TALLOC_CTX *mem_ctx, const char *str, size_t len)
+{
+ TDB_DATA key;
+
+ if (!strncmp(str, "0x", 2)) {
+ key = hextodata(mem_ctx, str + 2, len - 2);
+ } else {
+ key.dptr = talloc_memdup(mem_ctx, str, len);
+ key.dsize = len;
+ }
+
+ return key;
+}
+
/* Parse a nodestring. Parameter dd_ok controls what happens to nodes
* that are disconnected or deleted. If dd_ok is true those nodes are
* included in the output list of nodes. If dd_ok is false, those
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
int n;
uint32_t i;
- struct ctdb_node_map *nodemap;
+ struct ctdb_node_map_old *nodemap;
int ret;
*nodes = NULL;
uint32_t *dbid, const char **dbname, uint8_t *flags)
{
int i, ret;
- struct ctdb_dbid_map *dbmap=NULL;
+ struct ctdb_dbid_map_old *dbmap=NULL;
bool dbid_given = false, found = false;
uint32_t id;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- const char *name;
+ const char *name = NULL;
ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
if (ret != 0) {
for(i=0; i<dbmap->num; i++) {
if (dbid_given) {
- if (id == dbmap->dbs[i].dbid) {
+ if (id == dbmap->dbs[i].db_id) {
found = true;
break;
}
} else {
- ret = ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
+ ret = ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].db_id, tmp_ctx, &name);
if (ret != 0) {
- DEBUG(DEBUG_ERR, ("Unable to get dbname from dbid %u\n", dbmap->dbs[i].dbid));
+ DEBUG(DEBUG_ERR, ("Unable to get dbname from dbid %u\n", dbmap->dbs[i].db_id));
goto fail;
}
if (strcmp(name, dbarg) == 0) {
- id = dbmap->dbs[i].dbid;
+ id = dbmap->dbs[i].db_id;
found = true;
break;
}
}
if (found && dbid_given && dbname != NULL) {
- ret = ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
+ ret = ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].db_id, tmp_ctx, &name);
if (ret != 0) {
- DEBUG(DEBUG_ERR, ("Unable to get dbname from dbid %u\n", dbmap->dbs[i].dbid));
+ DEBUG(DEBUG_ERR, ("Unable to get dbname from dbid %u\n", dbmap->dbs[i].db_id));
found = false;
goto fail;
}
if (options.machinereadable){
if (show_header) {
- printf("CTDB version:");
- printf("Current time of statistics:");
- printf("Statistics collected since:");
+ printm("CTDB version:");
+ printm("Current time of statistics:");
+ printm("Statistics collected since:");
for (i=0;i<ARRAY_SIZE(fields);i++) {
- printf("%s:", fields[i].name);
+ printm("%s:", fields[i].name);
}
- printf("num_reclock_ctdbd_latency:");
- printf("min_reclock_ctdbd_latency:");
- printf("avg_reclock_ctdbd_latency:");
- printf("max_reclock_ctdbd_latency:");
-
- printf("num_reclock_recd_latency:");
- printf("min_reclock_recd_latency:");
- printf("avg_reclock_recd_latency:");
- printf("max_reclock_recd_latency:");
-
- printf("num_call_latency:");
- printf("min_call_latency:");
- printf("avg_call_latency:");
- printf("max_call_latency:");
-
- printf("num_lockwait_latency:");
- printf("min_lockwait_latency:");
- printf("avg_lockwait_latency:");
- printf("max_lockwait_latency:");
-
- printf("num_childwrite_latency:");
- printf("min_childwrite_latency:");
- printf("avg_childwrite_latency:");
- printf("max_childwrite_latency:");
- printf("\n");
- }
- printf("%d:", CTDB_VERSION);
- printf("%d:", (int)s->statistics_current_time.tv_sec);
- printf("%d:", (int)s->statistics_start_time.tv_sec);
+ printm("num_reclock_ctdbd_latency:");
+ printm("min_reclock_ctdbd_latency:");
+ printm("avg_reclock_ctdbd_latency:");
+ printm("max_reclock_ctdbd_latency:");
+
+ printm("num_reclock_recd_latency:");
+ printm("min_reclock_recd_latency:");
+ printm("avg_reclock_recd_latency:");
+ printm("max_reclock_recd_latency:");
+
+ printm("num_call_latency:");
+ printm("min_call_latency:");
+ printm("avg_call_latency:");
+ printm("max_call_latency:");
+
+ printm("num_lockwait_latency:");
+ printm("min_lockwait_latency:");
+ printm("avg_lockwait_latency:");
+ printm("max_lockwait_latency:");
+
+ printm("num_childwrite_latency:");
+ printm("min_childwrite_latency:");
+ printm("avg_childwrite_latency:");
+ printm("max_childwrite_latency:");
+ printm("\n");
+ }
+ printm("%d:", CTDB_PROTOCOL);
+ printm("%d:", (int)s->statistics_current_time.tv_sec);
+ printm("%d:", (int)s->statistics_start_time.tv_sec);
for (i=0;i<ARRAY_SIZE(fields);i++) {
- printf("%d:", *(uint32_t *)(fields[i].offset+(uint8_t *)s));
- }
- printf("%d:", s->reclock.ctdbd.num);
- printf("%.6f:", s->reclock.ctdbd.min);
- printf("%.6f:", s->reclock.ctdbd.num?s->reclock.ctdbd.total/s->reclock.ctdbd.num:0.0);
- printf("%.6f:", s->reclock.ctdbd.max);
-
- printf("%d:", s->reclock.recd.num);
- printf("%.6f:", s->reclock.recd.min);
- printf("%.6f:", s->reclock.recd.num?s->reclock.recd.total/s->reclock.recd.num:0.0);
- printf("%.6f:", s->reclock.recd.max);
-
- printf("%d:", s->call_latency.num);
- printf("%.6f:", s->call_latency.min);
- printf("%.6f:", s->call_latency.num?s->call_latency.total/s->call_latency.num:0.0);
- printf("%.6f:", s->call_latency.max);
-
- printf("%d:", s->childwrite_latency.num);
- printf("%.6f:", s->childwrite_latency.min);
- printf("%.6f:", s->childwrite_latency.num?s->childwrite_latency.total/s->childwrite_latency.num:0.0);
- printf("%.6f:", s->childwrite_latency.max);
- printf("\n");
+ printm("%d:", *(uint32_t *)(fields[i].offset+(uint8_t *)s));
+ }
+ printm("%d:", s->reclock.ctdbd.num);
+ printm("%.6f:", s->reclock.ctdbd.min);
+ printm("%.6f:", s->reclock.ctdbd.num?s->reclock.ctdbd.total/s->reclock.ctdbd.num:0.0);
+ printm("%.6f:", s->reclock.ctdbd.max);
+
+ printm("%d:", s->reclock.recd.num);
+ printm("%.6f:", s->reclock.recd.min);
+ printm("%.6f:", s->reclock.recd.num?s->reclock.recd.total/s->reclock.recd.num:0.0);
+ printm("%.6f:", s->reclock.recd.max);
+
+ printm("%d:", s->call_latency.num);
+ printm("%.6f:", s->call_latency.min);
+ printm("%.6f:", s->call_latency.num?s->call_latency.total/s->call_latency.num:0.0);
+ printm("%.6f:", s->call_latency.max);
+
+ printm("%d:", s->childwrite_latency.num);
+ printm("%.6f:", s->childwrite_latency.min);
+ printm("%.6f:", s->childwrite_latency.num?s->childwrite_latency.total/s->childwrite_latency.num:0.0);
+ printm("%.6f:", s->childwrite_latency.max);
+ printm("\n");
} else {
- printf("CTDB version %u\n", CTDB_VERSION);
+ printf("CTDB version %u\n", CTDB_PROTOCOL);
printf("Current time of statistics : %s", ctime(&s->statistics_current_time.tv_sec));
printf("Statistics collected since : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&s->statistics_start_time.tv_sec));
static int control_stats(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
- struct ctdb_statistics_wire *stats;
+ struct ctdb_statistics_list_old *stats;
int i, num_records = -1;
assert_single_node_only();
static int control_dbstatistics(struct ctdb_context *ctdb, int argc, const char **argv)
{
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_db_statistics *dbstat;
+ struct ctdb_db_statistics_old *dbstat;
int i;
uint32_t db_id;
int num_hot_keys;
0.0),
dbstat->locks.latency.max,
dbstat->locks.latency.num);
+ printf(" %-30s %.6f/%.6f/%.6f sec out of %d\n",
+ "vacuum_latency MIN/AVG/MAX",
+ dbstat->vacuum.latency.min,
+ (dbstat->vacuum.latency.num ?
+ dbstat->vacuum.latency.total /dbstat->vacuum.latency.num :
+ 0.0),
+ dbstat->vacuum.latency.max,
+ dbstat->vacuum.latency.num);
num_hot_keys = 0;
for (i=0; i<dbstat->num_hot_keys; i++) {
if (dbstat->hot_keys[i].count > 0) {
}
if (options.machinereadable){
- printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
- printf(":%u:%u:%u:%lf\n",
+ printm(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
+ printm(":%u:%u:%u:%lf\n",
(unsigned int)uptime->current_time.tv_sec,
(unsigned int)uptime->ctdbd_start_time.tv_sec,
(unsigned int)uptime->last_recovery_finished.tv_sec,
}
-struct pnn_node {
- struct pnn_node *next, *prev;
- const char *addr;
- int pnn;
-};
-
-static struct pnn_node *read_pnn_node_file(TALLOC_CTX *mem_ctx,
- const char *file)
-{
- int nlines;
- char **lines;
- int i, pnn;
- struct pnn_node *pnn_nodes = NULL;
- struct pnn_node *pnn_node;
-
- lines = file_lines_load(file, &nlines, mem_ctx);
- if (lines == NULL) {
- return NULL;
- }
- for (i=0, pnn=0; i<nlines; i++) {
- char *node;
-
- node = lines[i];
- /* strip leading spaces */
- while((*node == ' ') || (*node == '\t')) {
- node++;
- }
- if (*node == '#') {
- pnn++;
- continue;
- }
- if (strcmp(node, "") == 0) {
- continue;
- }
- pnn_node = talloc(mem_ctx, struct pnn_node);
- pnn_node->pnn = pnn++;
- pnn_node->addr = talloc_strdup(pnn_node, node);
-
- DLIST_ADD_END(pnn_nodes, pnn_node, NULL);
- }
-
- return pnn_nodes;
-}
-
-static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
+static struct ctdb_node_map_old *read_nodes_file(TALLOC_CTX *mem_ctx)
{
const char *nodes_list;
}
}
- return read_pnn_node_file(mem_ctx, nodes_list);
+ return ctdb_read_nodes_file(mem_ctx, nodes_list);
}
/*
discover the pnn by loading the nodes file and try to bind to all
addresses one at a time until the ip address is found.
*/
-static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
+static int find_node_xpnn(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
- struct pnn_node *pnn_nodes;
- struct pnn_node *pnn_node;
-
- assert_single_node_only();
+ struct ctdb_node_map_old *node_map;
+ int i, pnn;
- pnn_nodes = read_nodes_file(mem_ctx);
- if (pnn_nodes == NULL) {
- DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
+ node_map = read_nodes_file(mem_ctx);
+ if (node_map == NULL) {
talloc_free(mem_ctx);
return -1;
}
- for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
- ctdb_sock_addr addr;
-
- if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
- DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
- talloc_free(mem_ctx);
- return -1;
+ for (i = 0; i < node_map->num; i++) {
+ if (node_map->nodes[i].flags & NODE_FLAGS_DELETED) {
+ continue;
}
-
- if (ctdb_sys_have_ip(&addr)) {
- printf("PNN:%d\n", pnn_node->pnn);
+ if (ctdb_sys_have_ip(&node_map->nodes[i].addr)) {
+ pnn = node_map->nodes[i].pnn;
talloc_free(mem_ctx);
- return 0;
+ return pnn;
}
}
return -1;
}
+static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+ uint32_t pnn;
+
+ assert_single_node_only();
+
+ pnn = find_node_xpnn();
+ if (pnn == -1) {
+ return -1;
+ }
+
+ printf("PNN:%d\n", pnn);
+ return 0;
+}
+
/* Helpers for ctdb status
*/
static bool is_partially_online(struct ctdb_context *ctdb, struct ctdb_node_and_flags *node)
bool ret = false;
if (node->flags == 0) {
- struct ctdb_control_get_ifaces *ifaces;
+ struct ctdb_iface_list_old *ifaces;
if (ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), node->pnn,
tmp_ctx, &ifaces) == 0) {
static void control_status_header_machine(void)
{
- printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped"
+ printm(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped"
":Inactive:PartiallyOnline:ThisNode:\n");
}
static int control_status_1_machine(struct ctdb_context *ctdb, int mypnn,
struct ctdb_node_and_flags *node)
{
- printf(":%d:%s:%d:%d:%d:%d:%d:%d:%d:%c:\n", node->pnn,
+ printm(":%d:%s:%d:%d:%d:%d:%d:%d:%d:%c:\n", node->pnn,
ctdb_addr_to_str(&node->addr),
!!(node->flags&NODE_FLAGS_DISCONNECTED),
!!(node->flags&NODE_FLAGS_BANNED),
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
int i;
struct ctdb_vnn_map *vnnmap=NULL;
- struct ctdb_node_map *nodemap=NULL;
+ struct ctdb_node_map_old *nodemap=NULL;
uint32_t recmode, recmaster, mypnn;
int num_deleted_nodes = 0;
int ret;
{
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
int i, ret;
- struct ctdb_node_map *nodemap=NULL;
+ struct ctdb_node_map_old *nodemap=NULL;
uint32_t * nodes;
uint32_t pnn_mode, mypnn;
return ret;
}
-static struct pnn_node *read_natgw_nodes_file(struct ctdb_context *ctdb,
- TALLOC_CTX *mem_ctx)
-{
- const char *natgw_list;
- struct pnn_node *natgw_nodes = NULL;
-
- natgw_list = getenv("CTDB_NATGW_NODES");
- if (natgw_list == NULL) {
- natgw_list = talloc_asprintf(mem_ctx, "%s/natgw_nodes",
- getenv("CTDB_BASE"));
- if (natgw_list == NULL) {
- DEBUG(DEBUG_ALERT,(__location__ " Out of memory\n"));
- exit(1);
- }
- }
- /* The PNNs will be junk but they're not used */
- natgw_nodes = read_pnn_node_file(mem_ctx, natgw_list);
- if (natgw_nodes == NULL) {
- DEBUG(DEBUG_ERR,
- ("Failed to load natgw node list '%s'\n", natgw_list));
- }
- return natgw_nodes;
-}
-
-
/* talloc off the existing nodemap... */
-static struct ctdb_node_map *talloc_nodemap(struct ctdb_node_map *nodemap)
+static struct ctdb_node_map_old *talloc_nodemap(struct ctdb_node_map_old *nodemap)
{
return talloc_zero_size(nodemap,
- offsetof(struct ctdb_node_map, nodes) +
+ offsetof(struct ctdb_node_map_old, nodes) +
nodemap->num * sizeof(struct ctdb_node_and_flags));
}
-static struct ctdb_node_map *
-filter_nodemap_by_addrs(struct ctdb_context *ctdb,
- struct ctdb_node_map *nodemap,
- struct pnn_node *nodes)
+static struct ctdb_node_map_old *
+filter_nodemap_by_capabilities(struct ctdb_context *ctdb,
+ struct ctdb_node_map_old *nodemap,
+ uint32_t required_capabilities,
+ bool first_only)
{
int i;
- struct pnn_node *n;
- struct ctdb_node_map *ret;
+ uint32_t capabilities;
+ struct ctdb_node_map_old *ret;
ret = talloc_nodemap(nodemap);
CTDB_NO_MEMORY_NULL(ctdb, ret);
ret->num = 0;
for (i = 0; i < nodemap->num; i++) {
- for(n = nodes; n != NULL ; n = n->next) {
- if (!strcmp(n->addr,
- ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
- break;
- }
- }
- if (n == NULL) {
+ int res;
+
+ /* Disconnected nodes have no capabilities! */
+ if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
continue;
}
- ret->nodes[ret->num] = nodemap->nodes[i];
- ret->num++;
- }
-
- return ret;
-}
-
-static struct ctdb_node_map *
-filter_nodemap_by_capabilities(struct ctdb_context *ctdb,
- struct ctdb_node_map *nodemap,
- uint32_t required_capabilities)
-{
- int i;
- uint32_t capabilities;
- struct ctdb_node_map *ret;
-
- ret = talloc_nodemap(nodemap);
- CTDB_NO_MEMORY_NULL(ctdb, ret);
-
- ret->num = 0;
-
- for (i = 0; i < nodemap->num; i++) {
- int res = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(),
- nodemap->nodes[i].pnn,
- &capabilities);
+ res = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(),
+ nodemap->nodes[i].pnn,
+ &capabilities);
if (res != 0) {
DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n",
nodemap->nodes[i].pnn));
ret->nodes[ret->num] = nodemap->nodes[i];
ret->num++;
+ if (first_only) {
+ break;
+ }
}
return ret;
}
-static struct ctdb_node_map *
+static struct ctdb_node_map_old *
filter_nodemap_by_flags(struct ctdb_context *ctdb,
- struct ctdb_node_map *nodemap,
+ struct ctdb_node_map_old *nodemap,
uint32_t flags_mask)
{
int i;
- struct ctdb_node_map *ret;
+ struct ctdb_node_map_old *ret;
ret = talloc_nodemap(nodemap);
CTDB_NO_MEMORY_NULL(ctdb, ret);
*/
static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
{
- TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- int i, ret;
- struct pnn_node *natgw_nodes = NULL;
- struct ctdb_node_map *orig_nodemap=NULL;
- struct ctdb_node_map *cnodemap, *nodemap;
- uint32_t mypnn, pnn;
- const char *ip;
-
- /* When we have some nodes that could be the NATGW, make a
- * series of attempts to find the first node that doesn't have
- * certain status flags set.
- */
- uint32_t exclude_flags[] = {
- /* Look for a nice healthy node */
- NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY,
- /* If not found, an UNHEALTHY/BANNED node will do */
- NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED,
- /* If not found, a STOPPED node will do */
- NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED,
- 0,
- };
-
- /* read the natgw nodes file into a linked list */
- natgw_nodes = read_natgw_nodes_file(ctdb, tmp_ctx);
- if (natgw_nodes == NULL) {
- ret = -1;
- goto done;
- }
+ static char prog[PATH_MAX+1] = "";
- ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE,
- tmp_ctx, &orig_nodemap);
- if (ret != 0) {
- DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
- talloc_free(tmp_ctx);
- return -1;
- }
-
- /* Get a nodemap that includes only the nodes in the NATGW
- * group */
- nodemap = filter_nodemap_by_addrs(ctdb, orig_nodemap, natgw_nodes);
- if (nodemap == NULL) {
- ret = -1;
- goto done;
- }
-
- /* Get a nodemap that includes only the nodes with the NATGW
- * capability */
- cnodemap = filter_nodemap_by_capabilities(ctdb, nodemap,
- CTDB_CAP_NATGW);
- if (cnodemap == NULL) {
- ret = -1;
- goto done;
- }
-
- ret = 2; /* matches ENOENT */
- pnn = -1;
- ip = "0.0.0.0";
- for (i = 0; exclude_flags[i] != 0; i++) {
- struct ctdb_node_map *t =
- filter_nodemap_by_flags(ctdb, cnodemap,
- exclude_flags[i]);
- if (t == NULL) {
- /* No memory */
- ret = -1;
- goto done;
- }
- if (t->num > 0) {
- ret = 0;
- pnn = t->nodes[0].pnn;
- ip = ctdb_addr_to_str(&t->nodes[0].addr);
- break;
- }
- talloc_free(t);
+ if (argc != 0) {
+ usage();
}
- if (options.machinereadable) {
- printf(":Node:IP:\n");
- printf(":%d:%s:\n", pnn, ip);
- } else {
- printf("%d %s\n", pnn, ip);
+ if (!ctdb_set_helper("NAT gateway helper", prog, sizeof(prog),
+ "CTDB_NATGW_HELPER", CTDB_HELPER_BINDIR,
+ "ctdb_natgw")) {
+ DEBUG(DEBUG_ERR, ("Unable to set NAT gateway helper\n"));
+ exit(1);
}
- /* print the pruned list of nodes belonging to this natgw list */
- mypnn = getpnn(ctdb);
- if (options.machinereadable) {
- control_status_header_machine();
- } else {
- printf("Number of nodes:%d\n", nodemap->num);
- }
- for(i=0;i<nodemap->num;i++){
- if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
- continue;
- }
- if (options.machinereadable) {
- control_status_1_machine(ctdb, mypnn, &(nodemap->nodes[i]));
- } else {
- control_status_1_human(ctdb, mypnn, &(nodemap->nodes[i]));
- }
- }
+ execl(prog, prog, "natgwlist", NULL);
-done:
- talloc_free(tmp_ctx);
- return ret;
+ DEBUG(DEBUG_ERR,
+ ("Unable to run NAT gateway helper %s\n", strerror(errno)));
+ exit(1);
}
/*
display the status of the scripts for monitoring (or other events)
*/
static int control_one_scriptstatus(struct ctdb_context *ctdb,
- enum ctdb_eventscript_call type)
+ enum ctdb_event type)
{
- struct ctdb_scripts_wire *script_status;
+ struct ctdb_script_list_old *script_status;
int ret, i;
ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
}
if (!options.machinereadable) {
+ int num_run = 0;
+ for (i=0; i<script_status->num_scripts; i++) {
+ if (script_status->scripts[i].status != -ENOEXEC) {
+ num_run++;
+ }
+ }
printf("%d scripts were executed last %s cycle\n",
- script_status->num_scripts,
+ num_run,
ctdb_eventscript_call_names[type]);
}
for (i=0; i<script_status->num_scripts; i++) {
const char *status = NULL;
+ /* The ETIME status is ignored for certain events.
+ * In that case the status is 0, but endtime is not set.
+ */
+ if (script_status->scripts[i].status == 0 &&
+ timeval_is_zero(&script_status->scripts[i].finished)) {
+ script_status->scripts[i].status = -ETIME;
+ }
+
switch (script_status->scripts[i].status) {
case -ETIME:
status = "TIMEDOUT";
break;
}
if (options.machinereadable) {
- printf(":%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
+ printm(":%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
ctdb_eventscript_call_names[type],
script_status->scripts[i].name,
script_status->scripts[i].status,
int argc, const char **argv)
{
int ret;
- enum ctdb_eventscript_call type, min, max;
+ enum ctdb_event type, min, max;
const char *arg;
if (argc > 1) {
}
if (options.machinereadable) {
- printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
+ printm(":Type:Name:Code:Status:Start:End:Error Output...:\n");
}
for (type = min; type < max; type++) {
*/
static int control_add_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
{
- struct ctdb_tcp_connection t;
+ struct ctdb_connection t;
TDB_DATA data;
int ret;
usage();
}
- if (parse_ip_port(argv[0], &t.src_addr) == 0) {
+ if (parse_ip_port(argv[0], &t.src) == 0) {
DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
return -1;
}
- if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
+ if (parse_ip_port(argv[1], &t.dst) == 0) {
DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
return -1;
}
*/
static int control_del_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
{
- struct ctdb_tcp_connection t;
+ struct ctdb_connection t;
TDB_DATA data;
int ret;
usage();
}
- if (parse_ip_port(argv[0], &t.src_addr) == 0) {
+ if (parse_ip_port(argv[0], &t.src) == 0) {
DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
return -1;
}
- if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
+ if (parse_ip_port(argv[1], &t.dst) == 0) {
DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
return -1;
}
*/
static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
{
- struct ctdb_control_tcp_tickle_list *list;
+ struct ctdb_tickle_list_old *list;
ctdb_sock_addr addr;
int i, ret;
unsigned port = 0;
}
if (options.machinereadable){
- printf(":source ip:port:destination ip:port:\n");
- for (i=0;i<list->tickles.num;i++) {
- if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
+ printm(":source ip:port:destination ip:port:\n");
+ for (i=0;i<list->num;i++) {
+ if (port && port != ntohs(list->connections[i].dst.ip.sin_port)) {
continue;
}
- printf(":%s:%u", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
- printf(":%s:%u:\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
+ printm(":%s:%u", ctdb_addr_to_str(&list->connections[i].src), ntohs(list->connections[i].src.ip.sin_port));
+ printm(":%s:%u:\n", ctdb_addr_to_str(&list->connections[i].dst), ntohs(list->connections[i].dst.ip.sin_port));
}
} else {
printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
- printf("Num tickles:%u\n", list->tickles.num);
- for (i=0;i<list->tickles.num;i++) {
- if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
+ printf("Num tickles:%u\n", list->num);
+ for (i=0;i<list->num;i++) {
+ if (port && port != ntohs(list->connections[i].dst.ip.sin_port)) {
continue;
}
- printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
- printf("DST: %s:%u\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
+ printf("SRC: %s:%u ", ctdb_addr_to_str(&list->connections[i].src), ntohs(list->connections[i].src.ip.sin_port));
+ printf("DST: %s:%u\n", ctdb_addr_to_str(&list->connections[i].dst), ntohs(list->connections[i].dst.ip.sin_port));
}
}
static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
{
- struct ctdb_all_public_ips *ips;
+ struct ctdb_public_ip_list_old *ips;
struct ctdb_public_ip ip;
int i, ret;
uint32_t *nodes;
uint32_t disable_time;
TDB_DATA data;
- struct ctdb_node_map *nodemap=NULL;
+ struct ctdb_node_map_old *nodemap=NULL;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
disable_time = 30;
find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
{
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_all_public_ips *ips;
- struct ctdb_node_map *nodemap=NULL;
+ struct ctdb_public_ip_list_old *ips;
+ struct ctdb_node_map_old *nodemap=NULL;
int i, j, ret;
+ int pnn;
ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
if (ret != 0) {
for (j=0;j<ips->num;j++) {
if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
+ pnn = nodemap->nodes[i].pnn;
talloc_free(tmp_ctx);
- return nodemap->nodes[i].pnn;
+ return pnn;
}
}
talloc_free(ips);
uint32_t *nodes;
uint32_t disable_time;
TDB_DATA data;
- struct ctdb_node_map *nodemap=NULL;
+ struct ctdb_node_map_old *nodemap=NULL;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
disable_time = 30;
static int getips_store_callback(void *param, void *data)
{
struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
- struct ctdb_all_public_ips *ips = param;
+ struct ctdb_public_ip_list_old *ips = param;
int i;
i = ips->num++;
}
static int
-control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
+control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_public_ip_list_old **ips)
{
- struct ctdb_all_public_ips *tmp_ips;
- struct ctdb_node_map *nodemap=NULL;
+ struct ctdb_public_ip_list_old *tmp_ips;
+ struct ctdb_node_map_old *nodemap=NULL;
trbt_tree_t *ip_tree;
int i, j, len, ret;
uint32_t count;
count = 0;
trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
- len = offsetof(struct ctdb_all_public_ips, ips) +
+ len = offsetof(struct ctdb_public_ip_list_old, ips) +
count*sizeof(struct ctdb_public_ip);
tmp_ips = talloc_zero_size(tmp_ctx, len);
trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
}
-static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
+static void ctdb_every_second(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval t, void *p)
{
struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
- event_add_timed(ctdb->ev, ctdb,
- timeval_current_ofs(1, 0),
- ctdb_every_second, ctdb);
+ tevent_add_timer(ctdb->ev, ctdb, timeval_current_ofs(1, 0),
+ ctdb_every_second, ctdb);
}
struct srvid_reply_handler_data {
const char *srvid_str;
};
-static void srvid_broadcast_reply_handler(struct ctdb_context *ctdb,
- uint64_t srvid,
- TDB_DATA data,
+static void srvid_broadcast_reply_handler(uint64_t srvid, TDB_DATA data,
void *private_data)
{
struct srvid_reply_handler_data *d =
d->done = true;
for (i = 0; i < talloc_array_length(d->nodes); i++) {
if (d->nodes[i] == ret) {
- DEBUG(DEBUG_INFO,
+ DEBUG(DEBUG_DEBUG,
("%s reply received from node %u\n",
d->srvid_str, ret));
d->nodes[i] = -1;
TDB_DATA data;
uint32_t pnn;
uint64_t reply_srvid;
- struct srvid_request request;
- struct srvid_request_data request_data;
+ struct ctdb_srvid_message request;
+ struct ctdb_disable_message request_data;
struct srvid_reply_handler_data reply_data;
struct timeval tv;
ZERO_STRUCT(request);
/* Time ticks to enable timeouts to be processed */
- event_add_timed(ctdb->ev, ctdb,
- timeval_current_ofs(1, 0),
- ctdb_every_second, ctdb);
+ tevent_add_timer(ctdb->ev, ctdb, timeval_current_ofs(1, 0),
+ ctdb_every_second, ctdb);
pnn = ctdb_get_pnn(ctdb);
reply_srvid = getpid();
} else {
request_data.pnn = pnn;
request_data.srvid = reply_srvid;
- request_data.data = *arg;
+ request_data.timeout = *arg;
data.dptr = (uint8_t *)&request_data;
data.dsize = sizeof(request_data);
reply_data.done = false;
if (wait_for_all) {
- struct ctdb_node_map *nodemap;
+ struct ctdb_node_map_old *nodemap;
ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(),
CTDB_CURRENT_NODE, ctdb, &nodemap);
tv = timeval_current();
/* This loop terminates the reply is received */
while (timeval_elapsed(&tv) < 5.0 && !reply_data.done) {
- event_loop_once(ctdb->ev);
+ tevent_loop_once(ctdb->ev);
}
if (!reply_data.done) {
int len, retries = 0;
unsigned mask;
ctdb_sock_addr addr;
- struct ctdb_control_ip_iface *pub;
+ struct ctdb_addr_info_old *pub;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_all_public_ips *ips;
+ struct ctdb_public_ip_list_old *ips;
if (argc != 2) {
*/
alarm(0);
- len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
+ len = offsetof(struct ctdb_addr_info_old, iface) + strlen(argv[1]) + 1;
pub = talloc_size(tmp_ctx, len);
CTDB_NO_MEMORY(ctdb, pub);
static int control_ipiface(struct ctdb_context *ctdb, int argc, const char **argv)
{
ctdb_sock_addr addr;
+ char *iface = NULL;
if (argc != 1) {
usage();
return -1;
}
- printf("IP on interface %s\n", ctdb_sys_find_ifname(&addr));
+ iface = ctdb_sys_find_ifname(&addr);
+ if (iface == NULL) {
+ printf("Failed to get interface name for ip: %s", argv[0]);
+ return -1;
+ }
+
+ printf("IP on interface %s\n", iface);
+
+ free(iface);
return 0;
}
static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
{
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_node_map *nodemap=NULL;
- struct ctdb_all_public_ips *ips;
+ struct ctdb_node_map_old *nodemap=NULL;
+ struct ctdb_public_ip_list_old *ips;
int ret, i, j;
ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
{
int i, ret;
ctdb_sock_addr addr;
- struct ctdb_control_ip_iface pub;
+ struct ctdb_addr_info_old pub;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_all_public_ips *ips;
+ struct ctdb_public_ip_list_old *ips;
if (argc != 1) {
talloc_free(tmp_ctx);
static int kill_tcp_from_file(struct ctdb_context *ctdb,
int argc, const char **argv)
{
- struct ctdb_control_killtcp *killtcp;
+ struct ctdb_connection *killtcp;
int max_entries, current, i;
struct timeval timeout;
char line[128], src[128], dst[128];
if (current >= max_entries) {
max_entries += 1024;
killtcp = talloc_realloc(ctdb, killtcp,
- struct ctdb_control_killtcp,
+ struct ctdb_connection,
max_entries);
CTDB_NO_MEMORY(ctdb, killtcp);
}
- if (!parse_ip_port(src, &killtcp[current].src_addr)) {
+ if (!parse_ip_port(src, &killtcp[current].src)) {
DEBUG(DEBUG_ERR, ("Bad IP:port on line [%d]: '%s'\n",
linenum, src));
talloc_free(killtcp);
return -1;
}
- if (!parse_ip_port(dst, &killtcp[current].dst_addr)) {
+ if (!parse_ip_port(dst, &killtcp[current].dst)) {
DEBUG(DEBUG_ERR, ("Bad IP:port on line [%d]: '%s'\n",
linenum, dst));
talloc_free(killtcp);
for (i = 0; i < current; i++) {
- data.dsize = sizeof(struct ctdb_control_killtcp);
+ data.dsize = sizeof(struct ctdb_connection);
data.dptr = (unsigned char *)&killtcp[i];
timeout = TIMELIMIT();
static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
- struct ctdb_control_killtcp killtcp;
+ struct ctdb_connection killtcp;
assert_single_node_only();
usage();
}
- if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
+ if (!parse_ip_port(argv[0], &killtcp.src)) {
DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
return -1;
}
- if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
+ if (!parse_ip_port(argv[1], &killtcp.dst)) {
DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
return -1;
}
static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
- struct ctdb_server_id server_id;
+ struct ctdb_client_id server_id;
if (argc < 3) {
usage();
static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
- struct ctdb_server_id server_id;
+ struct ctdb_client_id server_id;
if (argc < 3) {
usage();
*/
static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
{
- uint32_t status;
+ uint32_t status = 0;
int ret;
- struct ctdb_server_id server_id;
+ struct ctdb_client_id server_id;
if (argc < 3) {
usage();
static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
{
int i, ret;
- struct ctdb_server_id_list *server_ids;
+ struct ctdb_client_id_list_old *server_ids;
ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
if (ret != 0) {
{
int i, ret;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_all_public_ips *ips;
+ struct ctdb_public_ip_list_old *ips;
+
+ if (argc == 1 && strcmp(argv[0], "all") == 0) {
+ options.pnn = CTDB_BROADCAST_ALL;
+ }
if (options.pnn == CTDB_BROADCAST_ALL) {
/* read the list of public ips from all nodes */
}
if (options.machinereadable){
- printf(":Public IP:Node:");
+ printm(":Public IP:Node:");
if (options.verbose){
- printf("ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:");
+ printm("ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:");
}
- printf("\n");
+ printm("\n");
} else {
if (options.pnn == CTDB_BROADCAST_ALL) {
printf("Public IPs on ALL nodes\n");
}
for (i=1;i<=ips->num;i++) {
- struct ctdb_control_public_ip_info *info = NULL;
+ struct ctdb_public_ip_info_old *info = NULL;
int32_t pnn;
char *aciface = NULL;
char *avifaces = NULL;
}
if (options.machinereadable){
- printf(":%s:%d:",
+ printm(":%s:%d:",
ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
ips->ips[ips->num-i].pnn);
if (options.verbose){
- printf("%s:%s:%s:",
+ printm("%s:%s:%s:",
aciface?aciface:"",
avifaces?avifaces:"",
cifaces?cifaces:"");
int i, ret;
ctdb_sock_addr addr;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_control_public_ip_info *info;
+ struct ctdb_public_ip_info_old *info;
if (argc != 1) {
talloc_free(tmp_ctx);
{
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
int i;
- struct ctdb_control_get_ifaces *ifaces;
+ struct ctdb_iface_list_old *ifaces;
int ret;
/* read the public ip list from this node */
}
if (options.machinereadable){
- printf(":Name:LinkStatus:References:\n");
+ printm(":Name:LinkStatus:References:\n");
} else {
printf("Interfaces on node %u\n", options.pnn);
}
for (i=0; i<ifaces->num; i++) {
if (options.machinereadable){
- printf(":%s:%s:%u\n",
+ printm(":%s:%s:%u:\n",
ifaces->ifaces[i].name,
ifaces->ifaces[i].link_state?"1":"0",
(unsigned int)ifaces->ifaces[i].references);
{
int ret;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_control_iface_info info;
+ struct ctdb_iface info;
ZERO_STRUCT(info);
const char *desc,
bool set_flag)
{
- struct ctdb_node_map *nodemap = NULL;
+ struct ctdb_node_map_old *nodemap = NULL;
bool flag_is_set;
int ret;
/* Ban a node */
static bool update_state_banned(struct ctdb_context *ctdb, void *data)
{
- struct ctdb_ban_time *bantime = (struct ctdb_ban_time *)data;
+ struct ctdb_ban_state *bantime = (struct ctdb_ban_state *)data;
int ret;
ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, bantime);
static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
{
- struct ctdb_ban_time bantime;
+ struct ctdb_ban_state bantime;
if (argc < 1) {
usage();
/* Unban a node */
static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
{
- struct ctdb_ban_time bantime;
+ struct ctdb_ban_state bantime;
bantime.pnn = options.pnn;
bantime.time = 0;
static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
- struct ctdb_node_map *nodemap=NULL;
- struct ctdb_ban_time *bantime;
+ struct ctdb_node_map_old *nodemap=NULL;
+ struct ctdb_ban_state *bantime;
/* verify the node exists */
ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
{
int ret;
uint32_t generation, next_generation;
- bool force;
-
- /* "force" option ignores freeze failure and forces recovery */
- force = (argc == 1) && (strcasecmp(argv[0], "force") == 0);
/* record the current generation number */
generation = get_generation(ctdb);
- ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
- if (ret != 0) {
- if (!force) {
- DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
- return ret;
- }
- DEBUG(DEBUG_WARNING, ("Unable to freeze node but proceeding because \"force\" option given\n"));
- }
-
ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
if (ret != 0) {
DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
if (!options.machinereadable){
printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
} else {
- printf(":mode:\n");
- printf(":%d:\n",monmode);
+ printm(":mode:\n");
+ printm(":%d:\n",monmode);
}
return 0;
}
DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
return -1;
}
-
+
if (!options.machinereadable){
printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
- printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
} else {
- printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
- printf(":%d:%d:%d:%d:\n",
+ printm(":RECMASTER:LMASTER:LVS:\n");
+ printm(":%d:%d:%d:\n",
!!(capabilities&CTDB_CAP_RECMASTER),
!!(capabilities&CTDB_CAP_LMASTER),
- !!(capabilities&CTDB_CAP_LVS),
- !!(capabilities&CTDB_CAP_NATGW));
+ !!(capabilities&CTDB_CAP_LVS));
}
return 0;
}
static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
{
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_node_map *orig_nodemap=NULL;
- struct ctdb_node_map *nodemap;
+ struct ctdb_node_map_old *orig_nodemap=NULL;
+ struct ctdb_node_map_old *nodemap;
int i, ret;
ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn,
}
nodemap = filter_nodemap_by_capabilities(ctdb, orig_nodemap,
- CTDB_CAP_LVS);
+ CTDB_CAP_LVS, false);
if (nodemap == NULL) {
/* No memory */
ret = -1;
ret = 0;
for (i = 0; lvs_exclude_flags[i] != 0; i++) {
- struct ctdb_node_map *t =
+ struct ctdb_node_map_old *t =
filter_nodemap_by_flags(ctdb, nodemap,
lvs_exclude_flags[i]);
if (t == NULL) {
static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
{
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_node_map *orig_nodemap=NULL;
- struct ctdb_node_map *nodemap;
+ struct ctdb_node_map_old *nodemap=NULL;
int i, ret;
ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn,
- tmp_ctx, &orig_nodemap);
+ tmp_ctx, &nodemap);
if (ret != 0) {
DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
talloc_free(tmp_ctx);
return -1;
}
- nodemap = filter_nodemap_by_capabilities(ctdb, orig_nodemap,
- CTDB_CAP_LVS);
- if (nodemap == NULL) {
- /* No memory */
- ret = -1;
- goto done;
- }
-
for (i = 0; lvs_exclude_flags[i] != 0; i++) {
- struct ctdb_node_map *t =
+ struct ctdb_node_map_old *t =
filter_nodemap_by_flags(ctdb, nodemap,
lvs_exclude_flags[i]);
if (t == NULL) {
goto done;
}
if (t->num > 0) {
- ret = 0;
- printf(options.machinereadable ?
- "%d\n" : "Node %d is LVS master\n",
- t->nodes[0].pnn);
- goto done;
+ struct ctdb_node_map_old *n;
+ n = filter_nodemap_by_capabilities(ctdb,
+ t,
+ CTDB_CAP_LVS,
+ true);
+ if (n == NULL) {
+ /* No memory */
+ ret = -1;
+ goto done;
+ }
+ if (n->num > 0) {
+ ret = 0;
+ if (options.machinereadable) {
+ printm("%d\n", n->nodes[0].pnn);
+ } else {
+ printf("Node %d is LVS master\n", n->nodes[0].pnn);
+ }
+ goto done;
+ }
}
talloc_free(t);
}
}
ZERO_STRUCT(c);
+ c.ctdb = ctdb;
c.f = stdout;
c.printemptyrecords = (bool)options.printemptyrecords;
c.printdatasize = (bool)options.printdatasize;
d->count++;
ZERO_STRUCT(c);
+ c.ctdb = d->ctdb;
c.f = stdout;
c.printemptyrecords = (bool)options.printemptyrecords;
c.printdatasize = (bool)options.printdatasize;
c.printhash = (bool)options.printhash;
c.printrecordflags = true;
- return ctdb_dumpdb_record(d->ctdb, key, data, &c);
+ return ctdb_dumpdb_record(key, data, &c);
}
/*
printf("Data: size:%d ptr:[%.*s]\n", (int)data.dsize, (int)data.dsize, data.dptr);
- talloc_free(ctdb_db);
talloc_free(tmp_ctx);
+ talloc_free(ctdb_db);
return 0;
}
}
talloc_free(h);
- talloc_free(ctdb_db);
talloc_free(tmp_ctx);
+ talloc_free(ctdb_db);
return 0;
}
talloc_free(tmp_ctx);
return -1;
}
- write(fd, data.dptr, data.dsize);
+ sys_write(fd, data.dptr, data.dsize);
close(fd);
} else {
- write(1, data.dptr, data.dsize);
+ sys_write(1, data.dptr, data.dsize);
}
/* abort the transaction */
return -1;
}
- if (!strncmp(argv[1], "0x", 2)) {
- key = hextodata(tmp_ctx, argv[1] + 2);
- if (key.dsize == 0) {
- printf("Failed to convert \"%s\" into a TDB_DATA\n", argv[1]);
- return -1;
- }
- } else {
- key.dptr = discard_const(argv[1]);
- key.dsize = strlen(argv[1]);
+ key = strtodata(tmp_ctx, argv[1], strlen(argv[1]));
+ if (key.dptr == NULL) {
+ printf("Failed to convert \"%s\" into a TDB_DATA\n", argv[1]);
+ return -1;
}
data = tdb_fetch(tdb, key);
return -1;
}
if (options.verbose){
- write(fd, data.dptr, data.dsize);
+ sys_write(fd, data.dptr, data.dsize);
} else {
- write(fd, data.dptr+sizeof(struct ctdb_ltdb_header), data.dsize-sizeof(struct ctdb_ltdb_header));
+ sys_write(fd, data.dptr+sizeof(struct ctdb_ltdb_header), data.dsize-sizeof(struct ctdb_ltdb_header));
}
close(fd);
} else {
if (options.verbose){
- write(1, data.dptr, data.dsize);
+ sys_write(1, data.dptr, data.dsize);
} else {
- write(1, data.dptr+sizeof(struct ctdb_ltdb_header), data.dsize-sizeof(struct ctdb_ltdb_header));
+ sys_write(1, data.dptr+sizeof(struct ctdb_ltdb_header), data.dsize-sizeof(struct ctdb_ltdb_header));
}
}
return -1;
}
- if (!strncmp(argv[1], "0x", 2)) {
- key = hextodata(tmp_ctx, argv[1] + 2);
- if (key.dsize == 0) {
- printf("Failed to convert \"%s\" into a TDB_DATA\n", argv[1]);
- return -1;
- }
- } else {
- key.dptr = discard_const(argv[1]);
- key.dsize = strlen(argv[1]);
+ key = strtodata(tmp_ctx, argv[1], strlen(argv[1]));
+ if (key.dptr == NULL) {
+ printf("Failed to convert \"%s\" into a TDB_DATA\n", argv[1]);
+ return -1;
}
- if (!strncmp(argv[2], "0x", 2)) {
- value = hextodata(tmp_ctx, argv[2] + 2);
- if (value.dsize == 0) {
- printf("Failed to convert \"%s\" into a TDB_DATA\n", argv[2]);
- return -1;
- }
- } else {
- value.dptr = discard_const(argv[2]);
- value.dsize = strlen(argv[2]);
+ value = strtodata(tmp_ctx, argv[2], strlen(argv[2]));
+ if (value.dptr == NULL) {
+ printf("Failed to convert \"%s\" into a TDB_DATA\n", argv[2]);
+ return -1;
}
ZERO_STRUCT(header);
talloc_free(tmp_ctx);
return -1;
}
- ret = read(fd, data.dptr, data.dsize);
+ ret = sys_read(fd, data.dptr, data.dsize);
if (ret != data.dsize) {
DEBUG(DEBUG_ERR,("Failed to read %d bytes of record data\n", (int)data.dsize));
close(fd);
return -1;
}
- key.dptr = discard_const(argv[1]);
- key.dsize = strlen(argv[1]);
+ key = strtodata(tmp_ctx, argv[1], strlen(argv[1]));
+ if (key.dptr == NULL) {
+ printf("Failed to convert \"%s\" into a TDB_DATA\n", argv[1]);
+ return -1;
+ }
+
ret = ctdb_transaction_store(h, key, data);
if (ret != 0) {
DEBUG(DEBUG_ERR,("Failed to store record\n"));
return -1;
}
- key.dptr = discard_const(argv[1]);
- key.dsize = strlen(argv[1]);
+ key = strtodata(tmp_ctx, argv[1], strlen(argv[1]));
+ if (key.dptr == NULL) {
+ printf("Failed to convert \"%s\" into a TDB_DATA\n", argv[1]);
+ return -1;
+ }
+
ret = ctdb_transaction_store(h, key, tdb_null);
if (ret != 0) {
DEBUG(DEBUG_ERR, ("Failed to delete record\n"));
n = strcspn(t, "\"");
if (t[n] == '"') {
if (n > 0) {
- data->dsize = n;
- data->dptr = talloc_memdup(mem_ctx, t, n);
+ *data = strtodata(mem_ctx, t, n);
CTDB_NOMEM_ABORT(data->dptr);
}
ret = t + n + 1;
port = atoi(argv[0]);
- s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == -1) {
printf("Failed to open local socket\n");
return errno;
}
bzero(&sin, sizeof(sin));
- sin.sin_family = PF_INET;
+ sin.sin_family = AF_INET;
sin.sin_port = htons(port);
ret = bind(s, (struct sockaddr *)&sin, sizeof(sin));
close(s);
}
-
-static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
- TDB_DATA data, void *private_data)
+/* Reload public IPs on a specified nodes */
+static int control_reloadips(struct ctdb_context *ctdb, int argc, const char **argv)
{
- DEBUG(DEBUG_ERR,("Log data received\n"));
- if (data.dsize > 0) {
- printf("%s", data.dptr);
- }
+ TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+ uint32_t *nodes;
+ uint32_t pnn_mode;
+ uint32_t timeout;
+ int ret;
- exit(0);
-}
+ assert_single_node_only();
-/*
- display a list of log messages from the in memory ringbuffer
- */
-static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
-{
- int ret, i;
- bool main_daemon;
- struct ctdb_get_log_addr log_addr;
- TDB_DATA data;
- struct timeval tv;
-
- /* Process options */
- main_daemon = true;
- log_addr.pnn = ctdb_get_pnn(ctdb);
- log_addr.level = DEBUG_NOTICE;
- for (i = 0; i < argc; i++) {
- if (strcmp(argv[i], "recoverd") == 0) {
- main_daemon = false;
- } else {
- if (isalpha(argv[i][0]) || argv[i][0] == '-') {
- log_addr.level = get_debug_by_desc(argv[i]);
- } else {
- log_addr.level = strtol(argv[i], NULL, 0);
- }
- }
- }
-
- /* Our message port is our PID */
- log_addr.srvid = getpid();
-
- data.dptr = (unsigned char *)&log_addr;
- data.dsize = sizeof(log_addr);
-
- DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
-
- ctdb_client_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
- sleep(1);
-
- DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
-
- if (main_daemon) {
- int32_t res;
- char *errmsg;
- TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
-
- ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
- 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
- if (ret != 0 || res != 0) {
- DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
- talloc_free(tmp_ctx);
- return -1;
- }
- talloc_free(tmp_ctx);
- } else {
- ret = ctdb_client_send_message(ctdb, options.pnn,
- CTDB_SRVID_GETLOG, data);
- if (ret != 0) {
- DEBUG(DEBUG_ERR,("Failed to send getlog request message to %u\n", options.pnn));
- return -1;
- }
- }
-
- tv = timeval_current();
- /* this loop will terminate when we have received the reply */
- while (timeval_elapsed(&tv) < (double)options.timelimit) {
- event_loop_once(ctdb->ev);
- }
-
- DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
-
- return 0;
-}
-
-/*
- clear the in memory log area
- */
-static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
-{
- int ret;
-
- if (argc == 0 || (argc >= 1 && strcmp(argv[0], "recoverd") != 0)) {
- /* "recoverd" not given - get logs from main daemon */
- int32_t res;
- char *errmsg;
- TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
-
- ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
- 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
- if (ret != 0 || res != 0) {
- DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
- talloc_free(tmp_ctx);
- return -1;
- }
-
- talloc_free(tmp_ctx);
- } else {
- TDB_DATA data; /* unused in recoverd... */
- data.dsize = 0;
-
- ret = ctdb_client_send_message(ctdb, options.pnn, CTDB_SRVID_CLEARLOG, data);
- if (ret != 0) {
- DEBUG(DEBUG_ERR,("Failed to send clearlog request message to %u\n", options.pnn));
- return -1;
- }
- }
-
- return 0;
-}
-
-/* Reload public IPs on a specified nodes */
-static int control_reloadips(struct ctdb_context *ctdb, int argc, const char **argv)
-{
- TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- uint32_t *nodes;
- uint32_t pnn_mode;
- uint32_t timeout;
- int ret;
-
- assert_single_node_only();
-
- if (argc > 1) {
- usage();
- }
+ if (argc > 1) {
+ usage();
+ }
/* Determine the nodes where IPs need to be reloaded */
if (!parse_nodestring(ctdb, tmp_ctx, argc == 1 ? argv[0] : NULL,
static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
{
int i, ret;
- struct ctdb_dbid_map *dbmap=NULL;
+ struct ctdb_dbid_map_old *dbmap=NULL;
ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
if (ret != 0) {
}
if(options.machinereadable){
- printf(":ID:Name:Path:Persistent:Sticky:Unhealthy:ReadOnly:\n");
+ printm(":ID:Name:Path:Persistent:Sticky:Unhealthy:ReadOnly:\n");
for(i=0;i<dbmap->num;i++){
- const char *path;
- const char *name;
- const char *health;
+ const char *path = NULL;
+ const char *name = NULL;
+ const char *health = NULL;
bool persistent;
bool readonly;
bool sticky;
ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
- dbmap->dbs[i].dbid, ctdb, &path);
+ dbmap->dbs[i].db_id, ctdb, &path);
ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
- dbmap->dbs[i].dbid, ctdb, &name);
+ dbmap->dbs[i].db_id, ctdb, &name);
ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
- dbmap->dbs[i].dbid, ctdb, &health);
+ dbmap->dbs[i].db_id, ctdb, &health);
persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
readonly = dbmap->dbs[i].flags & CTDB_DB_FLAGS_READONLY;
sticky = dbmap->dbs[i].flags & CTDB_DB_FLAGS_STICKY;
- printf(":0x%08X:%s:%s:%d:%d:%d:%d:\n",
- dbmap->dbs[i].dbid, name, path,
+ printm(":0x%08X:%s:%s:%d:%d:%d:%d:\n",
+ dbmap->dbs[i].db_id, name, path,
!!(persistent), !!(sticky),
!!(health), !!(readonly));
}
printf("Number of databases:%d\n", dbmap->num);
for(i=0;i<dbmap->num;i++){
- const char *path;
- const char *name;
- const char *health;
+ const char *path = NULL;
+ const char *name = NULL;
+ const char *health = NULL;
bool persistent;
bool readonly;
bool sticky;
- ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
- ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
- ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
+ ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].db_id, ctdb, &path);
+ ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].db_id, ctdb, &name);
+ ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].db_id, ctdb, &health);
persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
readonly = dbmap->dbs[i].flags & CTDB_DB_FLAGS_READONLY;
sticky = dbmap->dbs[i].flags & CTDB_DB_FLAGS_STICKY;
printf("dbid:0x%08x name:%s path:%s%s%s%s%s\n",
- dbmap->dbs[i].dbid, name, path,
+ dbmap->dbs[i].db_id, name, path,
persistent?" PERSISTENT":"",
sticky?" STICKY":"",
readonly?" READONLY":"",
const char *db_name;
uint32_t db_id;
uint8_t flags;
- const char *path;
- const char *health;
+ const char *path = NULL;
+ const char *health = NULL;
if (argc < 1) {
usage();
DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
return -1;
}
+ if (ret == 1) {
+ DEBUG(DEBUG_WARNING,
+ ("Setting obsolete tunable variable '%s'\n",
+ name));
+ }
return 0;
}
DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
return ret;
} else {
+ enum debug_level log_level = debug_level_from_int(level);
+ const char *desc = debug_level_to_string(log_level);
+ if (desc == NULL) {
+ /* This should never happen */
+ desc = "Unknown";
+ }
if (options.machinereadable){
- printf(":Name:Level:\n");
- printf(":%s:%d:\n",get_debug_by_level(level),level);
+ printm(":Name:Level:\n");
+ printm(":%s:%d:\n", desc, level);
} else {
- printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
+ printf("Node %u is at debug level %s (%d)\n",
+ options.pnn, desc, level);
}
}
return 0;
} else {
if (options.machinereadable){
if (reclock != NULL) {
- printf("%s", reclock);
+ printm("%s", reclock);
}
} else {
if (reclock == NULL) {
static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
- const char *reclock;
+ const char *reclock = NULL;
if (argc == 0) {
reclock = NULL;
return 0;
}
-/*
- set the natgw state on/off
- */
-static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
-{
- int ret;
- uint32_t natgwstate;
-
- if (argc == 0) {
- usage();
- }
-
- if (!strcmp(argv[0], "on")) {
- natgwstate = 1;
- } else if (!strcmp(argv[0], "off")) {
- natgwstate = 0;
- } else {
- usage();
- }
-
- ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
- if (ret != 0) {
- DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
- return ret;
- }
-
- return 0;
-}
-
/*
set the lmaster role on/off
*/
static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
- uint32_t lmasterrole;
+ uint32_t lmasterrole = 0;
if (argc == 0) {
usage();
static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
- uint32_t recmasterrole;
+ uint32_t recmasterrole = 0;
if (argc == 0) {
usage();
*/
static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
{
- int i, ret;
+ int ret;
int32_t level;
+ enum debug_level log_level;
if (argc == 0) {
printf("You must specify the debug level. Valid levels are:\n");
- for (i=0; debug_levels[i].description != NULL; i++) {
- printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
- }
-
+ printf("\tERROR | WARNING | NOTICE | INFO | DEBUG\n");
return 0;
}
- if (isalpha(argv[0][0]) || argv[0][0] == '-') {
- level = get_debug_by_desc(argv[0]);
- } else {
- level = strtol(argv[0], NULL, 0);
- }
-
- for (i=0; debug_levels[i].description != NULL; i++) {
- if (level == debug_levels[i].level) {
- break;
- }
- }
- if (debug_levels[i].description == NULL) {
+ if (!debug_level_parse(argv[0], &log_level)) {
printf("Invalid debug level, must be one of\n");
- for (i=0; debug_levels[i].description != NULL; i++) {
- printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
- }
+ printf("\tERROR | WARNING | NOTICE | INFO | DEBUG\n");
return -1;
}
+ level = debug_level_to_int(log_level);
+
ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
if (ret != 0) {
DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
return 0;
}
+/*
+ * detach from a database
+ */
+static int control_detach(struct ctdb_context *ctdb, int argc,
+ const char **argv)
+{
+ uint32_t db_id;
+ uint8_t flags;
+ int ret, i, status = 0;
+ struct ctdb_node_map_old *nodemap = NULL;
+ TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+ uint32_t recmode;
+
+ if (argc < 1) {
+ usage();
+ }
+
+ assert_single_node_only();
+
+ ret = ctdb_ctrl_getrecmode(ctdb, tmp_ctx, TIMELIMIT(), options.pnn,
+ &recmode);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR, ("Database cannot be detached "
+ "when recovery is active\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
+ &nodemap);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
+ options.pnn));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ for (i=0; i<nodemap->num; i++) {
+ uint32_t value;
+
+ if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
+ continue;
+ }
+
+ if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
+ continue;
+ }
+
+ if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
+ DEBUG(DEBUG_ERR, ("Database cannot be detached on "
+ "inactive (stopped or banned) node "
+ "%u\n", nodemap->nodes[i].pnn));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(),
+ nodemap->nodes[i].pnn,
+ "AllowClientDBAttach",
+ &value);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR, ("Unable to get tunable "
+ "AllowClientDBAttach from node %u\n",
+ nodemap->nodes[i].pnn));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ if (value == 1) {
+ DEBUG(DEBUG_ERR, ("Database access is still active on "
+ "node %u. Set AllowClientDBAttach=0 "
+ "on all nodes.\n",
+ nodemap->nodes[i].pnn));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+ }
+
+ talloc_free(tmp_ctx);
+
+ for (i=0; i<argc; i++) {
+ if (!db_exists(ctdb, argv[i], &db_id, NULL, &flags)) {
+ continue;
+ }
+
+ if (flags & CTDB_DB_FLAGS_PERSISTENT) {
+ DEBUG(DEBUG_ERR, ("Persistent database '%s' "
+ "cannot be detached\n", argv[i]));
+ status = -1;
+ continue;
+ }
+
+ ret = ctdb_detach(ctdb, db_id);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR, ("Database '%s' detach failed\n",
+ argv[i]));
+ status = ret;
+ }
+ }
+
+ return status;
+}
+
/*
set db priority
*/
ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
if (ret != 0 || res != 0) {
- DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
+ if (errmsg != NULL) {
+ DEBUG(DEBUG_ERR,
+ ("Failed to run eventscripts - %s\n", errmsg));
+ } else {
+ DEBUG(DEBUG_ERR, ("Failed to run eventscripts\n"));
+ }
talloc_free(tmp_ctx);
return -1;
}
static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
{
struct backup_data *bd = talloc_get_type(private, struct backup_data);
- struct ctdb_rec_data *rec;
+ struct ctdb_rec_data_old *rec;
/* add the record */
rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
goto done;
}
strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME-1);
- ret = write(fh, &dbhdr, sizeof(dbhdr));
+ ret = sys_write(fh, &dbhdr, sizeof(dbhdr));
if (ret == -1) {
DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
goto done;
}
- ret = write(fh, bd->records, bd->len);
+ ret = sys_write(fh, bd->records, bd->len);
if (ret == -1) {
DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
goto done;
TDB_DATA data;
struct db_file_header dbhdr;
struct ctdb_db_context *ctdb_db;
- struct ctdb_node_map *nodemap=NULL;
+ struct ctdb_node_map_old *nodemap=NULL;
struct ctdb_vnn_map *vnnmap=NULL;
int i, fh;
- struct ctdb_control_wipe_database w;
+ struct ctdb_transdb w;
uint32_t *nodes;
uint32_t generation;
struct tm *tm;
return -1;
}
- read(fh, &dbhdr, sizeof(dbhdr));
+ sys_read(fh, &dbhdr, sizeof(dbhdr));
if (dbhdr.version != DB_VERSION) {
DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
close(fh);
talloc_free(tmp_ctx);
return -1;
}
- read(fh, outdata.dptr, outdata.dsize);
+ sys_read(fh, outdata.dptr, outdata.dsize);
close(fh);
tm = localtime(&dbhdr.timestamp);
w.db_id = ctdb_db->db_id;
- w.transaction_id = generation;
+ w.tid = generation;
data.dptr = (void *)&w;
data.dsize = sizeof(w);
int i, fh;
struct tm *tm;
char tbuf[100];
- struct ctdb_rec_data *rec = NULL;
+ struct ctdb_rec_data_old *rec = NULL;
struct ctdb_marshall_buffer *m;
struct ctdb_dump_db_context c;
return -1;
}
- read(fh, &dbhdr, sizeof(dbhdr));
+ sys_read(fh, &dbhdr, sizeof(dbhdr));
if (dbhdr.version != DB_VERSION) {
DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
close(fh);
talloc_free(tmp_ctx);
return -1;
}
- read(fh, outdata.dptr, outdata.dsize);
+ sys_read(fh, outdata.dptr, outdata.dsize);
close(fh);
m = (struct ctdb_marshall_buffer *)outdata.dptr;
dbhdr.name, m->db_id, tbuf);
ZERO_STRUCT(c);
+ c.ctdb = ctdb;
c.f = stdout;
c.printemptyrecords = (bool)options.printemptyrecords;
c.printdatasize = (bool)options.printdatasize;
rec = ctdb_marshall_loop_next(m, rec, &reqid,
NULL, &key, &data);
- ctdb_dumpdb_record(ctdb, key, data, &c);
+ ctdb_dumpdb_record(key, data, &c);
}
printf("Dumped %d records\n", i);
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
TDB_DATA data;
struct ctdb_db_context *ctdb_db;
- struct ctdb_node_map *nodemap = NULL;
+ struct ctdb_node_map_old *nodemap = NULL;
struct ctdb_vnn_map *vnnmap = NULL;
int i;
- struct ctdb_control_wipe_database w;
+ struct ctdb_transdb w;
uint32_t *nodes;
uint32_t generation;
uint8_t flags;
}
w.db_id = ctdb_db->db_id;
- w.transaction_id = generation;
+ w.tid = generation;
data.dptr = (void *)&w;
data.dsize = sizeof(w);
talloc_free(tmp_ctx);
return -1;
}
- write(1, data.dptr, data.dsize);
+ sys_write(1, data.dptr, data.dsize);
talloc_free(tmp_ctx);
return 0;
}
/*
handler for memory dumps
*/
-static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
- TDB_DATA data, void *private_data)
+static void mem_dump_handler(uint64_t srvid, TDB_DATA data, void *private_data)
{
- write(1, data.dptr, data.dsize);
+ sys_write(1, data.dptr, data.dsize);
exit(0);
}
{
int ret;
TDB_DATA data;
- struct srvid_request rd;
+ struct ctdb_srvid_message rd;
rd.pnn = ctdb_get_pnn(ctdb);
rd.srvid = getpid();
}
/* this loop will terminate when we have received the reply */
- while (1) {
- event_loop_once(ctdb->ev);
+ while (1) {
+ tevent_loop_once(ctdb->ev);
}
return 0;
/*
handler for msglisten
*/
-static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
- TDB_DATA data, void *private_data)
+static void msglisten_handler(uint64_t srvid, TDB_DATA data,
+ void *private_data)
{
int i;
ctdb_client_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
printf("Listening for messages on srvid:%d\n", (int)srvid);
- while (1) {
- event_loop_once(ctdb->ev);
+ while (1) {
+ tevent_loop_once(ctdb->ev);
}
return 0;
static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
- struct pnn_node *pnn_nodes;
- struct pnn_node *pnn_node;
+ struct ctdb_node_map_old *node_map;
+ int i;
assert_single_node_only();
- pnn_nodes = read_nodes_file(mem_ctx);
- if (pnn_nodes == NULL) {
- DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
+ node_map = read_nodes_file(mem_ctx);
+ if (node_map == NULL) {
talloc_free(mem_ctx);
return -1;
}
- for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
- ctdb_sock_addr addr;
- if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
- DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
- talloc_free(mem_ctx);
- return -1;
+ for (i = 0; i < node_map->num; i++) {
+ const char *addr;
+
+ if (node_map->nodes[i].flags & NODE_FLAGS_DELETED) {
+ continue;
}
+ addr = ctdb_addr_to_str(&node_map->nodes[i].addr);
if (options.machinereadable){
- printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
+ printm(":%d:%s:\n", node_map->nodes[i].pnn, addr);
} else {
- printf("%s\n", pnn_node->addr);
+ printf("%s\n", addr);
}
}
talloc_free(mem_ctx);
return 0;
}
+/**********************************************************************/
+/* reload the nodes file on all nodes */
+
+static void get_nodes_files_callback(struct ctdb_context *ctdb,
+ uint32_t node_pnn, int32_t res,
+ TDB_DATA outdata, void *callback_data)
+{
+ struct ctdb_node_map_old **maps =
+ talloc_get_type(callback_data, struct ctdb_node_map_old *);
+
+ if (outdata.dsize < offsetof(struct ctdb_node_map_old, nodes) ||
+ outdata.dptr == NULL) {
+ DEBUG(DEBUG_ERR,
+ (__location__ " Invalid return data: %u %p\n",
+ (unsigned)outdata.dsize, outdata.dptr));
+ return;
+ }
+
+ if (node_pnn >= talloc_array_length(maps)) {
+ DEBUG(DEBUG_ERR,
+ (__location__ " unexpected PNN %u\n", node_pnn));
+ return;
+ }
+
+ maps[node_pnn] = talloc_memdup(maps, outdata.dptr, outdata.dsize);
+}
+
+static void get_nodes_files_fail_callback(struct ctdb_context *ctdb,
+ uint32_t node_pnn, int32_t res,
+ TDB_DATA outdata, void *callback_data)
+{
+ DEBUG(DEBUG_ERR,
+ ("ERROR: Failed to get nodes file from node %u\n", node_pnn));
+}
+
+static struct ctdb_node_map_old **
+ctdb_get_nodes_files(struct ctdb_context *ctdb,
+ TALLOC_CTX *mem_ctx,
+ struct timeval timeout,
+ struct ctdb_node_map_old *nodemap)
+{
+ uint32_t *nodes;
+ int ret;
+ struct ctdb_node_map_old **maps;
+
+ maps = talloc_zero_array(mem_ctx, struct ctdb_node_map_old *, nodemap->num);
+ CTDB_NO_MEMORY_NULL(ctdb, maps);
+
+ nodes = list_of_connected_nodes(ctdb, nodemap, mem_ctx, true);
+
+ ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_GET_NODES_FILE,
+ nodes, 0, TIMELIMIT(),
+ true, tdb_null,
+ get_nodes_files_callback,
+ get_nodes_files_fail_callback,
+ maps);
+ if (ret != 0) {
+ talloc_free(maps);
+ return NULL;
+ }
+
+ return maps;
+}
+
+static bool node_files_are_identical(struct ctdb_node_map_old *nm1,
+ struct ctdb_node_map_old *nm2)
+{
+ int i;
+
+ if (nm1->num != nm2->num) {
+ return false;
+ }
+ for (i = 0; i < nm1->num; i++) {
+ if (memcmp(&nm1->nodes[i], &nm2->nodes[i],
+ sizeof(struct ctdb_node_and_flags)) != 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool check_all_node_files_are_identical(struct ctdb_context *ctdb,
+ TALLOC_CTX *mem_ctx,
+ struct timeval timeout,
+ struct ctdb_node_map_old *nodemap,
+ struct ctdb_node_map_old *file_nodemap)
+{
+ static struct ctdb_node_map_old **maps;
+ int i;
+ bool ret = true;
+
+ maps = ctdb_get_nodes_files(ctdb, mem_ctx, timeout, nodemap);
+ if (maps == NULL) {
+ return false;
+ }
+
+ for (i = 0; i < talloc_array_length(maps); i++) {
+ if (maps[i] == NULL) {
+ continue;
+ }
+ if (!node_files_are_identical(file_nodemap, maps[i])) {
+ DEBUG(DEBUG_ERR,
+ ("ERROR: Node file on node %u differs from current node (%u)\n",
+ i, ctdb_get_pnn(ctdb)));
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
/*
reload the nodes file on the local node
*/
+static bool sanity_check_nodes_file_changes(TALLOC_CTX *mem_ctx,
+ struct ctdb_node_map_old *nodemap,
+ struct ctdb_node_map_old *file_nodemap)
+{
+ int i;
+ bool should_abort = false;
+ bool have_changes = false;
+
+ for (i=0; i<nodemap->num; i++) {
+ if (i >= file_nodemap->num) {
+ DEBUG(DEBUG_ERR,
+ ("ERROR: Node %u (%s) missing from nodes file\n",
+ nodemap->nodes[i].pnn,
+ ctdb_addr_to_str(&nodemap->nodes[i].addr)));
+ should_abort = true;
+ continue;
+ }
+ if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED &&
+ file_nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
+ /* Node remains deleted */
+ DEBUG(DEBUG_INFO,
+ ("Node %u is unchanged (DELETED)\n",
+ nodemap->nodes[i].pnn));
+ } else if (!(nodemap->nodes[i].flags & NODE_FLAGS_DELETED) &&
+ !(file_nodemap->nodes[i].flags & NODE_FLAGS_DELETED)) {
+ /* Node not newly nor previously deleted */
+ if (!ctdb_same_ip(&nodemap->nodes[i].addr,
+ &file_nodemap->nodes[i].addr)) {
+ DEBUG(DEBUG_ERR,
+ ("ERROR: Node %u has changed IP address (was %s, now %s)\n",
+ nodemap->nodes[i].pnn,
+ /* ctdb_addr_to_str() returns a static */
+ talloc_strdup(mem_ctx,
+ ctdb_addr_to_str(&nodemap->nodes[i].addr)),
+ ctdb_addr_to_str(&file_nodemap->nodes[i].addr)));
+ should_abort = true;
+ } else {
+ DEBUG(DEBUG_INFO,
+ ("Node %u is unchanged\n",
+ nodemap->nodes[i].pnn));
+ if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
+ DEBUG(DEBUG_WARNING,
+ ("WARNING: Node %u is disconnected. You MUST fix this node manually!\n",
+ nodemap->nodes[i].pnn));
+ }
+ }
+ } else if (file_nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
+ /* Node is being deleted */
+ DEBUG(DEBUG_NOTICE,
+ ("Node %u is DELETED\n",
+ nodemap->nodes[i].pnn));
+ have_changes = true;
+ if (!(nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
+ DEBUG(DEBUG_ERR,
+ ("ERROR: Node %u is still connected\n",
+ nodemap->nodes[i].pnn));
+ should_abort = true;
+ }
+ } else if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
+ /* Node was previously deleted */
+ DEBUG(DEBUG_NOTICE,
+ ("Node %u is UNDELETED\n", nodemap->nodes[i].pnn));
+ have_changes = true;
+ }
+ }
+
+ if (should_abort) {
+ DEBUG(DEBUG_ERR,
+ ("ERROR: Nodes will not be reloaded due to previous error\n"));
+ talloc_free(mem_ctx);
+ exit(1);
+ }
+
+ /* Leftover nodes in file are NEW */
+ for (; i < file_nodemap->num; i++) {
+ DEBUG(DEBUG_NOTICE, ("Node %u is NEW\n",
+ file_nodemap->nodes[i].pnn));
+ have_changes = true;
+ }
+
+ return have_changes;
+}
+
+static void reload_nodes_fail_callback(struct ctdb_context *ctdb,
+ uint32_t node_pnn, int32_t res,
+ TDB_DATA outdata, void *callback_data)
+{
+ DEBUG(DEBUG_WARNING,
+ ("WARNING: Node %u failed to reload nodes. You MUST fix this node manually!\n",
+ node_pnn));
+}
+
static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
{
int i, ret;
- int mypnn;
- struct ctdb_node_map *nodemap=NULL;
+ struct ctdb_node_map_old *nodemap=NULL;
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ struct ctdb_node_map_old *file_nodemap;
+ uint32_t *conn;
+ uint32_t timeout;
- assert_single_node_only();
+ assert_current_node_only(ctdb);
- mypnn = ctdb_get_pnn(ctdb);
+ /* Load both the current nodemap and the contents of the local
+ * nodes file. Compare and sanity check them before doing
+ * anything. */
ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
if (ret != 0) {
return ret;
}
- /* reload the nodes file on all remote nodes */
- for (i=0;i<nodemap->num;i++) {
- if (nodemap->nodes[i].pnn == mypnn) {
- continue;
- }
- DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
- ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
- nodemap->nodes[i].pnn);
- if (ret != 0) {
- DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
- }
+ file_nodemap = read_nodes_file(tmp_ctx);
+ if (file_nodemap == NULL) {
+ DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
+ talloc_free(tmp_ctx);
+ return -1;
}
- /* reload the nodes file on the local node */
- DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
- ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
- if (ret != 0) {
- DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
+ if (!check_all_node_files_are_identical(ctdb, tmp_ctx, TIMELIMIT(),
+ nodemap, file_nodemap)) {
+ return -1;
}
- /* initiate a recovery */
- control_recover(ctdb, argc, argv);
+ if (!sanity_check_nodes_file_changes(tmp_ctx, nodemap, file_nodemap)) {
+ DEBUG(DEBUG_NOTICE,
+ ("No change in nodes file, skipping unnecessary reload\n"));
+ talloc_free(tmp_ctx);
+ return 0;
+ }
+
+ /* Now make the changes */
+ conn = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
+ for (i = 0; i < talloc_array_length(conn); i++) {
+ DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n",
+ conn[i]));
+ }
+
+ /* Another timeout could be used, such as ReRecoveryTimeout or
+ * a new one for this purpose. However, this is the simplest
+ * option. */
+ timeout = options.timelimit;
+ srvid_broadcast(ctdb, CTDB_SRVID_DISABLE_RECOVERIES, &timeout,
+ "Disable recoveries", true);
+
+
+ ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELOAD_NODES_FILE,
+ conn, 0, TIMELIMIT(),
+ true, tdb_null,
+ NULL, reload_nodes_fail_callback,
+ NULL);
+
+ timeout = 0;
+ srvid_broadcast(ctdb, CTDB_SRVID_DISABLE_RECOVERIES, &timeout,
+ "Enable recoveries", true);
+
+ talloc_free(tmp_ctx);
return 0;
}
{ "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
{ "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
{ "getdebug", control_getdebug, true, false, "get debug level" },
- { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "[<level>] [recoverd]" },
- { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer", "[recoverd]" },
{ "attach", control_attach, true, false, "attach to a database", "<dbname> [persistent]" },
+ { "detach", control_detach, false, false, "detach from a database", "<dbname|dbid> [<dbname|dbid> ...]" },
{ "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
{ "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
{ "getpid", control_getpid, true, false, "get ctdbd process ID" },
{ "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
{ "getsrvids", getsrvids, false, false, "get a list of all server ids"},
{ "check_srvids", check_srvids, false, false, "check if a srvid exists", "<id>+" },
- { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
{ "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
{ "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
{ "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
{ "scriptstatus", control_scriptstatus, true, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
{ "enablescript", control_enablescript, true, false, "enable an eventscript", "<script>"},
{ "disablescript", control_disablescript, true, false, "disable an eventscript", "<script>"},
- { "natgwlist", control_natgwlist, true, false, "show the nodes belonging to this natgw configuration"},
+ { "natgwlist", control_natgwlist, false, true, "show the nodes belonging to this natgw configuration"},
{ "xpnn", control_xpnn, false, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
{ "getreclock", control_getreclock, true, false, "Show the reclock file of a node"},
{ "setreclock", control_setreclock, true, false, "Set/clear the reclock file of a node", "[filename]"},
- { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
{ "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
{ "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
{ "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbname|dbid> <prio:1-3>"},
"Usage: ctdb [options] <control>\n" \
"Options:\n" \
" -n <node> choose node number, or 'all' (defaults to local node)\n"
-" -Y generate machinereadable output\n"
+" -Y generate machine readable output\n"
+" -x <char> specify delimiter for machine readable output\n"
" -v generate verbose output\n"
" -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
printf("Controls:\n");
{
struct ctdb_context *ctdb;
char *nodestring = NULL;
+ int machineparsable = 0;
struct poptOption popt_options[] = {
POPT_AUTOHELP
POPT_CTDB_CMDLINE
{ "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
{ "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
- { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
+ { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machine readable output", NULL },
+ { NULL, 'x', POPT_ARG_STRING, &options.machineseparator, 0, "specify separator for machine readable output", "char" },
+ { NULL, 'X', POPT_ARG_NONE, &machineparsable, 0, "enable machine parsable output with separator |", NULL },
{ "verbose", 'v', POPT_ARG_NONE, &options.verbose, 0, "enable verbose output", NULL },
{ "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
{ "print-emptyrecords", 0, POPT_ARG_NONE, &options.printemptyrecords, 0, "print the empty records when dumping databases (catdb, cattdb, dumpdbbackup)", NULL },
int extra_argc = 0;
int ret=-1, i;
poptContext pc;
- struct event_context *ev;
+ struct tevent_context *ev;
const char *control;
setlinebuf(stdout);
}
}
+ if (machineparsable) {
+ options.machineseparator = "|";
+ }
+ if (options.machineseparator != NULL) {
+ if (strlen(options.machineseparator) != 1) {
+ printf("Invalid separator \"%s\" - "
+ "must be single character\n",
+ options.machineseparator);
+ exit(1);
+ }
+
+ /* -x implies -Y */
+ options.machinereadable = true;
+ } else if (options.machinereadable) {
+ options.machineseparator = ":";
+ }
+
signal(SIGALRM, ctdb_alarm);
alarm(options.maxruntime);
control = extra_argv[0];
/* Default value for CTDB_BASE - don't override */
- setenv("CTDB_BASE", ETCDIR "/ctdb", 0);
+ setenv("CTDB_BASE", CTDB_ETCDIR, 0);
- ev = event_context_init(NULL);
+ ev = tevent_context_init(NULL);
if (!ev) {
DEBUG(DEBUG_ERR, ("Failed to initialize event system\n"));
exit(1);
ctdb = ctdb_cmdline_client(ev, TIMELIMIT());
if (ctdb == NULL) {
+ uint32_t pnn;
DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
+
+ pnn = find_node_xpnn();
+ if (pnn == -1) {
+ DEBUG(DEBUG_ERR,
+ ("Is this node part of a CTDB cluster?\n"));
+ }
exit(1);
}