Refactor show diagnose to handle node IDs correctly.

See previous comments for `show matrix`.
This commit is contained in:
Ian Barwick
2016-09-30 01:46:01 +09:00
parent a2910eded9
commit c3971513b6
2 changed files with 163 additions and 96 deletions

237
repmgr.c
View File

@@ -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(&quoted_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");
}
}

View File

@@ -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