diff --git a/repmgr.c b/repmgr.c index 85f7f79a..a576f1e2 100644 --- a/repmgr.c +++ b/repmgr.c @@ -114,7 +114,7 @@ static void get_barman_property(char *dst, char *name, char *local_repmgr_direct static char *string_skip_prefix(const char *prefix, char *string); static char *string_remove_trailing_newlines(char *string); static int build_cluster_matrix(t_node_status_matrix *matrix, int *name_length); -static int build_cluster_diagnose(int **cube, char **node_names, int *name_length); +static int build_cluster_diagnose(t_node_status_cube ***cube, int *name_length); static char *make_pg_path(char *file); static char *make_barman_ssh_command(void); @@ -164,6 +164,7 @@ static void config_file_list_init(t_configfile_list *list, int max_size); static void config_file_list_add(t_configfile_list *list, const char *file, const char *filename, bool in_data_dir); static void matrix_set_node_status(t_node_status_matrix *matrix, int node_id, int connection_node_id, int connection_status); +static void cube_set_node_status(t_node_status_cube **cube, int n, int node_id, int matrix_node_id, int connection_node_id, int connection_status); /* Global variables */ static PQconninfoOption *opts = NULL; @@ -1116,21 +1117,16 @@ static void matrix_set_node_status(t_node_status_matrix *matrix, int node_id, int connection_node_id, int connection_status) { int i, j; -// printf("matrix_set_node_status() %i %i %i\n", node_id, connection_node_id, connection_status); for (i = 0; i < matrix->length; i++) { -// printf("xx %i\n", i); - - if (matrix->matrix_list[i]->node_id == node_id) + if (matrix->matrix_rec_list[i]->node_id == node_id) { for (j = 0; j < matrix->length; j++) { -//XS printf(" xx %i\n", j); - - if (matrix->matrix_list[i]->node_status_list[j]->node_id == connection_node_id) + if (matrix->matrix_rec_list[i]->node_status_list[j]->node_id == connection_node_id) { - matrix->matrix_list[i]->node_status_list[j]->node_status = connection_status; + matrix->matrix_rec_list[i]->node_status_list[j]->node_status = connection_status; break; } } @@ -1199,7 +1195,7 @@ build_cluster_matrix(t_node_status_matrix *matrix, int *name_length) matrix->length = n; - matrix->matrix_list = (t_node_status_matrix_rec **) pg_malloc0(sizeof(t_node_status_matrix_rec) * n); + matrix->matrix_rec_list = (t_node_status_matrix_rec **) pg_malloc0(sizeof(t_node_status_matrix_rec) * n); /* Initialise matrix structure for each node */ @@ -1207,25 +1203,25 @@ build_cluster_matrix(t_node_status_matrix *matrix, int *name_length) { int name_length_cur; - matrix->matrix_list[i] = (t_node_status_matrix_rec *) pg_malloc0(sizeof(t_node_status_matrix_rec)); + matrix->matrix_rec_list[i] = (t_node_status_matrix_rec *) pg_malloc0(sizeof(t_node_status_matrix_rec)); - matrix->matrix_list[i]->node_id = atoi(PQgetvalue(res, i, 4)); - strncpy(matrix->matrix_list[i]->node_name, PQgetvalue(res, i, 2), MAXLEN); + matrix->matrix_rec_list[i]->node_id = atoi(PQgetvalue(res, i, 4)); + strncpy(matrix->matrix_rec_list[i]->node_name, PQgetvalue(res, i, 2), MAXLEN); /* * Find the maximum length of a node name */ - name_length_cur = strlen(matrix->matrix_list[i]->node_name); + name_length_cur = strlen(matrix->matrix_rec_list[i]->node_name); if (name_length_cur > *name_length) *name_length = name_length_cur; - matrix->matrix_list[i]->node_status_list = (t_node_status_rec **) pg_malloc0(sizeof(t_node_status_rec) * n); + matrix->matrix_rec_list[i]->node_status_list = (t_node_status_rec **) pg_malloc0(sizeof(t_node_status_rec) * n); for (j = 0; j < n; j++) { - matrix->matrix_list[i]->node_status_list[j] = (t_node_status_rec *) pg_malloc0(sizeof(t_node_status_rec)); - matrix->matrix_list[i]->node_status_list[j]->node_id = atoi(PQgetvalue(res, j, 4)); - matrix->matrix_list[i]->node_status_list[j]->node_status = -2; /* default unknown */ + matrix->matrix_rec_list[i]->node_status_list[j] = (t_node_status_rec *) pg_malloc0(sizeof(t_node_status_rec)); + matrix->matrix_rec_list[i]->node_status_list[j]->node_id = atoi(PQgetvalue(res, j, 4)); + matrix->matrix_rec_list[i]->node_status_list[j]->node_status = -2; /* default unknown */ } } @@ -1341,9 +1337,9 @@ do_cluster_matrix() const char *node_header = "Name"; int name_length = strlen(node_header); - t_node_status_matrix *matrix_new = (t_node_status_matrix *) pg_malloc(sizeof(t_node_status_matrix)); + t_node_status_matrix *matrix = (t_node_status_matrix *) pg_malloc(sizeof(t_node_status_matrix)); - n = build_cluster_matrix(matrix_new, &name_length); + n = build_cluster_matrix(matrix, &name_length); if (runtime_options.csv_mode) { @@ -1351,9 +1347,9 @@ do_cluster_matrix() for (i = 0; i < n; i++) for (j = 0; j < n; j++) printf("%d,%d,%d\n", - matrix_new->matrix_list[i]->node_id, - matrix_new->matrix_list[i]->node_status_list[j]->node_id, - matrix_new->matrix_list[i]->node_status_list[j]->node_status); + matrix->matrix_rec_list[i]->node_id, + matrix->matrix_rec_list[i]->node_status_list[j]->node_id, + matrix->matrix_rec_list[i]->node_status_list[j]->node_status); } else @@ -1362,7 +1358,7 @@ do_cluster_matrix() printf("%*s | Id ", name_length, node_header); for (i = 0; i < n; i++) - printf("| %2d ", matrix_new->matrix_list[i]->node_id); + printf("| %2d ", matrix->matrix_rec_list[i]->node_id); printf("\n"); for (i = 0; i < name_length; i++) @@ -1375,12 +1371,11 @@ do_cluster_matrix() for (i = 0; i < n; i++) { printf("%*s | %2d ", name_length, - matrix_new->matrix_list[i]->node_name, - matrix_new->matrix_list[i]->node_id); + matrix->matrix_rec_list[i]->node_name, + matrix->matrix_rec_list[i]->node_id); for (j = 0; j < n; j++) { - //switch (matrix[i * n + j]) - switch (matrix_new->matrix_list[i]->node_status_list[j]->node_status) + switch (matrix->matrix_rec_list[i]->node_status_list[j]->node_status) { case -2: c = '?'; @@ -1402,19 +1397,47 @@ do_cluster_matrix() } } +static void +cube_set_node_status(t_node_status_cube **cube, int n, int execute_node_id, int matrix_node_id, int connection_node_id, int connection_status) +{ + int h, i, j; + + + for (h = 0; h < n; h++) + { + if (cube[h]->node_id == execute_node_id) + { + for (i = 0; i < n; i++) + { + if (cube[h]->matrix_list_rec[i]->node_id == matrix_node_id) + { + for (j = 0; j < n; j++) + { + if (cube[h]->matrix_list_rec[i]->node_status_list[j]->node_id == connection_node_id) + { + cube[h]->matrix_list_rec[i]->node_status_list[j]->node_status = connection_status; + break; + } + } + break; + } + } + } + } +} + + static int -build_cluster_diagnose(int **cube, char **node_names, int *name_length) +build_cluster_diagnose(t_node_status_cube ***dest_cube, int *name_length) { PGconn *conn; PGresult *res; char sqlquery[QUERY_STR_LEN]; - int i, j; + int h, i, j; - int x, y, z; int n = 0; /* number of nodes */ - PQExpBufferData command; - PQExpBufferData command_output; + t_node_status_cube **cube; /* We need to connect to get the list of nodes */ log_info(_("connecting to database\n")); @@ -1442,41 +1465,52 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) PQfinish(conn); /* - * Allocate an empty cube matrix + * Allocate an empty cube matrix structure * * -2 == NULL * -1 == Error * 0 == OK */ n = PQntuples(res); - *cube = (int *) pg_malloc(sizeof(int) * n * n * n); - for (i = 0; i < n * n * n; i++) - (*cube)[i] = -2; - /* - * Find the maximum length of a node name - */ - for (i = 0; i < n; i++) + cube = (t_node_status_cube **) pg_malloc(sizeof(t_node_status_cube *) * n); + + for (h = 0; h < n; h++) { int name_length_cur; - name_length_cur = strlen(PQgetvalue(res, i, 2)); + cube[h] = (t_node_status_cube *) pg_malloc(sizeof(t_node_status_cube)); + cube[h]->node_id = atoi(PQgetvalue(res, h, 4)); + + strncpy(cube[h]->node_name, PQgetvalue(res, h, 2), MAXLEN); + /* + * Find the maximum length of a node name + */ + name_length_cur = strlen(cube[h]->node_name); if (name_length_cur > *name_length) *name_length = name_length_cur; + + cube[h]->matrix_list_rec = (t_node_status_matrix_rec **) pg_malloc(sizeof(t_node_status_matrix_rec) * n); + + for (i = 0; i < n; i++) + { + cube[h]->matrix_list_rec[i] = (t_node_status_matrix_rec *) pg_malloc0(sizeof(t_node_status_matrix_rec)); + cube[h]->matrix_list_rec[i]->node_id = atoi(PQgetvalue(res, i, 4)); + + /* we don't need the name here */ + cube[h]->matrix_list_rec[i]->node_name[0] = '\0'; + + cube[h]->matrix_list_rec[i]->node_status_list = (t_node_status_rec **) pg_malloc0(sizeof(t_node_status_rec) * n); + + for (j = 0; j < n; j++) + { + cube[h]->matrix_list_rec[i]->node_status_list[j] = (t_node_status_rec *) pg_malloc0(sizeof(t_node_status_rec)); + cube[h]->matrix_list_rec[i]->node_status_list[j]->node_id = atoi(PQgetvalue(res, j, 4)); + cube[h]->matrix_list_rec[i]->node_status_list[j]->node_status = -2; /* default unknown */ + } + } } - /* - * Save node names into an array - */ - - *node_names = (char *) pg_malloc((*name_length + 1) * n); - - for (i = 0; i < n; i++) - { - strncpy(*node_names + i * (*name_length + 1), - PQgetvalue(res, i, 2), - strlen(PQgetvalue(res, i, 2)) + 1); - } /* * Build the connection cube @@ -1484,8 +1518,11 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) for (i = 0; i < n; i++) { - char *p; int remote_node_id; + PQExpBufferData command; + PQExpBufferData command_output; + + char *p; remote_node_id = atoi(PQgetvalue(res, i, 4)); @@ -1498,7 +1535,6 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) options.cluster_name, remote_node_id); - if (strlen(pg_bindir)) // XXX escape path! appendPQExpBuffer(&command, @@ -1506,11 +1542,11 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) pg_bindir); appendPQExpBuffer(&command, - "cluster matrix --csv"); + "cluster matrix --csv 2>/dev/null"); initPQExpBuffer(&command_output); - if (i + 1 == options.node) + if (cube[i]->node_id == options.node) { (void)local_command( command.data, @@ -1545,18 +1581,33 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) termPQExpBuffer("ed_command); } - termPQExpBuffer(&command); + p = command_output.data; + if(!strlen(command_output.data)) + { + continue; + } + for (j = 0; j < n * n; j++) { - if (sscanf(p, "%d,%d,%d", &x, &y, &z) != 3) + int matrix_rec_node_id; + int node_status_node_id; + int node_status; + + if (sscanf(p, "%d,%d,%d", &matrix_rec_node_id, &node_status_node_id, &node_status) != 3) { fprintf(stderr, _("cannot parse --csv output: %s\n"), p); exit(ERR_INTERNAL); } - (*cube)[i * n * n + (x - 1) * n + (y - 1)] = - (z == -1) ? -1 : 0; + + cube_set_node_status(cube, + n, + remote_node_id, + matrix_rec_node_id, + node_status_node_id, + node_status); + while (*p && (*p != '\n')) p++; if (*p == '\n') @@ -1564,23 +1615,23 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) } } - PQclear(res); - + *dest_cube = cube; return n; } + + static void do_cluster_diagnose(void) { - int i, j, k, u, v; - int n; + int i, n; char c; - char *node_names; - int *cube; const char *node_header = "Name"; int name_length = strlen(node_header); - n = build_cluster_diagnose(&cube, &node_names, &name_length); + t_node_status_cube **cube; + + n = build_cluster_diagnose(&cube, &name_length); printf("%*s | Id ", name_length, node_header); for (i = 0; i < n; i++) @@ -1596,13 +1647,17 @@ do_cluster_diagnose(void) for (i = 0; i < n; i++) { + int column_node_ix; + printf("%*s | %2d ", name_length, - node_names + (name_length + 1) * i, i + 1); - for (j = 0; j < n; j++) + cube[i]->node_name, + cube[i]->node_id); + + for (column_node_ix = 0; column_node_ix < n; column_node_ix++) { - u = cube[i * n + j]; - for (k = 1; k < n; k++) - { + int max_node_status = -2; + int node_ix; + /* * The value of entry (i,j) is equal to the * maximum value of all the (i,j,k). Indeed: @@ -1617,29 +1672,33 @@ do_cluster_diagnose(void) * (the node is in an unknown state). */ - v = cube[k * n * n + i * n + j]; - - if (v > u) u = v; + for(node_ix = 0; node_ix < n; node_ix ++) + { + int node_status = cube[node_ix]->matrix_list_rec[i]->node_status_list[column_node_ix]->node_status; + if (node_status > max_node_status) + max_node_status = node_status; } - switch (u) + switch (max_node_status) { - case -2: - c = '?'; - break; - case -1: - c = 'x'; - break; - case 0: - c = '*'; - break; - default: - exit(ERR_INTERNAL); + case -2: + c = '?'; + break; + case -1: + c = 'x'; + break; + case 0: + c = '*'; + break; + default: + exit(ERR_INTERNAL); } printf("| %c ", c); } + printf("\n"); + } } diff --git a/repmgr.h b/repmgr.h index dc7d3ebc..dfda1ecc 100644 --- a/repmgr.h +++ b/repmgr.h @@ -165,6 +165,8 @@ typedef struct t_configfile_info **files; } t_configfile_list; +#define T_CONFIGFILE_LIST_INITIALIZER { 0, 0, NULL } + typedef struct { @@ -172,6 +174,8 @@ typedef struct int node_status; } t_node_status_rec; +// for each node, list of statuses for other nodes +// output of "cluster show" typedef struct { int node_id; @@ -179,18 +183,22 @@ typedef struct t_node_status_rec **node_status_list; } t_node_status_matrix_rec; -typedef struct -{ - int length; - t_node_status_matrix_rec **matrix_list; -} t_node_status_matrix; + +// points to the output of "cluster matrix" on each node typedef struct { int node_id; - t_node_status_matrix **node_matrix; + char node_name[MAXLEN]; + t_node_status_matrix_rec **matrix_list_rec; } t_node_status_cube; -#define T_CONFIGFILE_LIST_INITIALIZER { 0, 0, NULL } +// not really needed +typedef struct +{ + int length; + t_node_status_matrix_rec **matrix_rec_list; +} t_node_status_matrix; + #endif