diff --git a/ctdb/common/ctdb.c b/ctdb/common/ctdb.c index 4b47a6e2a1d..63e5b654384 100644 --- a/ctdb/common/ctdb.c +++ b/ctdb/common/ctdb.c @@ -326,6 +326,7 @@ void ctdb_recv_raw_pkt(void *p, uint8_t *data, uint32_t length) static void ctdb_node_dead(struct ctdb_node *node) { node->ctdb->num_connected--; + node->flags &= ~NODE_FLAGS_CONNECTED; DEBUG(1,("%s: node %s is dead: %d connected\n", node->ctdb->name, node->name, node->ctdb->num_connected)); } @@ -336,6 +337,7 @@ static void ctdb_node_dead(struct ctdb_node *node) static void ctdb_node_connected(struct ctdb_node *node) { node->ctdb->num_connected++; + node->flags |= NODE_FLAGS_CONNECTED; DEBUG(1,("%s: connected to %s - %d connected\n", node->ctdb->name, node->name, node->ctdb->num_connected)); } diff --git a/ctdb/common/ctdb_client.c b/ctdb/common/ctdb_client.c index f3f3adb9bb5..415d38b0fce 100644 --- a/ctdb/common/ctdb_client.c +++ b/ctdb/common/ctdb_client.c @@ -793,6 +793,77 @@ int ctdb_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn return 0; } +/* + get a list of databases off a remote node + */ +int ctdb_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_dbid_map *dbmap) +{ + int ret; + TDB_DATA data, outdata; + int32_t i, res; + + ZERO_STRUCT(data); + ret = ctdb_control(ctdb, destnode, 0, + CTDB_CONTROL_GET_DBMAP, data, + ctdb, &outdata, &res); + if (ret != 0 || res != 0) { + DEBUG(0,(__location__ " ctdb_control for getvnnmap failed\n")); + return -1; + } + + dbmap->num = ((uint32_t *)outdata.dptr)[0]; + if (dbmap->dbids) { + talloc_free(dbmap->dbids); + dbmap->dbids=NULL; + } + dbmap->dbids=talloc_array(dbmap, uint32_t, dbmap->num); + if (!dbmap->dbids) { + DEBUG(0,(__location__ " failed to talloc dbmap\n")); + return -1; + } + for (i=0;inum;i++) { + dbmap->dbids[i] = ((uint32_t *)outdata.dptr)[i+1]; + } + + return 0; +} + + +/* + get a list of nodes (vnn and flags ) from a remote node + */ +int ctdb_getnodemap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_node_map *nodemap) +{ + int ret; + TDB_DATA data, outdata; + int32_t i, res; + + ZERO_STRUCT(data); + ret = ctdb_control(ctdb, destnode, 0, + CTDB_CONTROL_GET_NODEMAP, data, + ctdb, &outdata, &res); + if (ret != 0 || res != 0) { + DEBUG(0,(__location__ " ctdb_control for getnodes failed\n")); + return -1; + } + + nodemap->num = ((uint32_t *)outdata.dptr)[0]; + if (nodemap->nodes) { + talloc_free(nodemap->nodes); + nodemap->nodes=NULL; + } + nodemap->nodes=talloc_array(nodemap, struct ctdb_node_and_flags, nodemap->num); + if (!nodemap->nodes) { + DEBUG(0,(__location__ " failed to talloc nodemap\n")); + return -1; + } + for (i=0;inum;i++) { + nodemap->nodes[i].vnn = ((uint32_t *)outdata.dptr)[2*i+1]; + nodemap->nodes[i].flags = ((uint32_t *)outdata.dptr)[2*i+2]; + } + + return 0; +} /* set vnn map on a node @@ -877,19 +948,19 @@ int ctdb_get_config(struct ctdb_context *ctdb) /* find the real path to a ltdb */ -int ctdb_getdbpath(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx, +int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t dbid, TALLOC_CTX *mem_ctx, const char **path) { int ret; int32_t res; TDB_DATA data; - data.dptr = (uint8_t *)&ctdb_db->db_id; - data.dsize = sizeof(ctdb_db->db_id); + data.dptr = (uint8_t *)&dbid; + data.dsize = sizeof(dbid); - ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, + ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_GETDBPATH, data, - ctdb_db, &data, &res); + mem_ctx, &data, &res); if (ret != 0 || res != 0) { return -1; } diff --git a/ctdb/common/ctdb_control.c b/ctdb/common/ctdb_control.c index eac8b5170b5..83bac958e06 100644 --- a/ctdb/common/ctdb_control.c +++ b/ctdb/common/ctdb_control.c @@ -96,6 +96,56 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, return 0; } + case CTDB_CONTROL_GET_DBMAP: { + uint32_t i, len; + struct ctdb_db_context *ctdb_db; + + CHECK_CONTROL_DATA_SIZE(0); + len = 0; + for(ctdb_db=ctdb->db_list;ctdb_db;ctdb_db=ctdb_db->next){ + len++; + } + + outdata->dsize = (len+1)*sizeof(uint32_t); + outdata->dptr = (unsigned char *)talloc_array(outdata, uint32_t, len+1); + if (!outdata->dptr) { + DEBUG(0, (__location__ "Failed to allocate dbmap array\n")); + exit(1); + } + + ((uint32_t *)outdata->dptr)[0] = len; + for(i=0,ctdb_db=ctdb->db_list;ctdb_db;i++,ctdb_db=ctdb_db->next){ + ((uint32_t *)outdata->dptr)[i+1] = ctdb_db->db_id; + } + + return 0; + } + + case CTDB_CONTROL_GET_NODEMAP: { + uint32_t num_nodes, i, len; + struct ctdb_node *node; + + num_nodes = ctdb_get_num_nodes(ctdb); + len = 2*num_nodes + 1; + + outdata->dsize = len*sizeof(uint32_t); + outdata->dptr = (unsigned char *)talloc_array(outdata, uint32_t, len); + if (!outdata->dptr) { + DEBUG(0, (__location__ "Failed to allocate node array\n")); + exit(1); + } + + + ((uint32_t *)outdata->dptr)[0] = num_nodes; + for (i=0; inodes[i]; + ((uint32_t *)outdata->dptr)[i*2+1]=node->vnn; + ((uint32_t *)outdata->dptr)[i*2+2]=node->flags; + } + + return 0; + } + case CTDB_CONTROL_SETVNNMAP: { uint32_t *ptr, i; diff --git a/ctdb/include/ctdb.h b/ctdb/include/ctdb.h index 9c5d2399d6c..7dba352a46f 100644 --- a/ctdb/include/ctdb.h +++ b/ctdb/include/ctdb.h @@ -219,7 +219,29 @@ struct ctdb_vnn_map; int ctdb_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn_map *vnnmap); int ctdb_setvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn_map *vnnmap); -int ctdb_getdbpath(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx, const char **path); +/* table that contains a list of all dbids on a node + */ +struct ctdb_dbid_map { + uint32_t num; + uint32_t *dbids; +}; +int ctdb_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_dbid_map *dbmap); + + +/* table that contains a list of all nodes a ctdb knows about and their + status + */ +struct ctdb_node_and_flags { + uint32_t vnn; + uint32_t flags; +}; +struct ctdb_node_map { + uint32_t num; + struct ctdb_node_and_flags *nodes; +}; +int ctdb_getnodemap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_node_map *nodemap); + +int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t dbid, TALLOC_CTX *mem_ctx, const char **path); int ctdb_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid); diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 20efc5bd7eb..dbbce30a447 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -79,6 +79,8 @@ struct ctdb_node { const char *name; /* for debug messages */ void *private_data; /* private to transport */ uint32_t vnn; +#define NODE_FLAGS_CONNECTED 0x00000001 + uint32_t flags; }; /* @@ -250,7 +252,9 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS, CTDB_CONTROL_GETVNNMAP, CTDB_CONTROL_SETVNNMAP, CTDB_CONTROL_GET_DEBUG, - CTDB_CONTROL_SET_DEBUG}; + CTDB_CONTROL_SET_DEBUG, + CTDB_CONTROL_GET_DBMAP, + CTDB_CONTROL_GET_NODEMAP}; enum call_state {CTDB_CALL_WAIT, CTDB_CALL_DONE, CTDB_CALL_ERROR}; diff --git a/ctdb/tests/ctdb_test.c b/ctdb/tests/ctdb_test.c index 82555607a47..5e86041b744 100644 --- a/ctdb/tests/ctdb_test.c +++ b/ctdb/tests/ctdb_test.c @@ -23,6 +23,7 @@ #include "system/filesys.h" #include "popt.h" #include "cmdline.h" +#include "ctdb_private.h" enum my_functions {FUNC_SORT=1, FUNC_FETCH=2}; @@ -137,7 +138,7 @@ int main(int argc, const char *argv[]) ctdb_connect_wait(ctdb); /* find the full path to the database file */ - ctdb_getdbpath(ctdb_db, ctdb_db, &path); + ctdb_getdbpath(ctdb, ctdb_db->db_id, ctdb_db, &path); printf("path to database:[%s]\n",path); ZERO_STRUCT(call); diff --git a/ctdb/tools/ctdb_control.c b/ctdb/tools/ctdb_control.c index c3ad212f97b..6057a186f3d 100644 --- a/ctdb/tools/ctdb_control.c +++ b/ctdb/tools/ctdb_control.c @@ -40,6 +40,8 @@ static void usage(void) printf(" debuglevel display ctdb debug levels\n"); printf(" getvnnmap display ctdb vnnmap\n"); printf(" setvnnmap *\n"); + printf(" getdbmap lists databases on a node\n"); + printf(" getnodemap lists nodes known to a ctdb daemon\n"); exit(1); } @@ -154,6 +156,71 @@ static int control_getvnnmap(struct ctdb_context *ctdb, int argc, const char **a return 0; } +/* + display a list of the databases on a remote ctdb + */ +static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv) +{ + uint32_t vnn; + int i, ret; + struct ctdb_dbid_map *dbmap; + + if (argc < 1) { + usage(); + } + + vnn = strtoul(argv[0], NULL, 0); + + dbmap = talloc_zero(ctdb, struct ctdb_dbid_map); + ret = ctdb_getdbmap(ctdb, vnn, dbmap); + if (ret != 0) { + printf("Unable to get dbids from node %u\n", vnn); + talloc_free(dbmap); + return ret; + } + + printf("Number of databases:%d\n", dbmap->num); + for(i=0;inum;i++){ + const char *path; + + ctdb_getdbpath(ctdb, dbmap->dbids[i], dbmap, &path); + printf("dbid:0x%08x path:%s\n", dbmap->dbids[i], path); + } + talloc_free(dbmap); + return 0; +} + +/* + display a list nodes known to a remote ctdb + */ +static int control_getnodemap(struct ctdb_context *ctdb, int argc, const char **argv) +{ + uint32_t vnn; + int i, ret; + struct ctdb_node_map *nodemap; + + if (argc < 1) { + usage(); + } + + vnn = strtoul(argv[0], NULL, 0); + + nodemap = talloc_zero(ctdb, struct ctdb_node_map); + ret = ctdb_getnodemap(ctdb, vnn, nodemap); + if (ret != 0) { + printf("Unable to get nodemap from node %u\n", vnn); + talloc_free(nodemap); + return ret; + } + + printf("Number of nodes:%d\n", nodemap->num); + for(i=0;inum;i++){ + printf("vnn:%d %s\n", nodemap->nodes[i].vnn, nodemap->nodes[i].flags&NODE_FLAGS_CONNECTED?"UNAVAILABLE":"CONNECTED"); + } + talloc_free(nodemap); + return 0; +} + /* set remote ctdb vnn map */ @@ -304,6 +371,10 @@ int main(int argc, const char *argv[]) ret = control_status(ctdb, extra_argc-1, extra_argv+1); } else if (strcmp(control, "getvnnmap") == 0) { ret = control_getvnnmap(ctdb, extra_argc-1, extra_argv+1); + } else if (strcmp(control, "getdbmap") == 0) { + ret = control_getdbmap(ctdb, extra_argc-1, extra_argv+1); + } else if (strcmp(control, "getnodemap") == 0) { + ret = control_getnodemap(ctdb, extra_argc-1, extra_argv+1); } else if (strcmp(control, "setvnnmap") == 0) { ret = control_setvnnmap(ctdb, extra_argc-1, extra_argv+1); } else if (strcmp(control, "ping") == 0) {