Exemple #1
0
/* Returns -1 on error, 0 on success. Sets exit_val to exit value of
   4-backend, sets output to the output from running the command, and sets
   err to the reason for error. */
int fsab_start_local_kb(const unsigned char *kb_name, int *exit_val,
                        unsigned char **output, int *err)
{
    fsa_error(LOG_DEBUG, "starting kb '%s'", kb_name);

    /* set defaults to indicate no output or retval yet */
    *exit_val = -1;
    *output = NULL;

    fsa_kb_info *ki = fsab_get_local_kb_info(kb_name, err);
    if (ki == NULL) {
        /* failed to read metadata.nt, therefore kb doesn't exist */
        *err = ADM_ERR_KB_GET_INFO;
        return -1;
    }

    if (*err == ADM_ERR_KB_NOT_EXISTS) {
        fsa_kb_info_free(ki);
        return -1;
    }

    /* check whether kb is running */
    if (ki->status == KB_STATUS_RUNNING) {
        fs_error(LOG_INFO, "cannot start %s, already started", kb_name);
        *err = ADM_ERR_KB_STATUS_RUNNING;
        fsa_kb_info_free(ki);
        return -1;
    }
    fsa_kb_info_free(ki);

    char *cmdname = "4s-backend";
    char *args[1] = {(char *)kb_name};

    return exec_fs_cmd(cmdname, 1, args, exit_val, output, err);
}
Exemple #2
0
/* Return 0 on normal operation, -1 or error */
int fsab_delete_local_kb(const unsigned char *kb_name, int *exit_val,
                         unsigned char **output, int *err)
{
    fsa_error(LOG_DEBUG, "deleting kb '%s'", kb_name);

    fsa_kb_info *ki = fsab_get_local_kb_info(kb_name, err);
    if (ki == NULL) {
        return -1;
    }

    /* if kb does not exist, nothing to do */
    if (*err == ADM_ERR_KB_NOT_EXISTS) {
        fsa_error(LOG_DEBUG,
                  "kb '%s' does not exist, nothing to delete", kb_name);
        fsa_kb_info_free(ki);
        return 0;
    }

    /* if kb exists, attempt to stop it unless it is definitely stopped */
    if (ki->status != KB_STATUS_STOPPED) {
        /* ignore errors, we're deleting store anyway */
        fsab_stop_local_kb(kb_name, err);
    }
    fsa_kb_info_free(ki);

    /* use 4s-backend-destroy to delete the store */
    char *cmdname = "4s-backend-destroy";
    char *args[1] = {(char *)kb_name};

    return exec_fs_cmd(cmdname, 1, args, exit_val, output, err);
}
Exemple #3
0
static void handle_cmd_get_kb_info_all(int client_fd)
{
    int rv, len;
    fsa_kb_info *ki;
    unsigned char *response;

    /* get info on all running/stopped kbs on this host */
    int err;
    ki = fsab_get_local_kb_info_all(&err);
    if (ki == NULL) {
        send_error_message(client_fd, "failed to get local kb info");
        return;
    }

    /* encode response to send back to client */
    response = fsap_encode_rsp_get_kb_info_all(ki, &len);
    fsa_kb_info_free(ki); /* done with kb info now */
    if (response == NULL) {
        send_error_message(client_fd, "failed to encode response");
        return;
    }

    fsa_error(LOG_DEBUG, "response size is %d bytes", len);

    /* send entire response back to client */
    rv = fsa_sendall(client_fd, response, &len);
    free(response); /* done with response buffer */
    if (rv == -1) {
        fsa_error(LOG_ERR, "failed to send response to client: %s",
                  strerror(errno));
        return;
    }

    fsa_error(LOG_DEBUG, "%d bytes sent to client", len);
}
Exemple #4
0
void fsa_kb_info_free(fsa_kb_info *ki)
{
    if (ki == NULL) {
        return;
    }

    free(ki->name);
    free(ki->ipaddr);
    free(ki->p_segments_data);
    fsa_kb_info_free(ki->next);
    free(ki);
}
Exemple #5
0
/* get all local info about a kb. Uses errno to differentiate between
   returning NULL when there are no kbs, and NULL due to a read error */
