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; }
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; }