static couchstore_error_t write_header(Db *db) { sized_buf writebuf; size_t seqrootsize = 0, idrootsize = 0, localrootsize = 0; if (db->header.by_seq_root) { seqrootsize = ROOT_BASE_SIZE + db->header.by_seq_root->reduce_value.size; } if (db->header.by_id_root) { idrootsize = ROOT_BASE_SIZE + db->header.by_id_root->reduce_value.size; } if (db->header.local_docs_root) { localrootsize = ROOT_BASE_SIZE + db->header.local_docs_root->reduce_value.size; } writebuf.size = sizeof(raw_file_header) + seqrootsize + idrootsize + localrootsize; writebuf.buf = (char *) calloc(1, writebuf.size); raw_file_header* header = (raw_file_header*)writebuf.buf; header->version = encode_raw08(COUCH_DISK_VERSION); header->update_seq = encode_raw48(db->header.update_seq); header->purge_seq = encode_raw48(db->header.purge_seq); header->purge_ptr = encode_raw48(db->header.purge_ptr); header->seqrootsize = encode_raw16((uint16_t)seqrootsize); header->idrootsize = encode_raw16((uint16_t)idrootsize); header->localrootsize = encode_raw16((uint16_t)localrootsize); uint8_t *root = (uint8_t*)(header + 1); encode_root(root, db->header.by_seq_root); root += seqrootsize; encode_root(root, db->header.by_id_root); root += idrootsize; encode_root(root, db->header.local_docs_root); cs_off_t pos; couchstore_error_t errcode = db_write_header(&db->file, &writebuf, &pos); if (errcode == COUCHSTORE_SUCCESS) { db->header.position = pos; } free(writebuf.buf); return errcode; }
couchstore_error_t encode_index_header(const index_header_t *header, char **buffer, size_t *buffer_size) { char *buf = NULL, *b = NULL; size_t sz = 0; uint16_t id_btree_state_size; int i; size_t comp_size; char *comp; snappy_status res; sz += 1; /* version */ sz += 2; /* number of partitions */ sz += 3 * BITMASK_BYTE_SIZE; /* active/passive/cleanup bitmasks */ /* seqs */ sz += 2; sz += sorted_list_size(header->seqs) * (2 + 6); /* id btree state */ sz += 2; if (header->id_btree_state != NULL) { sz += sizeof(raw_btree_root); sz += header->id_btree_state->reduce_value.size; } /* view btree states */ sz += 1; for (i = 0; i < header->num_views; ++i) { sz += 2; if (header->view_states[i] != NULL) { sz += sizeof(raw_btree_root); sz += header->view_states[i]->reduce_value.size; } } /* has_replicas */ sz += 1; /* replicas_on_transfer */ sz += 2; sz += sorted_list_size(header->replicas_on_transfer) * 2; /* pending transition active */ sz += 2; sz += sorted_list_size(header->pending_transition.active) * 2; /* pending transition passive */ sz += 2; sz += sorted_list_size(header->pending_transition.passive) * 2; /* pending transition unindexable */ sz += 2; sz += sorted_list_size(header->pending_transition.unindexable) * 2; /* unindexable seqs */ sz += 2; sz += sorted_list_size(header->unindexable_seqs) * (2 + 6); /* partition versions */ if (header->version >= 2) { sz += size_of_partition_versions(header->part_versions); } b = buf = (char *) malloc(sz); if (buf == NULL) { goto alloc_error; } b[0] = (char) header->version; b += 1; enc_uint16(header->num_partitions, &b); memcpy(b, &header->active_bitmask, BITMASK_BYTE_SIZE); b += BITMASK_BYTE_SIZE; memcpy(b, &header->passive_bitmask, BITMASK_BYTE_SIZE); b += BITMASK_BYTE_SIZE; memcpy(b, &header->cleanup_bitmask, BITMASK_BYTE_SIZE); b += BITMASK_BYTE_SIZE; enc_part_seq_list(header->seqs, &b); if (header->id_btree_state != NULL) { id_btree_state_size = (uint16_t) sizeof(raw_btree_root); id_btree_state_size += (uint16_t) header->id_btree_state->reduce_value.size; } else { id_btree_state_size = 0; } enc_uint16(id_btree_state_size, &b); encode_root(b, header->id_btree_state); b += id_btree_state_size; b[0] = (char) header->num_views; b += 1; for (i = 0; i < header->num_views; ++i) { uint16_t view_state_size = 0; if (header->view_states[i] != NULL) { view_state_size = (uint16_t) sizeof(raw_btree_root); view_state_size += (uint16_t) header->view_states[i]->reduce_value.size; } enc_uint16(view_state_size, &b); encode_root(b, header->view_states[i]); b += view_state_size; } b[0] = (char) (header->has_replica ? 1 : 0); b += 1; enc_seq_list(header->replicas_on_transfer, &b); enc_seq_list(header->pending_transition.active, &b); enc_seq_list(header->pending_transition.passive, &b); enc_seq_list(header->pending_transition.unindexable, &b); enc_part_seq_list(header->unindexable_seqs, &b); if (header->version >= 2) { enc_part_versions_list(header->part_versions, &b); } comp_size = snappy_max_compressed_length(sz); comp = (char *) malloc(16 + comp_size); if (comp == NULL) { goto alloc_error; } res = snappy_compress(buf, sz, comp + 16, &comp_size); if (res != SNAPPY_OK) { /* TODO: a new error for couchstore_error_t */ free(comp); goto alloc_error; } memcpy(comp, header->signature, 16); *buffer = comp; *buffer_size = 16 + comp_size; free(buf); return COUCHSTORE_SUCCESS; alloc_error: free(buf); *buffer = NULL; *buffer_size = 0; return COUCHSTORE_ERROR_ALLOC_FAIL; }