fsa_kb_info *fsab_get_local_kb_info(const unsigned char *kb_name, int *err)
{
    int rv;
    fsa_kb_info *ki = fsa_kb_info_new();

    rv = fsab_kb_info_init(ki, kb_name, err);
    if (rv == -1) {
        fsa_error(LOG_ERR, "failed to get local kb info for kb %s", kb_name);
        fsa_kb_info_free(ki);
        return NULL;
    }

    return ki;
}
Exemple #6
0
/* get all information about a specific kb on this host, send to client */
static void handle_cmd_get_kb_info(int client_fd, uint16_t datasize)
{
    int rv, len, err;
    fsa_kb_info *ki;
    unsigned char *response;
    unsigned char *kb_name;

    kb_name = get_string_from_client(client_fd, datasize);
    if (kb_name == NULL) {
        /* errors already logged/handled */
        return;
    }

    /* should already have been checked by client */
    if (!fsa_is_valid_kb_name((const char *)kb_name)) {
        fsa_error(LOG_CRIT, "Invalid kb name received from client");
        send_error_message(client_fd, "kb name invalid");
        free(kb_name);
        return;
    }

    ki = fsab_get_local_kb_info(kb_name, &err);
    free(kb_name); /* done with kb_name */
    if (ki == NULL || err == ADM_ERR_KB_NOT_EXISTS) {
        send_error_message(client_fd, "failed to get local kb info");
        return;
    }

    /* encode message for client */
    response = fsap_encode_rsp_get_kb_info(ki, &len);
    fsa_kb_info_free(ki);
    if (response == NULL) {
        send_error_message(client_fd, "failed to encode kb info");
        return;
    }

    fsa_error(LOG_DEBUG, "response size is %d bytes", len);

    /* send entire response back to client */
    rv = fsa_sendall(client_fd, response, &len);
    free(response); /* done with response buffer */
    if (rv == -1) {
        fsa_error(LOG_ERR, "failed to send response to client: %s",
                  strerror(errno));
        return;
    }

    fsa_error(LOG_DEBUG, "%d bytes sent to client", len);
}
Exemple #7
0
/* get info on all kbs on this host */
fsa_kb_info *fsab_get_local_kb_info_all(int *err)
{
    struct dirent *entry;
    DIR *dp;
    fsa_kb_info *first_ki = NULL;
    fsa_kb_info *cur_ki = NULL;
    int rv;

    dp = opendir(FS_STORE_ROOT);
    if (dp == NULL) {
        fsa_error(LOG_ERR, "failed to open directory '%s': %s",
                  FS_STORE_ROOT, strerror(errno));
        *err = ADM_ERR_GENERIC;
        return NULL;
    }

    while ((entry = readdir(dp)) != NULL) {
        if (entry->d_name[0] == '.') {
            /* skip ., .., and hidden dirs */
            continue;
        }

        cur_ki = fsa_kb_info_new();
        rv = fsab_kb_info_init(cur_ki, (unsigned char *)entry->d_name, err);
        if (rv == -1) {
            fsa_error(LOG_ERR, "failed to initialise kb info for %s",
                      entry->d_name);
            fsa_kb_info_free(cur_ki);
            continue;
        }
        else {
            cur_ki->next = first_ki;
            first_ki = cur_ki;
        }
    }

    closedir(dp);

    /* set errno to differentiate between no kbs, and error */
    *err = 0;
    return first_ki;
}
Exemple #8
0
/* Return 0 on normal operation, -1 or error */
int fsab_create_local_kb(const fsa_kb_setup_args *ksargs, int *exit_val,
                         unsigned char **output, int *err)
{
    fsa_error(LOG_DEBUG, "creating kb '%s'", ksargs->name);

    /* check whether kb exists already, and it's state */
    fsa_kb_info *ki = fsab_get_local_kb_info(ksargs->name, err);

    /* if KB exists */
    if (ki != NULL && *err != ADM_ERR_KB_NOT_EXISTS) {
        /* do not overwrite existing kb */
        if (!ksargs->delete_existing) {
            *err = ADM_ERR_KB_EXISTS;
            fsa_error(LOG_DEBUG,
                      "kb '%s' exists, and delete_existing=0, doing nothing",
                      ksargs->name);
            fsa_kb_info_free(ki);
            return -1;
        }
        else {
            /* ok to overwrite, so stop first, ignoring errors */
            fsab_stop_local_kb(ksargs->name, err);
        }
    }

    fsa_kb_info_free(ki);

    /* kb should either not exist or be stopped by now */

    /* max args length is 11 */
    char *args[11];
    int n_args = 0;
    char node_id_str[4];        /* holds uint8 */
    char cluster_size_str[4];   /* holds uint8 */
    char num_segments_str[6];   /* holds uint16 */

    sprintf(node_id_str, "%d", ksargs->node_id);
    sprintf(cluster_size_str, "%d", ksargs->cluster_size);
    sprintf(num_segments_str, "%d", ksargs->num_segments);

    args[n_args++] = "--node";
    args[n_args++] = node_id_str;
    args[n_args++] = "--cluster";
    args[n_args++] = cluster_size_str;
    args[n_args++] = "--segments";
    args[n_args++] = num_segments_str;

    if (ksargs->password != NULL) {
        args[n_args++] = "--password";
        args[n_args++] = (char *)ksargs->password;
    }

    if (ksargs->mirror_segments) {
        args[n_args++] = "--mirror";
    }

    if (ksargs->model_files) {
        args[n_args++] = "--model-files";
    }

    args[n_args++] = (char *)ksargs->name;

    /* use 4s-backend-setup to delete the store */
    char *cmdname = "4s-backend-setup";

    return exec_fs_cmd(cmdname, n_args, args, exit_val, output, err);
}
Exemple #9
0
/* return 0 on success, -1 otherwise, and sets err */
int fsab_stop_local_kb(const unsigned char *kb_name, int *err)
{
    fs_error(LOG_DEBUG, "stopping kb '%s'", kb_name);

    fsa_kb_info *ki = fsab_get_local_kb_info(kb_name, err);
    if (ki == NULL) {
        return -1;
    }

    if (*err == ADM_ERR_KB_NOT_EXISTS) {
        fsa_kb_info_free(ki);
        return -1;
    }

    /* check whether kb is running */
    if (ki->status == KB_STATUS_STOPPED) {
        fs_error(LOG_INFO, "cannot stop %s, already stopped", kb_name);
        *err = ADM_ERR_KB_STATUS_STOPPED;
        fsa_kb_info_free(ki);
        return -1;
    }
    else if (ki->status == KB_STATUS_UNKNOWN) {
        fs_error(LOG_ERR, "cannot stop %s, runtime status unknown", kb_name);
        *err = ADM_ERR_KB_STATUS_UNKNOWN;
        fsa_kb_info_free(ki);
        return -1;
    }

    /* sanity check */
    if (ki->status != KB_STATUS_RUNNING) {
        *err = ADM_ERR_GENERIC;
        fsa_kb_info_free(ki);
        return -1;
    }

    /* only need pid from here on */
    int pid = ki->pid;
    fsa_kb_info_free(ki);

    /* check that we've got a sensible pid of the running store */
    if (pid == 0) {
        fs_error(LOG_ERR, "cannot stop %s, no pid found", kb_name);
        *err = ADM_ERR_GENERIC;
        return -1;
    }

    /* send sigterm to 4s-backend process, returns 0 or -1, sets errno  */
    int rv = kill(pid, SIGTERM);
    if (rv != 0) {
        *err = ADM_ERR_SEE_ERRNO;
        return -1;
    }

    /* poll for few seconds until process is dead */
    long int nanosecs = 50000000L; /* 0.05s */
    int n_tries = 200; /* 10s total */
    struct timespec req = {0, nanosecs};
    while (n_tries > 0) {
        rv = kill(pid, 0);
        if (rv == -1 && errno == ESRCH) {
            /* process with pid not found, kill successful */
            return 0;
        }

        /* ignore errors */
        nanosleep(&req, NULL);

        n_tries -= 1;
    }

    *err = ADM_ERR_KILL_FAILED;
    return -1;
}
Exemple #10
0
static void start_or_stop_kb_all(int client_fd, int action)
{
    int rv, err;
    int n_kbs = 0;
    int max_kb_len = 0;

    /* get all local kbs */
    fsa_kb_info *ki = fsab_get_local_kb_info_all(&err);
    if (ki == NULL) {
        if (err == 0) {
            /* no kbs on this host */
            send_expect_n_kb(client_fd, 0, 0);
        }
        else {
            send_error_message(client_fd, "failed to read store information");
        }
        return;
    }

    /* count number of kbs */
    for (fsa_kb_info *p = ki; p != NULL; p = p->next) {
        int kb_len = strlen((char *)p->name);
        if (kb_len > max_kb_len) {
            max_kb_len = kb_len;
        }
        n_kbs += 1;
    }

    /* tell client to expect a message for each */
    rv = send_expect_n_kb(client_fd, n_kbs, max_kb_len);
    if (rv == -1) {
        /* failed to send message to client, so give up */
        fsa_kb_info_free(ki);
        return;
    }

    int exit_val; /* ignored for now */
    unsigned char *msg = NULL; /* sent back to client */
    int return_val; /* sent back to client */

    int len; /* response length */
    unsigned char *response = NULL; /* response buffer */

    for (fsa_kb_info *p = ki; p != NULL; p = p->next) {
        if (action == STOP_STORES) {
            rv = fsab_stop_local_kb(p->name, &err);
        }
        else if (action == START_STORES) {
            rv = fsab_start_local_kb(p->name, &exit_val, &msg, &err);
        }

        if (rv < 0) {
            return_val = err;
        }
        else {
            return_val = ADM_ERR_OK;
        }

        /* encode message for client */
        if (action == STOP_STORES) {
            response =
                fsap_encode_rsp_stop_kb(return_val, p->name, msg, &len);
        }
        else if (action == START_STORES) {
            response =
                fsap_encode_rsp_start_kb(return_val, p->name, msg, &len);
        }

        if (msg != NULL) {
            free(msg);
            msg = NULL;
        }

        fsa_error(LOG_DEBUG, "response size is %d bytes", len);

        /* send entire response back to client */
        rv = fsa_sendall(client_fd, response, &len);
        free(response); /* done with response buffer */
        response = NULL;
        if (rv == -1) {
            fsa_error(LOG_ERR, "failed to send response to client: %s",
                      strerror(errno));
            continue;
        }

        fsa_error(LOG_DEBUG, "%d bytes sent to client", len);
    }

    fsa_kb_info_free(ki);
}
Exemple #11
0
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;
}
Exemple #12
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;
}