static couchstore_error_t by_id_read_docinfo(DocInfo **pInfo, sized_buf *k, sized_buf *v) { const raw_id_index_value *raw = (const raw_id_index_value*)v->buf; ssize_t revMetaSize = v->size - sizeof(*raw); if (revMetaSize < 0) { return COUCHSTORE_ERROR_CORRUPT; } uint32_t datasize, deleted; uint8_t content_meta; uint64_t bp, seq, revnum; seq = decode_raw48(raw->db_seq); datasize = decode_raw32(raw->size); bp = decode_raw48(raw->bp); deleted = (bp & BP_DELETED_FLAG) != 0; bp &= ~BP_DELETED_FLAG; content_meta = decode_raw08(raw->content_meta); revnum = decode_raw48(raw->rev_seq); sized_buf rev_meta = {v->buf + sizeof(*raw), revMetaSize}; DocInfo* docInfo = couchstore_alloc_docinfo(k, &rev_meta); if (!docInfo) { return COUCHSTORE_ERROR_ALLOC_FAIL; } docInfo->db_seq = seq; docInfo->rev_seq = revnum; docInfo->deleted = deleted; docInfo->bp = bp; docInfo->size = datasize; docInfo->content_meta = content_meta; *pInfo = docInfo; return COUCHSTORE_SUCCESS; }
static couchstore_error_t by_seq_read_docinfo(DocInfo **pInfo, sized_buf *k, sized_buf *v) { const raw_seq_index_value *raw = (const raw_seq_index_value*)v->buf; ssize_t extraSize = v->size - sizeof(*raw); if (extraSize < 0) { return COUCHSTORE_ERROR_CORRUPT; } uint32_t idsize, datasize; decode_kv_length(&raw->sizes, &idsize, &datasize); uint64_t bp = decode_raw48(raw->bp); int deleted = (bp & BP_DELETED_FLAG) != 0; bp &= ~BP_DELETED_FLAG; uint8_t content_meta = decode_raw08(raw->content_meta); uint64_t rev_seq = decode_raw48(raw->rev_seq); uint64_t db_seq = decode_sequence_key(k); sized_buf id = {v->buf + sizeof(*raw), idsize}; sized_buf rev_meta = {id.buf + idsize, extraSize - id.size}; DocInfo* docInfo = couchstore_alloc_docinfo(&id, &rev_meta); if (!docInfo) { return COUCHSTORE_ERROR_ALLOC_FAIL; } docInfo->db_seq = db_seq; docInfo->rev_seq = rev_seq; docInfo->deleted = deleted; docInfo->bp = bp; docInfo->size = datasize; docInfo->content_meta = content_meta; *pInfo = docInfo; return COUCHSTORE_SUCCESS; }
// Attempts to initialize the database from a header at the given file position static couchstore_error_t find_header_at_pos(Db *db, cs_off_t pos) { int errcode = COUCHSTORE_SUCCESS; raw_file_header *header_buf = NULL; uint8_t buf[2]; ssize_t readsize = db->file.ops->pread(db->file.handle, buf, 2, pos); error_unless(readsize == 2, COUCHSTORE_ERROR_READ); if (buf[0] == 0) { return COUCHSTORE_ERROR_NO_HEADER; } else if (buf[0] != 1) { return COUCHSTORE_ERROR_CORRUPT; } int header_len = pread_header(&db->file, pos, (char**)&header_buf); if (header_len < 0) { error_pass(header_len); } db->header.position = pos; db->header.disk_version = decode_raw08(header_buf->version); error_unless(db->header.disk_version == COUCH_DISK_VERSION, COUCHSTORE_ERROR_HEADER_VERSION); db->header.update_seq = decode_raw48(header_buf->update_seq); db->header.purge_seq = decode_raw48(header_buf->purge_seq); db->header.purge_ptr = decode_raw48(header_buf->purge_ptr); error_unless(db->header.purge_ptr <= db->header.position, COUCHSTORE_ERROR_CORRUPT); int seqrootsize = decode_raw16(header_buf->seqrootsize); int idrootsize = decode_raw16(header_buf->idrootsize); int localrootsize = decode_raw16(header_buf->localrootsize); error_unless(header_len == HEADER_BASE_SIZE + seqrootsize + idrootsize + localrootsize, COUCHSTORE_ERROR_CORRUPT); char *root_data = (char*) (header_buf + 1); // i.e. just past *header_buf error_pass(read_db_root(db, &db->header.by_seq_root, root_data, seqrootsize)); root_data += seqrootsize; error_pass(read_db_root(db, &db->header.by_id_root, root_data, idrootsize)); root_data += idrootsize; error_pass(read_db_root(db, &db->header.local_docs_root, root_data, localrootsize)); cleanup: free(header_buf); return errcode; }
static int by_id_read_docinfo(DocInfo **pInfo, sized_buf *k, sized_buf *v) { const raw_id_index_value *raw = (const raw_id_index_value*)v->buf; ssize_t revMetaSize = v->size - sizeof(*raw); if (revMetaSize < 0) { return COUCHSTORE_ERROR_CORRUPT; } uint32_t datasize, deleted; uint8_t content_meta; uint64_t bp, seq, revnum; seq = decode_raw48(raw->db_seq); datasize = decode_raw32(raw->size); bp = decode_raw48(raw->bp); deleted = (bp & BP_DELETED_FLAG) != 0; bp &= ~BP_DELETED_FLAG; content_meta = decode_raw08(raw->content_meta); revnum = decode_raw48(raw->rev_seq); DocInfo* docInfo = malloc(sizeof(DocInfo) + revMetaSize + k->size); if (!docInfo) { return COUCHSTORE_ERROR_ALLOC_FAIL; } char *rbuf = (char *) docInfo; memcpy(rbuf + sizeof(DocInfo), v->buf + sizeof(*raw), revMetaSize); *pInfo = docInfo; docInfo->db_seq = seq; docInfo->rev_seq = revnum; docInfo->deleted = deleted; docInfo->bp = bp; docInfo->size = datasize; docInfo->content_meta = content_meta; docInfo->rev_meta.buf = rbuf + sizeof(DocInfo); docInfo->rev_meta.size = revMetaSize; docInfo->id.buf = docInfo->rev_meta.buf + docInfo->rev_meta.size; docInfo->id.size = k->size; memcpy(docInfo->id.buf, k->buf, k->size); return 0; }
static int by_seq_read_docinfo(DocInfo **pInfo, sized_buf *k, sized_buf *v) { const raw_seq_index_value *raw = (const raw_seq_index_value*)v->buf; ssize_t extraSize = v->size - sizeof(*raw); if (extraSize < 0) { return COUCHSTORE_ERROR_CORRUPT; } uint32_t idsize, datasize; decode_kv_length(&raw->sizes, &idsize, &datasize); uint64_t bp = decode_raw48(raw->bp); int deleted = (bp & BP_DELETED_FLAG) != 0; bp &= ~BP_DELETED_FLAG; uint8_t content_meta = decode_raw08(raw->content_meta); uint64_t rev_seq = decode_raw48(raw->rev_seq); uint64_t db_seq = decode_sequence_key(k); DocInfo* docInfo = malloc(sizeof(DocInfo) + extraSize); if (!docInfo) { return COUCHSTORE_ERROR_ALLOC_FAIL; } char *rbuf = (char *) docInfo; memcpy(rbuf + sizeof(DocInfo), v->buf + sizeof(*raw), extraSize); *pInfo = docInfo; docInfo->db_seq = db_seq; docInfo->rev_seq = rev_seq; docInfo->deleted = deleted; docInfo->bp = bp; docInfo->size = datasize; docInfo->content_meta = content_meta; docInfo->id.buf = rbuf + sizeof(DocInfo); docInfo->id.size = idsize; docInfo->rev_meta.buf = rbuf + sizeof(DocInfo) + idsize; docInfo->rev_meta.size = extraSize - idsize; return 0; }
static void test_raw_08(uint8_t value) { raw_08 raw; raw = encode_raw08(value); assert(decode_raw08(raw) == value); }