Example #1
0
LIBCOUCHSTORE_API
uint64_t couchstore_read_int(FILE *in, char *buf, size_t size,
                                                  couchstore_error_t *ret)
{
    uint64_t val;
    *ret = COUCHSTORE_SUCCESS;

    if (couchstore_read_line(in, buf, size) != buf) {
        *ret = COUCHSTORE_ERROR_READ;
        return 0;
    }

    if (sscanf(buf, "%"SCNu64, &val) != 1) {
        *ret = COUCHSTORE_ERROR_READ;
        return 0;
    }

    return val;
}
Example #2
0
LIBCOUCHSTORE_API
view_group_info_t *couchstore_read_view_group_info(FILE *in_stream,
                                                   FILE *error_stream)
{
    view_group_info_t *info;
    char buf[4096];
    char *dup;
    int i, j;
    int reduce_len;

    info = (view_group_info_t *) calloc(1, sizeof(*info));
    if (info == NULL) {
        fprintf(error_stream, "Memory allocation failure\n");
        goto out_error;
    }

    if (couchstore_read_line(in_stream, buf, sizeof(buf)) != buf) {
        fprintf(stderr, "Error reading source index file path\n");
        goto out_error;
    }
    dup = strdup(buf);
    if (dup == NULL) {
        fprintf(error_stream, "Memory allocation failure\n");
        goto out_error;
    }
    info->filepath = (const char *) dup;

    if (fscanf(in_stream, "%" SCNu64 "\n", &info->header_pos) != 1) {
        fprintf(error_stream, "Error reading header position\n");
        goto out_error;
    }

    if (fscanf(in_stream, "%d\n", &info->num_btrees) != 1) {
        fprintf(error_stream, "Error reading number of btrees\n");
        goto out_error;
    }

    info->btree_infos = (view_btree_info_t *)
        calloc(info->num_btrees, sizeof(view_btree_info_t));
    if (info->btree_infos == NULL) {
        fprintf(error_stream, "Memory allocation failure\n");
        info->num_btrees = 0;
        goto out_error;
    }

    for (i = 0; i < info->num_btrees; ++i) {
        view_btree_info_t *bti = &info->btree_infos[i];

        if (fscanf(in_stream, "%d\n", &bti->num_reducers) != 1) {
            fprintf(error_stream,
                    "Error reading number of reducers for btree %d\n", i);
            goto out_error;
        }

        bti->names = (const char **) calloc(bti->num_reducers, sizeof(char *));
        if (bti->names == NULL) {
            fprintf(error_stream, "Memory allocation failure\n");
            bti->num_reducers = 0;
            goto out_error;
        }

        bti->reducers = (const char **) calloc(bti->num_reducers, sizeof(char *));
        if (bti->reducers == NULL) {
            fprintf(error_stream, "Memory allocation failure\n");
            bti->num_reducers = 0;
            free(bti->names);
            goto out_error;
        }

        for (j = 0; j < bti->num_reducers; ++j) {
            if (couchstore_read_line(in_stream, buf, sizeof(buf)) != buf) {
                fprintf(error_stream,
                        "Error reading btree %d view %d name\n", i, j);
                goto out_error;
            }
            dup = strdup(buf);
            if (dup == NULL) {
                fprintf(error_stream, "Memory allocation failure\n");
                goto out_error;
            }
            bti->names[j] = (const char *) dup;

            if (fscanf(in_stream, "%d\n", &reduce_len) != 1) {
                fprintf(error_stream,
                        "Error reading btree %d view %d "
                        "reduce function size\n", i, j);
                goto out_error;
            }

            dup = (char *) malloc(reduce_len + 1);
            if (dup == NULL) {
                fprintf(error_stream, "Memory allocation failure\n");
                goto out_error;
            }

            if (fread(dup, reduce_len, 1, in_stream) != 1) {
                fprintf(error_stream,
                        "Error reading btree %d view %d reducer\n", i, j);
                free(dup);
                goto out_error;
            }
            dup[reduce_len] = '\0';
            bti->reducers[j] = (const char *) dup;
        }
    }

    return info;

out_error:
    couchstore_free_view_group_info(info);

    return NULL;
}
int main(int argc, char *argv[])
{
    char view_file_type;
    int num_files;
    int i, j;
    char **view_files;
    char dest_file[LINE_BUF_SIZE];
    file_merger_error_t error;
    cb_thread_t exit_thread;
    int status = 0;

    (void) argc;
    (void) argv;

    /*
     * Disable buffering for stdout since file merger messages needs
     * to be immediately available at erlang side
     */
    setvbuf(stdout, (char *) NULL, _IONBF, 0);

    if (set_binary_mode() < 0) {
        fprintf(stderr, "Error setting binary mode\n");
        exit(EXIT_FAILURE);
    }

    if (fscanf(stdin, "%c\n", &view_file_type) != 1) {
        fprintf(stderr, "Error reading view file type.\n");
        exit(EXIT_FAILURE);
    }
    if (view_file_type != 'i' && view_file_type != 'v') {
        fprintf(stderr, "View file type must be 'i' or 'v'.\n");
        exit(EXIT_FAILURE);
    }

    if (fscanf(stdin, "%d\n", &num_files) != 1) {
        fprintf(stderr, "Error reading number of files to merge.\n");
        exit(EXIT_FAILURE);
    }
    if (num_files <= 0) {
        fprintf(stderr, "Number of files to merge is negative or zero.\n");
        exit(EXIT_FAILURE);
    }

    view_files = (char **) malloc(sizeof(char *) * num_files);
    if (view_files == NULL) {
        fprintf(stderr, "Memory allocation failure.\n");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < num_files; ++i) {
        view_files[i] = (char *) malloc(LINE_BUF_SIZE);
        if (view_files[i] == NULL) {
            for (j = 0; j < i; ++j) {
                free(view_files[j]);
            }
            free(view_files);
            fprintf(stderr, "Memory allocation failure.\n");
            exit(EXIT_FAILURE);
        }

        if (couchstore_read_line(stdin, view_files[i], LINE_BUF_SIZE) != view_files[i]) {
            for (j = 0; j <= i; ++j) {
                free(view_files[j]);
            }
            free(view_files);
            fprintf(stderr, "Error reading view file number %d.\n", (i + 1));
            exit(EXIT_FAILURE);
        }
    }

    if (couchstore_read_line(stdin, dest_file, LINE_BUF_SIZE) != dest_file) {
        fprintf(stderr, "Error reading destination file name.\n");
        status = 1;
        goto finished;
    }

    status = start_exit_listener(&exit_thread);
    if (status) {
        fprintf(stderr, "Error starting stdin exit listener thread\n");
        goto finished;
    }

    if (num_files > 1) {
        const char **src_files = (const char **) view_files;
        switch (view_file_type) {
        case 'i':
            error = merge_view_ids_ops_files(src_files, num_files, dest_file);
            break;
        case 'v':
            error = merge_view_kvs_ops_files(src_files, num_files, dest_file);
            break;
        default:
            fprintf(stderr, "Unknown view file type: %c\n", view_file_type);
            status = 1;
            goto finished;
        }

        if (error == FILE_MERGER_SUCCESS) {
            for (i = 0; i < num_files; ++i) {
                /* Ignore failures.
                   Erlang side will eventually delete the files later. */
                remove(view_files[i]);
            }
        } else {
            status = MERGE_ERROR_CODE(error);
            goto finished;
        }
    } else {
        if (rename(view_files[0], dest_file) != 0) {
            fprintf(stderr, "Error renaming file %s to %s: %s\n",
                    view_files[0], dest_file, strerror(errno));
            status = 1;
            goto finished;
        }
    }

 finished:
    for (i = 0; i < num_files; ++i) {
        free(view_files[i]);
    }
    free(view_files);

    return status;
}
int main(int argc, char *argv[])
{
    view_group_info_t *group_info = NULL;
    char buf[BUF_SIZE];
    char **source_files = NULL;
    char *dest_file = NULL;
    int i;
    size_t len;
    int ret = 2;
    uint64_t header_pos;
    view_error_t error_info;

    (void) argc;
    (void) argv;

    group_info = couchstore_read_view_group_info(stdin, stderr);
    if (group_info == NULL) {
        ret = COUCHSTORE_ERROR_ALLOC_FAIL;
        goto out;
    }

    source_files = (char **) calloc(group_info->num_btrees + 1, sizeof(char *));
    if (source_files == NULL) {
        fprintf(stderr, "Memory allocation failure\n");
        ret = COUCHSTORE_ERROR_ALLOC_FAIL;
        goto out;
    }

    if (couchstore_read_line(stdin, buf, BUF_SIZE) != buf) {
        fprintf(stderr, "Error reading destination file\n");
        ret = COUCHSTORE_ERROR_INVALID_ARGUMENTS;
        goto out;
    }
    len = strlen(buf);
    dest_file = (char *) malloc(len + 1);
    if (dest_file == NULL) {
        fprintf(stderr, "Memory allocation failure\n");
        ret = COUCHSTORE_ERROR_ALLOC_FAIL;
        goto out;
    }
    memcpy(dest_file, buf, len);
    dest_file[len] = '\0';

    for (i = 0; i <= group_info->num_btrees; ++i) {
        if (couchstore_read_line(stdin, buf, BUF_SIZE) != buf) {
            if (i == 0) {
                fprintf(stderr, "Error reading source file for id btree\n");
            } else {
                fprintf(stderr,
                        "Error reading source file for btree %d\n", i - 1);
            }
            ret = COUCHSTORE_ERROR_INVALID_ARGUMENTS;
            goto out;
        }

        len = strlen(buf);
        source_files[i] = (char *) malloc(len + 1);
        if (source_files[i] == NULL) {
            fprintf(stderr, "Memory allocation failure\n");
            ret = COUCHSTORE_ERROR_ALLOC_FAIL;
            goto out;
        }
        memcpy(source_files[i], buf, len);
        source_files[i][len] = '\0';
    }

    ret = couchstore_build_view_group(group_info,
                                      source_files[0],
                                      (const char **) &source_files[1],
                                      dest_file,
                                      &header_pos,
                                      &error_info);

    if (ret != COUCHSTORE_SUCCESS) {
        if (error_info.error_msg != NULL && error_info.view_name != NULL) {
            fprintf(stderr,
                    "Error building index for view `%s`, reason: %s\n",
                    error_info.view_name,
                    error_info.error_msg);
        }
        goto out;
    }

out:
    if (source_files != NULL) {
        for (i = 0; i <= group_info->num_btrees; ++i) {
            free(source_files[i]);
        }
        free(source_files);
    }
    free(dest_file);
    couchstore_free_view_group_info(group_info);
    free((void *) error_info.error_msg);
    free((void *) error_info.view_name);

    return (ret < 0) ? (100 + ret) : ret;
}