void fsa_node_addr_free(fsa_node_addr *na) { if (na == NULL) { return; } free(na->host); fsa_node_addr_free(na->next); free(na); }
/* get single node_addr based on matching host name in config file */ static fsa_node_addr *node_name_to_node_addr(char *name) { GKeyFile *config = fsa_get_config(); int default_port = fsa_get_admind_port(config); fsa_node_addr *nodes = NULL; /* use localhost if no config file found */ if (config == NULL) { if (strcmp(name, "localhost") == 0) { nodes = fsa_node_addr_new("localhost"); nodes->port = default_port; return nodes; } else { return NULL; } } nodes = fsa_get_node_list(config); /* done with config */ fsa_config_free(config); /* if no nodes found in config file, use localhost */ if (nodes == NULL) { if (strcmp(name, "localhost") == 0) { nodes = fsa_node_addr_new("localhost"); nodes->port = default_port; return nodes; } else { return NULL; } } /* count through node list to get node node_num in */ fsa_node_addr *cur = nodes; fsa_node_addr *tmp = NULL; while (cur != NULL) { if (strcmp(name, cur->host) == 0) { /* free rest of node list, then return the current */ fsa_node_addr_free(cur->next); cur->next = NULL; return cur; } /* free current node then move to next */ tmp = cur; cur = cur->next; fsa_node_addr_free_one(tmp); } return NULL; }
fsa_node_addr *fsa_node_addr_new(const char *host) { fsa_node_addr *na = (fsa_node_addr *)malloc(sizeof(fsa_node_addr)); if (na == NULL) { errno = ENOMEM; return NULL; } na->port = 0; na->next = NULL; na->host = (char *)malloc(strlen(host) + 1); if (na->host == NULL) { errno = ENOMEM; fsa_node_addr_free(na); return NULL; } strcpy(na->host, host); return na; }
/* Get info on a kb from any number of nodes. For all kbs, or all nodes, set the corresponding argument to NULL */ fsa_kb_info *fsaf_fetch_kb_info(const unsigned char *kb_name, fsa_node_addr *nodes) { fsa_node_addr *cur_node; int free_nodes = 0; /* free nodes if they werem't passed to function */ /* if no nodes given, get all nodes from config */ if (nodes == NULL) { fsa_error(LOG_DEBUG, "fetching kb info for all nodes"); GKeyFile *conf = fsa_get_config(); nodes = fsa_get_node_list(conf); fsa_config_free(conf); free_nodes = 1; } unsigned char *buf; unsigned char header_buf[ADM_HEADER_LEN]; /* store single header packet */ int nbytes, sock_fd, rv; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; /* command to be sent to all stores */ int cmd_len; /* length of command packet */ unsigned char *cmd_pkt; /* command packet itself */ fsa_kb_info *ki_list = NULL; uint8_t cmdval; uint16_t datasize; char ipaddr[INET6_ADDRSTRLEN]; /* large enough to hold a v4 or v6 addr */ if (kb_name == NULL) { /* get info on all kbs */ fsa_error(LOG_DEBUG, "fetching info for all kbs"); cmd_pkt = fsap_encode_cmd_get_kb_info_all(&cmd_len); } else { /* request info on named kb */ fsa_error(LOG_DEBUG, "fetching info for kb '%s'", kb_name); cmd_pkt = fsap_encode_cmd_get_kb_info(kb_name, &cmd_len); } fsa_error(LOG_DEBUG, "admin command length is %d bytes", cmd_len); /* connect to each storage node */ for (cur_node = nodes; cur_node != NULL; cur_node = cur_node->next) { sock_fd = fsaf_connect_to_admind(cur_node->host, cur_node->port, &hints, ipaddr); if (sock_fd == -1) { fsa_error(LOG_ERR, "failed to connect to %s:%d, skipping node", cur_node->host, cur_node->port); continue; } /* send command to node */ nbytes = cmd_len; rv = fsa_sendall(sock_fd, cmd_pkt, &nbytes); if (rv == -1) { fsa_error(LOG_ERR, "failed to send command to %s:%d, skipping node", cur_node->host, cur_node->port); continue; } fsa_error(LOG_DEBUG, "header (%d bytes) sent to %s:%d, waiting for response", nbytes, cur_node->host, cur_node->port); /* get response header from node */ rv = fsa_fetch_header(sock_fd, header_buf); if (rv == -1) { fsa_error(LOG_ERR, "failed to get response from %s:%d, skipping node", cur_node->host, cur_node->port); continue; } fsa_error(LOG_DEBUG, "response received from %s:%d", cur_node->host, cur_node->port); /* server sent us data */ rv = fsap_decode_header(header_buf, &cmdval, &datasize); if (rv == -1) { fsa_error(LOG_ERR, "unable to decode header from %s:%d", cur_node->host, cur_node->port); close(sock_fd); continue; } /* alloc buffer for receiving further data into */ buf = (unsigned char *)malloc(datasize); if (buf == NULL) { errno = ENOMEM; free(cmd_pkt); return NULL; } fsa_error(LOG_DEBUG, "response header from %s:%d decoded", cur_node->host, cur_node->port); /* handle response from client */ if (cmdval == ADM_RSP_GET_KB_INFO_ALL) { fsa_error(LOG_DEBUG, "ADM_RSP_GET_KB_INFO_ALL received"); fsa_error(LOG_DEBUG, "fetching data from client"); nbytes = fsaf_recv_from_admind(sock_fd, buf, datasize); if (nbytes <= 0) { /* error already handled */ free(buf); continue; } /* local list of kb info for a single node */ fsa_kb_info *kid = fsap_decode_rsp_get_kb_info_all(buf); free(buf); fsa_kb_info *tmp_ki = NULL; fsa_kb_info *cur_ki = NULL; /* add kb info to list of info across nodes */ if (kid != NULL) { tmp_ki = kid; /* pointer to start of list */ cur_ki = kid; int done = 0; while (!done) { cur_ki->ipaddr = (unsigned char *)strdup(ipaddr); if (cur_ki->next == NULL) { /* if last item in list */ cur_ki->next = ki_list; /* append existing vals */ ki_list = tmp_ki; /* point to new head */ done = 1; } else { cur_ki = cur_ki->next; } } } } else if (cmdval == ADM_RSP_GET_KB_INFO) { fsa_error(LOG_DEBUG, "ADM_RSP_GET_KB_INFO_ALL received"); fsa_error(LOG_DEBUG, "fetching data from client"); nbytes = fsaf_recv_from_admind(sock_fd, buf, datasize); if (nbytes <= 0) { /* error already handled */ free(buf); continue; } fsa_kb_info *kid = fsap_decode_rsp_get_kb_info(buf); free(buf); if (kid != NULL) { /* copy ip addr to struct */ kid->ipaddr = (unsigned char *)strdup(ipaddr); kid->next = ki_list; ki_list = kid; } } close(sock_fd); } free(cmd_pkt); if (free_nodes) { fsa_node_addr_free(nodes); } return ki_list; }
/* gets host info from config file based on node number (starting at 0) */ static fsa_node_addr *node_num_to_node_addr(int node_num) { /* sanity check node number */ if (node_num < 0 || node_num >= FS_MAX_SEGMENTS) { return NULL; } GKeyFile *config = fsa_get_config(); fsa_node_addr *nodes = NULL; int default_port = fsa_get_admind_port(config); /* assume localhost if no config file found */ if (config == NULL) { if (node_num == 0) { nodes = fsa_node_addr_new("localhost"); nodes->port = default_port; return nodes; } else { return NULL; } } /* if no nodes found in config file, use localhost */ nodes = fsa_get_node_list(config); /* done with config */ fsa_config_free(config); if (nodes == NULL) { if (node_num == 0) { nodes = fsa_node_addr_new("localhost"); nodes->port = default_port; return nodes; } else { return NULL; } } /* count through node list to get node node_num in */ int i = 0; fsa_node_addr *cur = nodes; fsa_node_addr *tmp = NULL; while (cur != NULL) { if (i == node_num) { /* free rest of node list, then return the current */ fsa_node_addr_free(cur->next); cur->next = NULL; return cur; } /* free current node then move to next */ tmp = cur; cur = cur->next; fsa_node_addr_free_one(tmp); i += 1; } return NULL; }
/* Check whether admin daemon on all nodes is reachable */ static int cmd_list_nodes(void) { /* this command has no arguments, exit if any are found */ if (args_index >= 0) { print_invalid_arg(); return 1; } /* network related vars */ struct addrinfo hints; int default_port = FS_ADMIND_PORT; fsa_node_addr *nodes = NULL; fsa_node_addr *p; int sock_fd; char ipaddr[INET6_ADDRSTRLEN]; /* printing/output related vars */ int all_nodes_ok = 0; int hostlen = 13; int len; int node_num = 0; int n_nodes = 0; /* Setup hints information */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; /* attempt to read /etc/4store.conf */ GKeyFile *config = fsa_get_config(); if (config == NULL) { /* assume localhost if no config file found */ fsa_error(LOG_WARNING, "Unable to read config file at '%s', assuming localhost\n", fs_get_config_file()); } else { nodes = fsa_get_node_list(config); if (nodes == NULL) { fsa_error(LOG_WARNING, "No nodes found in '%s', assuming localhost\n", fs_get_config_file()); default_port = fsa_get_admind_port(config); } } if (nodes == NULL) { /* Use localhost and default port */ nodes = fsa_node_addr_new("localhost"); nodes->port = default_port; } /* loop through once to get lengths of various fields */ for (p = nodes; p != NULL; p = p->next) { len = strlen(p->host) + 1; if (len > hostlen) { hostlen = len; } n_nodes += 1; } int n_nodes_len = int_len(n_nodes); if (n_nodes_len < 11) { n_nodes_len = 11; } /* print column headers */ if (colour_flag) { printf(ANSI_COLOUR_BLUE); } printf("%-*s %-*s port status ip_address\n", n_nodes_len, "node_number", hostlen, "hostname"); if (colour_flag) { printf(ANSI_COLOUR_RESET); } /* loop through all nodes and attempt to connect admin daemon on each */ for (p = nodes; p != NULL; p = p->next) { /* set default output for IP address */ strcpy(ipaddr, "unknown"); /* check if we can open conn to admin daemon */ sock_fd = fsaf_connect_to_admind(p->host, p->port, &hints, ipaddr); /* print result of attempted connection */ printf("%-*d %-*s %-5d ", n_nodes_len, node_num, hostlen, p->host, p->port); if (sock_fd == -1) { print_colour("unreachable", ANSI_COLOUR_RED); all_nodes_ok = 2; } else { print_colour("ok ", ANSI_COLOUR_GREEN); close(sock_fd); } printf(" %s\n", ipaddr); node_num += 1; } fsa_node_addr_free(nodes); fsa_config_free(config); return all_nodes_ok; }
static int cmd_list_stores(void) { /* verbose listing moved to separate function for clarity */ if (verbosity >= V_VERBOSE) { return cmd_list_stores_verbose(); } fsa_node_addr *nodes = get_nodes_from_cmd_line(); if (nodes == NULL) { /* error messages already printed */ return 1; } GHashTable *kb_hash = g_hash_table_new(g_str_hash, g_str_equal); fsa_node_addr *node = nodes; fsa_node_addr *tmp_node = NULL; fsa_kb_info *kis; fsa_kb_info *ki; fsa_kb_info *next_ki; int node_num = 0; int name_len; int max_name_len = 10; /* track lengths of kb names */ /* connect to each node separately */ while (node != NULL) { /* only pass a single node to fetch_kb_info, so break linked list */ tmp_node = node->next; node->next = NULL; kis = fsaf_fetch_kb_info(NULL, node); /* restore next item in list */ node->next = tmp_node; if (kis != NULL) { /* insert each kb info record into hash table */ ki = kis; while (ki != NULL) { /* will be breaking the linked list, so track next */ next_ki = ki->next; /* will return NULL if key not found */ ki->next = g_hash_table_lookup(kb_hash, ki->name); g_hash_table_insert(kb_hash, ki->name, ki); /* used to align columns when printing */ name_len = strlen((char *)ki->name); if (name_len > max_name_len) { max_name_len = name_len; } ki = next_ki; } } node_num += 1; node = node->next; } /* sort hash keys, print info for each kb in turn */ GList *kb_name_list = g_hash_table_get_keys(kb_hash); kb_name_list = g_list_sort(kb_name_list, (GCompareFunc)strcmp); char *kb_name; int n_total, n_running, n_stopped, n_unknown; int comma = 0; int print_store_header = 1; if (kb_name_list == NULL) { printf("No stores found\n"); } while (kb_name_list != NULL) { if (print_store_header) { if (colour_flag) { printf(ANSI_COLOUR_BLUE); } printf("%-*s store_status backend_status\n", max_name_len, "store_name"); if (colour_flag) { printf(ANSI_COLOUR_RESET); } print_store_header = 0; } n_running = n_stopped = n_unknown = 0; kb_name = kb_name_list->data; kis = g_hash_table_lookup(kb_hash, kb_name); for (ki = kis; ki != NULL; ki = ki->next) { switch (ki->status) { case KB_STATUS_RUNNING: n_running += 1; break; case KB_STATUS_STOPPED: n_stopped += 1; break; case KB_STATUS_UNKNOWN: n_unknown += 1; break; default: break; } } n_total = n_running + n_stopped + n_unknown; /* output info for this kb */ printf("%-*s ", max_name_len, kb_name); if (n_running == n_total) { print_colour("available ", ANSI_COLOUR_GREEN); } else { print_colour("unavailable ", ANSI_COLOUR_RED); } comma = 0; if (n_running > 0) { printf("%d/%d ", n_running, n_total); print_colour("running", ANSI_COLOUR_GREEN); comma = 1; } if (n_stopped > 0) { if (comma) { printf(", "); } printf("%d/%d ", n_stopped, n_total); print_colour("stopped", ANSI_COLOUR_RED); comma = 1; } if (n_unknown > 0) { if (comma) { printf(", "); } printf("%d/%d ", n_unknown, n_total); print_colour("unknown", ANSI_COLOUR_YELLOW); } printf("\n"); /* done with data in hash entry now */ fsa_kb_info_free(kis); kb_name_list = g_list_next(kb_name_list); } kb_name_list = g_list_first(kb_name_list); g_list_free(kb_name_list); fsa_node_addr_free(nodes); g_hash_table_destroy(kb_hash); return 0; }
static int cmd_list_stores_verbose(void) { fsa_node_addr *nodes = get_nodes_from_cmd_line(); if (nodes == NULL) { /* error messages already printed */ return 1; } fsa_node_addr *node = nodes; fsa_node_addr *tmp_node = NULL; fsa_kb_info *ki; fsa_kb_info *kis; int node_num = 0; int info_header_printed = 0; int print_node_header = 1; /* connect to each node separately */ while (node != NULL) { print_node_line(node_num, node->host, print_node_header); print_node_header = 0; /* only pass a single node to fetch_kb_info, so break linked list */ tmp_node = node->next; node->next = NULL; kis = fsaf_fetch_kb_info(NULL, node); /* restore next item in list */ node->next = tmp_node; /* TODO: better error handling, differentiate between err and no * stores */ if (kis != NULL) { /* get column widths */ int max_name = 10; int max_segs = 10; int curlen; for (ki = kis; ki != NULL; ki = ki->next) { curlen = strlen((char *)ki->name); if (curlen > max_name) { max_name = curlen; } curlen = ki->p_segments_len * 3; if (curlen > max_segs) { max_segs = curlen; } } /* print header */ if (!info_header_printed) { if (colour_flag) { printf(ANSI_COLOUR_BLUE); } printf(" %-*s status port number_of_segments\n", max_name, "store_name"); if (colour_flag) { printf(ANSI_COLOUR_RESET); } info_header_printed = 1; } /* print kb info */ for (ki = kis; ki != NULL; ki = ki->next) { printf(" %-*s ", max_name, ki->name); const char *kistat = fsa_kb_info_status_to_string(ki->status); if (ki->status == KB_STATUS_RUNNING) { print_colour(kistat, ANSI_COLOUR_GREEN); } else if (ki->status == KB_STATUS_STOPPED) { print_colour(kistat, ANSI_COLOUR_RED); } else { print_colour(kistat, ANSI_COLOUR_YELLOW); } printf(" "); if (ki->port > 0) { printf("%-5d ", ki->port); } else { printf(" "); } if (ki->p_segments_len > 0) { if (verbosity == V_VERBOSE) { for (int i = 0; i < ki->p_segments_len; i++) { printf("%d", ki->p_segments_data[i]); if (i == ki->p_segments_len-1) { printf(" of %d", ki->num_segments); } else { printf(","); } } } else { /* print summary of segments */ printf("%d of %d", ki->p_segments_len, ki->num_segments); } } printf("\n"); } } fsa_kb_info_free(kis); node_num += 1; node = node->next; } fsa_node_addr_free(nodes); return 0; }