#include "system/filesys.h"
#include "system/time.h"
#include "system/wait.h"
+#include "system/dir.h"
#include <ctype.h>
#include <popt.h>
#include <tevent.h>
#include <tdb.h>
-#include "ctdb_version.h"
+#include "common/version.h"
#include "lib/util/debug.h"
#include "lib/util/samba_util.h"
+#include "lib/util/sys_rw.h"
#include "common/db_hash.h"
#include "common/logging.h"
+#include "common/path.h"
#include "protocol/protocol.h"
#include "protocol/protocol_api.h"
-#include "common/system.h"
+#include "protocol/protocol_util.h"
+#include "common/system_socket.h"
#include "client/client.h"
+#include "client/client_sync.h"
#define TIMEOUT() timeval_current_ofs(options.timelimit, 0)
#define SRVID_CTDB_PUSHDB (CTDB_SRVID_TOOL_RANGE | 0x0002000000000000LL)
static struct {
- const char *socket;
const char *debuglevelstr;
int timelimit;
int pnn;
ctdb_sock_addr addr;
uint32_t num;
struct ctdb_node_and_flags *n;
+ int ret;
- if (! parse_ip(nstr, NULL, 0, &addr)) {
+ ret = ctdb_sock_addr_from_string(nstr, &addr, false);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", nstr);
return false;
}
static struct ctdb_node_map *read_nodes_file(TALLOC_CTX *mem_ctx, uint32_t pnn)
{
struct ctdb_node_map *nodemap;
- char *nodepath;
const char *nodes_list = NULL;
- if (pnn != CTDB_UNKNOWN_PNN) {
- nodepath = talloc_asprintf(mem_ctx, "CTDB_NODES_%u", pnn);
- if (nodepath != NULL) {
- nodes_list = getenv(nodepath);
- }
- }
- if (nodes_list == NULL) {
- nodes_list = getenv("CTDB_NODES");
+ const char *basedir = getenv("CTDB_BASE");
+ if (basedir == NULL) {
+ basedir = CTDB_ETCDIR;
}
+ nodes_list = talloc_asprintf(mem_ctx, "%s/nodes", basedir);
if (nodes_list == NULL) {
- const char *basedir = getenv("CTDB_BASE");
- if (basedir == NULL) {
- basedir = CTDB_ETCDIR;
- }
- nodes_list = talloc_asprintf(mem_ctx, "%s/nodes", basedir);
- if (nodes_list == NULL) {
- fprintf(stderr, "Memory allocation error\n");
- return NULL;
- }
+ fprintf(stderr, "Memory allocation error\n");
+ return NULL;
}
nodemap = ctdb_read_nodes_file(mem_ctx, nodes_list);
return h - 'a' + 10;
}
if (h >= 'A' && h <= 'F') {
- return h - 'f' + 10;
+ return h - 'A' + 10;
}
return h - '0';
}
return ret;
}
-static int run_helper(const char *command, const char *path, const char *arg1)
+static int run_helper(TALLOC_CTX *mem_ctx, const char *command,
+ const char *path, int argc, const char **argv)
{
pid_t pid;
int save_errno, status, ret;
+ const char **new_argv;
+ int i;
+
+ new_argv = talloc_array(mem_ctx, const char *, argc + 2);
+ if (new_argv == NULL) {
+ return ENOMEM;
+ }
+
+ new_argv[0] = path;
+ for (i=0; i<argc; i++) {
+ new_argv[i+1] = argv[i];
+ }
+ new_argv[argc+1] = NULL;
pid = fork();
if (pid < 0) {
save_errno = errno;
+ talloc_free(new_argv);
fprintf(stderr, "Failed to fork %s (%s) - %s\n",
command, path, strerror(save_errno));
return save_errno;
}
if (pid == 0) {
- ret = execl(path, path, arg1, NULL);
+ ret = execv(path, discard_const(new_argv));
if (ret == -1) {
- _exit(errno);
+ _exit(64+errno);
}
/* Should not happen */
- _exit(ENOEXEC);
+ _exit(64+ENOEXEC);
}
+ talloc_free(new_argv);
+
ret = waitpid(pid, &status, 0);
if (ret == -1) {
save_errno = errno;
}
if (WIFEXITED(status)) {
- ret = WEXITSTATUS(status);
+ int pstatus = WEXITSTATUS(status);
+ if (WIFSIGNALED(status)) {
+ fprintf(stderr, "%s terminated with signal %d\n",
+ command, WTERMSIG(status));
+ ret = EINTR;
+ } else if (pstatus >= 64 && pstatus < 255) {
+ fprintf(stderr, "%s failed with error %d\n",
+ command, pstatus-64);
+ ret = pstatus - 64;
+ } else {
+ ret = pstatus;
+ }
return ret;
- }
-
- if (WIFSIGNALED(status)) {
+ } else if (WIFSIGNALED(status)) {
fprintf(stderr, "%s terminated with signal %d\n",
command, WTERMSIG(status));
return EINTR;
static int control_version(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
int argc, const char **argv)
{
- printf("%s\n", CTDB_VERSION_STRING);
+ printf("%s\n", ctdb_version_string);
return 0;
}
printf("%s%u%s%s%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%c%s\n",
options.sep,
node->pnn, options.sep,
- ctdb_sock_addr_to_string(mem_ctx, &node->addr),
+ ctdb_sock_addr_to_string(mem_ctx, &node->addr, false),
options.sep,
!! (node->flags & NODE_FLAGS_DISCONNECTED), options.sep,
!! (node->flags & NODE_FLAGS_BANNED), options.sep,
}
static void print_nodemap(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- struct ctdb_node_map *nodemap, uint32_t mypnn)
+ struct ctdb_node_map *nodemap, uint32_t mypnn,
+ bool print_header)
{
struct ctdb_node_and_flags *node;
int num_deleted_nodes = 0;
}
}
- if (num_deleted_nodes == 0) {
- printf("Number of nodes:%d\n", nodemap->num);
- } else {
- printf("Number of nodes:%d (including %d deleted nodes)\n",
- nodemap->num, num_deleted_nodes);
+ if (print_header) {
+ if (num_deleted_nodes == 0) {
+ printf("Number of nodes:%d\n", nodemap->num);
+ } else {
+ printf("Number of nodes:%d "
+ "(including %d deleted nodes)\n",
+ nodemap->num, num_deleted_nodes);
+ }
}
for (i=0; i<nodemap->num; i++) {
printf("pnn:%u %-16s %s%s\n",
node->pnn,
- ctdb_sock_addr_to_string(mem_ctx, &node->addr),
+ ctdb_sock_addr_to_string(mem_ctx, &node->addr, false),
partially_online(mem_ctx, ctdb, node) ?
"PARTIALLYONLINE" :
pretty_print_flags(mem_ctx, node->flags),
{
int i;
- print_nodemap(mem_ctx, ctdb, nodemap, mypnn);
+ print_nodemap(mem_ctx, ctdb, nodemap, mypnn, true);
if (vnnmap->generation == INVALID_GENERATION) {
printf("Generation:INVALID\n");
STATISTICS_FIELD(node.req_message),
STATISTICS_FIELD(node.req_control),
STATISTICS_FIELD(node.reply_control),
+ STATISTICS_FIELD(node.req_tunnel),
STATISTICS_FIELD(client.req_call),
STATISTICS_FIELD(client.req_message),
STATISTICS_FIELD(client.req_control),
+ STATISTICS_FIELD(client.req_tunnel),
STATISTICS_FIELD(timeouts.call),
STATISTICS_FIELD(timeouts.control),
STATISTICS_FIELD(timeouts.traverse),
return 0;
}
+static int ctdb_public_ip_cmp(const void *a, const void *b)
+{
+ const struct ctdb_public_ip *ip_a = a;
+ const struct ctdb_public_ip *ip_b = b;
+
+ return ctdb_sock_addr_cmp(&ip_a->addr, &ip_b->addr);
+}
+
static void print_ip(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
struct ctdb_public_ip_list *ips,
struct ctdb_public_ip_info **ipinfo,
}
}
- /* IPs are reverse sorted */
- for (i=ips->num-1; i>=0; i--) {
+ for (i = 0; i < ips->num; i++) {
if (options.machinereadable == 1) {
printf("%s%s%s%d%s", options.sep,
ctdb_sock_addr_to_string(
- mem_ctx, &ips->ip[i].addr),
+ mem_ctx, &ips->ip[i].addr, false),
options.sep,
(int)ips->ip[i].pnn, options.sep);
} else {
printf("%s", ctdb_sock_addr_to_string(
- mem_ctx, &ips->ip[i].addr));
+ mem_ctx, &ips->ip[i].addr, false));
}
if (options.verbose == 0) {
avail = NULL;
active = NULL;
+ if (ipinfo[i] == NULL) {
+ goto skip_ipinfo;
+ }
+
for (j=0; j<ipinfo[i]->ifaces->num; j++) {
struct ctdb_iface *iface;
conf = talloc_strdup(mem_ctx, iface->name);
} else {
conf = talloc_asprintf_append(
- mem_ctx, ",%s", iface->name);
+ conf, ",%s", iface->name);
}
if (ipinfo[i]->active_idx == j) {
avail = talloc_strdup(mem_ctx, iface->name);
} else {
avail = talloc_asprintf_append(
- mem_ctx, ",%s", iface->name);
+ avail, ",%s", iface->name);
}
}
+ skip_ipinfo:
+
if (options.machinereadable == 1) {
printf("%s%s%s%s%s%s\n",
active ? active : "", options.sep,
avail ? avail : "", options.sep,
conf ? conf : "", options.sep);
} else {
- printf(" node[%u] active[%s] available[%s] configured[%s]\n",
- ips->ip[i].pnn, active ? active : "",
+ printf(" node[%d] active[%s] available[%s]"
+ " configured[%s]\n",
+ (int)ips->ip[i].pnn, active ? active : "",
avail ? avail : "", conf ? conf : "");
}
}
for (i=0; i<count; i++) {
ret = ctdb_ctrl_get_public_ips(mem_ctx, ctdb->ev, ctdb->client,
- pnn_list[i], TIMEOUT(), &ips);
+ pnn_list[i], TIMEOUT(),
+ false, &ips);
if (ret != 0) {
goto failed;
}
ip.pnn = ips->ip[j].pnn;
ip.addr = ips->ip[j].addr;
- ret = db_hash_add(ipdb, (uint8_t *)&ip.addr,
- sizeof(ip.addr),
- (uint8_t *)&ip, sizeof(ip));
- if (ret != 0) {
- goto failed;
+ if (pnn_list[i] == ip.pnn) {
+ /* Node claims IP is hosted on it, so
+ * save that information
+ */
+ ret = db_hash_add(ipdb, (uint8_t *)&ip.addr,
+ sizeof(ip.addr),
+ (uint8_t *)&ip, sizeof(ip));
+ if (ret != 0) {
+ goto failed;
+ }
+ } else {
+ /* Node thinks IP is hosted elsewhere,
+ * so overwrite with CTDB_UNKNOWN_PNN
+ * if there's no existing entry
+ */
+ ret = db_hash_exists(ipdb, (uint8_t *)&ip.addr,
+ sizeof(ip.addr));
+ if (ret == ENOENT) {
+ ip.pnn = CTDB_UNKNOWN_PNN;
+ ret = db_hash_add(ipdb,
+ (uint8_t *)&ip.addr,
+ sizeof(ip.addr),
+ (uint8_t *)&ip,
+ sizeof(ip));
+ if (ret != 0) {
+ goto failed;
+ }
+ }
}
}
ret = get_all_public_ips(ctdb, mem_ctx, &ips);
} else {
ret = ctdb_ctrl_get_public_ips(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT(), &ips);
+ ctdb->cmd_pnn, TIMEOUT(),
+ false, &ips);
}
if (ret != 0) {
return ret;
}
+ qsort(ips->ip, ips->num, sizeof(struct ctdb_public_ip),
+ ctdb_public_ip_cmp);
+
ipinfo = talloc_array(mem_ctx, struct ctdb_public_ip_info *, ips->num);
if (ipinfo == NULL) {
return 1;
} else {
pnn = ctdb->cmd_pnn;
}
+ if (pnn == CTDB_UNKNOWN_PNN) {
+ ipinfo[i] = NULL;
+ continue;
+ }
ret = ctdb_ctrl_get_public_ip_info(mem_ctx, ctdb->ev,
ctdb->client, pnn,
TIMEOUT(), &ips->ip[i].addr,
usage("ipinfo");
}
- if (! parse_ip(argv[0], NULL, 0, &addr)) {
+ ret = ctdb_sock_addr_from_string(argv[0], &addr, false);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[0]);
return 1;
}
}
printf("Public IP[%s] info on node %u\n",
- ctdb_sock_addr_to_string(mem_ctx, &ipinfo->ip.addr),
+ ctdb_sock_addr_to_string(mem_ctx, &ipinfo->ip.addr, false),
ctdb->cmd_pnn);
printf("IP:%s\nCurrentNode:%u\nNumInterfaces:%u\n",
- ctdb_sock_addr_to_string(mem_ctx, &ipinfo->ip.addr),
+ ctdb_sock_addr_to_string(mem_ctx, &ipinfo->ip.addr, false),
ipinfo->ip.pnn, ipinfo->ifaces->num);
for (i=0; i<ipinfo->ifaces->num; i++) {
int argc, const char **argv)
{
pid_t pid;
+ uint64_t srvid = 0;
int ret, status;
- if (argc != 1) {
+ if (argc != 1 && argc != 2) {
usage("process-exists");
}
pid = atoi(argv[0]);
- ret = ctdb_ctrl_process_exists(mem_ctx, ctdb->ev, ctdb->client,
+ if (argc == 2) {
+ srvid = strtoull(argv[1], NULL, 0);
+ }
+
+ if (srvid == 0) {
+ ret = ctdb_ctrl_process_exists(mem_ctx, ctdb->ev, ctdb->client,
ctdb->cmd_pnn, TIMEOUT(), pid, &status);
+ } else {
+ struct ctdb_pid_srvid pid_srvid;
+
+ pid_srvid.pid = pid;
+ pid_srvid.srvid = srvid;
+
+ ret = ctdb_ctrl_check_pid_srvid(mem_ctx, ctdb->ev,
+ ctdb->client, ctdb->cmd_pnn,
+ TIMEOUT(), &pid_srvid,
+ &status);
+ }
+
if (ret != 0) {
return ret;
}
- if (status == 0) {
- printf("PID %u exists\n", pid);
+ if (srvid == 0) {
+ printf("PID %d %s\n", pid,
+ (status == 0 ? "exists" : "does not exist"));
} else {
- printf("PID %u does not exist\n", pid);
+ printf("PID %d with SRVID 0x%"PRIx64" %s\n", pid, srvid,
+ (status == 0 ? "exists" : "does not exist"));
}
return status;
}
}
if (options.machinereadable == 1) {
- printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
options.sep,
"ID", options.sep,
"Name", options.sep,
"Persistent", options.sep,
"Sticky", options.sep,
"Unhealthy", options.sep,
- "Readonly", options.sep);
+ "Readonly", options.sep,
+ "Replicated", options.sep);
} else {
printf("Number of databases:%d\n", dbmap->num);
}
bool persistent;
bool readonly;
bool sticky;
+ bool replicated;
uint32_t db_id;
db_id = dbmap->dbs[i].db_id;
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;
+ replicated = dbmap->dbs[i].flags & CTDB_DB_FLAGS_REPLICATED;
if (options.machinereadable == 1) {
- printf("%s0x%08X%s%s%s%s%s%d%s%d%s%d%s%d%s\n",
+ printf("%s0x%08X%s%s%s%s%s%d%s%d%s%d%s%d%s%d%s\n",
options.sep,
db_id, options.sep,
name, options.sep,
!! (persistent), options.sep,
!! (sticky), options.sep,
!! (health), options.sep,
- !! (readonly), options.sep);
+ !! (readonly), options.sep,
+ !! (replicated), options.sep);
} else {
- printf("dbid:0x%08x name:%s path:%s%s%s%s%s\n",
+ printf("dbid:0x%08x name:%s path:%s%s%s%s%s%s\n",
db_id, name, path,
persistent ? " PERSISTENT" : "",
sticky ? " STICKY" : "",
readonly ? " READONLY" : "",
+ replicated ? " REPLICATED" : "",
health ? " UNHEALTHY" : "");
}
}
printf("dbid: 0x%08x\nname: %s\npath: %s\n", db_id, db_name, db_path);
- printf("PERSISTENT: %s\nSTICKY: %s\nREADONLY: %s\nHEALTH: %s\n",
+ printf("PERSISTENT: %s\nREPLICATED: %s\nSTICKY: %s\nREADONLY: %s\n",
(db_flags & CTDB_DB_FLAGS_PERSISTENT ? "yes" : "no"),
+ (db_flags & CTDB_DB_FLAGS_REPLICATED ? "yes" : "no"),
(db_flags & CTDB_DB_FLAGS_STICKY ? "yes" : "no"),
- (db_flags & CTDB_DB_FLAGS_READONLY ? "yes" : "no"),
- (db_health ? db_health : "OK"));
+ (db_flags & CTDB_DB_FLAGS_READONLY ? "yes" : "no"));
+ printf("HEALTH: %s\n", (db_health ? db_health : "OK"));
return 0;
}
return 0;
}
-struct traverse_state {
- TALLOC_CTX *mem_ctx;
- bool done;
- ctdb_rec_parser_func_t func;
- struct dump_record_state sub_state;
-};
-
-static void traverse_handler(uint64_t srvid, TDB_DATA data, void *private_data)
-{
- struct traverse_state *state = (struct traverse_state *)private_data;
- struct ctdb_rec_data *rec;
- struct ctdb_ltdb_header header;
- int ret;
-
- ret = ctdb_rec_data_pull(data.dptr, data.dsize, state->mem_ctx, &rec);
- if (ret != 0) {
- return;
- }
-
- if (rec->key.dsize == 0 && rec->data.dsize == 0) {
- talloc_free(rec);
- /* end of traverse */
- state->done = true;
- return;
- }
-
- ret = ctdb_ltdb_header_extract(&rec->data, &header);
- if (ret != 0) {
- talloc_free(rec);
- return;
- }
-
- if (rec->data.dsize == 0) {
- talloc_free(rec);
- return;
- }
-
- ret = state->func(rec->reqid, &header, rec->key, rec->data,
- &state->sub_state);
- talloc_free(rec);
- if (ret != 0) {
- state->done = true;
- }
-}
-
static int control_catdb(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
int argc, const char **argv)
{
const char *db_name;
uint32_t db_id;
uint8_t db_flags;
- struct ctdb_traverse_start_ext traverse;
- struct traverse_state state;
+ struct dump_record_state state;
int ret;
if (argc != 1) {
return ret;
}
- /* Valgrind fix */
- ZERO_STRUCT(traverse);
-
- traverse.db_id = db_id;
- traverse.reqid = 0;
- traverse.srvid = next_srvid(ctdb);
- traverse.withemptyrecords = false;
-
- state.mem_ctx = mem_ctx;
- state.done = false;
- state.func = dump_record;
- state.sub_state.count = 0;
-
- ret = ctdb_client_set_message_handler(ctdb->ev, ctdb->client,
- traverse.srvid,
- traverse_handler, &state);
- if (ret != 0) {
- return ret;
- }
-
- ret = ctdb_ctrl_traverse_start_ext(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT(),
- &traverse);
- if (ret != 0) {
- return ret;
- }
-
- ctdb_client_wait(ctdb->ev, &state.done);
+ state.count = 0;
- printf("Dumped %u records\n", state.sub_state.count);
+ ret = ctdb_db_traverse(mem_ctx, ctdb->ev, ctdb->client, db,
+ ctdb->cmd_pnn, TIMEOUT(),
+ dump_record, &state);
- ret = ctdb_client_remove_message_handler(ctdb->ev, ctdb->client,
- traverse.srvid, &state);
- if (ret != 0) {
- return ret;
- }
+ printf("Dumped %u records\n", state.count);
- return 0;
+ return ret;
}
static int control_cattdb(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
}
state.count = 0;
- ret = ctdb_db_traverse(db, true, true, dump_record, &state);
+ ret = ctdb_db_traverse_local(db, true, true, dump_record, &state);
printf("Dumped %u record(s)\n", state.count);
return ret;
}
-static int control_getmonmode(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- int mode, ret;
-
- if (argc != 0) {
- usage("getmonmode");
- }
-
- ret = ctdb_ctrl_get_monmode(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT(), &mode);
- if (ret != 0) {
- return ret;
- }
-
- printf("%s\n",
- (mode == CTDB_MONITORING_ENABLED) ? "ENABLED" : "DISABLED");
- return 0;
-}
-
static int control_getcapabilities(TALLOC_CTX *mem_ctx,
struct ctdb_context *ctdb,
int argc, const char **argv)
return 1;
}
- return run_helper("LVS helper", lvs_helper, argv[0]);
-}
-
-static int control_disable_monitor(TALLOC_CTX *mem_ctx,
- struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- int ret;
-
- if (argc != 0) {
- usage("disablemonitor");
- }
-
- ret = ctdb_ctrl_disable_monitor(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT());
- if (ret != 0) {
- return ret;
- }
-
- return 0;
-}
-
-static int control_enable_monitor(TALLOC_CTX *mem_ctx,
- struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- int ret;
-
- if (argc != 0) {
- usage("enablemonitor");
- }
-
- ret = ctdb_ctrl_enable_monitor(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT());
- if (ret != 0) {
- return ret;
- }
-
- return 0;
+ return run_helper(mem_ctx, "LVS helper", lvs_helper, argc, argv);
}
static int control_setdebug(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
int argc, const char **argv)
{
- enum debug_level log_level;
+ int log_level;
int ret;
bool found;
static int control_getdebug(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
int argc, const char **argv)
{
- enum debug_level loglevel;
+ int loglevel;
const char *log_str;
int ret;
db_flags = CTDB_DB_FLAGS_READONLY;
} else if (strcmp(argv[1], "sticky") == 0) {
db_flags = CTDB_DB_FLAGS_STICKY;
+ } else if (strcmp(argv[1], "replicated") == 0) {
+ db_flags = CTDB_DB_FLAGS_REPLICATED;
} else {
usage("attach");
}
continue;
}
- if (db_flags & CTDB_DB_FLAGS_PERSISTENT) {
+ if (db_flags &
+ (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED)) {
fprintf(stderr,
- "Persistent database %s cannot be detached\n",
- argv[0]);
+ "Only volatile databases can be detached\n");
return 1;
}
- ret = ctdb_detach(mem_ctx, ctdb->ev, ctdb->client,
- TIMEOUT(), db_id);
+ ret = ctdb_detach(ctdb->ev, ctdb->client, TIMEOUT(), db_id);
if (ret != 0) {
fprintf(stderr, "Database %s detach failed\n", db_name);
ret2 = ret;
}
}
+static int ctdb_ctrl_modflags(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ struct ctdb_client_context *client,
+ uint32_t destnode, struct timeval timeout,
+ uint32_t set, uint32_t clear)
+{
+ struct ctdb_node_map *nodemap;
+ struct ctdb_node_flag_change flag_change;
+ struct ctdb_req_control request;
+ uint32_t *pnn_list;
+ int ret, count;
+
+ ret = ctdb_ctrl_get_nodemap(mem_ctx, ev, client, destnode,
+ tevent_timeval_zero(), &nodemap);
+ if (ret != 0) {
+ return ret;
+ }
+
+ flag_change.pnn = destnode;
+ flag_change.old_flags = nodemap->node[destnode].flags;
+ flag_change.new_flags = flag_change.old_flags | set;
+ flag_change.new_flags &= ~clear;
+
+ count = list_of_connected_nodes(nodemap, -1, mem_ctx, &pnn_list);
+ if (count == -1) {
+ return ENOMEM;
+ }
+
+ ctdb_req_control_modify_flags(&request, &flag_change);
+ ret = ctdb_client_control_multi(mem_ctx, ev, client, pnn_list, count,
+ tevent_timeval_zero(), &request,
+ NULL, NULL);
+ return ret;
+}
+
struct ipreallocate_state {
int status;
bool done;
}
+static void wait_for_shutdown(void *private_data)
+{
+ bool *done = (bool *)private_data;
+
+ *done = true;
+}
+
static int control_shutdown(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
int argc, const char **argv)
{
int ret;
+ bool done = false;
if (argc != 0) {
usage("shutdown");
}
+ if (ctdb->pnn == ctdb->cmd_pnn) {
+ ctdb_client_set_disconnect_callback(ctdb->client,
+ wait_for_shutdown,
+ &done);
+ }
+
ret = ctdb_ctrl_shutdown(mem_ctx, ctdb->ev, ctdb->client,
ctdb->cmd_pnn, TIMEOUT());
if (ret != 0) {
return ret;
}
+ if (ctdb->pnn == ctdb->cmd_pnn) {
+ ctdb_client_wait(ctdb->ev, &done);
+ }
+
return 0;
}
usage("gratarp");
}
- if (! parse_ip(argv[0], NULL, 0, &addr_info.addr)) {
+ ret = ctdb_sock_addr_from_string(argv[0], &addr_info.addr, false);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[0]);
return 1;
}
}
if (argc == 0) {
- struct ctdb_connection *clist;
- int count;
- int i, num_failed;
+ struct ctdb_connection_list *clist;
+ int i;
+ unsigned int num_failed;
- ret = ctdb_parse_connections(stdin, mem_ctx, &count, &clist);
+ /* Client first but the src/dst logic is confused */
+ ret = ctdb_connection_list_read(mem_ctx, 0, false, &clist);
if (ret != 0) {
return ret;
}
num_failed = 0;
- for (i=0; i<count; i++) {
- ret = ctdb_sys_send_tcp(&clist[i].src,
- &clist[i].dst,
+ for (i = 0; i < clist->num; i++) {
+ ret = ctdb_sys_send_tcp(&clist->conn[i].src,
+ &clist->conn[i].dst,
0, 0, 0);
if (ret != 0) {
num_failed += 1;
}
- if (! parse_ip_port(argv[0], &src)) {
+ ret = ctdb_sock_addr_from_string(argv[0], &src, true);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[0]);
return 1;
}
- if (! parse_ip_port(argv[1], &dst)) {
+ ret = ctdb_sock_addr_from_string(argv[1], &dst, true);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[1]);
return 1;
}
port = strtoul(argv[1], NULL, 10);
}
- if (! parse_ip(argv[0], NULL, port, &addr)) {
+ ret = ctdb_sock_addr_from_string(argv[0], &addr, false);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[0]);
return 1;
}
+ ctdb_sock_addr_set_port(&addr, port);
ret = ctdb_ctrl_get_tcp_tickle_list(mem_ctx, ctdb->ev, ctdb->client,
ctdb->cmd_pnn, TIMEOUT(), &addr,
for (i=0; i<tickles->num; i++) {
printf("%s%s%s%u%s%s%s%u%s\n", options.sep,
ctdb_sock_addr_to_string(
- mem_ctx, &tickles->conn[i].src),
+ mem_ctx, &tickles->conn[i].src, false),
options.sep,
ntohs(tickles->conn[i].src.ip.sin_port),
options.sep,
ctdb_sock_addr_to_string(
- mem_ctx, &tickles->conn[i].dst),
+ mem_ctx, &tickles->conn[i].dst, false),
options.sep,
ntohs(tickles->conn[i].dst.ip.sin_port),
options.sep);
}
} else {
printf("Connections for IP: %s\n",
- ctdb_sock_addr_to_string(mem_ctx, &tickles->addr));
+ ctdb_sock_addr_to_string(mem_ctx,
+ &tickles->addr, false));
printf("Num connections: %u\n", tickles->num);
for (i=0; i<tickles->num; i++) {
- printf("SRC: %s:%u DST: %s:%u\n",
+ printf("SRC: %s DST: %s\n",
ctdb_sock_addr_to_string(
- mem_ctx, &tickles->conn[i].src),
- ntohs(tickles->conn[i].src.ip.sin_port),
+ mem_ctx, &tickles->conn[i].src, true),
ctdb_sock_addr_to_string(
- mem_ctx, &tickles->conn[i].dst),
- ntohs(tickles->conn[i].dst.ip.sin_port));
+ mem_ctx, &tickles->conn[i].dst, true));
}
}
typedef int (*clist_reply_func)(struct ctdb_reply_control *reply);
struct process_clist_state {
- struct ctdb_connection *clist;
+ struct ctdb_connection_list *clist;
int count;
int num_failed, num_total;
clist_reply_func reply_func;
static struct tevent_req *process_clist_send(
TALLOC_CTX *mem_ctx,
struct ctdb_context *ctdb,
- struct ctdb_connection *clist,
- int count,
+ struct ctdb_connection_list *clist,
clist_request_func request_func,
clist_reply_func reply_func)
{
}
state->clist = clist;
- state->count = count;
state->reply_func = reply_func;
- for (i=0; i<count; i++) {
- request_func(&request, &clist[i]);
+ for (i = 0; i < clist->num; i++) {
+ request_func(&request, &clist->conn[i]);
subreq = ctdb_client_control_send(state, ctdb->ev,
ctdb->client, ctdb->cmd_pnn,
TIMEOUT(), &request);
done:
state->num_total += 1;
- if (state->num_total == state->count) {
+ if (state->num_total == state->clist->num) {
tevent_req_done(req);
}
}
}
if (argc == 0) {
- struct ctdb_connection *clist;
+ struct ctdb_connection_list *clist;
struct tevent_req *req;
- int count;
- ret = ctdb_parse_connections(stdin, mem_ctx, &count, &clist);
+ /* Client first but the src/dst logic is confused */
+ ret = ctdb_connection_list_read(mem_ctx, 0, false, &clist);
if (ret != 0) {
return ret;
}
- if (count == 0) {
+ if (clist->num == 0) {
return 0;
}
- req = process_clist_send(mem_ctx, ctdb, clist, count,
+ req = process_clist_send(mem_ctx, ctdb, clist,
ctdb_req_control_tcp_add_delayed_update,
ctdb_reply_control_tcp_add_delayed_update);
if (req == NULL) {
return 0;
}
- if (! parse_ip_port(argv[0], &conn.src)) {
+ ret = ctdb_sock_addr_from_string(argv[0], &conn.src, true);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[0]);
return 1;
}
- if (! parse_ip_port(argv[1], &conn.dst)) {
+ ret = ctdb_sock_addr_from_string(argv[1], &conn.dst, true);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[1]);
return 1;
}
}
if (argc == 0) {
- struct ctdb_connection *clist;
+ struct ctdb_connection_list *clist;
struct tevent_req *req;
- int count;
- ret = ctdb_parse_connections(stdin, mem_ctx, &count, &clist);
+ /* Client first but the src/dst logic is confused */
+ ret = ctdb_connection_list_read(mem_ctx, 0, false, &clist);
if (ret != 0) {
return ret;
}
- if (count == 0) {
+ if (clist->num == 0) {
return 0;
}
- req = process_clist_send(mem_ctx, ctdb, clist, count,
+ req = process_clist_send(mem_ctx, ctdb, clist,
ctdb_req_control_tcp_remove,
ctdb_reply_control_tcp_remove);
if (req == NULL) {
return 0;
}
- if (! parse_ip_port(argv[0], &conn.src)) {
+ ret = ctdb_sock_addr_from_string(argv[0], &conn.src, true);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[0]);
return 1;
}
- if (! parse_ip_port(argv[1], &conn.dst)) {
+ ret = ctdb_sock_addr_from_string(argv[1], &conn.dst, true);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[1]);
return 1;
}
return 0;
}
-static int control_check_srvids(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- uint64_t *srvid;
- uint8_t *result;
- int ret, i;
-
- if (argc == 0) {
- usage("check_srvids");
- }
-
- srvid = talloc_array(mem_ctx, uint64_t, argc);
- if (srvid == NULL) {
- fprintf(stderr, "Memory allocation error\n");
- return 1;
- }
-
- for (i=0; i<argc; i++) {
- srvid[i] = strtoull(argv[i], NULL, 0);
- }
-
- ret = ctdb_ctrl_check_srvids(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT(), srvid, argc,
- &result);
- if (ret != 0) {
- fprintf(stderr, "Failed to check srvids on node %u\n",
- ctdb->cmd_pnn);
- return ret;
- }
-
- for (i=0; i<argc; i++) {
- printf("SRVID 0x%" PRIx64 " %s\n", srvid[i],
- (result[i] ? "exists" : "does not exist"));
- }
-
- return 0;
-}
-
static int control_listnodes(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
int argc, const char **argv)
{
printf("%s%u%s%s%s\n", options.sep,
nodemap->node[i].pnn, options.sep,
ctdb_sock_addr_to_string(
- mem_ctx, &nodemap->node[i].addr),
+ mem_ctx, &nodemap->node[i].addr, false),
options.sep);
} else {
printf("%s\n",
ctdb_sock_addr_to_string(
- mem_ctx, &nodemap->node[i].addr));
+ mem_ctx, &nodemap->node[i].addr, false));
}
}
"Node %u (%s) missing from nodes file\n",
nm->node[i].pnn,
ctdb_sock_addr_to_string(
- mem_ctx, &nm->node[i].addr));
+ mem_ctx, &nm->node[i].addr, false));
check_failed = true;
continue;
}
" (was %s, now %s)\n",
nm->node[i].pnn,
ctdb_sock_addr_to_string(
- mem_ctx, &nm->node[i].addr),
+ mem_ctx,
+ &nm->node[i].addr, false),
ctdb_sock_addr_to_string(
- mem_ctx, &fnm->node[i].addr));
+ mem_ctx,
+ &fnm->node[i].addr, false));
check_failed = true;
} else {
if (nm->node[i].flags & NODE_FLAGS_DISCONNECTED) {
}
ret = ctdb_ctrl_get_public_ips(mem_ctx, ctdb->ev, ctdb->client,
- pnn, TIMEOUT(), &pubip_list);
+ pnn, TIMEOUT(), false, &pubip_list);
if (ret != 0) {
fprintf(stderr, "Failed to get Public IPs from node %u\n",
pnn);
if (i == pubip_list->num) {
fprintf(stderr, "Node %u CANNOT host IP address %s\n",
- pnn, ctdb_sock_addr_to_string(mem_ctx, addr));
+ pnn, ctdb_sock_addr_to_string(mem_ctx, addr, false));
return 1;
}
usage("moveip");
}
- if (! parse_ip(argv[0], NULL, 0, &addr)) {
+ ret = ctdb_sock_addr_from_string(argv[0], &addr, false);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[0]);
return 1;
}
return 0;
}
-static int control_rebalanceip(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- ctdb_sock_addr addr;
- struct ctdb_node_map *nodemap;
- struct ctdb_public_ip pubip;
- struct ctdb_req_control request;
- uint32_t *pnn_list;
- int ret, count;
-
- if (argc != 1) {
- usage("rebalanceip");
- }
-
- if (parse_ip(argv[0], NULL, 0, &addr)) {
- fprintf(stderr, "Invalid IP address %s\n", argv[0]);
- return 1;
- }
-
- ret = ctdb_message_disable_ip_check(mem_ctx, ctdb->ev, ctdb->client,
- CTDB_BROADCAST_CONNECTED,
- 2*options.timelimit);
- if (ret != 0) {
- fprintf(stderr, "Failed to disable IP check\n");
- return 1;
- }
-
- nodemap = get_nodemap(ctdb, false);
- if (nodemap == NULL) {
- return 1;
- }
-
- count = list_of_active_nodes(nodemap, -1, mem_ctx, &pnn_list);
- if (count <= 0) {
- fprintf(stderr, "Memory allocation error\n");
- return 1;
- }
-
- pubip.pnn = CTDB_UNKNOWN_PNN;
- pubip.addr = addr;
-
- ctdb_req_control_release_ip(&request, &pubip);
- ret = ctdb_client_control_multi(mem_ctx, ctdb->ev, ctdb->client,
- pnn_list, count, TIMEOUT(),
- &request, NULL, NULL);
- if (ret != 0) {
- fprintf(stderr, "Failed to release IP from nodes\n");
- return 1;
- }
-
- return ipreallocate(mem_ctx, ctdb);
-}
-
static int rebalancenode(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
uint32_t pnn)
{
usage("addip");
}
- if (! parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
+ ret = ctdb_sock_addr_mask_from_string(argv[0], &addr, &mask);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP/Mask %s\n", argv[0]);
return 1;
}
ret = ctdb_ctrl_get_public_ips(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT(), &pubip_list);
+ ctdb->cmd_pnn, TIMEOUT(),
+ false, &pubip_list);
if (ret != 0) {
fprintf(stderr, "Failed to get Public IPs from node %u\n",
ctdb->cmd_pnn);
for (i=0; i<pubip_list->num; i++) {
if (ctdb_same_ip(&addr, &pubip_list->ip[i].addr)) {
fprintf(stderr, "Node already knows about IP %s\n",
- ctdb_sock_addr_to_string(mem_ctx, &addr));
+ ctdb_sock_addr_to_string(mem_ctx,
+ &addr, false));
return 0;
}
}
return ret;
}
- return ipreallocate(mem_ctx, ctdb);
+ return 0;
}
static int control_delip(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
usage("delip");
}
- if (! parse_ip(argv[0], NULL, 0, &addr)) {
+ ret = ctdb_sock_addr_from_string(argv[0], &addr, false);
+ if (ret != 0) {
fprintf(stderr, "Invalid IP address %s\n", argv[0]);
return 1;
}
ret = ctdb_ctrl_get_public_ips(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT(), &pubip_list);
+ ctdb->cmd_pnn, TIMEOUT(),
+ false, &pubip_list);
if (ret != 0) {
fprintf(stderr, "Failed to get Public IPs from node %u\n",
ctdb->cmd_pnn);
if (i == pubip_list->num) {
fprintf(stderr, "Node does not know about IP address %s\n",
- ctdb_sock_addr_to_string(mem_ctx, &addr));
+ ctdb_sock_addr_to_string(mem_ctx, &addr, false));
return 0;
}
return 0;
}
-static int control_eventscript(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- int ret;
-
- if (argc != 1) {
- usage("eventscript");
- }
-
- if (strcmp(argv[0], "monitor") != 0) {
- fprintf(stderr, "Only monitor event can be run\n");
- return 1;
- }
-
- ret = ctdb_ctrl_run_eventscripts(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT(), argv[0]);
- if (ret != 0) {
- fprintf(stderr, "Failed to run monitor event on node %u\n",
- ctdb->cmd_pnn);
- return ret;
- }
-
- return 0;
-}
-
#define DB_VERSION 3
#define MAX_DB_NAME 64
#define MAX_REC_BUFFER_SIZE (100*1000)
state.nbuf = 0;
state.nrec = 0;
- ret = ctdb_db_traverse(db, true, false, backup_handler, &state);
+ ret = ctdb_db_traverse_local(db, true, false, backup_handler, &state);
if (ret != 0) {
fprintf(stderr, "Failed to collect records from DB %s\n",
db_name);
uint32_t generation;
uint32_t *pnn_list;
char timebuf[128];
+ ssize_t n;
int fd, i;
int count, ret;
+ uint8_t db_flags;
if (argc < 1 || argc > 2) {
usage("restoredb");
db_name = argv[1];
}
- ret = read(fd, &db_hdr, sizeof(struct db_header));
- if (ret == -1) {
+ n = read(fd, &db_hdr, sizeof(struct db_header));
+ if (n == -1) {
ret = errno;
close(fd);
fprintf(stderr, "Failed to read db header from file %s\n",
argv[0]);
return ret;
}
+ db_hdr.name[sizeof(db_hdr.name)-1] = '\0';
if (db_hdr.version != DB_VERSION) {
fprintf(stderr,
localtime(&db_hdr.timestamp));
printf("Restoring database %s from backup @ %s\n", db_name, timebuf);
+ db_flags = db_hdr.flags & 0xff;
ret = ctdb_attach(ctdb->ev, ctdb->client, TIMEOUT(), db_name,
- db_hdr.flags, &db);
+ db_flags, &db);
if (ret != 0) {
- fprintf(stderr, "Failed to attach to DB %s\n", db_hdr.name);
+ fprintf(stderr, "Failed to attach to DB %s\n", db_name);
+ close(fd);
return ret;
}
for (i=0; i<db_hdr.nbuf; i++) {
struct ctdb_req_message message;
TDB_DATA data;
+ size_t np;
ret = ctdb_rec_buffer_read(fd, mem_ctx, &recbuf);
if (ret != 0) {
goto failed;
}
- ctdb_rec_buffer_push(recbuf, data.dptr);
+ ctdb_rec_buffer_push(recbuf, data.dptr, &np);
message.srvid = pulldb.srvid;
message.data.data = data;
}
printf("Database %s restored\n", db_name);
+ close(fd);
return 0;
struct db_header db_hdr;
char timebuf[128];
struct dumpdbbackup_state state;
+ ssize_t n;
int fd, ret, i;
if (argc != 1) {
return ret;
}
- ret = read(fd, &db_hdr, sizeof(struct db_header));
- if (ret == -1) {
+ n = read(fd, &db_hdr, sizeof(struct db_header));
+ if (n == -1) {
ret = errno;
close(fd);
fprintf(stderr, "Failed to read db header from file %s\n",
argv[0]);
return ret;
}
+ db_hdr.name[sizeof(db_hdr.name)-1] = '\0';
if (db_hdr.version != DB_VERSION) {
fprintf(stderr,
return 0;
}
-static void print_scriptstatus_one(struct ctdb_script_list *slist,
- const char *event_str)
+static int control_event(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
+ int argc, const char **argv)
{
- int i;
- int num_run = 0;
-
- if (slist == NULL) {
- if (! options.machinereadable) {
- printf("%s cycle never run\n", event_str);
- }
- return;
- }
-
- for (i=0; i<slist->num_scripts; i++) {
- if (slist->script[i].status != -ENOEXEC) {
- num_run++;
- }
- }
-
- if (! options.machinereadable) {
- printf("%d scripts were executed last %s cycle\n",
- num_run, event_str);
- }
-
- for (i=0; i<slist->num_scripts; i++) {
- const char *status = NULL;
-
- switch (slist->script[i].status) {
- case -ETIME:
- status = "TIMEDOUT";
- break;
- case -ENOEXEC:
- status = "DISABLED";
- break;
- case 0:
- status = "OK";
- break;
- default:
- if (slist->script[i].status > 0) {
- status = "ERROR";
- }
- break;
- }
+ char *t, *event_helper = NULL;
- if (options.machinereadable) {
- printf("%s%s%s%s%s%i%s%s%s%lu.%06lu%s%lu.%06lu%s%s%s\n",
- options.sep,
- event_str, options.sep,
- slist->script[i].name, options.sep,
- slist->script[i].status, options.sep,
- status, options.sep,
- slist->script[i].start.tv_sec,
- slist->script[i].start.tv_usec, options.sep,
- slist->script[i].finished.tv_sec,
- slist->script[i].finished.tv_usec, options.sep,
- slist->script[i].output, options.sep);
- continue;
- }
-
- if (status) {
- printf("%-20s Status:%s ",
- slist->script[i].name, status);
- } else {
- /* Some other error, eg from stat. */
- printf("%-20s Status:CANNOT RUN (%s)",
- slist->script[i].name,
- strerror(-slist->script[i].status));
- }
-
- if (slist->script[i].status >= 0) {
- printf("Duration:%.3lf ",
- timeval_delta(&slist->script[i].finished,
- &slist->script[i].start));
- }
- if (slist->script[i].status != -ENOEXEC) {
- printf("%s", ctime(&slist->script[i].start.tv_sec));
- if (slist->script[i].status != 0) {
- printf(" OUTPUT:%s\n",
- slist->script[i].output);
- }
- } else {
- printf("\n");
- }
+ t = getenv("CTDB_EVENT_HELPER");
+ if (t != NULL) {
+ event_helper = talloc_strdup(mem_ctx, t);
+ } else {
+ event_helper = talloc_asprintf(mem_ctx, "%s/ctdb-event",
+ CTDB_HELPER_BINDIR);
}
-}
-static void print_scriptstatus(struct ctdb_script_list **slist,
- int count, const char **event_str)
-{
- int i;
-
- if (options.machinereadable) {
- printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
- options.sep,
- "Type", options.sep,
- "Name", options.sep,
- "Code", options.sep,
- "Status", options.sep,
- "Start", options.sep,
- "End", options.sep,
- "Error Output", options.sep);
+ if (event_helper == NULL) {
+ fprintf(stderr, "Unable to set event daemon helper\n");
+ return 1;
}
- for (i=0; i<count; i++) {
- print_scriptstatus_one(slist[i], event_str[i]);
- }
+ return run_helper(mem_ctx, "event daemon helper", event_helper,
+ argc, argv);
}
static int control_scriptstatus(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
int argc, const char **argv)
{
- struct ctdb_script_list **slist;
- const char *event_str;
- enum ctdb_event event;
- const char *all_events[] = {
- "init", "setup", "startup", "monitor",
- "takeip", "releaseip", "updateip", "ipreallocated" };
- bool valid;
- int ret, i, j;
- int count, start, end, num;
+ const char *new_argv[4];
if (argc > 1) {
usage("scriptstatus");
}
- if (argc == 0) {
- event_str = "monitor";
- } else {
- event_str = argv[0];
- }
-
- valid = false;
- end = 0;
-
- for (i=0; i<ARRAY_SIZE(all_events); i++) {
- if (strcmp(event_str, all_events[i]) == 0) {
- valid = true;
- count = 1;
- start = i;
- end = i+1;
- break;
- }
- }
-
- if (strcmp(event_str, "all") == 0) {
- valid = true;
- count = ARRAY_SIZE(all_events);
- start = 0;
- end = count-1;
- }
-
- if (! valid) {
- fprintf(stderr, "Unknown event name %s\n", argv[0]);
- usage("scriptstatus");
- }
-
- slist = talloc_array(mem_ctx, struct ctdb_script_list *, count);
- if (slist == NULL) {
- fprintf(stderr, "Memory allocation error\n");
- return 1;
- }
-
- num = 0;
- for (i=start; i<end; i++) {
- event = ctdb_event_from_string(all_events[i]);
-
- ret = ctdb_ctrl_get_event_script_status(mem_ctx, ctdb->ev,
- ctdb->client,
- ctdb->cmd_pnn,
- TIMEOUT(), event,
- &slist[num]);
- if (ret != 0) {
- fprintf(stderr,
- "failed to get script status for %s event\n",
- all_events[i]);
- return 1;
- }
-
- if (slist[num] == NULL) {
- num++;
- continue;
- }
-
- /* The ETIME status is ignored for certain events.
- * In that case the status is 0, but endtime is not set.
- */
- for (j=0; j<slist[num]->num_scripts; j++) {
- if (slist[num]->script[j].status == 0 &&
- timeval_is_zero(&slist[num]->script[j].finished)) {
- slist[num]->script[j].status = -ETIME;
- }
- }
-
- num++;
- }
-
- print_scriptstatus(slist, count, &all_events[start]);
- return 0;
-}
-
-static int control_enablescript(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- int ret;
-
- if (argc != 1) {
- usage("enablescript");
- }
-
- ret = ctdb_ctrl_enable_script(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT(), argv[0]);
- if (ret != 0) {
- fprintf(stderr, "Failed to enable script %s\n", argv[0]);
- return ret;
- }
-
- return 0;
-}
-
-static int control_disablescript(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- int ret;
-
- if (argc != 1) {
- usage("disablescript");
- }
-
- ret = ctdb_ctrl_disable_script(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->cmd_pnn, TIMEOUT(), argv[0]);
- if (ret != 0) {
- fprintf(stderr, "Failed to disable script %s\n", argv[0]);
- return ret;
- }
+ new_argv[0] = "status";
+ new_argv[1] = "legacy";
+ new_argv[2] = (argc == 0) ? "monitor" : argv[0];
+ new_argv[3] = NULL;
+ (void) control_event(mem_ctx, ctdb, 3, new_argv);
return 0;
}
return 1;
}
- return run_helper("NAT gateway helper", natgw_helper, argv[0]);
-}
-
-static int control_natgwlist(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- char *t, *natgw_helper = NULL;
-
- if (argc != 0) {
- usage("natgwlist");
- }
-
- t = getenv("CTDB_NATGW_HELPER");
- if (t != NULL) {
- natgw_helper = talloc_strdup(mem_ctx, t);
- } else {
- natgw_helper = talloc_asprintf(mem_ctx, "%s/ctdb_natgw",
- CTDB_HELPER_BINDIR);
- }
-
- if (natgw_helper == NULL) {
- fprintf(stderr, "Unable to set NAT gateway helper\n");
- return 1;
- }
-
- return run_helper("NAT gateway helper", natgw_helper, "natgwlist");
+ return run_helper(mem_ctx, "NAT gateway helper", natgw_helper,
+ argc, argv);
}
/*
return 1;
}
- if (db_flags & CTDB_DB_FLAGS_PERSISTENT) {
- fprintf(stderr, "Cannot set READONLY on persistent DB\n");
+ if (db_flags & (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED)) {
+ fprintf(stderr, "READONLY can be set only on volatile DB\n");
return 1;
}
return 1;
}
- if (db_flags & CTDB_DB_FLAGS_PERSISTENT) {
- fprintf(stderr, "Cannot set STICKY on persistent DB\n");
+ if (db_flags & (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED)) {
+ fprintf(stderr, "STICKY can be set only on volatile DB\n");
return 1;
}
TDB_DATA key, data;
int ret;
- if (argc < 2 || argc > 3) {
+ if (argc != 2) {
usage("pfetch");
}
return 1;
}
- if (! (db_flags & CTDB_DB_FLAGS_PERSISTENT)) {
- fprintf(stderr, "DB %s is not a persistent database\n",
+ if (! (db_flags &
+ (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED))) {
+ fprintf(stderr, "Transactions not supported on DB %s\n",
db_name);
return 1;
}
return 1;
}
- if (! (db_flags & CTDB_DB_FLAGS_PERSISTENT)) {
- fprintf(stderr, "DB %s is not a persistent database\n",
+ if (! (db_flags &
+ (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED))) {
+ fprintf(stderr, "Transactions not supported on DB %s\n",
db_name);
return 1;
}
return 1;
}
- if (! (db_flags & CTDB_DB_FLAGS_PERSISTENT)) {
- fprintf(stderr, "DB %s is not a persistent database\n",
+ if (! (db_flags &
+ (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED))) {
+ fprintf(stderr, "Transactions not supported on DB %s\n",
db_name);
return 1;
}
return 1;
}
- if (! (db_flags & CTDB_DB_FLAGS_PERSISTENT)) {
- fprintf(stderr, "DB %s is not a persistent database\n",
+ if (! (db_flags &
+ (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED))) {
+ fprintf(stderr, "Transactions not supported on DB %s\n",
db_name);
return 1;
}
int argc, const char **argv)
{
struct tdb_context *tdb;
- TDB_DATA key, data, value;
+ TDB_DATA key, data[2], value;
struct ctdb_ltdb_header header;
- size_t offset;
+ uint8_t header_buf[sizeof(struct ctdb_ltdb_header)];
+ size_t np;
int ret;
if (argc < 3 || argc > 5) {
header.flags = (uint32_t)atol(argv[5]);
}
- offset = ctdb_ltdb_header_len(&header);
- data.dsize = offset + value.dsize;
- data.dptr = talloc_size(mem_ctx, data.dsize);
- if (data.dptr == NULL) {
- fprintf(stderr, "Memory allocation error\n");
- tdb_close(tdb);
- return 1;
- }
+ ctdb_ltdb_header_push(&header, header_buf, &np);
+
+ data[0].dsize = np;
+ data[0].dptr = header_buf;
- ctdb_ltdb_header_push(&header, data.dptr);
- memcpy(data.dptr + offset, value.dptr, value.dsize);
+ data[1].dsize = value.dsize;
+ data[1].dptr = value.dptr;
- ret = tdb_store(tdb, key, data, TDB_REPLACE);
+ ret = tdb_storev(tdb, key, data, 2, TDB_REPLACE);
if (ret != 0) {
fprintf(stderr, "Failed to write record %s to file %s\n",
argv[1], argv[0]);
return 1;
}
- if (db_flags & CTDB_DB_FLAGS_PERSISTENT) {
+ if (db_flags & (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED)) {
fprintf(stderr, "DB %s is not a volatile database\n",
db_name);
return 1;
return 1;
}
- if (db_flags & CTDB_DB_FLAGS_PERSISTENT) {
+ if (db_flags & (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED)) {
fprintf(stderr, "DB %s is not a volatile database\n",
db_name);
return 1;
return 1;
}
- if (db_flags & CTDB_DB_FLAGS_PERSISTENT) {
+ if (db_flags & (CTDB_DB_FLAGS_PERSISTENT | CTDB_DB_FLAGS_REPLICATED)) {
fprintf(stderr, "DB %s is not a volatile database\n",
db_name);
return 1;
return 0;
}
-static int control_rebalancenode(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- if (argc != 0) {
- usage("rebalancenode");
- }
-
- if (! rebalancenode(mem_ctx, ctdb, ctdb->cmd_pnn)) {
- fprintf(stderr, "Failed to rebalance IPs on node %u\n",
- ctdb->cmd_pnn);
- return 1;
- }
-
- return 0;
-}
-
static int control_getdbseqnum(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
int argc, const char **argv)
{
const char *nodestring = NULL;
struct ctdb_node_map *nodemap;
int ret, i;
+ bool print_hdr = false;
if (argc > 1) {
usage("nodestatus");
if (argc == 1) {
nodestring = argv[0];
+ if (strcmp(nodestring, "all") == 0) {
+ print_hdr = true;
+ }
}
if (! parse_nodestring(mem_ctx, ctdb, nodestring, &nodemap)) {
return 1;
}
- nodemap = get_nodemap(ctdb, false);
- if (nodemap == NULL) {
- return 1;
- }
-
if (options.machinereadable) {
print_nodemap_machine(mem_ctx, ctdb, nodemap, ctdb->cmd_pnn);
} else {
- print_nodemap(mem_ctx, ctdb, nodemap, ctdb->cmd_pnn);
+ print_nodemap(mem_ctx, ctdb, nodemap, ctdb->cmd_pnn, print_hdr);
}
ret = 0;
DBSTATISTICS_FIELD(locks.num_current),
DBSTATISTICS_FIELD(locks.num_pending),
DBSTATISTICS_FIELD(locks.num_failed),
- DBSTATISTICS_FIELD(db_ro_delegations),
};
static void print_dbstatistics(const char *db_name,
return ipreallocate(mem_ctx, ctdb);
}
-static int control_ipiface(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- ctdb_sock_addr addr;
- char *iface;
-
- if (argc != 1) {
- usage("ipiface");
- }
-
- if (! parse_ip(argv[0], NULL, 0, &addr)) {
- fprintf(stderr, "Failed to Parse IP %s\n", argv[0]);
- return 1;
- }
-
- iface = ctdb_sys_find_ifname(&addr);
- if (iface == NULL) {
- fprintf(stderr, "Failed to find interface for IP %s\n",
- argv[0]);
- return 1;
- }
- free(iface);
-
- return 0;
-}
-
static const struct ctdb_cmd {
const char *name;
{ "uptime", control_uptime, false, true,
"show node uptime", NULL },
{ "ping", control_ping, false, true,
- "ping all nodes", NULL },
+ "ping a node", NULL },
{ "runstate", control_runstate, false, true,
"get/check runstate of a node",
"[setup|first_recovery|startup|running]" },
{ "setifacelink", control_setifacelink, false, true,
"set interface link status", "<iface> up|down" },
{ "process-exists", control_process_exists, false, true,
- "check if a process exists on a node", "<pid>" },
+ "check if a process exists on a node", "<pid> [<srvid>]" },
{ "getdbmap", control_getdbmap, false, true,
"show attached databases", NULL },
{ "getdbstatus", control_getdbstatus, false, true,
"dump cluster-wide ctdb database", "<dbname|dbid>" },
{ "cattdb", control_cattdb, false, false,
"dump local ctdb database", "<dbname|dbid>" },
- { "getmonmode", control_getmonmode, false, true,
- "show monitoring mode", NULL },
{ "getcapabilities", control_getcapabilities, false, true,
"show node capabilities", NULL },
{ "pnn", control_pnn, false, false,
"show the pnn of the currnet node", NULL },
{ "lvs", control_lvs, false, false,
"show lvs configuration", "master|list|status" },
- { "disablemonitor", control_disable_monitor, false, true,
- "disable monitoring", NULL },
- { "enablemonitor", control_enable_monitor, false, true,
- "enable monitoring", NULL },
{ "setdebug", control_setdebug, false, true,
"set debug level", "ERROR|WARNING|NOTICE|INFO|DEBUG" },
{ "getdebug", control_getdebug, false, true,
"get debug level", NULL },
{ "attach", control_attach, false, false,
- "attach a database", "<dbname> [persistent]" },
+ "attach a database", "<dbname> [persistent|replicated]" },
{ "detach", control_detach, false, false,
"detach database(s)", "<dbname|dbid> ..." },
{ "dumpmemory", control_dumpmemory, false, true,
"add a tickle", "<ip>:<port> <ip>:<port>" },
{ "deltickle", control_deltickle, false, true,
"delete a tickle", "<ip>:<port> <ip>:<port>" },
- { "check_srvids", control_check_srvids, false, true,
- "check if srvid is registered", "<id> [<id> ...]" },
{ "listnodes", control_listnodes, true, true,
"list nodes in the cluster", NULL },
{ "reloadnodes", control_reloadnodes, false, false,
"reload the nodes file all nodes", NULL },
{ "moveip", control_moveip, false, false,
"move an ip address to another node", "<ip> <node>" },
- { "rebalanceip", control_rebalanceip, false, false,
- "move an ip address optimally to another node", "<ip>" },
{ "addip", control_addip, false, true,
"add an ip address to a node", "<ip/mask> <iface>" },
{ "delip", control_delip, false, true,
"delete an ip address from a node", "<ip>" },
- { "eventscript", control_eventscript, false, true,
- "run an event", "monitor" },
{ "backupdb", control_backupdb, false, false,
"backup a database into a file", "<dbname|dbid> <file>" },
{ "restoredb", control_restoredb, false, false,
"wipe the contents of a database.", "<dbname|dbid>"},
{ "recmaster", control_recmaster, false, true,
"show the pnn for the recovery master", NULL },
- { "scriptstatus", control_scriptstatus, false, true,
+ { "event", control_event, true, false,
+ "event and event script commands", NULL },
+ { "scriptstatus", control_scriptstatus, true, false,
"show event script status",
"[init|setup|startup|monitor|takeip|releaseip|ipreallocated]" },
- { "enablescript", control_enablescript, false, true,
- "enable an eventscript", "<script>"},
- { "disablescript", control_disablescript, false, true,
- "disable an eventscript", "<script>"},
{ "natgw", control_natgw, false, false,
"show natgw configuration", "master|list|status" },
- { "natgwlist", control_natgwlist, false, false,
- "show the nodes belonging to this natgw configuration", NULL },
{ "getreclock", control_getreclock, false, true,
"get recovery lock file", NULL },
{ "setlmasterrole", control_setlmasterrole, false, true,
{ "setdbsticky", control_setdbsticky, false, true,
"enable sticky records", "<dbname|dbid>"},
{ "pfetch", control_pfetch, false, false,
- "fetch record from persistent database", "<dbname|dbid> <key> [<file>]" },
+ "fetch record from persistent database", "<dbname|dbid> <key>" },
{ "pstore", control_pstore, false, false,
"write record to persistent database", "<dbname|dbid> <key> <value>" },
{ "pdelete", control_pdelete, false, false,
"delete a database key", "<dbname|dbid> <key>" },
{ "checktcpport", control_checktcpport, true, false,
"check if a service is bound to a specific tcp port or not", "<port>" },
- { "rebalancenode", control_rebalancenode, false, true,
- "mark nodes as forced IP rebalancing targets", NULL },
{ "getdbseqnum", control_getdbseqnum, false, false,
"get database sequence number", "<dbname|dbid>" },
{ "nodestatus", control_nodestatus, false, true,
"show database statistics", "<dbname|dbid>" },
{ "reloadips", control_reloadips, false, false,
"reload the public addresses file", "[all|<pnn-list>]" },
- { "ipiface", control_ipiface, true, false,
- "Find the interface an ip address is hosted on", "<ip>" },
};
static const struct ctdb_cmd *match_command(const char *command)
struct poptOption cmdline_options[] = {
POPT_AUTOHELP
- { "socket", 's', POPT_ARG_STRING, &options.socket, 0,
- "CTDB socket path", "filename" },
{ "debug", 'd', POPT_ARG_STRING, &options.debuglevelstr, 0,
"debug level"},
{ "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0,
{
TALLOC_CTX *tmp_ctx;
struct ctdb_context *ctdb;
+ const char *ctdb_socket;
int ret;
bool status;
uint64_t srvid_offset;
goto fail;
}
- ret = ctdb_client_init(ctdb, ctdb->ev, options.socket, &ctdb->client);
+ ctdb_socket = path_socket(ctdb, "ctdbd");
+ if (ctdb_socket == NULL) {
+ fprintf(stderr, "Memory allocation error\n");
+ goto fail;
+ }
+
+ ret = ctdb_client_init(ctdb, ctdb->ev, ctdb_socket, &ctdb->client);
if (ret != 0) {
fprintf(stderr, "Failed to connect to CTDB daemon (%s)\n",
- options.socket);
+ ctdb_socket);
if (!find_node_xpnn(ctdb, NULL)) {
fprintf(stderr, "Is this node part of CTDB cluster?\n");
const char **extra_argv;
int extra_argc;
const struct ctdb_cmd *cmd;
- const char *ctdb_socket;
- enum debug_level loglevel;
+ int loglevel;
+ bool ok;
int ret;
setlinebuf(stdout);
/* Set default options */
- options.socket = CTDB_SOCKET;
options.debuglevelstr = NULL;
options.timelimit = 10;
options.sep = "|";
options.maxruntime = 0;
options.pnn = -1;
- ctdb_socket = getenv("CTDB_SOCKET");
- if (ctdb_socket != NULL) {
- options.socket = ctdb_socket;
- }
-
pc = poptGetContext(argv[0], argc, argv, cmdline_options,
POPT_CONTEXT_KEEP_FIRST);
while ((opt = poptGetNextOpt(pc)) != -1) {
/* Enable logging */
setup_logging("ctdb", DEBUG_STDERR);
- if (debug_level_parse(options.debuglevelstr, &loglevel)) {
- DEBUGLEVEL = loglevel;
- } else {
- DEBUGLEVEL = DEBUG_ERR;
+ ok = debug_level_parse(options.debuglevelstr, &loglevel);
+ if (!ok) {
+ loglevel = DEBUG_ERR;
}
+ debuglevel_set(loglevel);
signal(SIGALRM, alarm_handler);
alarm(options.maxruntime);