1bc68bb02SChiyoung Seo/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
27c0433f5SJung-Sang Ahn/*
3bc68bb02SChiyoung Seo *     Copyright 2010 Couchbase, Inc
4bc68bb02SChiyoung Seo *
5bc68bb02SChiyoung Seo *   Licensed under the Apache License, Version 2.0 (the "License");
6bc68bb02SChiyoung Seo *   you may not use this file except in compliance with the License.
7bc68bb02SChiyoung Seo *   You may obtain a copy of the License at
8bc68bb02SChiyoung Seo *
9bc68bb02SChiyoung Seo *       http://www.apache.org/licenses/LICENSE-2.0
10bc68bb02SChiyoung Seo *
11bc68bb02SChiyoung Seo *   Unless required by applicable law or agreed to in writing, software
12bc68bb02SChiyoung Seo *   distributed under the License is distributed on an "AS IS" BASIS,
13bc68bb02SChiyoung Seo *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14bc68bb02SChiyoung Seo *   See the License for the specific language governing permissions and
15bc68bb02SChiyoung Seo *   limitations under the License.
167c0433f5SJung-Sang Ahn */
177c0433f5SJung-Sang Ahn
187c0433f5SJung-Sang Ahn#include <stdio.h>
197c0433f5SJung-Sang Ahn#include <stdlib.h>
207c0433f5SJung-Sang Ahn#include <string.h>
217c0433f5SJung-Sang Ahn
227c0433f5SJung-Sang Ahn#include "docio.h"
23abe1d5a9SSundar Sridharan#include "wal.h"
24f9a2bf6bSJens Alfke#include "fdb_internal.h"
256b0f6ee5SJung-Sang Ahn#ifdef _DOC_COMP
266b0f6ee5SJung-Sang Ahn#include "snappy-c.h"
276b0f6ee5SJung-Sang Ahn#endif
287c0433f5SJung-Sang Ahn
293d812dfcSJung-Sang Ahn#include "memleak.h"
303d812dfcSJung-Sang Ahn
316b0f6ee5SJung-Sang Ahnvoid docio_init(struct docio_handle *handle,
326b0f6ee5SJung-Sang Ahn                struct filemgr *file,
33f145a9b7SChiyoung Seo                bool compress_document_body)
347c0433f5SJung-Sang Ahn{
35d9045a26SChiyoung Seo    handle->file = file;
36d9045a26SChiyoung Seo    handle->curblock = BLK_NOT_FOUND;
37d9045a26SChiyoung Seo    handle->curpos = 0;
382889254eSJung-Sang Ahn    handle->lastbid = BLK_NOT_FOUND;
396b0f6ee5SJung-Sang Ahn    handle->compress_document_body = compress_document_body;
40f693a021SSundar Sridharan    malloc_align(handle->readbuffer, FDB_SECTOR_SIZE, file->blocksize);
41d5c88c55SJung-Sang Ahn}
42d5c88c55SJung-Sang Ahn
43d5c88c55SJung-Sang Ahnvoid docio_free(struct docio_handle *handle)
44d5c88c55SJung-Sang Ahn{
45f693a021SSundar Sridharan    free_align(handle->readbuffer);
467c0433f5SJung-Sang Ahn}
477c0433f5SJung-Sang Ahn
487be5b070SJung-Sang Ahn#ifdef __CRC32
4901e33605SChiyoung Seo#define _add_blk_marker(file, bid, blocksize, marker, log_callback) \
5001e33605SChiyoung Seo    filemgr_write_offset((file), (bid), (blocksize), BLK_MARKER_SIZE, (marker), (log_callback))
517be5b070SJung-Sang Ahn#else
52cb0f0747SSundar Sridharan#define _add_blk_marker(file, bid, blocksize, marker, log_callback) \
53cb0f0747SSundar Sridharan    FDB_RESULT_SUCCESS
547be5b070SJung-Sang Ahn#endif
557be5b070SJung-Sang Ahn
565aa14abcSSundar SridharanINLINE fdb_status _docio_fill_zero(struct docio_handle *handle, bid_t bid,
575aa14abcSSundar Sridharan                                   size_t pos)
586ef65b54SJung-Sang Ahn{
596ef65b54SJung-Sang Ahn    // Fill next few bytes (sizeof(struct docio_length)) with zero
606ef65b54SJung-Sang Ahn    // to avoid false positive docio_length checksum during file scanning.
616ef65b54SJung-Sang Ahn    // (Note that the checksum value of zero-filled docio_length is 0x6F.)
626ef65b54SJung-Sang Ahn
636ef65b54SJung-Sang Ahn    size_t blocksize = handle->file->blocksize;
646ef65b54SJung-Sang Ahn    size_t len_size = sizeof(struct docio_length);
656ef65b54SJung-Sang Ahn    uint8_t *zerobuf = alca(uint8_t, len_size);
666ef65b54SJung-Sang Ahn
676ef65b54SJung-Sang Ahn#ifdef __CRC32
686ef65b54SJung-Sang Ahn    blocksize -= BLK_MARKER_SIZE;
696ef65b54SJung-Sang Ahn#endif
706ef65b54SJung-Sang Ahn
716ef65b54SJung-Sang Ahn    if (pos + len_size <= blocksize) {
726ef65b54SJung-Sang Ahn        // enough space in the block
736ef65b54SJung-Sang Ahn        memset(zerobuf, 0x0, len_size);
746ef65b54SJung-Sang Ahn        return filemgr_write_offset(handle->file, bid, pos, len_size,
756ef65b54SJung-Sang Ahn                                    zerobuf, handle->log_callback);
766ef65b54SJung-Sang Ahn    } else {
776ef65b54SJung-Sang Ahn        // lack of space .. we don't need to fill zero bytes.
786ef65b54SJung-Sang Ahn        return FDB_RESULT_SUCCESS;
796ef65b54SJung-Sang Ahn    }
806ef65b54SJung-Sang Ahn}
816ef65b54SJung-Sang Ahn
8201e33605SChiyoung Seobid_t docio_append_doc_raw(struct docio_handle *handle, uint64_t size, void *buf)
837c0433f5SJung-Sang Ahn{
842889254eSJung-Sang Ahn    uint32_t offset;
85818cce61SJung-Sang Ahn    uint8_t marker[BLK_MARKER_SIZE];
86fa5a43c0SJung-Sang Ahn    size_t blocksize = handle->file->blocksize;
87fa5a43c0SJung-Sang Ahn    size_t real_blocksize = blocksize;
8801e33605SChiyoung Seo    err_log_callback *log_callback = handle->log_callback;
89fa5a43c0SJung-Sang Ahn#ifdef __CRC32
90818cce61SJung-Sang Ahn    blocksize -= BLK_MARKER_SIZE;
91818cce61SJung-Sang Ahn    memset(marker, BLK_MARKER_DOC, BLK_MARKER_SIZE);
92fa5a43c0SJung-Sang Ahn#endif
939ceccb2cSJung-Sang Ahn
942889254eSJung-Sang Ahn    if (handle->curblock == BLK_NOT_FOUND) {
952889254eSJung-Sang Ahn        // allocate new block
9601e33605SChiyoung Seo        handle->curblock = filemgr_alloc(handle->file, log_callback);
972889254eSJung-Sang Ahn        handle->curpos = 0;
982889254eSJung-Sang Ahn    }
992889254eSJung-Sang Ahn    if (!filemgr_is_writable(handle->file, handle->curblock)) {
1002889254eSJung-Sang Ahn        // allocate new block
10101e33605SChiyoung Seo        handle->curblock = filemgr_alloc(handle->file, log_callback);
1022889254eSJung-Sang Ahn        handle->curpos = 0;
1032889254eSJung-Sang Ahn    }
1042889254eSJung-Sang Ahn
105fa5a43c0SJung-Sang Ahn    if (size <= blocksize - handle->curpos) {
106704daaa2SChiyoung Seo        fdb_status fs = FDB_RESULT_SUCCESS;
1072889254eSJung-Sang Ahn        // simply append to current block
1082889254eSJung-Sang Ahn        offset = handle->curpos;
109704daaa2SChiyoung Seo        fs = _add_blk_marker(handle->file, handle->curblock, blocksize, marker,
110704daaa2SChiyoung Seo                             log_callback);
111704daaa2SChiyoung Seo        if (fs != FDB_RESULT_SUCCESS) {
112704daaa2SChiyoung Seo            fdb_log(log_callback, fs,
113c279f70eSChiyoung Seo                    "Error in appending a doc block marker for a block id %" _F64
114c279f70eSChiyoung Seo                    " into a database file '%s'", handle->curblock,
115704daaa2SChiyoung Seo                    handle->file->filename);
116cb0f0747SSundar Sridharan            return BLK_NOT_FOUND;
117cb0f0747SSundar Sridharan        }
118704daaa2SChiyoung Seo        fs = filemgr_write_offset(handle->file, handle->curblock, offset, size,
119704daaa2SChiyoung Seo                                  buf, log_callback);
120704daaa2SChiyoung Seo        if (fs != FDB_RESULT_SUCCESS) {
121704daaa2SChiyoung Seo            fdb_log(log_callback, fs,
122c279f70eSChiyoung Seo                    "Error in writing a doc block with id %" _F64 ", offset %d, size %"
123c279f70eSChiyoung Seo                    _F64 " to a database file '%s'", handle->curblock, offset, size,
124704daaa2SChiyoung Seo                    handle->file->filename);
125cb0f0747SSundar Sridharan            return BLK_NOT_FOUND;
126cb0f0747SSundar Sridharan        }
1272889254eSJung-Sang Ahn        handle->curpos += size;
1282889254eSJung-Sang Ahn
1296ef65b54SJung-Sang Ahn        if (_docio_fill_zero(handle, handle->curblock, handle->curpos) !=
1306ef65b54SJung-Sang Ahn            FDB_RESULT_SUCCESS) {
1316ef65b54SJung-Sang Ahn            return BLK_NOT_FOUND;
1326ef65b54SJung-Sang Ahn        }
1336ef65b54SJung-Sang Ahn
134fa5a43c0SJung-Sang Ahn        return handle->curblock * real_blocksize + offset;
1359ceccb2cSJung-Sang Ahn
136704daaa2SChiyoung Seo    } else {
1372889254eSJung-Sang Ahn        // not simply fitted into current block
1382889254eSJung-Sang Ahn        bid_t begin, end, i, startpos;
139fa5a43c0SJung-Sang Ahn        uint32_t nblock = size / blocksize;
140fa5a43c0SJung-Sang Ahn        uint32_t remain = size % blocksize;
1412889254eSJung-Sang Ahn        uint64_t remainsize = size;
142704daaa2SChiyoung Seo        fdb_status fs = FDB_RESULT_SUCCESS;
1432889254eSJung-Sang Ahn
144704daaa2SChiyoung Seo#ifdef DOCIO_BLOCK_ALIGN
1453d812dfcSJung-Sang Ahn        offset = blocksize - handle->curpos;
1469ceccb2cSJung-Sang Ahn        if (remain <= blocksize - handle->curpos &&
1479ceccb2cSJung-Sang Ahn            filemgr_alloc_multiple_cond(handle->file, handle->curblock+1,
14801e33605SChiyoung Seo                                        nblock + ((remain>offset)?1:0), &begin, &end,
14901e33605SChiyoung Seo                                        log_callback) == handle->curblock+1) {
1502889254eSJung-Sang Ahn
1512889254eSJung-Sang Ahn            // start from current block
152b6be7a1dSSundar Sridharan            fdb_assert(begin == handle->curblock + 1, begin, handle->curblock+1);
1539ceccb2cSJung-Sang Ahn
154704daaa2SChiyoung Seo            fs = _add_blk_marker(handle->file, handle->curblock, blocksize,
1550ad09ae7STommie McAfee                                 marker, log_callback);
156704daaa2SChiyoung Seo            if (fs != FDB_RESULT_SUCCESS) {
157704daaa2SChiyoung Seo                fdb_log(log_callback, fs,
158c279f70eSChiyoung Seo                        "Error in appending a doc block marker for a block id %" _F64
159c279f70eSChiyoung Seo                        " into a database file '%s'", handle->curblock,
160704daaa2SChiyoung Seo                        handle->file->filename);
161cb0f0747SSundar Sridharan                return BLK_NOT_FOUND;
162cb0f0747SSundar Sridharan            }
163fa5a43c0SJung-Sang Ahn            if (offset > 0) {
164704daaa2SChiyoung Seo                fs = filemgr_write_offset(handle->file, handle->curblock,
165704daaa2SChiyoung Seo                                          handle->curpos, offset, buf, log_callback);
166704daaa2SChiyoung Seo                if (fs != FDB_RESULT_SUCCESS) {
167704daaa2SChiyoung Seo                    fdb_log(log_callback, fs,
168c279f70eSChiyoung Seo                            "Error in writing a doc block with id %" _F64 ", offset %d, "
169c279f70eSChiyoung Seo                            "size %" _F64 " to a database file '%s'", handle->curblock,
170704daaa2SChiyoung Seo                            offset, size, handle->file->filename);
171cb0f0747SSundar Sridharan                    return BLK_NOT_FOUND;
172cb0f0747SSundar Sridharan                }
173fa5a43c0SJung-Sang Ahn            }
1742889254eSJung-Sang Ahn            remainsize -= offset;
1752889254eSJung-Sang Ahn
1769ceccb2cSJung-Sang Ahn            startpos = handle->curblock * real_blocksize + handle->curpos;
17701e33605SChiyoung Seo        } else {
178e6449f52SJung-Sang Ahn            // next block to be allocated is not continuous .. allocate new multiple blocks
17901e33605SChiyoung Seo            filemgr_alloc_multiple(handle->file, nblock+((remain>0)?1:0),
18001e33605SChiyoung Seo                                   &begin, &end, log_callback);
1812889254eSJung-Sang Ahn            offset = 0;
1822889254eSJung-Sang Ahn
183fa5a43c0SJung-Sang Ahn            startpos = begin * real_blocksize;
1842889254eSJung-Sang Ahn        }
1852889254eSJung-Sang Ahn
186704daaa2SChiyoung Seo#else
1872889254eSJung-Sang Ahn        // simple append mode .. always append at the end of file
1883d812dfcSJung-Sang Ahn        offset = blocksize - handle->curpos;
189e6449f52SJung-Sang Ahn        if (filemgr_alloc_multiple_cond(handle->file, handle->curblock+1,
19001e33605SChiyoung Seo                                        nblock + ((remain>offset)?1:0), &begin, &end,
19101e33605SChiyoung Seo                                        log_callback) == handle->curblock+1) {
1922889254eSJung-Sang Ahn            // start from current block
193b6be7a1dSSundar Sridharan            fdb_assert(begin == handle->curblock + 1, begin, handle->curblock+1);
1949ceccb2cSJung-Sang Ahn
195704daaa2SChiyoung Seo            fs = _add_blk_marker(handle->file, handle->curblock, blocksize,
196704daaa2SChiyoung Seo                                 marker, log_callback);
197704daaa2SChiyoung Seo            if (fs != FDB_RESULT_SUCCESS) {
198704daaa2SChiyoung Seo                fdb_log(log_callback, fs,
199c279f70eSChiyoung Seo                        "Error in appending a doc block marker for a block id %" _F64
200c279f70eSChiyoung Seo                        " into a database file '%s'", handle->curblock,
201704daaa2SChiyoung Seo                        handle->file->filename);
202cb0f0747SSundar Sridharan                return BLK_NOT_FOUND;
203cb0f0747SSundar Sridharan            }
204fa5a43c0SJung-Sang Ahn            if (offset > 0) {
205704daaa2SChiyoung Seo                fs = filemgr_write_offset(handle->file, handle->curblock,
206704daaa2SChiyoung Seo                                          handle->curpos, offset, buf, log_callback);
207704daaa2SChiyoung Seo                if (fs != FDB_RESULT_SUCCESS) {
208704daaa2SChiyoung Seo                    fdb_log(log_callback, fs,
209c279f70eSChiyoung Seo                            "Error in writing a doc block with id %" _F64 ", offset %d, "
210c279f70eSChiyoung Seo                            "size %" _F64 " to a database file '%s'", handle->curblock,
211704daaa2SChiyoung Seo                            offset, size, handle->file->filename);
212cb0f0747SSundar Sridharan                    return BLK_NOT_FOUND;
213cb0f0747SSundar Sridharan                }
214fa5a43c0SJung-Sang Ahn            }
2152889254eSJung-Sang Ahn            remainsize -= offset;
2162889254eSJung-Sang Ahn
2179ceccb2cSJung-Sang Ahn            startpos = handle->curblock * real_blocksize + handle->curpos;
21801e33605SChiyoung Seo        } else {
219e6449f52SJung-Sang Ahn            // next block to be allocated is not continuous .. allocate new multiple blocks
22001e33605SChiyoung Seo            filemgr_alloc_multiple(handle->file, nblock+((remain>0)?1:0),
22101e33605SChiyoung Seo                                   &begin, &end, log_callback);
2222889254eSJung-Sang Ahn            offset = 0;
2232889254eSJung-Sang Ahn
224fa5a43c0SJung-Sang Ahn            startpos = begin * real_blocksize;
2252889254eSJung-Sang Ahn        }
2262889254eSJung-Sang Ahn
227704daaa2SChiyoung Seo#endif
2282889254eSJung-Sang Ahn
2292889254eSJung-Sang Ahn        for (i=begin; i<=end; ++i) {
2302889254eSJung-Sang Ahn            handle->curblock = i;
231fa5a43c0SJung-Sang Ahn            if (remainsize >= blocksize) {
2322889254eSJung-Sang Ahn                // write entire block
233704daaa2SChiyoung Seo                fs = _add_blk_marker(handle->file, i, blocksize, marker,
234704daaa2SChiyoung Seo                                     log_callback);
235704daaa2SChiyoung Seo                if (fs != FDB_RESULT_SUCCESS) {
236704daaa2SChiyoung Seo                    fdb_log(log_callback, fs,
237704daaa2SChiyoung Seo                            "Error in appending a doc block marker for a block "
238c279f70eSChiyoung Seo                            "id %" _F64 " into a database file '%s'", i,
239704daaa2SChiyoung Seo                            handle->file->filename);
240cb0f0747SSundar Sridharan                    return BLK_NOT_FOUND;
241cb0f0747SSundar Sridharan                }
242704daaa2SChiyoung Seo                fs = filemgr_write_offset(handle->file, i, 0, blocksize,
243704daaa2SChiyoung Seo                                          (uint8_t *)buf + offset, log_callback);
244704daaa2SChiyoung Seo                if (fs != FDB_RESULT_SUCCESS) {
245704daaa2SChiyoung Seo                    fdb_log(log_callback, fs,
246c279f70eSChiyoung Seo                            "Error in writing an entire doc block with id %" _F64
247c279f70eSChiyoung Seo                            ", size %" _F64 " to a database file '%s'", i, blocksize,
248704daaa2SChiyoung Seo                            handle->file->filename);
249cb0f0747SSundar Sridharan                    return BLK_NOT_FOUND;
250cb0f0747SSundar Sridharan                }
251fa5a43c0SJung-Sang Ahn                offset += blocksize;
252fa5a43c0SJung-Sang Ahn                remainsize -= blocksize;
253fa5a43c0SJung-Sang Ahn                handle->curpos = blocksize;
2549ceccb2cSJung-Sang Ahn
25501e33605SChiyoung Seo            } else {
2562889254eSJung-Sang Ahn                // write rest of document
257b6be7a1dSSundar Sridharan                fdb_assert(i==end, i, end);
258704daaa2SChiyoung Seo                fs = _add_blk_marker(handle->file, i, blocksize, marker,
259704daaa2SChiyoung Seo                                     log_callback);
260704daaa2SChiyoung Seo                if (fs != FDB_RESULT_SUCCESS) {
261704daaa2SChiyoung Seo                    fdb_log(log_callback, fs,
262704daaa2SChiyoung Seo                            "Error in appending a doc block marker for a block "
263c279f70eSChiyoung Seo                            "id %" _F64 " into a database file '%s'", i,
264704daaa2SChiyoung Seo                            handle->file->filename);
265cb0f0747SSundar Sridharan                    return BLK_NOT_FOUND;
266cb0f0747SSundar Sridharan                }
267704daaa2SChiyoung Seo                fs = filemgr_write_offset(handle->file, i, 0, remainsize,
268704daaa2SChiyoung Seo                                          (uint8_t *)buf + offset, log_callback);
269704daaa2SChiyoung Seo                if (fs != FDB_RESULT_SUCCESS) {
270704daaa2SChiyoung Seo                    fdb_log(log_callback, fs,
271c279f70eSChiyoung Seo                            "Error in writing a doc block with id %" _F64 ", "
272c279f70eSChiyoung Seo                            "size %" _F64 " to a database file '%s'", i, remainsize,
273704daaa2SChiyoung Seo                            handle->file->filename);
274cb0f0747SSundar Sridharan                    return BLK_NOT_FOUND;
275cb0f0747SSundar Sridharan                }
2762889254eSJung-Sang Ahn                offset += remainsize;
2772889254eSJung-Sang Ahn                handle->curpos = remainsize;
2786ef65b54SJung-Sang Ahn
2796ef65b54SJung-Sang Ahn                if (_docio_fill_zero(handle, i, handle->curpos) !=
2806ef65b54SJung-Sang Ahn                    FDB_RESULT_SUCCESS) {
2816ef65b54SJung-Sang Ahn                    return BLK_NOT_FOUND;
2826ef65b54SJung-Sang Ahn                }
2832889254eSJung-Sang Ahn            }
2842889254eSJung-Sang Ahn        }
2852889254eSJung-Sang Ahn
2862889254eSJung-Sang Ahn        return startpos;
2872889254eSJung-Sang Ahn    }
2882889254eSJung-Sang Ahn
2892889254eSJung-Sang Ahn    return 0;
290d5c88c55SJung-Sang Ahn}
291d5c88c55SJung-Sang Ahn
2926d79432aSJung-Sang Ahn#ifdef __ENDIAN_SAFE
2936b0f6ee5SJung-Sang AhnINLINE struct docio_length _docio_length_encode(struct docio_length length)
2946d79432aSJung-Sang Ahn{
2956d79432aSJung-Sang Ahn    struct docio_length ret;
2966d79432aSJung-Sang Ahn    ret = length;
2976d79432aSJung-Sang Ahn    ret.keylen = _endian_encode(length.keylen);
2986d79432aSJung-Sang Ahn    ret.metalen = _endian_encode(length.metalen);
2996d79432aSJung-Sang Ahn    ret.bodylen = _endian_encode(length.bodylen);
3006b0f6ee5SJung-Sang Ahn    ret.bodylen_ondisk = _endian_encode(length.bodylen_ondisk);
3016d79432aSJung-Sang Ahn    return ret;
3026d79432aSJung-Sang Ahn}
3036b0f6ee5SJung-Sang AhnINLINE struct docio_length _docio_length_decode(struct docio_length length)
3046d79432aSJung-Sang Ahn{
3056d79432aSJung-Sang Ahn    struct docio_length ret;
3066d79432aSJung-Sang Ahn    ret = length;
3076d79432aSJung-Sang Ahn    ret.keylen = _endian_decode(length.keylen);
3086d79432aSJung-Sang Ahn    ret.metalen = _endian_decode(length.metalen);
3096d79432aSJung-Sang Ahn    ret.bodylen = _endian_decode(length.bodylen);
3106b0f6ee5SJung-Sang Ahn    ret.bodylen_ondisk = _endian_decode(length.bodylen_ondisk);
3116d79432aSJung-Sang Ahn    return ret;
3126d79432aSJung-Sang Ahn}
3136d79432aSJung-Sang Ahn#else
3146b0f6ee5SJung-Sang Ahn#define _docio_length_encode(a)
3156b0f6ee5SJung-Sang Ahn#define _docio_length_decode(a)
3166d79432aSJung-Sang Ahn#endif
3176d79432aSJung-Sang Ahn
31835fc43f6SJung-Sang AhnINLINE uint8_t _docio_length_checksum(struct docio_length length)
31935fc43f6SJung-Sang Ahn{
32035fc43f6SJung-Sang Ahn    return (uint8_t)(
3214f2ebc0aSJung-Sang Ahn        chksum(&length,
3224f2ebc0aSJung-Sang Ahn               sizeof(keylen_t) + sizeof(uint16_t) + sizeof(uint32_t)*2)
32335fc43f6SJung-Sang Ahn        & 0xff);
32435fc43f6SJung-Sang Ahn}
32535fc43f6SJung-Sang Ahn
326505f35b8SJung-Sang AhnINLINE bid_t _docio_append_doc(struct docio_handle *handle, struct docio_object *doc)
3277c0433f5SJung-Sang Ahn{
3286b0f6ee5SJung-Sang Ahn    size_t _len;
3292889254eSJung-Sang Ahn    uint32_t offset = 0;
33002b71b99SJung-Sang Ahn    uint32_t crc;
3316d79432aSJung-Sang Ahn    uint64_t docsize;
3326d79432aSJung-Sang Ahn    void *buf;
3336d79432aSJung-Sang Ahn    bid_t ret_offset;
3346d79432aSJung-Sang Ahn    fdb_seqnum_t _seqnum;
3351907e9beSJung-Sang Ahn    timestamp_t _timestamp;
3366d79432aSJung-Sang Ahn    struct docio_length length, _length;
33701e33605SChiyoung Seo    err_log_callback *log_callback = handle->log_callback;
3382889254eSJung-Sang Ahn
3392889254eSJung-Sang Ahn    length = doc->length;
3406b0f6ee5SJung-Sang Ahn    length.bodylen_ondisk = length.bodylen;
3412889254eSJung-Sang Ahn
34235fc43f6SJung-Sang Ahn#ifdef _DOC_COMP
34343f70b82SJens Alfke    int ret;
3445aa14abcSSundar Sridharan    void *compbuf = NULL;
34543f70b82SJens Alfke    uint32_t compbuf_len;
3466b0f6ee5SJung-Sang Ahn    if (doc->length.bodylen > 0 && handle->compress_document_body) {
34735fc43f6SJung-Sang Ahn        compbuf_len = snappy_max_compressed_length(length.bodylen);
34835fc43f6SJung-Sang Ahn        compbuf = (void *)malloc(compbuf_len);
3492889254eSJung-Sang Ahn
3506b0f6ee5SJung-Sang Ahn        _len = compbuf_len;
3516b58e35eSJung-Sang Ahn        ret = snappy_compress((char*)doc->body, length.bodylen, (char*)compbuf, &_len);
352e4da0646SChiyoung Seo        if (ret < 0) { // LCOV_EXCL_START
353f9a2bf6bSJens Alfke            fdb_log(log_callback, FDB_RESULT_COMPRESSION_FAIL,
354704daaa2SChiyoung Seo                    "Error in compressing the doc body of key '%s' from "
355704daaa2SChiyoung Seo                    "a database file '%s'",
356704daaa2SChiyoung Seo                    (char *) doc->key, handle->file->filename);
357953ee6bdSChiyoung Seo            free(compbuf);
3586b58e35eSJung-Sang Ahn            // we use BLK_NOT_FOUND for error code of appending instead of 0
3596b58e35eSJung-Sang Ahn            // because document can be written at the byte offset 0
3606b58e35eSJung-Sang Ahn            return BLK_NOT_FOUND;
361e4da0646SChiyoung Seo        } // LCOV_EXCL_STOP
3626b58e35eSJung-Sang Ahn
3636b0f6ee5SJung-Sang Ahn        length.bodylen_ondisk = compbuf_len = _len;
3646b0f6ee5SJung-Sang Ahn        length.flag |= DOCIO_COMPRESSED;
3656b0f6ee5SJung-Sang Ahn
3666b0f6ee5SJung-Sang Ahn        docsize = sizeof(struct docio_length) + length.keylen + length.metalen;
3676b0f6ee5SJung-Sang Ahn        docsize += compbuf_len;
3686b0f6ee5SJung-Sang Ahn    } else {
3696b0f6ee5SJung-Sang Ahn        docsize = sizeof(struct docio_length) + length.keylen + length.metalen + length.bodylen;
3705aa14abcSSundar Sridharan        compbuf_len = length.bodylen;
37135fc43f6SJung-Sang Ahn    }
3726b0f6ee5SJung-Sang Ahn#else
3736b0f6ee5SJung-Sang Ahn    docsize = sizeof(struct docio_length) + length.keylen + length.metalen + length.bodylen;
37435fc43f6SJung-Sang Ahn#endif
3751907e9beSJung-Sang Ahn    docsize += sizeof(timestamp_t);
3762889254eSJung-Sang Ahn
37735fc43f6SJung-Sang Ahn    docsize += sizeof(fdb_seqnum_t);
3785379abc9SJung-Sang Ahn
37935fc43f6SJung-Sang Ahn#ifdef __CRC32
38035fc43f6SJung-Sang Ahn    docsize += sizeof(crc);
38135fc43f6SJung-Sang Ahn#endif
3826b0f6ee5SJung-Sang Ahn
3836b0f6ee5SJung-Sang Ahn    doc->length = length;
3842889254eSJung-Sang Ahn    buf = (void *)malloc(docsize);
3852889254eSJung-Sang Ahn
3866b0f6ee5SJung-Sang Ahn    _length = _docio_length_encode(length);
3876d79432aSJung-Sang Ahn
38835fc43f6SJung-Sang Ahn    // calculate checksum of LENGTH using crc
3896d79432aSJung-Sang Ahn    _length.checksum = _docio_length_checksum(_length);
39035fc43f6SJung-Sang Ahn
3916d79432aSJung-Sang Ahn    memcpy((uint8_t *)buf + offset, &_length, sizeof(struct docio_length));
3922889254eSJung-Sang Ahn    offset += sizeof(struct docio_length);
3932889254eSJung-Sang Ahn
3942889254eSJung-Sang Ahn    // copy key
3958e1b9ec2SJung-Sang Ahn    memcpy((uint8_t *)buf + offset, doc->key, length.keylen);
3962889254eSJung-Sang Ahn    offset += length.keylen;
3972889254eSJung-Sang Ahn
3981907e9beSJung-Sang Ahn    // copy timestamp
3991907e9beSJung-Sang Ahn    _timestamp = _endian_encode(doc->timestamp);
4001907e9beSJung-Sang Ahn    memcpy((uint8_t*)buf + offset, &_timestamp, sizeof(_timestamp));
4011907e9beSJung-Sang Ahn    offset += sizeof(_timestamp);
4021907e9beSJung-Sang Ahn
40335fc43f6SJung-Sang Ahn    // copy seqeunce number (optional)
4046d79432aSJung-Sang Ahn    _seqnum = _endian_encode(doc->seqnum);
4056d79432aSJung-Sang Ahn    memcpy((uint8_t *)buf + offset, &_seqnum, sizeof(fdb_seqnum_t));
40635fc43f6SJung-Sang Ahn    offset += sizeof(fdb_seqnum_t);
40702cf2f57SJung-Sang Ahn
4082889254eSJung-Sang Ahn    // copy metadata (optional)
4092889254eSJung-Sang Ahn    if (length.metalen > 0) {
4108e1b9ec2SJung-Sang Ahn        memcpy((uint8_t *)buf + offset, doc->meta, length.metalen);
4112889254eSJung-Sang Ahn        offset += length.metalen;
4122889254eSJung-Sang Ahn    }
4132889254eSJung-Sang Ahn
4142889254eSJung-Sang Ahn    // copy body (optional)
4152889254eSJung-Sang Ahn    if (length.bodylen > 0) {
41643f70b82SJens Alfke#ifdef _DOC_COMP
4176b0f6ee5SJung-Sang Ahn        if (length.flag & DOCIO_COMPRESSED) {
4186b0f6ee5SJung-Sang Ahn            // compressed body
4196b0f6ee5SJung-Sang Ahn            memcpy((uint8_t*)buf + offset, compbuf, compbuf_len);
4206b0f6ee5SJung-Sang Ahn            offset += compbuf_len;
4216b0f6ee5SJung-Sang Ahn            free(compbuf);
4226b0f6ee5SJung-Sang Ahn        } else {
4236b0f6ee5SJung-Sang Ahn            memcpy((uint8_t *)buf + offset, doc->body, length.bodylen);
4246b0f6ee5SJung-Sang Ahn            offset += length.bodylen;
4256b0f6ee5SJung-Sang Ahn        }
42643f70b82SJens Alfke#else
42743f70b82SJens Alfke        memcpy((uint8_t *)buf + offset, doc->body, length.bodylen);
42843f70b82SJens Alfke        offset += length.bodylen;
42943f70b82SJens Alfke#endif
4302889254eSJung-Sang Ahn    }
4312889254eSJung-Sang Ahn
43235fc43f6SJung-Sang Ahn#ifdef __CRC32
4334f2ebc0aSJung-Sang Ahn    crc = chksum(buf, docsize - sizeof(crc));
43435fc43f6SJung-Sang Ahn    memcpy((uint8_t *)buf + offset, &crc, sizeof(crc));
43535fc43f6SJung-Sang Ahn#endif
43602b71b99SJung-Sang Ahn
437fa5a43c0SJung-Sang Ahn    ret_offset = docio_append_doc_raw(handle, docsize, buf);
4382889254eSJung-Sang Ahn    free(buf);
4399ceccb2cSJung-Sang Ahn
440fa5a43c0SJung-Sang Ahn    return ret_offset;
4417c0433f5SJung-Sang Ahn}
4427c0433f5SJung-Sang Ahn
44359c1c4f5SJung-Sang Ahnbid_t docio_append_commit_mark(struct docio_handle *handle, uint64_t doc_offset)
44459c1c4f5SJung-Sang Ahn{
44559c1c4f5SJung-Sang Ahn    uint32_t offset = 0;
44659c1c4f5SJung-Sang Ahn    uint64_t docsize;
44759c1c4f5SJung-Sang Ahn    uint64_t _doc_offset;
44859c1c4f5SJung-Sang Ahn    void *buf;
44959c1c4f5SJung-Sang Ahn    bid_t ret_offset;
45059c1c4f5SJung-Sang Ahn    struct docio_length length, _length;
45159c1c4f5SJung-Sang Ahn
45259c1c4f5SJung-Sang Ahn    memset(&length, 0, sizeof(struct docio_length));
45359c1c4f5SJung-Sang Ahn    length.flag = DOCIO_TXN_COMMITTED;
45459c1c4f5SJung-Sang Ahn
45559c1c4f5SJung-Sang Ahn    docsize = sizeof(struct docio_length) + sizeof(doc_offset);
45659c1c4f5SJung-Sang Ahn    buf = (void *)malloc(docsize);
45759c1c4f5SJung-Sang Ahn
45859c1c4f5SJung-Sang Ahn    _length = _docio_length_encode(length);
45959c1c4f5SJung-Sang Ahn
46059c1c4f5SJung-Sang Ahn    // calculate checksum of LENGTH using crc
46159c1c4f5SJung-Sang Ahn    _length.checksum = _docio_length_checksum(_length);
46259c1c4f5SJung-Sang Ahn
46359c1c4f5SJung-Sang Ahn    memcpy((uint8_t *)buf + offset, &_length, sizeof(struct docio_length));
46459c1c4f5SJung-Sang Ahn    offset += sizeof(struct docio_length);
46559c1c4f5SJung-Sang Ahn
46659c1c4f5SJung-Sang Ahn    // copy doc_offset
46759c1c4f5SJung-Sang Ahn    _doc_offset = _endian_encode(doc_offset);
46859c1c4f5SJung-Sang Ahn    memcpy((uint8_t *)buf + offset, &_doc_offset, sizeof(_doc_offset));
46959c1c4f5SJung-Sang Ahn
47059c1c4f5SJung-Sang Ahn    ret_offset = docio_append_doc_raw(handle, docsize, buf);
47159c1c4f5SJung-Sang Ahn    free(buf);
47259c1c4f5SJung-Sang Ahn
47359c1c4f5SJung-Sang Ahn    return ret_offset;
47459c1c4f5SJung-Sang Ahn}
47559c1c4f5SJung-Sang Ahn
476f64e6bb5SChiyoung Seobid_t docio_append_doc(struct docio_handle *handle, struct docio_object *doc,
47759c1c4f5SJung-Sang Ahn                       uint8_t deleted, uint8_t txn_enabled)
478505f35b8SJung-Sang Ahn{
479505f35b8SJung-Sang Ahn    doc->length.flag = DOCIO_NORMAL;
480f64e6bb5SChiyoung Seo    if (deleted) {
481f64e6bb5SChiyoung Seo        doc->length.flag |= DOCIO_DELETED;
482f64e6bb5SChiyoung Seo    }
48359c1c4f5SJung-Sang Ahn    if (txn_enabled) {
48459c1c4f5SJung-Sang Ahn        doc->length.flag |= DOCIO_TXN_DIRTY;
48559c1c4f5SJung-Sang Ahn    }
486505f35b8SJung-Sang Ahn    return _docio_append_doc(handle, doc);
487505f35b8SJung-Sang Ahn}
488d5c88c55SJung-Sang Ahn
489d32401daSJung-Sang Ahnbid_t docio_append_doc_system(struct docio_handle *handle, struct docio_object *doc)
490d32401daSJung-Sang Ahn{
491d32401daSJung-Sang Ahn    doc->length.flag = DOCIO_NORMAL | DOCIO_SYSTEM;
492d32401daSJung-Sang Ahn    return _docio_append_doc(handle, doc);
493d32401daSJung-Sang Ahn}
494d32401daSJung-Sang Ahn
4953c6d74b4SSundar SridharanINLINE fdb_status _docio_read_through_buffer(struct docio_handle *handle,
4963c6d74b4SSundar Sridharan                                             bid_t bid,
497c6c3d274SChiyoung Seo                                             err_log_callback *log_callback,
498c6c3d274SChiyoung Seo                                             bool read_on_cache_miss)
499d5c88c55SJung-Sang Ahn{
5003c6d74b4SSundar Sridharan    fdb_status status = FDB_RESULT_SUCCESS;
5012889254eSJung-Sang Ahn    // to reduce the overhead from memcpy the same block
5022889254eSJung-Sang Ahn    if (handle->lastbid != bid) {
5033c6d74b4SSundar Sridharan        status = filemgr_read(handle->file, bid, handle->readbuffer,
504c6c3d274SChiyoung Seo                              log_callback, read_on_cache_miss);
5053c6d74b4SSundar Sridharan        if (status != FDB_RESULT_SUCCESS) {
506c6c3d274SChiyoung Seo            if (read_on_cache_miss) {
507c6c3d274SChiyoung Seo                fdb_log(log_callback, status,
508c6c3d274SChiyoung Seo                        "Error in reading a doc block with id %" _F64 " from "
509c6c3d274SChiyoung Seo                        "a database file '%s'", bid, handle->file->filename);
510c6c3d274SChiyoung Seo            }
5113c6d74b4SSundar Sridharan            return status;
5123c6d74b4SSundar Sridharan        }
513505f35b8SJung-Sang Ahn
514a09d7ea4SJung-Sang Ahn        if (filemgr_is_writable(handle->file, bid)) {
515a09d7ea4SJung-Sang Ahn            // this block can be modified later .. must be re-read
516a09d7ea4SJung-Sang Ahn            handle->lastbid = BLK_NOT_FOUND;
517a09d7ea4SJung-Sang Ahn        }else{
518a09d7ea4SJung-Sang Ahn            handle->lastbid = bid;
519a09d7ea4SJung-Sang Ahn        }
5202889254eSJung-Sang Ahn    }
5213c6d74b4SSundar Sridharan
5223c6d74b4SSundar Sridharan    return status;
523d5c88c55SJung-Sang Ahn}
524d5c88c55SJung-Sang Ahn
5256ef65b54SJung-Sang AhnINLINE int _docio_check_buffer(struct docio_handle *handle)
5266ef65b54SJung-Sang Ahn{
5276ef65b54SJung-Sang Ahn    uint8_t marker[BLK_MARKER_SIZE];
5286ef65b54SJung-Sang Ahn    marker[0] = *(((uint8_t *)handle->readbuffer)
5296ef65b54SJung-Sang Ahn                 + handle->file->blocksize - BLK_MARKER_SIZE);
5306ef65b54SJung-Sang Ahn    return (marker[0] == BLK_MARKER_DOC);
5316ef65b54SJung-Sang Ahn}
5326ef65b54SJung-Sang Ahn
533f80ddf4dSChiyoung Seostatic uint64_t _docio_read_length(struct docio_handle *handle,
534f80ddf4dSChiyoung Seo                                   uint64_t offset,
535f80ddf4dSChiyoung Seo                                   struct docio_length *length,
536c6c3d274SChiyoung Seo                                   err_log_callback *log_callback,
537c6c3d274SChiyoung Seo                                   bool read_on_cache_miss)
5387c0433f5SJung-Sang Ahn{
539fa5a43c0SJung-Sang Ahn    size_t blocksize = handle->file->blocksize;
540fa5a43c0SJung-Sang Ahn    size_t real_blocksize = blocksize;
541fa5a43c0SJung-Sang Ahn#ifdef __CRC32
542818cce61SJung-Sang Ahn    blocksize -= BLK_MARKER_SIZE;
543fa5a43c0SJung-Sang Ahn#endif
544fa5a43c0SJung-Sang Ahn
545704daaa2SChiyoung Seo    uint64_t file_pos = filemgr_get_pos(handle->file);
546704daaa2SChiyoung Seo    if (file_pos < (offset + sizeof(struct docio_length))) {
547704daaa2SChiyoung Seo        fdb_log(log_callback, FDB_RESULT_READ_FAIL,
548c279f70eSChiyoung Seo                "Read request with offset %" _F64 " and size %d exceeds the current "
549c279f70eSChiyoung Seo                "size %" _F64 " of a database file '%s'",
550704daaa2SChiyoung Seo                offset, sizeof(struct docio_length), file_pos,
551704daaa2SChiyoung Seo                handle->file->filename);
5525cb673f8SChiyoung Seo        return offset;
5535cb673f8SChiyoung Seo    }
5545cb673f8SChiyoung Seo
555fa5a43c0SJung-Sang Ahn    bid_t bid = offset / real_blocksize;
556fa5a43c0SJung-Sang Ahn    uint32_t pos = offset % real_blocksize;
5572889254eSJung-Sang Ahn    void *buf = handle->readbuffer;
5582889254eSJung-Sang Ahn    uint32_t restsize;
5592889254eSJung-Sang Ahn
560fa5a43c0SJung-Sang Ahn    restsize = blocksize - pos;
5612889254eSJung-Sang Ahn    // read length structure
562c6c3d274SChiyoung Seo    fdb_status fs = _docio_read_through_buffer(handle, bid, log_callback,
563c6c3d274SChiyoung Seo                                               read_on_cache_miss);
564704daaa2SChiyoung Seo    if (fs != FDB_RESULT_SUCCESS) {
565c6c3d274SChiyoung Seo        if (read_on_cache_miss) {
566c6c3d274SChiyoung Seo            fdb_log(log_callback, fs,
567c6c3d274SChiyoung Seo                    "Error in reading a doc length from a block with block id %" _F64
568c6c3d274SChiyoung Seo                    " from a database file '%s'", bid, handle->file->filename);
569c6c3d274SChiyoung Seo        }
570704daaa2SChiyoung Seo        return offset;
571704daaa2SChiyoung Seo    }
5726ef65b54SJung-Sang Ahn    if (!_docio_check_buffer(handle)) {
5736ef65b54SJung-Sang Ahn        return offset;
5746ef65b54SJung-Sang Ahn    }
5759ceccb2cSJung-Sang Ahn
5762889254eSJung-Sang Ahn    if (restsize >= sizeof(struct docio_length)) {
5778e1b9ec2SJung-Sang Ahn        memcpy(length, (uint8_t *)buf + pos, sizeof(struct docio_length));
5782889254eSJung-Sang Ahn        pos += sizeof(struct docio_length);
5799ceccb2cSJung-Sang Ahn
5806ef65b54SJung-Sang Ahn    } else {
5818e1b9ec2SJung-Sang Ahn        memcpy(length, (uint8_t *)buf + pos, restsize);
5822889254eSJung-Sang Ahn        // read additional block
5832889254eSJung-Sang Ahn        bid++;
584c6c3d274SChiyoung Seo        fs = _docio_read_through_buffer(handle, bid, log_callback, true);
585704daaa2SChiyoung Seo        if (fs != FDB_RESULT_SUCCESS) {
586704daaa2SChiyoung Seo            fdb_log(log_callback, fs,
587704daaa2SChiyoung Seo                    "Error in reading a doc length from an additional block "
588c279f70eSChiyoung Seo                    "with block id %" _F64 " from a database file '%s'",
589704daaa2SChiyoung Seo                    bid, handle->file->filename);
590704daaa2SChiyoung Seo            return offset;
591704daaa2SChiyoung Seo        }
5926ef65b54SJung-Sang Ahn        if (!_docio_check_buffer(handle)) {
5936ef65b54SJung-Sang Ahn            return offset;
5946ef65b54SJung-Sang Ahn        }
5952889254eSJung-Sang Ahn        // memcpy rest of data
5968e1b9ec2SJung-Sang Ahn        memcpy((uint8_t *)length + restsize, buf, sizeof(struct docio_length) - restsize);
5972889254eSJung-Sang Ahn        pos = sizeof(struct docio_length) - restsize;
5982889254eSJung-Sang Ahn    }
5992889254eSJung-Sang Ahn
600fa5a43c0SJung-Sang Ahn    return bid * real_blocksize + pos;
6017c0433f5SJung-Sang Ahn}
6027c0433f5SJung-Sang Ahn
603f80ddf4dSChiyoung Seostatic uint64_t _docio_read_doc_component(struct docio_handle *handle,
604f80ddf4dSChiyoung Seo                                          uint64_t offset,
605f80ddf4dSChiyoung Seo                                          uint32_t len,
606f80ddf4dSChiyoung Seo                                          void *buf_out,
607f80ddf4dSChiyoung Seo                                          err_log_callback *log_callback)
6087c0433f5SJung-Sang Ahn{
6092889254eSJung-Sang Ahn    uint32_t rest_len;
610fa5a43c0SJung-Sang Ahn    size_t blocksize = handle->file->blocksize;
611fa5a43c0SJung-Sang Ahn    size_t real_blocksize = blocksize;
612fa5a43c0SJung-Sang Ahn#ifdef __CRC32
613818cce61SJung-Sang Ahn    blocksize -= BLK_MARKER_SIZE;
614fa5a43c0SJung-Sang Ahn#endif
6159ceccb2cSJung-Sang Ahn
616fa5a43c0SJung-Sang Ahn    bid_t bid = offset / real_blocksize;
617fa5a43c0SJung-Sang Ahn    uint32_t pos = offset % real_blocksize;
6182889254eSJung-Sang Ahn    //uint8_t buf[handle->file->blocksize];
6192889254eSJung-Sang Ahn    void *buf = handle->readbuffer;
6202889254eSJung-Sang Ahn    uint32_t restsize;
621704daaa2SChiyoung Seo    fdb_status fs = FDB_RESULT_SUCCESS;
6222889254eSJung-Sang Ahn
6232889254eSJung-Sang Ahn    rest_len = len;
6242889254eSJung-Sang Ahn
6252889254eSJung-Sang Ahn    while(rest_len > 0) {
626c6c3d274SChiyoung Seo        fs = _docio_read_through_buffer(handle, bid, log_callback, true);
627704daaa2SChiyoung Seo        if (fs != FDB_RESULT_SUCCESS) {
628704daaa2SChiyoung Seo            fdb_log(log_callback, FDB_RESULT_READ_FAIL,
629c279f70eSChiyoung Seo                    "Error in reading a doc block with block id %" _F64 " from "
630704daaa2SChiyoung Seo                    "a database file '%s'", bid, handle->file->filename);
631704daaa2SChiyoung Seo            return 0;
632704daaa2SChiyoung Seo        }
633fa5a43c0SJung-Sang Ahn        restsize = blocksize - pos;
6342889254eSJung-Sang Ahn
6352889254eSJung-Sang Ahn        if (restsize >= rest_len) {
6368e1b9ec2SJung-Sang Ahn            memcpy((uint8_t *)buf_out + (len - rest_len), (uint8_t *)buf + pos, rest_len);
6372889254eSJung-Sang Ahn            pos += rest_len;
6382889254eSJung-Sang Ahn            rest_len = 0;
6392889254eSJung-Sang Ahn        }else{
6408e1b9ec2SJung-Sang Ahn            memcpy((uint8_t *)buf_out + (len - rest_len), (uint8_t *)buf + pos, restsize);
6412889254eSJung-Sang Ahn            bid++;
6422889254eSJung-Sang Ahn            pos = 0;
6432889254eSJung-Sang Ahn            rest_len -= restsize;
644505f35b8SJung-Sang Ahn
6456b0f6ee5SJung-Sang Ahn            if (rest_len > 0 &&
6466b0f6ee5SJung-Sang Ahn                bid >= filemgr_get_pos(handle->file) / handle->file->blocksize) {
647505f35b8SJung-Sang Ahn                // no more data in the file .. the file is corrupted
648f9a2bf6bSJens Alfke                fdb_log(log_callback, FDB_RESULT_FILE_CORRUPTION,
649f9a2bf6bSJens Alfke                        "Fatal error!!! Database file '%s' is corrupted.",
650f9a2bf6bSJens Alfke                        handle->file->filename);
65101e33605SChiyoung Seo                // TODO: Need to return a better error code.
652505f35b8SJung-Sang Ahn                return 0;
653505f35b8SJung-Sang Ahn            }
6542889254eSJung-Sang Ahn        }
6552889254eSJung-Sang Ahn    }
6562889254eSJung-Sang Ahn
657fa5a43c0SJung-Sang Ahn    return bid * real_blocksize + pos;
6587c0433f5SJung-Sang Ahn}
6597c0433f5SJung-Sang Ahn
6607c0433f5SJung-Sang Ahn#ifdef _DOC_COMP
6617c0433f5SJung-Sang Ahn
662f80ddf4dSChiyoung Seostatic uint64_t _docio_read_doc_component_comp(struct docio_handle *handle,
663f80ddf4dSChiyoung Seo                                               uint64_t offset,