#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 "version.h"
#include "lib/util/debug.h"
#include "lib/util/samba_util.h"
+#include "lib/util/sys_rw.h"
+#include "lib/util/smb_strtox.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;
struct ctdb_node_map *nodemap,
uint32_t pnn)
{
- int i;
+ unsigned int i;
for (i=0; i<nodemap->num; i++) {
if (nodemap->node[i].pnn == pnn) {
{ NODE_FLAGS_INACTIVE, "INACTIVE" },
};
char *flags_str = NULL;
- int i;
+ size_t i;
for (i=0; i<ARRAY_SIZE(flag_names); i++) {
if (flags & flag_names[i].flag) {
{
struct ctdb_node_map *nodemap;
bool found;
- int i;
+ unsigned int i;
if (pnn == -1) {
return false;
found = false;
for (i=0; i<nodemap->num; i++) {
- if (nodemap->node[i].pnn == pnn) {
+ if (nodemap->node[i].pnn == (uint32_t)pnn) {
found = true;
break;
}
{
struct ctdb_node_map *nodemap, *nodemap2;
struct ctdb_node_and_flags *node;
- int i;
+ unsigned int i;
nodemap = get_nodemap(ctdb, false);
if (nodemap == NULL) {
goto done;
} else {
char *ns, *tok;
+ int error = 0;
ns = talloc_strdup(mem_ctx, nodestring);
if (ns == NULL) {
tok = strtok(ns, ",");
while (tok != NULL) {
uint32_t pnn;
- char *endptr;
- pnn = (uint32_t)strtoul(tok, &endptr, 0);
- if (pnn == 0 && tok == endptr) {
+ pnn = (uint32_t)smb_strtoul(tok,
+ NULL,
+ 0,
+ &error,
+ SMB_STR_STANDARD);
+ if (error != 0) {
fprintf(stderr, "Invalid node %s\n", tok);
return false;
}
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);
- }
+ 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) {
- nodes_list = getenv("CTDB_NODES");
- }
- 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);
{
struct ctdb_dbid *db = NULL;
const char *name;
- int ret, i;
+ unsigned int i;
+ int ret;
for (i=0; i<dbmap->num; i++) {
ret = ctdb_ctrl_get_dbname(mem_ctx, ctdb->ev, ctdb->client,
struct ctdb_dbid *db = NULL;
uint32_t id = 0;
const char *name = NULL;
- int ret, i;
+ unsigned int i;
+ int ret = 0;
ret = ctdb_ctrl_get_dbmap(mem_ctx, ctdb->ev, ctdb->client,
ctdb->pnn, TIMEOUT(), &dbmap);
}
if (strncmp(db_arg, "0x", 2) == 0) {
- id = strtoul(db_arg, NULL, 0);
+ id = smb_strtoul(db_arg, NULL, 0, &ret, SMB_STR_STANDARD);
+ if (ret != 0) {
+ return false;
+ }
for (i=0; i<dbmap->num; i++) {
if (id == dbmap->dbs[i].db_id) {
db = &dbmap->dbs[i];
return h - 'a' + 10;
}
if (h >= 'A' && h <= 'F') {
- return h - 'f' + 10;
+ return h - 'A' + 10;
}
return h - '0';
}
static int hex_to_data(const char *str, size_t len, TALLOC_CTX *mem_ctx,
TDB_DATA *out)
{
- int i;
+ unsigned int i;
TDB_DATA data;
if (len & 0x01) {
if (strncmp(str, "0x", 2) == 0) {
ret = hex_to_data(str+2, len-2, mem_ctx, &data);
+ if (ret != 0) {
+ return ret;
+ }
} else {
data.dptr = talloc_memdup(mem_ctx, str, len);
if (data.dptr == NULL) {
}
*out = data;
- return ret;
+ return 0;
}
-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", SAMBA_VERSION_STRING);
return 0;
}
struct ctdb_node_and_flags *node)
{
struct ctdb_iface_list *iface_list;
- int ret, i;
+ unsigned int i;
+ int ret;
bool status = false;
if (node->flags != 0) {
uint32_t mypnn)
{
struct ctdb_node_and_flags *node;
- int i;
+ unsigned int i;
printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
options.sep,
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;
- int i;
+ unsigned int i;
for (i=0; i<nodemap->num; i++) {
if (nodemap->node[i].flags & NODE_FLAGS_DELETED) {
}
}
- 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),
struct ctdb_vnn_map *vnnmap, int recmode,
uint32_t recmaster)
{
- int i;
+ unsigned 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");
{
struct ctdb_var_list *tun_var_list;
struct ctdb_tunable tunable;
- int ret, i;
bool found;
+ int i;
+ int ret = 0;
if (argc != 2) {
usage("setvar");
}
tunable.name = argv[0];
- tunable.value = strtoul(argv[1], NULL, 0);
+ tunable.value = smb_strtoul(argv[1], NULL, 0, &ret, SMB_STR_STANDARD);
+ if (ret != 0) {
+ return ret;
+ }
ret = ctdb_ctrl_set_tunable(mem_ctx, ctdb->ev, ctdb->client,
ctdb->cmd_pnn, TIMEOUT(), &tunable);
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),
static void print_statistics_machine(struct ctdb_statistics *s,
bool show_header)
{
- int i;
+ size_t i;
if (show_header) {
printf("CTDB version%s", options.sep);
printf("%.6f%s", LATENCY_AVG(s->call_latency), options.sep);
printf("%.6f%s", s->call_latency.max, options.sep);
+ printf("%u%s", s->locks.latency.num, options.sep);
+ printf("%.6f%s", s->locks.latency.min, options.sep);
+ printf("%.6f%s", LATENCY_AVG(s->locks.latency), options.sep);
+ printf("%.6f%s", s->locks.latency.max, options.sep);
+
printf("%d%s", s->childwrite_latency.num, options.sep);
printf("%.6f%s", s->childwrite_latency.min, options.sep);
printf("%.6f%s", LATENCY_AVG(s->childwrite_latency), options.sep);
static void print_statistics(struct ctdb_statistics *s)
{
int tmp, days, hours, minutes, seconds;
- int i;
+ size_t i;
const char *prefix = NULL;
int preflen = 0;
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,
bool all_nodes)
{
- int i, j;
+ unsigned int i, j;
char *conf, *avail, *active;
if (options.machinereadable == 1) {
}
}
- /* 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 : "");
}
}
struct ctdb_public_ip_list *ips;
struct db_hash_context *ipdb;
uint32_t *pnn_list;
- int ret, count, i, j;
+ unsigned int j;
+ int ret, count, i;
nodemap = get_nodemap(ctdb, false);
if (nodemap == NULL) {
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;
+ }
+ }
}
}
goto failed;
}
- if (count != ips->num) {
+ if ((unsigned int)count != ips->num) {
goto failed;
}
{
struct ctdb_public_ip_list *ips;
struct ctdb_public_ip_info **ipinfo;
- int ret, i;
+ unsigned int i;
+ int ret;
bool do_all = false;
if (argc > 1) {
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,
{
struct ctdb_public_ip_info *ipinfo;
ctdb_sock_addr addr;
- int ret, i;
+ unsigned int i;
+ int ret;
if (argc != 1) {
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)
{
struct ctdb_iface_list *ifaces;
- int ret, i;
+ unsigned int i;
+ int ret;
if (argc != 0) {
usage("ifaces");
{
struct ctdb_iface_list *ifaces;
struct ctdb_iface *iface;
- int ret, i;
+ unsigned int i;
+ int ret;
if (argc != 2) {
usage("setifacelink");
int argc, const char **argv)
{
pid_t pid;
- int ret, status;
+ uint64_t srvid = 0;
+ int status;
+ int ret = 0;
- 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 = smb_strtoull(argv[1], NULL, 0, &ret, SMB_STR_STANDARD);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ 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;
}
int argc, const char **argv)
{
struct ctdb_dbid_map *dbmap;
- int ret, i;
+ unsigned int i;
+ int ret;
if (argc != 0) {
usage("getdbmap");
}
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;
}
static void dump_tdb_data(const char *name, TDB_DATA val)
{
- int i;
+ size_t i;
fprintf(stdout, "%s(%zu) = \"", name, val.dsize);
for (i=0; i<val.dsize; i++) {
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) {
- 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,
int ret;
if (argc != 1) {
- usage("catdb");
+ usage("cattdb");
}
if (! db_exists(mem_ctx, ctdb, argv[0], &db_id, &db_name, &db_flags)) {
}
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");
}
uint8_t db_flags;
struct ctdb_node_map *nodemap;
int recmode;
+ unsigned int j;
int ret, ret2, i;
if (argc < 1) {
return 1;
}
- for (i=0; i<nodemap->num; i++) {
+ for (j=0; j<nodemap->num; j++) {
uint32_t value;
- if (nodemap->node[i].flags & NODE_FLAGS_DISCONNECTED) {
+ if (nodemap->node[j].flags & NODE_FLAGS_DISCONNECTED) {
continue;
}
- if (nodemap->node[i].flags & NODE_FLAGS_DELETED) {
+ if (nodemap->node[j].flags & NODE_FLAGS_DELETED) {
continue;
}
- if (nodemap->node[i].flags & NODE_FLAGS_INACTIVE) {
+ if (nodemap->node[j].flags & NODE_FLAGS_INACTIVE) {
fprintf(stderr, "Database cannot be detached on"
" inactive (stopped or banned) node %u\n",
- nodemap->node[i].pnn);
+ nodemap->node[j].pnn);
return 1;
}
ret = ctdb_ctrl_get_tunable(mem_ctx, ctdb->ev, ctdb->client,
- nodemap->node[i].pnn, TIMEOUT(),
+ nodemap->node[j].pnn, TIMEOUT(),
"AllowClientDBAttach", &value);
if (ret != 0) {
fprintf(stderr,
"Unable to get tunable AllowClientDBAttach"
- " from node %u\n", nodemap->node[i].pnn);
+ " from node %u\n", nodemap->node[j].pnn);
return ret;
}
fprintf(stderr,
"Database access is still active on node %u."
" Set AllowclientDBAttach=0 on all nodes.\n",
- nodemap->node[i].pnn);
+ nodemap->node[j].pnn);
return 1;
}
}
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;
return ret;
}
- n = write(1, mem_str, strlen(mem_str)+1);
- if (n < 0 || n != strlen(mem_str)+1) {
+ n = write(1, mem_str, strlen(mem_str));
+ if (n < 0 || (size_t)n != strlen(mem_str)) {
fprintf(stderr, "Failed to write talloc summary\n");
return 1;
}
static void dump_memory(uint64_t srvid, TDB_DATA data, void *private_data)
{
bool *done = (bool *)private_data;
+ size_t len;
ssize_t n;
- n = write(1, data.dptr, data.dsize);
- if (n < 0 || n != data.dsize) {
+ len = strnlen((const char *)data.dptr, data.dsize);
+ n = write(1, data.dptr, len);
+ if (n < 0 || (size_t)n != len) {
fprintf(stderr, "Failed to write talloc summary\n");
}
}
}
+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;
int argc, const char **argv)
{
struct ctdb_ban_state ban_state;
- int ret;
+ int ret = 0;
if (argc != 1) {
usage("ban");
}
ban_state.pnn = ctdb->cmd_pnn;
- ban_state.time = strtoul(argv[0], NULL, 0);
+ ban_state.time = smb_strtoul(argv[0], NULL, 0, &ret, SMB_STR_STANDARD);
+ if (ret != 0) {
+ return ret;
+ }
if (ban_state.time == 0) {
fprintf(stderr, "Ban time cannot be zero\n");
}
+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;
}
return ret;
}
- if (vnnmap->generation == 1) {
+ if (vnnmap->generation == INVALID_GENERATION) {
talloc_free(vnnmap);
sleep(1);
goto again;
return ipreallocate(mem_ctx, ctdb);
}
-static int control_isnotrecmaster(TALLOC_CTX *mem_ctx,
- struct ctdb_context *ctdb,
- int argc, const char **argv)
-{
- uint32_t recmaster;
- int ret;
-
- if (argc != 0) {
- usage("isnotrecmaster");
- }
-
- ret = ctdb_ctrl_get_recmaster(mem_ctx, ctdb->ev, ctdb->client,
- ctdb->pnn, TIMEOUT(), &recmaster);
- if (ret != 0) {
- fprintf(stderr, "Failed to get recmaster\n");
- return ret;
- }
-
- if (recmaster != ctdb->pnn) {
- printf("this node is not the recmaster\n");
- return 1;
- }
-
- printf("this node is the recmaster\n");
- return 0;
-}
-
static int control_gratarp(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
int argc, const char **argv)
{
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;
+ unsigned 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;
}
}
+ TALLOC_FREE(clist);
+
if (num_failed > 0) {
fprintf(stderr, "Failed to send %d tickles\n",
num_failed);
}
- 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;
}
ctdb_sock_addr addr;
struct ctdb_tickle_list *tickles;
unsigned port = 0;
- int ret, i;
+ unsigned int i;
+ int ret = 0;
if (argc < 1 || argc > 2) {
usage("gettickles");
}
if (argc == 2) {
- port = strtoul(argv[1], NULL, 10);
+ port = smb_strtoul(argv[1], NULL, 10, &ret, SMB_STR_STANDARD);
+ if (ret != 0) {
+ return ret;
+ }
}
- 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));
}
}
+ talloc_free(tickles);
return 0;
}
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;
+ unsigned 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)
{
struct tevent_req *req, *subreq;
struct process_clist_state *state;
struct ctdb_req_control request;
- int i;
+ unsigned int i;
req = tevent_req_create(mem_ctx, &state, struct process_clist_state);
if (req == NULL) {
}
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 (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) {
+ talloc_free(clist);
return ENOMEM;
}
tevent_req_poll(req, ctdb->ev);
+ talloc_free(clist);
ret = process_clist_recv(req);
if (ret != 0) {
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 (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) {
+ talloc_free(clist);
return ENOMEM;
}
tevent_req_poll(req, ctdb->ev);
+ talloc_free(clist);
ret = process_clist_recv(req);
if (ret != 0) {
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)
{
struct ctdb_node_map *nodemap;
- int i;
+ unsigned int i;
if (argc != 0) {
usage("listnodes");
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));
}
}
static bool nodemap_identical(struct ctdb_node_map *nodemap1,
struct ctdb_node_map *nodemap2)
{
- int i;
+ unsigned int i;
if (nodemap1->num != nodemap2->num) {
return false;
struct ctdb_node_map *fnm,
bool *reload)
{
- int i;
+ unsigned int i;
bool check_failed = false;
*reload = 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) {
struct disable_recoveries_state {
uint32_t *pnn_list;
- int node_count;
+ unsigned int node_count;
bool *reply;
int status;
bool done;
{
struct disable_recoveries_state *state =
(struct disable_recoveries_state *)private_data;
- int ret, i;
+ unsigned int i;
+ int ret;
if (data.dsize != sizeof(int)) {
/* Ignore packet */
return;
}
for (i=0; i<state->node_count; i++) {
- if (state->pnn_list[i] == ret) {
+ if (state->pnn_list[i] == (uint32_t)ret) {
state->reply[i] = true;
break;
}
struct ctdb_req_control request;
struct ctdb_reply_control **reply;
bool reload;
- int ret, i;
- uint32_t *pnn_list;
+ unsigned int i;
int count;
+ int ret;
+ uint32_t *pnn_list;
nodemap = get_nodemap(ctdb, false);
if (nodemap == NULL) {
&request, NULL, &reply);
if (ret != 0) {
bool failed = false;
+ int j;
- for (i=0; i<count; i++) {
- ret = ctdb_reply_control_reload_nodes_file(reply[i]);
+ for (j=0; j<count; j++) {
+ ret = ctdb_reply_control_reload_nodes_file(reply[j]);
if (ret != 0) {
fprintf(stderr,
"Node %u failed to reload nodes\n",
- pnn_list[i]);
+ pnn_list[j]);
failed = true;
}
}
struct ctdb_node_map *nodemap;
struct ctdb_req_control request;
uint32_t *pnn_list;
- int ret, i, count;
+ unsigned int i;
+ int ret, count;
ret = ctdb_message_disable_ip_check(mem_ctx, ctdb->ev, ctdb->client,
CTDB_BROADCAST_CONNECTED,
}
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;
}
{
ctdb_sock_addr addr;
uint32_t pnn;
- int ret, retries = 0;
+ int retries = 0;
+ int ret = 0;
if (argc != 2) {
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;
}
- pnn = strtoul(argv[1], NULL, 10);
- if (pnn == CTDB_UNKNOWN_PNN) {
+ pnn = smb_strtoul(argv[1], NULL, 10, &ret, SMB_STR_STANDARD);
+ if (pnn == CTDB_UNKNOWN_PNN || ret != 0) {
fprintf(stderr, "Invalid PNN %s\n", argv[1]);
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)
{
ctdb_sock_addr addr;
struct ctdb_public_ip_list *pubip_list;
struct ctdb_addr_info addr_info;
- unsigned int mask;
- int ret, i, retries = 0;
+ unsigned int mask, i;
+ int ret, retries = 0;
if (argc != 2) {
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,
ctdb_sock_addr addr;
struct ctdb_public_ip_list *pubip_list;
struct ctdb_addr_info addr_info;
- int ret, i;
+ unsigned int i;
+ int ret;
if (argc != 1) {
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];
- int fd, i;
- int count, ret;
+ ssize_t n;
+ int fd;
+ unsigned long i, count;
+ int 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;
- int fd, ret, i;
+ ssize_t n;
+ unsigned long i;
+ int fd, ret;
if (argc != 1) {
usage("dumpbackup");
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,
"Wrong version of backup file, expected %u, got %lu\n",
DB_VERSION, db_hdr.version);
+ close(fd);
return EINVAL;
}
ret = ctdb_rec_buffer_read(fd, mem_ctx, &recbuf);
if (ret != 0) {
fprintf(stderr, "Failed to read records\n");
+ close(fd);
return ret;
}
&state);
if (ret != 0) {
fprintf(stderr, "Failed to dump records\n");
+ close(fd);
return ret;
}
}
+ close(fd);
printf("Dumped %u record(s)\n", state.sub_state.count);
return 0;
}
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;
+ char *t, *event_helper = NULL;
- 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;
- }
-
- 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;
- 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);
}
/*
static bool find_node_xpnn(TALLOC_CTX *mem_ctx, uint32_t *pnn)
{
struct ctdb_node_map *nodemap;
- int i;
+ unsigned int i;
nodemap = read_nodes_file(mem_ctx, CTDB_UNKNOWN_PNN);
if (nodemap == NULL) {
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;
}
if (ret != 0) {
fprintf(stderr, "Failed to read record for key %s\n",
argv[1]);
+ ctdb_transaction_cancel(h);
return ret;
}
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;
}
if (ret != 0) {
fprintf(stderr, "Failed to store record for key %s\n",
argv[1]);
+ ctdb_transaction_cancel(h);
return ret;
}
if (ret != 0) {
fprintf(stderr, "Failed to commit transaction on db %s\n",
db_name);
+ ctdb_transaction_cancel(h);
return ret;
}
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;
}
if (ret != 0) {
fprintf(stderr, "Failed to delete record for key %s\n",
argv[1]);
+ ctdb_transaction_cancel(h);
return ret;
}
if (ret != 0) {
fprintf(stderr, "Failed to commit transaction on db %s\n",
db_name);
+ ctdb_transaction_cancel(h);
return ret;
}
struct ctdb_transaction_handle *h;
uint8_t db_flags;
FILE *file;
- TDB_DATA key, value;
+ TDB_DATA key = tdb_null, value = tdb_null;
int ret;
if (argc < 1 || argc > 2) {
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;
}
if (ret != 0) {
fprintf(stderr, "Failed to commit transaction on db %s\n",
db_name);
+ ctdb_transaction_cancel(h);
}
done:
ret = str_to_data(argv[1], strlen(argv[1]), mem_ctx, &key);
if (ret != 0) {
fprintf(stderr, "Failed to parse key %s\n", argv[1]);
+ tdb_close(tdb);
return ret;
}
data = tdb_fetch(tdb, key);
if (data.dptr == NULL) {
fprintf(stderr, "No record for key %s\n", argv[1]);
+ tdb_close(tdb);
return 1;
}
if (data.dsize < sizeof(struct ctdb_ltdb_header)) {
fprintf(stderr, "Invalid record for key %s\n", argv[1]);
+ tdb_close(tdb);
return 1;
}
}
nwritten = sys_write(fd, data.dptr, data.dsize);
- if (nwritten != data.dsize) {
+ if (nwritten == -1 ||
+ (size_t)nwritten != data.dsize) {
fprintf(stderr, "Failed to write record to file\n");
close(fd);
goto fail;
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;
- int ret;
+ uint8_t header_buf[sizeof(struct ctdb_ltdb_header)];
+ size_t np;
+ int ret = 0;
if (argc < 3 || argc > 5) {
usage("tstore");
ret = str_to_data(argv[1], strlen(argv[1]), mem_ctx, &key);
if (ret != 0) {
fprintf(stderr, "Failed to parse key %s\n", argv[1]);
+ tdb_close(tdb);
return ret;
}
ret = str_to_data(argv[2], strlen(argv[2]), mem_ctx, &value);
if (ret != 0) {
fprintf(stderr, "Failed to parse value %s\n", argv[2]);
+ tdb_close(tdb);
return ret;
}
ZERO_STRUCT(header);
if (argc > 3) {
- header.rsn = (uint64_t)strtoull(argv[3], NULL, 0);
+ header.rsn = (uint64_t)smb_strtoull(argv[3],
+ NULL,
+ 0,
+ &ret,
+ SMB_STR_STANDARD);
+ if (ret != 0) {
+ return ret;
+ }
}
if (argc > 4) {
header.dmaster = (uint32_t)atol(argv[4]);
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");
- 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;
v = fcntl(s, F_GETFL, 0);
if (v == -1 || fcntl(s, F_SETFL, v | O_NONBLOCK)) {
fprintf(stderr, "Unable to set socket non-blocking\n");
+ close(s);
return errno;
}
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;
+ unsigned int i;
+ int ret;
+ 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;
for (i=0; i<nodemap->num; i++) {
- ret |= nodemap->node[i].flags;
+ uint32_t flags = nodemap->node[i].flags;
+
+ if ((flags & NODE_FLAGS_DELETED) != 0) {
+ continue;
+ }
+
+ ret |= flags;
}
return ret;
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,
struct ctdb_db_statistics *s)
{
- int i;
+ size_t i;
const char *prefix = NULL;
int preflen = 0;
printf(" Num Hot Keys: %d\n", s->num_hot_keys);
for (i=0; i<s->num_hot_keys; i++) {
- int j;
+ size_t j;
printf(" Count:%d Key:", s->hot_keys[i].count);
for (j=0; j<s->hot_keys[i].key.dsize; j++) {
printf("%02x", s->hot_keys[i].key.dptr[j] & 0xff);
struct disable_takeover_runs_state {
uint32_t *pnn_list;
- int node_count;
+ unsigned int node_count;
bool *reply;
int status;
bool done;
{
struct disable_takeover_runs_state *state =
(struct disable_takeover_runs_state *)private_data;
- int ret, i;
+ unsigned int i;
+ int ret;
if (data.dsize != sizeof(int)) {
/* Ignore packet */
return;
}
for (i=0; i<state->node_count; i++) {
- if (state->pnn_list[i] == ret) {
+ if (state->pnn_list[i] == (uint32_t)ret) {
state->reply[i] = true;
break;
}
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 },
+ "show lvs configuration", "leader|list|status" },
{ "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,
"run ip reallocation (deprecated)", NULL },
{ "ipreallocate", control_ipreallocate, false, true,
"run ip reallocation", NULL },
- { "isnotrecmaster", control_isnotrecmaster, false, false,
- "check if local node is the recmaster", NULL },
{ "gratarp", control_gratarp, false, true,
"send a gratuitous arp", "<ip> <interface>" },
- { "tickle", control_tickle, false, false,
+ { "tickle", control_tickle, true, false,
"send a tcp tickle ack", "<srcip:port> <dstip:port>" },
{ "gettickles", control_gettickles, false, true,
"get the list of tickles", "<ip> [<port>]" },
"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 },
+ "show natgw configuration", "leader|list|status" },
{ "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)
{
const struct ctdb_cmd *cmd;
- int i;
+ size_t i;
for (i=0; i<ARRAY_SIZE(ctdb_commands); i++) {
cmd = &ctdb_commands[i];
*/
static void usage_full(void)
{
- int i;
+ size_t i;
poptPrintHelp(pc, stdout, 0);
printf("\nCommands:\n");
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,
- "timelimit (in seconds)" },
- { "node", 'n', POPT_ARG_INT, &options.pnn, 0,
- "node specification - integer" },
- { NULL, 'Y', POPT_ARG_NONE, &options.machinereadable, 0,
- "enable machine readable output", NULL },
- { "separator", 'x', POPT_ARG_STRING, &options.sep, 0,
- "specify separator for machine readable output", "CHAR" },
- { NULL, 'X', POPT_ARG_NONE, &options.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)" },
+ {
+ .longName = "debug",
+ .shortName = 'd',
+ .argInfo = POPT_ARG_STRING,
+ .arg = &options.debuglevelstr,
+ .val = 0,
+ .descrip = "debug level",
+ },
+ {
+ .longName = "timelimit",
+ .shortName = 't',
+ .argInfo = POPT_ARG_INT,
+ .arg = &options.timelimit,
+ .val = 0,
+ .descrip = "timelimit (in seconds)",
+ },
+ {
+ .longName = "node",
+ .shortName = 'n',
+ .argInfo = POPT_ARG_INT,
+ .arg = &options.pnn,
+ .val = 0,
+ .descrip = "node specification - integer",
+ },
+ {
+ .longName = NULL,
+ .shortName = 'Y',
+ .argInfo = POPT_ARG_NONE,
+ .arg = &options.machinereadable,
+ .val = 0,
+ .descrip = "enable machine readable output",
+ },
+ {
+ .longName = "separator",
+ .shortName = 'x',
+ .argInfo = POPT_ARG_STRING,
+ .arg = &options.sep,
+ .val = 0,
+ .descrip = "specify separator for machine readable output",
+ .argDescrip = "CHAR",
+ },
+ {
+ .shortName = 'X',
+ .argInfo = POPT_ARG_NONE,
+ .arg = &options.machineparsable,
+ .val = 0,
+ .descrip = "enable machine parsable output with separator |",
+ },
+ {
+ .longName = "verbose",
+ .shortName = 'v',
+ .argInfo = POPT_ARG_NONE,
+ .arg = &options.verbose,
+ .val = 0,
+ .descrip = "enable verbose output",
+ },
+ {
+ .longName = "maxruntime",
+ .shortName = 'T',
+ .argInfo = POPT_ARG_INT,
+ .arg = &options.maxruntime,
+ .val = 0,
+ .descrip = "die if runtime exceeds this limit (in seconds)",
+ },
POPT_TABLEEND
};
{
TALLOC_CTX *tmp_ctx;
struct ctdb_context *ctdb;
+ const char *ctdb_socket;
int ret;
bool status;
uint64_t srvid_offset;
goto fail;
}
- return cmd->fn(tmp_ctx, NULL, argc-1, argv+1);
+ ret = cmd->fn(tmp_ctx, NULL, argc-1, argv+1);
+ talloc_free(tmp_ctx);
+ return ret;
}
ctdb = talloc_zero(tmp_ctx, struct ctdb_context);
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 ret;
+ const char *test_mode;
+ int loglevel;
+ bool ok;
+ int ret = 0;
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) {
ctdb_timeout = getenv("CTDB_TIMEOUT");
if (ctdb_timeout != NULL) {
- options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
+ options.maxruntime = smb_strtoul(ctdb_timeout,
+ NULL,
+ 0,
+ &ret,
+ SMB_STR_STANDARD);
+ if (ret != 0) {
+ fprintf(stderr, "Invalid value CTDB_TIMEOUT\n");
+ exit(1);
+ }
} else {
options.maxruntime = 120;
}
}
- if (options.maxruntime <= 120) {
- /* default timeout is 120 seconds */
- options.maxruntime = 120;
- }
if (options.machineparsable) {
options.machinereadable = 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);
+
+ /* Stop process group kill in alarm_handler() from killing tests */
+ test_mode = getenv("CTDB_TEST_MODE");
+ if (test_mode != NULL) {
+ const char *have_setpgid = getenv("CTDB_TOOL_SETPGID");
+ if (have_setpgid == NULL) {
+ setpgid(0, 0);
+ setenv("CTDB_TOOL_SETPGID", "1", 1);
+ }
}
signal(SIGALRM, alarm_handler);