LCOV - code coverage report
Current view: top level - src - btree.cc (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 693 780 88.8 %
Date: 2015-01-12 15:17:13 Functions: 30 31 96.8 %
Branches: 343 428 80.1 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
       2                 :            : /*
       3                 :            :  * Generic B+Tree
       4                 :            :  * (C) 2013  Jung-Sang Ahn <jungsang.ahn@gmail.com>
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <stdio.h>
       8                 :            : #include <stdlib.h>
       9                 :            : #include <string.h>
      10                 :            : #include <assert.h>
      11                 :            : 
      12                 :            : #include "btree.h"
      13                 :            : #include "common.h"
      14                 :            : 
      15                 :            : #include "list.h"
      16                 :            : 
      17                 :            : #ifdef __DEBUG
      18                 :            :     #include "memleak.h"
      19                 :            : #ifndef __DEBUG_BTREE
      20                 :            :     #undef DBG
      21                 :            :     #undef DBGCMD
      22                 :            :     #undef DBGSW
      23                 :            :     #define DBG(...)
      24                 :            :     #define DBGCMD(...)
      25                 :            :     #define DBGSW(n, ...)
      26                 :            : #endif
      27                 :            : #endif
      28                 :            : 
      29                 :            : #define METASIZE_ALIGN_UNIT (16)
      30                 :            : #ifdef METASIZE_ALIGN_UNIT
      31                 :            :     #define _metasize_align(size) \
      32                 :            :         (((( (size + sizeof(metasize_t)) + (METASIZE_ALIGN_UNIT-1)) \
      33                 :            :             / METASIZE_ALIGN_UNIT) * METASIZE_ALIGN_UNIT) - sizeof(metasize_t))
      34                 :            : #else
      35                 :            :     #define _metasize_align(size) (size)
      36                 :            : #endif
      37                 :            : 
      38                 :  124724593 : INLINE int is_subblock(bid_t subbid)
      39                 :            : {
      40                 :            :     uint8_t flag;
      41                 :  124724593 :     flag = (subbid >> (8 * (sizeof(bid_t)-2))) & 0x00ff;
      42                 :  124724593 :     return flag;
      43                 :            : }
      44                 :            : 
      45                 :  148729749 : INLINE struct bnode *_fetch_bnode(struct btree *btree, void *addr, uint16_t level)
      46                 :            : {
      47                 :  148729749 :     struct bnode *node = NULL;
      48                 :            : 
      49                 :  148729749 :     node = (struct bnode *)addr;
      50                 :            : 
      51         [ +  + ]:  148729749 :     if (!(node->flag & BNODE_MASK_METADATA)) {
      52                 :            :         // no metadata
      53                 :   63908403 :         node->data = (uint8_t *)addr + sizeof(struct bnode);
      54                 :            :     } else {
      55                 :            :         // metadata
      56                 :            :         metasize_t metasize;
      57                 :   84821346 :         memcpy(&metasize, (uint8_t *)addr + sizeof(struct bnode), sizeof(metasize_t));
      58                 :   84821346 :         metasize = _endian_decode(metasize);
      59                 :            :         node->data = (uint8_t *)addr + sizeof(struct bnode) + sizeof(metasize_t) +
      60                 :   84821346 :                      _metasize_align(metasize);
      61                 :            :     }
      62                 :  148729749 :     return node;
      63                 :            : }
      64                 :            : 
      65                 :   26370247 : struct bnode ** btree_get_bnode_array(void *addr, size_t *nnode_out)
      66                 :            : {
      67                 :            :     // original b+tree always has only a single node per block
      68                 :            :     struct bnode **ret;
      69                 :   26370247 :     *nnode_out = 1;
      70                 :   26370247 :     ret = (struct bnode **)malloc(sizeof(struct bnode*) * (*nnode_out));
      71                 :   26370247 :     ret[0] = _fetch_bnode(NULL, addr, 0);
      72                 :            : 
      73                 :   26372846 :     return ret;
      74                 :            : }
      75                 :            : 
      76                 :    8605000 : INLINE int _bnode_size(
      77                 :            :     struct btree *btree, struct bnode *node, void *new_minkey, void *key_arr, void *value_arr, size_t len)
      78                 :            : {
      79                 :    8605000 :     int nodesize = 0;
      80                 :            : 
      81         [ +  + ]:    8605000 :     if (node->flag & BNODE_MASK_METADATA) {
      82                 :            :         metasize_t size;
      83                 :      92803 :         memcpy(&size, (uint8_t *)node + sizeof(struct bnode), sizeof(metasize_t));
      84                 :      92803 :         size = _endian_decode(size);
      85                 :            :         nodesize =
      86                 :            :             sizeof(struct bnode) +
      87                 :      92803 :             btree->kv_ops->get_data_size(node, new_minkey, key_arr, value_arr, len) +
      88                 :      92803 :             _metasize_align(size) + sizeof(metasize_t);
      89                 :            :     }else{
      90                 :            :         nodesize =
      91                 :            :             sizeof(struct bnode) +
      92                 :    8512197 :             btree->kv_ops->get_data_size(node, new_minkey, key_arr, value_arr, len);
      93                 :            :     }
      94                 :            : 
      95                 :    8605009 :     return nodesize;
      96                 :            : }
      97                 :            : 
      98                 :            : struct kv_ins_item {
      99                 :            :     void *key;
     100                 :            :     void *value;
     101                 :            :     struct list_elem le;
     102                 :            : };
     103                 :            : 
     104                 :    8602510 : INLINE struct kv_ins_item * _kv_ins_item_create(
     105                 :            :     struct btree *btree, void *key, void *value)
     106                 :            : {
     107                 :            :     struct kv_ins_item *item;
     108                 :    8602510 :     item = (struct kv_ins_item*)malloc(sizeof(struct kv_ins_item));
     109                 :    8602510 :     item->key = (void *)malloc(btree->ksize);
     110                 :    8602510 :     item->value = (void *)malloc(btree->vsize);
     111                 :            : 
     112         [ +  - ]:    8602510 :     if (btree->kv_ops->init_kv_var) {
     113                 :    8602519 :         btree->kv_ops->init_kv_var(btree, item->key, item->value);
     114                 :            :     }
     115         [ +  + ]:    8602516 :     if (key) {
     116                 :    8548577 :         btree->kv_ops->set_key(btree, item->key, key);
     117                 :            :     }
     118         [ +  - ]:    8602516 :     if (value) {
     119                 :    8602516 :         btree->kv_ops->set_value(btree, item->value, value);
     120                 :            :     }
     121                 :    8602514 :     return item;
     122                 :            : }
     123                 :            : 
     124                 :    8602513 : INLINE void _kv_ins_item_free(struct kv_ins_item *item){
     125                 :    8602513 :     free(item->key);
     126                 :    8602513 :     free(item->value);
     127                 :    8602513 :     free(item);
     128                 :    8602513 : }
     129                 :            : 
     130                 :    8604993 : INLINE int _bnode_size_check(
     131                 :            :     struct btree *btree, bid_t bid, struct bnode *node,
     132                 :            :     void *new_minkey, struct list *kv_ins_list, size_t *size_out)
     133                 :            : {
     134                 :            :     size_t nitem;
     135                 :            :     size_t cursize;
     136                 :            :     size_t nodesize;
     137                 :            :     struct list_elem *e;
     138                 :            :     struct kv_ins_item *item;
     139                 :            : 
     140                 :    8604993 :     nodesize = btree->blk_ops->blk_get_size(btree->blk_handle, bid);
     141                 :            : #ifdef __CRC32
     142                 :    8604997 :     nodesize -= BLK_MARKER_SIZE;
     143                 :            : #endif
     144                 :            : 
     145                 :    8604997 :     nitem = 0;
     146         [ +  + ]:    8604997 :     if (kv_ins_list) {
     147                 :    8604995 :         e = list_begin(kv_ins_list);
     148         [ +  + ]:   17209770 :         while(e){
     149                 :    8604776 :             nitem++;
     150                 :    8604776 :             e = list_next(e);
     151                 :            :         }
     152                 :            :     }
     153                 :            : 
     154         [ -  + ]:    8604996 :     if (nitem > 1) {
     155                 :            :         int i;
     156                 :            :         void *key_arr, *value_arr;
     157                 :            : 
     158                 :          0 :         key_arr = (void*)malloc(btree->ksize * nitem);
     159                 :          0 :         value_arr = (void*)malloc(btree->vsize * nitem);
     160                 :            : 
     161                 :          0 :         i = 0;
     162                 :          0 :         e = list_begin(kv_ins_list);
     163         [ #  # ]:          0 :         while(e){
     164                 :          0 :             item = _get_entry(e, struct kv_ins_item, le);
     165                 :          0 :             memcpy((uint8_t *)key_arr + btree->ksize * i, item->key, btree->ksize);
     166                 :          0 :             memcpy((uint8_t *)value_arr + btree->ksize * i, item->value, btree->ksize);
     167                 :          0 :             i++;
     168                 :          0 :             e = list_next(e);
     169                 :            :         }
     170                 :          0 :         cursize = _bnode_size(btree, node, new_minkey, key_arr, value_arr, nitem);
     171                 :            : 
     172                 :          0 :         free(key_arr);
     173                 :          0 :         free(value_arr);
     174         [ +  + ]:    8604996 :     }else if (nitem == 1) {
     175                 :    8604776 :         e = list_begin(kv_ins_list);
     176                 :    8604775 :         item = _get_entry(e, struct kv_ins_item, le);
     177                 :    8604775 :         cursize = _bnode_size(btree, node, new_minkey, item->key, item->value, 1);
     178                 :            :     } else {
     179         [ -  + ]:        220 :         assert(nitem == 0); /* nitem should never be negative due to size_t */
     180                 :        220 :         cursize = _bnode_size(btree, node, new_minkey, NULL, NULL, 0);
     181                 :            :     }
     182                 :            : 
     183                 :    8605002 :     *size_out = cursize;
     184                 :    8605002 :     return ( cursize <= nodesize );
     185                 :            : }
     186                 :            : 
     187                 :      56998 : INLINE struct bnode * _btree_init_node(
     188                 :            :     struct btree *btree, bid_t bid, void *addr, bnode_flag_t flag, uint16_t level, struct btree_meta *meta)
     189                 :            : {
     190                 :            :     struct bnode *node;
     191                 :            :     void *node_addr;
     192                 :            :     metasize_t _size;
     193                 :            : 
     194                 :      56998 :     node_addr = addr;
     195                 :            : 
     196                 :      56998 :     node = (struct bnode *)node_addr;
     197                 :      56998 :     node->kvsize = btree->ksize<<4 | btree->vsize;
     198                 :      56998 :     node->nentry = 0;
     199                 :      56998 :     node->level = level;
     200                 :      56998 :     node->flag = flag;
     201                 :            : 
     202 [ +  + ][ +  - ]:      56998 :     if ((flag & BNODE_MASK_METADATA) && meta) {
     203                 :       2481 :         _size = _endian_encode(meta->size);
     204                 :       2481 :         memcpy((uint8_t *)node_addr + sizeof(struct bnode), &_size, sizeof(metasize_t));
     205                 :       2481 :         memcpy((uint8_t *)node_addr + sizeof(struct bnode) + sizeof(metasize_t),
     206                 :       4962 :                meta->data, meta->size);
     207                 :            :         node->data = (uint8_t *)node_addr + sizeof(struct bnode) + sizeof(metasize_t) +
     208                 :       2481 :                      _metasize_align(meta->size);
     209                 :            :     }else{
     210                 :      54517 :         node->data = (uint8_t *)node_addr + sizeof(struct bnode);
     211                 :            :     }
     212                 :            : 
     213                 :      56998 :     return node;
     214                 :            : }
     215                 :            : 
     216                 :      54469 : INLINE size_t _btree_get_nsplitnode(struct btree *btree, bid_t bid, struct bnode *node, size_t size)
     217                 :            : {
     218                 :            :     size_t headersize, dataspace;
     219                 :            :     size_t nodesize;
     220                 :      54469 :     size_t nnode = 0;
     221                 :            : 
     222                 :      54469 :     nodesize = btree->blk_ops->blk_get_size(btree->blk_handle, bid);
     223                 :            : #ifdef __CRC32
     224                 :      54469 :     nodesize -= BLK_MARKER_SIZE;
     225                 :            : #endif
     226                 :            : 
     227         [ +  + ]:      54469 :     if (node->flag & BNODE_MASK_METADATA) {
     228                 :            :         metasize_t size;
     229                 :        510 :         memcpy(&size, (uint8_t *)node + sizeof(struct bnode), sizeof(metasize_t));
     230                 :        510 :         size = _endian_decode(size);
     231                 :        510 :         headersize = sizeof(struct bnode) + _metasize_align(size) + sizeof(metasize_t);
     232                 :            :     }else{
     233                 :      53959 :         headersize = sizeof(struct bnode);
     234                 :            :     }
     235                 :            : 
     236                 :      54469 :     dataspace = nodesize - headersize;
     237                 :            :     // round up
     238                 :      54469 :     nnode = ((size - headersize) + (dataspace-1)) / dataspace;
     239                 :            : 
     240                 :      54469 :     return nnode;
     241                 :            : }
     242                 :            : 
     243                 :   24476795 : metasize_t btree_read_meta(struct btree *btree, void *buf)
     244                 :            : {
     245                 :            :     void *addr;
     246                 :            :     void *ptr;
     247                 :            :     metasize_t size;
     248                 :            :     struct bnode *node;
     249                 :            : 
     250                 :   24476795 :     addr = btree->blk_ops->blk_read(btree->blk_handle, btree->root_bid);
     251                 :   24471099 :     node = _fetch_bnode(btree, addr, btree->height);
     252         [ +  + ]:   24477158 :     if (node->flag & BNODE_MASK_METADATA) {
     253                 :   24477138 :         ptr = ((uint8_t *)node) + sizeof(struct bnode);
     254                 :   24477138 :         memcpy(&size, (uint8_t *)ptr, sizeof(metasize_t));
     255                 :   24477138 :         size = _endian_decode(size);
     256                 :   24477138 :         memcpy(buf, (uint8_t *)ptr + sizeof(metasize_t), size);
     257                 :            :     } else {
     258                 :         20 :         size = 0;
     259                 :            :     }
     260                 :            : 
     261                 :   24477158 :     return size;
     262                 :            : }
     263                 :            : 
     264                 :        576 : void btree_update_meta(struct btree *btree, struct btree_meta *meta)
     265                 :            : {
     266                 :            :     void *addr;
     267                 :            :     void *ptr;
     268                 :            :     metasize_t metasize, _metasize;
     269                 :            :     metasize_t old_metasize;
     270                 :            :     struct bnode *node;
     271                 :            : 
     272                 :            :     // read root node
     273                 :        576 :     addr = btree->blk_ops->blk_read(btree->blk_handle, btree->root_bid);
     274                 :        576 :     node = _fetch_bnode(btree, addr, btree->height);
     275                 :            : 
     276                 :        576 :     ptr = ((uint8_t *)node) + sizeof(struct bnode);
     277                 :            : 
     278         [ +  + ]:        576 :     if (node->flag & BNODE_MASK_METADATA) {
     279                 :        556 :         memcpy(&old_metasize, ptr, sizeof(metasize_t));
     280                 :        556 :         old_metasize = _endian_decode(old_metasize);
     281                 :            :     }
     282                 :            : 
     283         [ +  + ]:        576 :     if (meta) {
     284                 :         46 :         metasize = meta->size;
     285                 :            : 
     286                 :            :         // new meta size cannot be larger than old meta size
     287         [ -  + ]:         46 :         assert(metasize <= old_metasize);
     288                 :            :         (void)metasize;
     289                 :            : 
     290                 :            :         // overwrite
     291         [ +  - ]:         46 :         if (meta->size > 0) {
     292                 :         46 :             _metasize = _endian_encode(metasize);
     293                 :         46 :             memcpy(ptr, &_metasize, sizeof(metasize_t));
     294                 :         46 :             memcpy((uint8_t *)ptr + sizeof(metasize_t), meta->data, metasize);
     295                 :         46 :             node->flag |= BNODE_MASK_METADATA;
     296                 :            :         }else{
     297                 :            :             // clear the flag
     298                 :          0 :             node->flag &= ~BNODE_MASK_METADATA;
     299                 :            :         }
     300                 :            :         // move kv-pairs (only if meta size is changed)
     301         [ +  + ]:         46 :         if (_metasize_align(metasize) < _metasize_align(old_metasize)){
     302                 :            :             memmove(
     303                 :          1 :                 (uint8_t *)ptr + sizeof(metasize_t) + _metasize_align(metasize),
     304                 :            :                 node->data,
     305                 :          1 :                 btree->kv_ops->get_data_size(node, NULL, NULL, NULL, 0));
     306                 :            :             node->data = (uint8_t *)node->data - (_metasize_align(old_metasize) -
     307                 :          1 :                          _metasize_align(metasize));
     308                 :            :         }
     309                 :            : 
     310                 :            :     }else {
     311         [ +  + ]:        530 :         if (node->flag & BNODE_MASK_METADATA) {
     312                 :            :             // existing metadata is removed
     313                 :            :             memmove(ptr, node->data, btree->kv_ops->get_data_size(node,
     314                 :        510 :                                                     NULL, NULL, NULL, 0));
     315                 :            :             node->data = (uint8_t *)node->data - (_metasize_align(old_metasize) +
     316                 :        510 :                          sizeof(metasize_t));
     317                 :            :             // clear the flag
     318                 :        510 :             node->flag &= ~BNODE_MASK_METADATA;
     319                 :            :         }
     320                 :            :     }
     321                 :            : 
     322         [ +  + ]:        576 :     if (!btree->blk_ops->blk_is_writable(btree->blk_handle, btree->root_bid)) {
     323                 :            :         // already flushed block -> cannot overwrite, we have to move to new block
     324                 :            :         btree->blk_ops->blk_move(btree->blk_handle, btree->root_bid,
     325                 :          5 :                                 &btree->root_bid);
     326                 :            :     }else{
     327                 :        571 :         btree->blk_ops->blk_set_dirty(btree->blk_handle, btree->root_bid);
     328                 :            :     }
     329                 :        576 : }
     330                 :            : 
     331                 :   24490989 : btree_result btree_init_from_bid(struct btree *btree, void *blk_handle,
     332                 :            :                                  struct btree_blk_ops *blk_ops,
     333                 :            :                                  struct btree_kv_ops *kv_ops,
     334                 :            :                                  uint32_t nodesize, bid_t root_bid)
     335                 :            : {
     336                 :            :     void *addr;
     337                 :            :     struct bnode *root;
     338                 :            : 
     339                 :   24490989 :     btree->blk_ops = blk_ops;
     340                 :   24490989 :     btree->blk_handle = blk_handle;
     341                 :   24490989 :     btree->kv_ops = kv_ops;
     342                 :   24490989 :     btree->blksize = nodesize;
     343                 :   24490989 :     btree->root_bid = root_bid;
     344                 :            : 
     345                 :   24490989 :     addr = btree->blk_ops->blk_read(btree->blk_handle, btree->root_bid);
     346                 :   24478102 :     root = _fetch_bnode(btree, addr, 0);
     347                 :            : 
     348                 :   24481625 :     btree->root_flag = root->flag;
     349                 :   24481625 :     btree->height = root->level;
     350                 :   24481625 :     _get_kvsize(root->kvsize, btree->ksize, btree->vsize);
     351                 :            : 
     352                 :   24481625 :     return BTREE_RESULT_SUCCESS;
     353                 :            : }
     354                 :            : 
     355                 :       2000 : btree_result btree_init(
     356                 :            :         struct btree *btree, void *blk_handle,
     357                 :            :         struct btree_blk_ops *blk_ops,     struct btree_kv_ops *kv_ops,
     358                 :            :         uint32_t nodesize, uint8_t ksize, uint8_t vsize,
     359                 :            :         bnode_flag_t flag, struct btree_meta *meta)
     360                 :            : {
     361                 :            :     void *addr;
     362                 :       2000 :     size_t min_nodesize = 0;
     363                 :            : 
     364                 :       2000 :     btree->root_flag = BNODE_MASK_ROOT | flag;
     365                 :       2000 :     btree->blk_ops = blk_ops;
     366                 :       2000 :     btree->blk_handle = blk_handle;
     367                 :       2000 :     btree->kv_ops = kv_ops;
     368                 :       2000 :     btree->height = 1;
     369                 :       2000 :     btree->blksize = nodesize;
     370                 :       2000 :     btree->ksize = ksize;
     371                 :       2000 :     btree->vsize = vsize;
     372         [ +  + ]:       2000 :     if (meta) {
     373                 :       1972 :         btree->root_flag |= BNODE_MASK_METADATA;
     374                 :            :         min_nodesize = sizeof(struct bnode) + _metasize_align(meta->size) +
     375                 :       1972 :                        sizeof(metasize_t) + BLK_MARKER_SIZE;
     376                 :            :     } else {
     377                 :         28 :         min_nodesize = sizeof(struct bnode) + BLK_MARKER_SIZE;
     378                 :            :     }
     379                 :            : 
     380         [ +  + ]:       2000 :     if (min_nodesize > btree->blksize) {
     381                 :            :         // too large metadata .. init fail
     382                 :          1 :         return BTREE_RESULT_FAIL;
     383                 :            :     }
     384                 :            : 
     385                 :            :     // create the first root node
     386 [ +  - ][ +  - ]:       1999 :     if (btree->blk_ops->blk_alloc_sub && btree->blk_ops->blk_enlarge_node) {
     387                 :       1999 :         addr = btree->blk_ops->blk_alloc_sub(btree->blk_handle, &btree->root_bid);
     388         [ +  + ]:       1999 :         if (meta) {
     389                 :            :             // check if the initial node size including metadata is
     390                 :            :             // larger than the subblock size
     391                 :            :             size_t subblock_size;
     392                 :            :             subblock_size = btree->blk_ops->blk_get_size(btree->blk_handle,
     393                 :       1971 :                                                          btree->root_bid);
     394         [ +  + ]:       1971 :             if (subblock_size < min_nodesize) {
     395                 :            :                 addr = btree->blk_ops->blk_enlarge_node(btree->blk_handle,
     396                 :            :                                                         btree->root_bid,
     397                 :            :                                                         min_nodesize,
     398                 :        305 :                                                         &btree->root_bid);
     399                 :            :             }
     400                 :       1999 :         }
     401                 :            :     } else {
     402                 :          0 :         addr = btree->blk_ops->blk_alloc (btree->blk_handle, &btree->root_bid);
     403                 :            :     }
     404                 :            :     _btree_init_node(btree, btree->root_bid, addr,
     405                 :       1999 :                      btree->root_flag, BNODE_MASK_ROOT, meta);
     406                 :            : 
     407                 :       2000 :     return BTREE_RESULT_SUCCESS;
     408                 :            : }
     409                 :            : 
     410                 :            : /*
     411                 :            : return index# of largest key equal or smaller than KEY
     412                 :            : example)
     413                 :            : node: [2 4 6 8]
     414                 :            : key: 5
     415                 :            : largest key equal or smaller than KEY: 4
     416                 :            : return: 1 (index# of the key '4')
     417                 :            : */
     418                 :   75926138 : idx_t _btree_find_entry(struct btree *btree, struct bnode *node, void *key)
     419                 :            : {
     420                 :            :     idx_t start, end, middle, temp;
     421                 :   75926138 :     uint8_t *k = alca(uint8_t, btree->ksize);
     422                 :            :     int cmp;
     423                 :            :     #ifdef __BIT_CMP
     424                 :   75926138 :         idx_t *_map1[3] = {&end, &start, &start};
     425                 :   75926138 :         idx_t *_map2[3] = {&temp, &end, &temp};
     426                 :            :     #endif
     427                 :            : 
     428         [ +  - ]:   75926138 :     if (btree->kv_ops->init_kv_var) btree->kv_ops->init_kv_var(btree, k, NULL);
     429                 :            : 
     430                 :   75928544 :     start = middle = 0;
     431                 :   75928544 :     end = node->nentry;
     432                 :            : 
     433         [ +  + ]:   75928544 :     if (end > 0) {
     434                 :            :         // compare with smallest key
     435                 :   75926059 :         btree->kv_ops->get_kv(node, 0, k, NULL);
     436                 :            :         // smaller than smallest key
     437         [ +  + ]:   75922409 :         if (btree->kv_ops->cmp(key, k, btree->aux) < 0) {
     438         [ +  + ]:       7043 :             if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, NULL);
     439                 :       7043 :             return BTREE_IDX_NOT_FOUND;
     440                 :            :         }
     441                 :            : 
     442                 :            :         // compare with largest key
     443                 :   75888864 :         btree->kv_ops->get_kv(node, end-1, k, NULL);
     444                 :            :         // larger than largest key
     445         [ +  + ]:   75901578 :         if (btree->kv_ops->cmp(key, k, btree->aux) >= 0) {
     446         [ +  + ]:   42576253 :             if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, NULL);
     447                 :   42577358 :             return end-1;
     448                 :            :         }
     449                 :            : 
     450                 :            :         // binary search
     451         [ +  + ]:  248147986 :         while(start+1 < end) {
     452                 :  214790048 :             middle = (start + end) >> 1;
     453                 :            : 
     454                 :            :             // get key at middle
     455                 :  214790048 :             btree->kv_ops->get_kv(node, middle, k, NULL);
     456                 :  214832374 :             cmp = btree->kv_ops->cmp(key, k, btree->aux);
     457                 :            : 
     458                 :            :             #ifdef __BIT_CMP
     459                 :  214798720 :                 cmp = _MAP(cmp) + 1;
     460                 :  214798720 :                 *_map1[cmp] = middle;
     461                 :  214798720 :                 *_map2[cmp] = 0;
     462                 :            :             #else
     463                 :            :                 if (cmp < 0) end = middle;
     464                 :            :                 else if (cmp > 0) start = middle;
     465                 :            :                 else {
     466                 :            :                     if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, NULL);
     467                 :            :                     return middle;
     468                 :            :                 }
     469                 :            :             #endif
     470                 :            :         }
     471         [ +  + ]:   33357938 :         if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, NULL);
     472                 :   33370678 :         return start;
     473                 :            :     }
     474                 :            : 
     475         [ +  + ]:       2485 :     if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, NULL);
     476                 :   75957564 :     return BTREE_IDX_NOT_FOUND;
     477                 :            : }
     478                 :            : 
     479                 :    8603566 : idx_t _btree_add_entry(struct btree *btree, struct bnode *node, void *key, void *value)
     480                 :            : {
     481                 :            :     idx_t idx, idx_insert;
     482                 :    8603566 :     uint8_t *k = alca(uint8_t, btree->ksize);
     483                 :            : 
     484         [ +  - ]:    8603566 :     if (btree->kv_ops->init_kv_var) btree->kv_ops->init_kv_var(btree, k, NULL);
     485                 :            : 
     486         [ +  + ]:    8603567 :     if (node->nentry > 0) {
     487                 :    8601043 :         idx = _btree_find_entry(btree, node, key);
     488                 :            : 
     489         [ +  + ]:    8601059 :         if (idx == BTREE_IDX_NOT_FOUND) idx_insert = 0;
     490                 :            :         else {
     491                 :    8598959 :             btree->kv_ops->get_kv(node, idx, k, NULL);
     492         [ +  + ]:    8598958 :             if (!btree->kv_ops->cmp(key, k, btree->aux)) {
     493                 :            :                 // if same key already exists -> update its value
     494                 :     505632 :                 btree->kv_ops->set_kv(node, idx, key, value);
     495         [ +  + ]:     505632 :                 if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, NULL);
     496                 :     505632 :                 return idx;
     497                 :            :             }else{
     498                 :    8093322 :                 idx_insert = idx+1;
     499                 :            :             }
     500                 :            :         }
     501                 :            : 
     502         [ +  + ]:    8095422 :         if (idx_insert < node->nentry) {
     503                 :            : 
     504                 :            :             /*
     505                 :            :             shift [idx+1, nentry) key-value pairs to right
     506                 :            :             example)
     507                 :            :             idx = 1 (i.e. idx_insert = 2)
     508                 :            :             [2 4 6 8] -> [2 4 _ 6 8]
     509                 :            :             return 2
     510                 :            :             */
     511                 :    3860741 :             btree->kv_ops->ins_kv(node, idx_insert, key, value);
     512                 :            :         }else{
     513                 :    4234681 :             btree->kv_ops->set_kv(node, idx_insert, key, value);
     514                 :            :         }
     515                 :            : 
     516                 :            :     }else{
     517                 :       2524 :         idx_insert = 0;
     518                 :            :         // add at idx_insert
     519                 :       2524 :         btree->kv_ops->set_kv(node, idx_insert, key, value);
     520                 :            :     }
     521                 :            : 
     522                 :            :     // add at idx_insert
     523                 :    8097914 :     node->nentry++;
     524                 :            : 
     525         [ +  + ]:    8097914 :     if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, NULL);
     526                 :    8603546 :     return idx_insert;
     527                 :            : }
     528                 :            : 
     529                 :         16 : idx_t _btree_remove_entry(struct btree *btree, struct bnode *node, void *key)
     530                 :            : {
     531                 :            :     idx_t idx;
     532                 :            : 
     533         [ +  - ]:         16 :     if (node->nentry > 0) {
     534                 :         16 :         idx = _btree_find_entry(btree, node, key);
     535                 :            : 
     536         [ -  + ]:         16 :         if (idx == BTREE_IDX_NOT_FOUND) return idx;
     537                 :            : 
     538                 :            :         /*
     539                 :            :         shift [idx+1, nentry) key-value pairs to left
     540                 :            :         example)
     541                 :            :         idx = 2
     542                 :            :         [2 4 6 8 10] -> [2 4 8 10]
     543                 :            :         return 2
     544                 :            :         */
     545                 :         16 :         btree->kv_ops->ins_kv(node, idx, NULL, NULL);
     546                 :            : 
     547                 :         16 :         node->nentry--;
     548                 :            : 
     549                 :         16 :         return idx;
     550                 :            : 
     551                 :            :     }else{
     552                 :         16 :         return BTREE_IDX_NOT_FOUND;
     553                 :            :     }
     554                 :            : }
     555                 :            : 
     556                 :         88 : void _btree_print_node(struct btree *btree, int depth, bid_t bid, btree_print_func func)
     557                 :            : {
     558                 :            :     int i;
     559                 :         88 :     uint8_t *k = alca(uint8_t, btree->ksize);
     560                 :         88 :     uint8_t *v = alca(uint8_t, btree->vsize);
     561                 :            :     void *addr;
     562                 :            :     bid_t _bid;
     563                 :            :     struct bnode *node;
     564                 :            : 
     565         [ +  - ]:         88 :     if (btree->kv_ops->init_kv_var) btree->kv_ops->init_kv_var(btree, k, v);
     566                 :            : 
     567                 :         88 :     addr = btree->blk_ops->blk_read(btree->blk_handle, bid);
     568                 :         88 :     node = _fetch_bnode(btree, addr, depth);
     569                 :            : 
     570                 :         88 :     fprintf(stderr, "[d:%d n:%d f:%x b:%" _F64 " ", node->level, node->nentry, node->flag, bid);
     571                 :            : 
     572         [ +  + ]:        274 :     for (i=0;i<node->nentry;++i){
     573                 :        186 :         btree->kv_ops->get_kv(node, i, k, v);
     574                 :        186 :         _bid = btree->kv_ops->value2bid(v);
     575                 :        186 :         _bid = _endian_decode(_bid);
     576                 :        186 :         func(btree, k, (void*)&_bid);
     577                 :            :     }
     578                 :         88 :     fprintf(stderr, "]\n");
     579         [ +  + ]:         88 :     if (depth > 1) {
     580         [ +  + ]:        112 :         for (i=0;i<node->nentry;++i){
     581                 :         78 :             btree->kv_ops->get_kv(node, i, k, v);
     582                 :         78 :             _bid = btree->kv_ops->value2bid(v);
     583                 :         78 :             _bid = _endian_decode(_bid);
     584                 :         78 :             _btree_print_node(btree, depth-1, _bid, func);
     585                 :            :         }
     586                 :            :     }
     587                 :            : 
     588         [ -  + ]:         88 :     if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, v);
     589                 :         88 : }
     590                 :            : 
     591                 :         10 : void btree_print_node(struct btree *btree, btree_print_func func)
     592                 :            : {
     593                 :         10 :     fprintf(stderr, "tree height: %d\n", btree->height);
     594                 :         10 :     _btree_print_node(btree, btree->height, btree->root_bid, func);
     595                 :         10 : }
     596                 :            : 
     597                 :          5 : btree_result btree_get_key_range(
     598                 :            :     struct btree *btree, idx_t num, idx_t den, void *key_begin, void *key_end)
     599                 :            : {
     600                 :            :     void *addr;
     601                 :          5 :     uint8_t *k = alca(uint8_t, btree->ksize);
     602                 :          5 :     uint8_t *v = alca(uint8_t, btree->vsize);
     603                 :            :     idx_t idx_begin, idx_end, idx;
     604                 :            :     bid_t bid;
     605                 :            :     struct bnode *root, *node;
     606                 :            :     uint64_t _num, _den, _nentry, resolution, mask, _idx_begin, _idx_end;
     607                 :            : 
     608         [ -  + ]:          5 :     assert(num < den);
     609                 :          5 :     resolution = 1<<4; mask = resolution-1;
     610                 :            : 
     611         [ +  - ]:          5 :     if (btree->kv_ops->init_kv_var) btree->kv_ops->init_kv_var(btree, k, v);
     612                 :          5 :     _num = (uint64_t)num * resolution;
     613                 :          5 :     _den = (uint64_t)den * resolution;
     614                 :            : 
     615                 :            :     // get root node
     616                 :          5 :     addr = btree->blk_ops->blk_read(btree->blk_handle, btree->root_bid);
     617                 :          5 :     root = _fetch_bnode(btree, addr, btree->height);
     618                 :          5 :     _nentry = (uint64_t)root->nentry * resolution;
     619                 :            : 
     620         [ +  - ]:          5 :     if (btree->height == 1) {
     621                 :          5 :         btree->kv_ops->get_kv(root, ((num+0) * root->nentry / den)-0, key_begin, NULL);
     622                 :          5 :         btree->kv_ops->get_kv(root, ((num+1) * root->nentry / den)-1, key_end, NULL);
     623                 :            :     }else{
     624                 :          0 :         _idx_begin = (_num * _nentry / _den);
     625                 :          0 :         _idx_end = ((_num+resolution) * _nentry / _den)-1;
     626                 :            : 
     627                 :          0 :         idx_begin = _idx_begin / resolution;
     628                 :          0 :         idx_end = (_idx_end / resolution);
     629         [ #  # ]:          0 :         if (idx_end >= root->nentry) idx_end = root->nentry-1;
     630                 :            : 
     631                 :            :         // get first child node (for KEY_BEGIN)
     632                 :          0 :         btree->kv_ops->get_kv(root, idx_begin, k, v);
     633                 :          0 :         bid = btree->kv_ops->value2bid(v);
     634                 :          0 :         bid = _endian_decode(bid);
     635                 :          0 :         addr = btree->blk_ops->blk_read(btree->blk_handle, bid);
     636                 :          0 :         node = _fetch_bnode(btree, addr, btree->height-1);
     637                 :            : 
     638                 :          0 :         idx = ((_idx_begin & mask) * (node->nentry-1) / (resolution-1));
     639                 :          0 :         btree->kv_ops->get_kv(node, idx, key_begin, NULL);
     640                 :            : 
     641                 :            :         // get second child node (for KEY_END)
     642         [ #  # ]:          0 :         if (idx_end != idx_begin) {
     643                 :          0 :             btree->kv_ops->get_kv(root, idx_end, k, v);
     644                 :          0 :             bid = btree->kv_ops->value2bid(v);
     645                 :          0 :             bid = _endian_decode(bid);
     646                 :          0 :             addr = btree->blk_ops->blk_read(btree->blk_handle, bid);
     647                 :          0 :             node = _fetch_bnode(btree, addr, btree->height-1);
     648                 :            :         }
     649                 :            : 
     650                 :          0 :         idx = ((_idx_end & mask) * (node->nentry-1) / (resolution-1));
     651                 :          0 :         btree->kv_ops->get_kv(node, idx, key_end, NULL);
     652                 :            :     }
     653                 :            : 
     654         [ -  + ]:          5 :     if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, v);
     655                 :          5 :     return BTREE_RESULT_SUCCESS;
     656                 :            : }
     657                 :            : 
     658                 :   24674718 : btree_result btree_find(struct btree *btree, void *key, void *value_buf)
     659                 :            : {
     660                 :            :     void *addr;
     661                 :   24674718 :     uint8_t *k = alca(uint8_t, btree->ksize);
     662                 :   24674718 :     uint8_t *v = alca(uint8_t, btree->vsize);
     663                 :   24674718 :     idx_t *idx = alca(idx_t, btree->height);
     664                 :   24674718 :     bid_t *bid = alca(bid_t, btree->height);
     665                 :   24674718 :     struct bnode **node = alca(struct bnode *, btree->height);
     666                 :            :     int i;
     667                 :            : 
     668         [ +  - ]:   24674718 :     if (btree->kv_ops->init_kv_var) btree->kv_ops->init_kv_var(btree, k, v);
     669                 :            : 
     670                 :            :     // set root
     671                 :   24679879 :     bid[btree->height-1] = btree->root_bid;
     672                 :            : 
     673         [ +  + ]:   59743769 :     for (i=btree->height-1; i>=0; --i) {
     674                 :            :         // read block using bid
     675                 :   44938591 :         addr = btree->blk_ops->blk_read(btree->blk_handle, bid[i]);
     676                 :            :         // fetch node structure from block
     677                 :   44937951 :         node[i] = _fetch_bnode(btree, addr, i+1);
     678                 :            : 
     679                 :            :         // lookup key in current node
     680                 :   44930881 :         idx[i] = _btree_find_entry(btree, node[i], key);
     681                 :            : 
     682         [ +  + ]:   44935201 :         if (idx[i] == BTREE_IDX_NOT_FOUND) {
     683                 :            :             // not found .. return NULL
     684         [ -  + ]:        949 :             if (btree->blk_ops->blk_operation_end)
     685                 :          0 :                 btree->blk_ops->blk_operation_end(btree->blk_handle);
     686         [ +  + ]:        949 :             if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, v);
     687                 :        949 :             return BTREE_RESULT_FAIL;
     688                 :            :         }
     689                 :            : 
     690                 :   44934252 :         btree->kv_ops->get_kv(node[i], idx[i], k, v);
     691                 :            : 
     692         [ +  + ]:   44950423 :         if (i>0) {
     693                 :            :             // index (non-leaf) node
     694                 :            :             // get bid of child node from value
     695                 :   20282080 :             bid[i-1] = btree->kv_ops->value2bid(v);
     696                 :   20284709 :             bid[i-1] = _endian_decode(bid[i-1]);
     697                 :            :         }else{
     698                 :            :             // leaf node
     699                 :            :             // return (address of) value if KEY == k
     700         [ +  + ]:   24668343 :             if (!btree->kv_ops->cmp(key, k, btree->aux)) {
     701                 :   14805105 :                 btree->kv_ops->set_value(btree, value_buf, v);
     702                 :            :             }else{
     703         [ -  + ]:    9868001 :                 if (btree->blk_ops->blk_operation_end)
     704                 :          0 :                     btree->blk_ops->blk_operation_end(btree->blk_handle);
     705         [ +  + ]:    9868002 :                 if (btree->kv_ops->free_kv_var) {
     706                 :       7719 :                     btree->kv_ops->free_kv_var(btree, k, v);
     707                 :            :                 }
     708                 :    9868002 :                 return BTREE_RESULT_FAIL;
     709                 :            :             }
     710                 :            :         }
     711                 :            :     }
     712         [ -  + ]:   14805178 :     if (btree->blk_ops->blk_operation_end) {
     713                 :          0 :         btree->blk_ops->blk_operation_end(btree->blk_handle);
     714                 :            :     }
     715         [ +  + ]:   14805189 :     if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, v);
     716                 :   24674140 :     return BTREE_RESULT_SUCCESS;
     717                 :            : }
     718                 :            : 
     719                 :      54469 : int _btree_split_node(
     720                 :            :     struct btree *btree, void *key, struct bnode **node, bid_t *bid, idx_t *idx, int i,
     721                 :            :     struct list *kv_ins_list, size_t nsplitnode, void *k, void *v,
     722                 :            :     int8_t *modified, int8_t *minkey_replace, int8_t *ins)
     723                 :            : {
     724                 :            :     void *addr;
     725                 :      54469 :     size_t nnode = nsplitnode;
     726                 :      54469 :     int j, *nentry = alca(int, nnode);
     727                 :            :     bid_t _bid;
     728                 :      54469 :     bid_t *new_bid = alca(bid_t, nnode);
     729                 :      54469 :     idx_t *split_idx = alca(idx_t, nnode+1);
     730                 :      54469 :     idx_t *idx_ins = alca(idx_t, btree->height);
     731                 :            :     struct list_elem *e;
     732                 :      54469 :     struct bnode **new_node = alca(struct bnode *, nnode);
     733                 :            :     struct kv_ins_item *kv_item;
     734                 :            : 
     735                 :            :     // allocate new block(s)
     736                 :      54469 :     new_node[0] = node[i];
     737         [ +  + ]:     108938 :     for (j=1;j<nnode;++j){
     738                 :      54469 :         addr = btree->blk_ops->blk_alloc(btree->blk_handle, &new_bid[j]);
     739                 :     108938 :         new_node[j] = _btree_init_node(btree, new_bid[j], addr, 0x0,
     740                 :      54469 :                                        node[i]->level, NULL);
     741                 :            :     }
     742                 :            : 
     743                 :            :     // calculate # entry
     744         [ +  + ]:     217876 :     for (j=0;j<nnode+1;++j){
     745                 :     163407 :         btree->kv_ops->get_nth_idx(node[i], j, nnode, &split_idx[j]);
     746         [ +  + ]:     163407 :         if (j>0) {
     747                 :     108938 :             nentry[j-1] = split_idx[j] - split_idx[j-1];
     748                 :            :         }
     749                 :            :     }
     750                 :            : 
     751                 :            :     // copy kv-pairs to new node(s)
     752         [ +  + ]:     108938 :     for (j=1;j<nnode;++j){
     753                 :     163407 :         btree->kv_ops->copy_kv(new_node[j], node[i], 0, split_idx[j],
     754                 :      54469 :                                nentry[j]);
     755                 :            :     }
     756                 :      54469 :     j = 0;
     757                 :      54469 :     btree->kv_ops->copy_kv(new_node[j], node[i], 0, split_idx[j], nentry[j]);
     758                 :            : 
     759                 :            :     // header
     760         [ +  + ]:     163407 :     for (j=0;j<nnode;++j){
     761                 :     108938 :         new_node[j]->nentry = nentry[j];
     762                 :            :     }
     763                 :      54469 :     modified[i] = 1;
     764                 :            : 
     765         [ +  - ]:      54469 :     if (ins[i]) {
     766                 :            :         // insert kv-pair(s) to appropriate node
     767                 :      54469 :         e = list_begin(&kv_ins_list[i]);
     768         [ +  + ]:     108938 :         while(e) {
     769                 :      54469 :             kv_item = _get_entry(e, struct kv_ins_item, le);
     770                 :            : 
     771                 :      54469 :             idx_ins[i] = BTREE_IDX_NOT_FOUND;
     772         [ +  + ]:      99062 :             for (j=1;j<nnode;++j){
     773                 :      54469 :                 btree->kv_ops->get_kv(new_node[j], 0, k, v);
     774         [ +  + ]:      54469 :                 if (btree->kv_ops->cmp(kv_item->key, k, btree->aux) < 0) {
     775                 :       9876 :                     idx_ins[i] =
     776                 :       9876 :                         _btree_add_entry(btree, new_node[j-1], kv_item->key,
     777                 :       9876 :                                          kv_item->value);
     778                 :       9876 :                     break;
     779                 :            :                 }
     780                 :            :             }
     781         [ +  + ]:      54469 :             if (idx_ins[i] == BTREE_IDX_NOT_FOUND) {
     782                 :            :                 // insert into the last split node
     783                 :      44593 :                 idx_ins[i] =
     784                 :      44593 :                     _btree_add_entry(btree, new_node[nnode-1], kv_item->key,
     785                 :      44593 :                                      kv_item->value);
     786                 :            :             }
     787                 :      54469 :             e = list_next(e);
     788                 :            :         }
     789                 :            :     }
     790         [ -  + ]:      54469 :     if (minkey_replace[i]){
     791                 :            :         // replace the minimum key in the (first split) node to KEY
     792                 :          0 :         btree->kv_ops->get_kv(new_node[0], idx[i], k, v);
     793                 :          0 :         btree->kv_ops->set_kv(new_node[0], idx[i], key, v);
     794                 :            :     }
     795                 :            : 
     796         [ +  + ]:      54469 :     if (i+1 < btree->height) {
     797                 :            :         // non-root node
     798                 :            :         // reserve kv-pair (i.e. splitters) to be inserted into parent node
     799         [ +  + ]:     107878 :         for (j=1; j<nnode; ++j){
     800                 :      53939 :             _bid = _endian_encode(new_bid[j]);
     801                 :      53939 :             kv_item = _kv_ins_item_create(btree, NULL, (void *)&_bid);
     802                 :     107878 :             btree->kv_ops->get_nth_splitter(new_node[j-1], new_node[j],
     803                 :      53939 :                                             kv_item->key);
     804                 :      53939 :             list_push_back(&kv_ins_list[i+1], &kv_item->le);
     805                 :            :         }
     806                 :      53939 :         ins[i+1] = 1;
     807                 :            : 
     808                 :            :     }else{
     809                 :            :         //2 root node -> height grow up
     810                 :            :         // allocate new block for new root node
     811                 :            :         bid_t new_root_bid;
     812                 :            :         struct bnode *new_root;
     813                 :        530 :         uint8_t *buf = alca(uint8_t, btree->blksize);
     814                 :            :         struct btree_meta meta;
     815                 :            : 
     816                 :        530 :         meta.size = btree_read_meta(btree, buf);
     817                 :        530 :         meta.data = buf;
     818                 :            :         // remove metadata section of existing node
     819                 :            :         // (this node is not root anymore)
     820                 :        530 :         btree_update_meta(btree, NULL);
     821                 :            : 
     822                 :        530 :         btree->height++;
     823                 :            : 
     824                 :        530 :         addr = btree->blk_ops->blk_alloc(btree->blk_handle, &new_root_bid);
     825         [ +  + ]:        530 :         if (meta.size > 0)
     826                 :            :             new_root =
     827                 :            :                 _btree_init_node(
     828                 :            :                     btree, new_root_bid, addr, btree->root_flag,
     829                 :        510 :                     node[i]->level + 1, &meta);
     830                 :            :         else
     831                 :            :             new_root =
     832                 :            :                 _btree_init_node(
     833                 :            :                     btree, new_root_bid, addr, btree->root_flag,
     834                 :         20 :                     node[i]->level + 1, NULL);
     835                 :            : 
     836                 :            :         // clear old root node flag
     837                 :        530 :         node[i]->flag &= ~BNODE_MASK_ROOT;
     838                 :        530 :         node[i]->flag &= ~BNODE_MASK_SEQTREE;
     839                 :            :         // change root bid
     840                 :        530 :         btree->root_bid = new_root_bid;
     841                 :            : 
     842                 :            :         // move the former node if not dirty
     843         [ +  + ]:        530 :         if (!btree->blk_ops->blk_is_writable(btree->blk_handle, bid[i])) {
     844                 :          5 :             addr = btree->blk_ops->blk_move(btree->blk_handle, bid[i], &bid[i]);
     845                 :          5 :             node[i] = _fetch_bnode(btree, addr, i+1);
     846                 :            :         }else{
     847                 :        525 :             btree->blk_ops->blk_set_dirty(btree->blk_handle, bid[i]);
     848                 :            :         }
     849                 :            : 
     850                 :            :         // insert kv-pairs pointing to their child nodes
     851                 :            :         // original (i.e. the first node)
     852                 :        530 :         btree->kv_ops->get_kv(node[i], 0, k, v);
     853                 :        530 :         _bid = _endian_encode(bid[i]);
     854                 :        530 :         _btree_add_entry(btree, new_root, k, btree->kv_ops->bid2value(&_bid));
     855                 :            : 
     856                 :            :         // the others
     857         [ +  + ]:       1060 :         for (j=1;j<nnode;++j){
     858                 :            :             //btree->kv_ops->get_kv(new_node[j], 0, k, v);
     859                 :        530 :             btree->kv_ops->get_nth_splitter(new_node[j-1], new_node[j], k);
     860                 :        530 :             _bid = _endian_encode(new_bid[j]);
     861                 :            :             _btree_add_entry(btree, new_root, k,
     862                 :        530 :                              btree->kv_ops->bid2value(&_bid));
     863                 :            :         }
     864                 :            : 
     865                 :      54469 :         return 1;
     866                 :            :     } // height growup
     867                 :            : 
     868                 :      53939 :     return 0;
     869                 :            : }
     870                 :            : 
     871                 :      36194 : int _btree_move_modified_node(
     872                 :            :     struct btree *btree, void *key, struct bnode **node, bid_t *bid,
     873                 :            :     idx_t *idx, int i,
     874                 :            :     struct list *kv_ins_list, void *k, void *v,
     875                 :            :     int8_t *modified, int8_t *minkey_replace, int8_t *ins, int8_t *moved)
     876                 :            : {
     877                 :            :     void *addr;
     878                 :            : 
     879                 :            :     // get new bid[i]
     880                 :      36194 :     addr = btree->blk_ops->blk_move(btree->blk_handle, bid[i], &bid[i]);
     881                 :            :     (void)addr;
     882                 :            :     //node[i] = _fetch_bnode(btree, addr, i+1);
     883                 :      36194 :     moved[i] = 1;
     884                 :            : 
     885         [ +  + ]:      36194 :     if (i+1 == btree->height)
     886                 :            :         // if moved node is root node
     887                 :       2787 :         btree->root_bid = bid[i];
     888                 :            : 
     889                 :      36194 :     return 0;
     890                 :            : }
     891                 :            : 
     892                 :    8548582 : btree_result btree_insert(struct btree *btree, void *key, void *value)
     893                 :            : {
     894                 :            :     void *addr;
     895                 :    8548582 :     size_t nsplitnode = 1;
     896                 :    8548582 :     uint8_t *k = alca(uint8_t, btree->ksize);
     897                 :    8548582 :     uint8_t *v = alca(uint8_t, btree->vsize);
     898                 :            :     // index# and block ID for each level
     899                 :    8548582 :     idx_t *idx = alca(idx_t, btree->height);
     900                 :    8548582 :     bid_t *bid = alca(bid_t, btree->height);
     901                 :            :     bid_t _bid;
     902                 :            :     // flags
     903                 :    8548582 :     int8_t *modified = alca(int8_t, btree->height);
     904                 :    8548582 :     int8_t *moved = alca(int8_t, btree->height);
     905                 :    8548582 :     int8_t *ins = alca(int8_t, btree->height);
     906                 :    8548582 :     int8_t *minkey_replace = alca(int8_t, btree->height);
     907                 :            :     int8_t height_growup;
     908                 :            : 
     909                 :            :     // key, value to be inserted
     910                 :    8548582 :     struct list *kv_ins_list = alca(struct list, btree->height);
     911                 :            :     struct kv_ins_item *kv_item;
     912                 :            :     struct list_elem *e;
     913                 :            : 
     914                 :            :     // index# where kv is inserted
     915                 :    8548582 :     idx_t *idx_ins = alca(idx_t, btree->height);
     916                 :    8548582 :     struct bnode **node = alca(struct bnode *, btree->height);
     917                 :    8548582 :     int i, j, _is_update = 0;
     918                 :            : 
     919                 :            :     // initialize flags
     920         [ +  + ]:   30938361 :     for (i=0;i<btree->height;++i) {
     921                 :   22389779 :         moved[i] = modified[i] = ins[i] = minkey_replace[i] = 0;
     922                 :            :     }
     923                 :    8548582 :     height_growup = 0;
     924                 :            : 
     925                 :            :     // initialize temporary variables
     926         [ +  - ]:    8548582 :     if (btree->kv_ops->init_kv_var) {
     927                 :    8548582 :         btree->kv_ops->init_kv_var(btree, k, v);
     928         [ +  + ]:   30938366 :         for (i=0;i<btree->height;++i){
     929                 :   22389784 :             list_init(&kv_ins_list[i]);
     930                 :            :         }
     931                 :            :     }
     932                 :            : 
     933                 :            :     // copy key-value pair to be inserted into leaf node
     934                 :    8548582 :     kv_item = _kv_ins_item_create(btree, key, value);
     935                 :    8548575 :     list_push_back(&kv_ins_list[0], &kv_item->le);
     936                 :            : 
     937                 :    8548498 :     ins[0] = 1;
     938                 :            : 
     939                 :            :     // set root node
     940                 :    8548498 :     bid[btree->height-1] = btree->root_bid;
     941                 :            : 
     942                 :            :     // find path from root to leaf
     943         [ +  + ]:   30938157 :     for (i=btree->height-1; i>=0; --i){
     944                 :            :         // read block using bid
     945                 :   22389600 :         addr = btree->blk_ops->blk_read(btree->blk_handle, bid[i]);
     946                 :            :         // fetch node structure from block
     947                 :   22389601 :         node[i] = _fetch_bnode(btree, addr, i+1);
     948                 :            : 
     949                 :            :         // lookup key in current node
     950                 :   22389616 :         idx[i] = _btree_find_entry(btree, node[i], key);
     951                 :            : 
     952         [ +  + ]:   22389655 :         if (i > 0) {
     953                 :            :             // index (non-leaf) node
     954         [ +  + ]:   13841174 :             if (idx[i] == BTREE_IDX_NOT_FOUND)
     955                 :            :                 // KEY is smaller than the smallest key in this node ..
     956                 :            :                 // just follow the smallest key
     957                 :        223 :                 idx[i] = 0;
     958                 :            : 
     959                 :            :             // get bid of child node from value
     960                 :   13841174 :             btree->kv_ops->get_kv(node[i], idx[i], k, v);
     961                 :   13841178 :             bid[i-1] = btree->kv_ops->value2bid(v);
     962                 :   13841178 :             bid[i-1] = _endian_decode(bid[i-1]);
     963                 :            :         }else{
     964                 :            :             // leaf node .. do nothing
     965                 :            :         }
     966                 :            :     }
     967                 :            : 
     968                 :            :     // cascaded insert from leaf to root
     969         [ +  + ]:   30937758 :     for (i=0;i<btree->height;++i){
     970                 :            : 
     971         [ +  + ]:   22389678 :         if (idx[i] != BTREE_IDX_NOT_FOUND)
     972                 :   22385610 :             btree->kv_ops->get_kv(node[i], idx[i], k, NULL);
     973                 :            : 
     974         [ +  + ]:   22389704 :         if (i > 0) {
     975                 :            :             // in case of index node
     976                 :            :             // when KEY is smaller than smallest key in index node
     977 [ +  + ][ +  + ]:   13841208 :             if (idx[i] == 0 && btree->kv_ops->cmp(key, k, btree->aux) < 0) {
                 [ +  + ]
     978                 :            :                 // change node's smallest key
     979                 :        223 :                 minkey_replace[i] = 1;
     980                 :            :             }
     981                 :            : 
     982                 :            :             // when child node is moved to new block
     983         [ +  + ]:   13841208 :             if (moved[i-1]) {
     984                 :            :                 // replace the bid (value)
     985                 :      33407 :                 _bid = _endian_encode(bid[i-1]);
     986                 :      66814 :                 btree->kv_ops->set_kv(node[i], idx[i], k,
     987                 :      33407 :                                       btree->kv_ops->bid2value(&_bid));
     988                 :      33407 :                 modified[i] = 1;
     989                 :            :             }
     990                 :            :         }
     991                 :            : 
     992 [ +  + ][ +  + ]:   22389704 :         if (ins[i] || minkey_replace[i]) {
     993                 :            :             // there is a key-value pair to be inserted into this (level of)
     994                 :            :             // node check whether btree node space is enough to add new
     995                 :            :             // key-value pair or not, OR action is not insertion but update
     996                 :            :             // (key_ins exists in current node)
     997                 :    8602714 :             _is_update = 0;
     998                 :            :             size_t nodesize;
     999         [ +  + ]:    8602714 :             void *new_minkey = (minkey_replace[i])?(key):(NULL);
    1000                 :            : 
    1001         [ +  + ]:    8602714 :             if (i==0) {
    1002                 :    8548558 :                 e = list_begin(&kv_ins_list[i]);
    1003                 :    8548559 :                 kv_item = _get_entry(e, struct kv_ins_item, le);
    1004                 :            :                 _is_update =
    1005                 :    8548559 :                     (idx[i] != BTREE_IDX_NOT_FOUND &&
    1006 [ +  + ][ +  + ]:    8548559 :                      !btree->kv_ops->cmp(kv_item->key, k, btree->aux));
    1007                 :            :             }
    1008                 :            : 
    1009                 :            :         check_node:;
    1010                 :            :             int _size_check =
    1011                 :   17209982 :                 _bnode_size_check(btree, bid[i], node[i], new_minkey,
    1012                 :    8604991 :                                   &kv_ins_list[i], &nodesize);
    1013                 :            : 
    1014 [ +  + ][ +  + ]:    8605001 :             if (_size_check || _is_update ) {
    1015                 :            :                 //2 enough space
    1016         [ +  + ]:    8548261 :                 if (ins[i]) {
    1017                 :            :                     // insert key/value pair(s)
    1018                 :            :                     // insert all kv pairs on list
    1019                 :    8548041 :                     e = list_begin(&kv_ins_list[i]);
    1020         [ +  + ]:   17096054 :                     while(e) {
    1021                 :    8548038 :                         kv_item = _get_entry(e, struct kv_ins_item, le);
    1022                 :   17096076 :                         idx_ins[i] = _btree_add_entry(btree, node[i],
    1023                 :    8548038 :                                                  kv_item->key, kv_item->value);
    1024                 :    8548018 :                         e = list_next(e);
    1025                 :            :                     }
    1026                 :            :                 }
    1027         [ +  + ]:    8548236 :                 if (minkey_replace[i]) {
    1028                 :            :                     // replace the minimum key in the node to KEY
    1029                 :        223 :                     btree->kv_ops->get_kv(node[i], idx[i], k, v);
    1030                 :        223 :                     btree->kv_ops->set_kv(node[i], idx[i], key, v);
    1031                 :            :                 }
    1032                 :    8548240 :                 modified[i] = 1;
    1033                 :            : 
    1034                 :            :             }else{
    1035                 :            :                 //2 not enough
    1036                 :            :                 // first check if the node can be enlarged
    1037   [ +  -  +  + ]:     113480 :                 if (btree->blk_ops->blk_enlarge_node &&
                 [ +  + ]
    1038                 :      56740 :                     is_subblock(bid[i])) {
    1039                 :            :                     bid_t new_bid;
    1040                 :            :                     addr = btree->blk_ops->blk_enlarge_node(btree->blk_handle,
    1041                 :       2271 :                         bid[i], nodesize, &new_bid);
    1042         [ +  - ]:       2271 :                     if (addr) {
    1043                 :            :                         // the node can be enlarged .. fetch the enlarged node
    1044                 :       2271 :                         moved[i] = 1;
    1045                 :       2271 :                         bid[i] = new_bid;
    1046                 :       2271 :                         node[i] = _fetch_bnode(btree, addr, i+1);
    1047         [ +  - ]:       2271 :                         if (i+1 == btree->height) {
    1048                 :            :                             // if moved node is root node
    1049                 :       2271 :                             btree->root_bid = bid[i];
    1050                 :            :                         }
    1051                 :            :                         // start over
    1052                 :       2271 :                         goto check_node;
    1053                 :            :                     }
    1054                 :            :                 }
    1055                 :            : 
    1056                 :            :                 //otherwise, split the node
    1057                 :            :                 nsplitnode = _btree_get_nsplitnode(btree, BLK_NOT_FOUND,
    1058                 :      54469 :                                                    node[i], nodesize);
    1059                 :            :                 // force the node split when the node size of new layout is
    1060                 :            :                 // larger than the current node size
    1061         [ -  + ]:      54469 :                 if (nsplitnode == 1) nsplitnode = 2;
    1062                 :            : 
    1063                 :            :                 height_growup = _btree_split_node(
    1064                 :            :                     btree, key, node, bid, idx, i,
    1065                 :            :                     kv_ins_list, nsplitnode, k, v,
    1066                 :      54469 :                     modified, minkey_replace, ins);
    1067                 :            :             } // split
    1068                 :            :         } // insert
    1069                 :            : 
    1070         [ +  + ]:   22389699 :         if (height_growup) break;
    1071                 :            : 
    1072         [ +  + ]:   22389169 :         if (modified[i]) {
    1073                 :            :             //2 when the node is modified
    1074         [ +  + ]:    8635584 :             if (!btree->blk_ops->blk_is_writable(btree->blk_handle, bid[i])) {
    1075                 :            :                 // not writable .. already flushed block -> cannot overwrite,
    1076                 :            :                 // we have to move to new block
    1077                 :            :                 height_growup = _btree_move_modified_node(
    1078                 :            :                     btree, key, node, bid, idx, i,
    1079                 :            :                     kv_ins_list, k, v,
    1080                 :      36194 :                     modified, minkey_replace, ins, moved);
    1081                 :            : 
    1082         [ -  + ]:      36194 :                 if (height_growup) break;
    1083                 :            :             }else{
    1084                 :            :                 // writable .. just set dirty to write back into storage
    1085                 :    8599425 :                 btree->blk_ops->blk_set_dirty(btree->blk_handle, bid[i]);
    1086                 :            :             } // is writable
    1087                 :            :         } // is modified
    1088                 :            :     } // for loop
    1089                 :            : 
    1090                 :            :     // release temporary resources
    1091         [ -  + ]:    8548610 :     if (btree->blk_ops->blk_operation_end) {
    1092                 :          0 :         btree->blk_ops->blk_operation_end(btree->blk_handle);
    1093                 :            :     }
    1094         [ +  + ]:    8548561 :     if (btree->kv_ops->free_kv_var) btree->kv_ops->free_kv_var(btree, k, v);
    1095                 :            : 
    1096 [ +  + ][ +  + ]:   30938355 :     for (j=0; j < ((height_growup)?(btree->height-1):(btree->height)); ++j){
    1097                 :   22389772 :         e = list_begin(&kv_ins_list[j]);
    1098         [ +  + ]:   30992307 :         while(e) {
    1099                 :    8602513 :             kv_item = _get_entry(e, struct kv_ins_item, le);
    1100                 :    8602513 :             e = list_remove(&kv_ins_list[j], e);
    1101                 :            : 
    1102         [ +  + ]:    8602513 :             if (btree->kv_ops->free_kv_var) {
    1103                 :       9346 :                 btree->kv_ops->free_kv_var(btree, kv_item->key, kv_item->value);
    1104                 :            :             }
    1105                 :    8602513 :             _kv_ins_item_free(kv_item);
    1106                 :            :         }
    1107                 :            :     }
    1108                 :            : 
    1109         [ +  + ]:    8548583 :     if (_is_update) {
    1110                 :     505632 :         return BTREE_RESULT_UPDATE;
    1111                 :            :     }else{
    1112                 :    8548583 :         return BTREE_RESULT_SUCCESS;
    1113                 :            :     }
    1114                 :            : }
    1115                 :            : 
    1116                 :         16 : btree_result btree_remove(struct btree *btree, void *key)
    1117                 :            : {
    1118                 :            :     void *addr;
    1119                 :         16 :     uint8_t *k = alca(uint8_t, btree->ksize);
    1120                 :         16 :     uint8_t *v= alca(uint8_t, btree->vsize);
    1121                 :         16 :     uint8_t *kk = alca(uint8_t, btree->ksize);
    1122                 :         16 :     uint8_t *vv = alca(uint8_t, btree->vsize);
    1123                 :            :     // index# and block ID for each level
    1124                 :         16 :     idx_t *idx = alca(idx_t, btree->height);
    1125                 :         16 :     bid_t *bid= alca(bid_t, btree->height);
    1126                 :            :     bid_t _bid;
    1127                 :            :     // flags
    1128                 :         16 :     int8_t *modified = alca(int8_t, btree->height);
    1129                 :         16 :     int8_t *moved = alca(int8_t, btree->height);
    1130                 :         16 :     int8_t *rmv = alca(int8_t, btree->height);
    1131                 :            :     // index# of removed key
    1132                 :         16 :     idx_t *idx_rmv = alca(idx_t, btree->height);
    1133                 :         16 :     struct bnode **node = alca(struct bnode *, btree->height);
    1134                 :            :     int i;
    1135                 :            : 
    1136                 :            :     // initialize flags
    1137         [ +  + ]:         32 :     for (i=0;i<btree->height;++i) {
    1138                 :         16 :         moved[i] = modified[i] = rmv[i] = 0;
    1139                 :            :     }
    1140         [ +  - ]:         16 :     if (btree->kv_ops->init_kv_var) {
    1141                 :         16 :         btree->kv_ops->init_kv_var(btree, k, v);
    1142                 :         16 :         btree->kv_ops->init_kv_var(btree, kk, vv);
    1143                 :            :     }
    1144                 :            : 
    1145                 :         16 :     rmv[0] = 1;
    1146                 :            : 
    1147                 :            :     // set root
    1148                 :         16 :     bid[btree->height-1] = btree->root_bid;
    1149                 :            : 
    1150                 :            :     // find path from root to leaf
    1151         [ +  + ]:         32 :     for (i=btree->height-1; i>=0; --i) {
    1152                 :            :         // read block using bid
    1153                 :         16 :         addr = btree->blk_ops->blk_read(btree->blk_handle, bid[i]);
    1154                 :            :         // fetch node structure from block
    1155                 :         16 :         node[i] = _fetch_bnode(btree, addr, i+1);
    1156                 :            : 
    1157                 :            :         // lookup key in current node
    1158                 :         16 :         idx[i] = _btree_find_entry(btree, node[i], key);
    1159                 :            : 
    1160         [ -  + ]:         16 :         if (idx[i] == BTREE_IDX_NOT_FOUND) {
    1161                 :            :             // not found
    1162         [ #  # ]:          0 :             if (btree->blk_ops->blk_operation_end)
    1163                 :          0 :                 btree->blk_ops->blk_operation_end(btree->blk_handle);
    1164         [ #  # ]:          0 :             if (btree->kv_ops->free_kv_var) {
    1165                 :          0 :                 btree->kv_ops->free_kv_var(btree, k, v);
    1166                 :          0 :                 btree->kv_ops->free_kv_var(btree, kk, vv);
    1167                 :            :             }
    1168                 :          0 :             return BTREE_RESULT_FAIL;
    1169                 :            :         }
    1170                 :            : 
    1171                 :         16 :         btree->kv_ops->get_kv(node[i], idx[i], k, v);
    1172                 :            : 
    1173         [ -  + ]:         16 :         if (i>0) {
    1174                 :            :             // index (non-leaf) node
    1175                 :            :             // get bid of child node from value
    1176                 :          0 :             bid[i-1] = btree->kv_ops->value2bid(v);
    1177                 :          0 :             bid[i-1] = _endian_decode(bid[i-1]);
    1178                 :            :         }else{
    1179                 :            :             // leaf node
    1180                 :            :         }
    1181                 :            :     }
    1182                 :            : 
    1183                 :            :     // cascaded remove from leaf to root
    1184         [ +  + ]:         32 :     for (i=0;i<btree->height;++i){
    1185                 :            :         // in case of index node
    1186         [ -  + ]:         16 :         if (i > 0) {
    1187                 :          0 :             btree->kv_ops->get_kv(node[i], idx[i], k, v);
    1188                 :            : 
    1189                 :            :             // when child node's smallest key is changed due to remove
    1190         [ #  # ]:          0 :               if (node[i-1]->nentry > 0) {
    1191                 :          0 :                 btree->kv_ops->get_kv(node[i-1], 0, kk, vv);
    1192         [ #  # ]:          0 :                 if (btree->kv_ops->cmp(kk, k, btree->aux)) {
    1193                 :            :                     // change current node's corresponding key
    1194                 :          0 :                     btree->kv_ops->set_kv(node[i], idx[i], kk, v);
    1195                 :            :                     //memcpy(k, kk, btree->ksize);
    1196                 :          0 :                     btree->kv_ops->set_key(btree, k, kk);
    1197                 :          0 :                     modified[i] = 1;
    1198                 :            :                 }
    1199                 :            :             }
    1200                 :            : 
    1201                 :            :             // when child node is moved to new block
    1202         [ #  # ]:          0 :             if (moved[i-1]) {
    1203                 :            :                 // replace the bid (value)
    1204                 :          0 :                 _bid = _endian_encode(bid[i-1]);
    1205                 :          0 :                 btree->kv_ops->set_kv(node[i], idx[i], k,
    1206                 :          0 :                                       btree->kv_ops->bid2value(&_bid));
    1207                 :          0 :                 modified[i] = 1;
    1208                 :            :             }
    1209                 :            :         }
    1210                 :            : 
    1211         [ +  - ]:         16 :         if (rmv[i]) {
    1212                 :            :             // there is a key-value pair to be removed
    1213                 :         16 :             btree->kv_ops->get_kv(node[i], idx[i], k, v);
    1214                 :         16 :             idx_rmv[i] = _btree_remove_entry(btree, node[i], k);
    1215                 :         16 :             modified[i] = 1;
    1216                 :            : 
    1217                 :            :             /*
    1218                 :            :             remove the node when
    1219                 :            :             1. non-root node has no kv-pair or
    1220                 :            :             2. root node has less or equal than one kv-pair
    1221                 :            :             */
    1222 [ +  + ][ +  - ]:         16 :             if (((node[i]->nentry < 1 && i+1 < btree->height) ||
         [ +  + ][ +  - ]
                 [ -  + ]
    1223                 :         16 :                 (node[i]->nentry <= 1 && i+1 == btree->height)) &&
    1224                 :            :                 btree->height > 1) {
    1225                 :            :                 // remove the node
    1226                 :          0 :                 btree->blk_ops->blk_remove(btree->blk_handle, bid[i]);
    1227         [ #  # ]:          0 :                 if (i+1 < btree->height) {
    1228                 :            :                     // if non-root node
    1229                 :          0 :                     rmv[i+1] = 1;
    1230                 :            :                 }else{
    1231                 :            :                     // if root node
    1232                 :          0 :                     btree->height--;
    1233                 :          0 :                     btree->kv_ops->get_kv(node[i], 0, k, v);
    1234                 :          0 :                     btree->root_bid = btree->kv_ops->value2bid(v);
    1235                 :          0 :                     btree->root_bid = _endian_decode(btree->root_bid);
    1236                 :            :                 }
    1237                 :            :             }
    1238                 :            :         }
    1239                 :            : 
    1240         [ +  - ]:         16 :         if (modified[i]) {
    1241                 :            :             // when node is modified
    1242         [ +  + ]:         16 :             if (!btree->blk_ops->blk_is_writable(btree->blk_handle, bid[i])) {
    1243                 :            :                 // already flushed block -> cannot overwrite, so
    1244                 :            :                 // we have to move to new block
    1245                 :            :                 // get new bid[i]
    1246                 :         11 :                 addr = btree->blk_ops->blk_move(btree->blk_handle, bid[i],
    1247                 :         11 :                                                 &bid[i]);
    1248                 :         11 :                 node[i] = _fetch_bnode(btree, addr, i+1);
    1249                 :         11 :                 moved[i] = 1;
    1250                 :            : 
    1251         [ +  - ]:         11 :                 if (i+1 == btree->height)
    1252                 :            :                     // if moved node is root node
    1253                 :         11 :                     btree->root_bid = bid[i];
    1254                 :            : 
    1255                 :            :             }else{
    1256                 :          5 :                 btree->blk_ops->blk_set_dirty(btree->blk_handle, bid[i]);
    1257                 :            :             }
    1258                 :            : 
    1259                 :            :         }
    1260                 :            :     }
    1261                 :            : 
    1262         [ -  + ]:         16 :     if (btree->blk_ops->blk_operation_end) {
    1263                 :          0 :         btree->blk_ops->blk_operation_end(btree->blk_handle);
    1264                 :            :     }
    1265         [ +  + ]:         16 :     if (btree->kv_ops->free_kv_var) {
    1266                 :          1 :         btree->kv_ops->free_kv_var(btree, k, v);
    1267                 :          1 :         btree->kv_ops->free_kv_var(btree, kk, vv);
    1268                 :            :     }
    1269                 :         16 :     return BTREE_RESULT_SUCCESS;
    1270                 :            : }
    1271                 :            : 
    1272                 :          0 : btree_result btree_operation_end(struct btree *btree)
    1273                 :            : {
    1274         [ #  # ]:          0 :     if (btree->blk_ops->blk_operation_end) {
    1275                 :          0 :         btree->blk_ops->blk_operation_end(btree->blk_handle);
    1276                 :            :     }
    1277                 :          0 :     return BTREE_RESULT_SUCCESS;
    1278                 :            : }
    1279                 :            : 
    1280                 :      15783 : btree_result btree_iterator_init(struct btree *btree,
    1281                 :            :                                  struct btree_iterator *it, void *initial_key)
    1282                 :            : {
    1283                 :            :     int i;
    1284                 :            : 
    1285                 :      15783 :     it->btree = *btree;
    1286                 :      15783 :     it->curkey = (void *)mempool_alloc(btree->ksize);
    1287         [ +  - ]:      15783 :     if (btree->kv_ops->init_kv_var) {
    1288                 :      15783 :         btree->kv_ops->init_kv_var(btree, it->curkey, NULL);
    1289                 :            :     }
    1290         [ +  + ]:      15783 :     if (initial_key) {
    1291                 :            :         // set initial key if exists
    1292                 :            :         //memcpy(it->curkey, initial_key, btree->ksize);
    1293                 :      11886 :         btree->kv_ops->set_key(btree, it->curkey, initial_key);
    1294                 :            :     }else{
    1295                 :            :         // NULL initial key .. set minimum key (start from leftmost key)
    1296                 :            :         // replaced by kv_ops->init_kv_var
    1297                 :            :         //memset(it->curkey, 0, btree->ksize);
    1298                 :            :     }
    1299                 :      15783 :     it->bid = (bid_t*)mempool_alloc(sizeof(bid_t) * btree->height);
    1300                 :      15783 :     it->idx = (idx_t*)mempool_alloc(sizeof(idx_t) * btree->height);
    1301                 :            :     it->node = (struct bnode **)mempool_alloc(sizeof(struct bnode *)
    1302                 :      15783 :                                                               * btree->height);
    1303                 :      15783 :     it->addr = (void**)mempool_alloc(sizeof(void*) * btree->height);
    1304                 :            : 
    1305         [ +  + ]:      31671 :     for (i=0;i<btree->height;++i){
    1306                 :      15888 :         it->bid[i] = BTREE_BLK_NOT_FOUND;
    1307                 :      15888 :         it->idx[i] = BTREE_IDX_NOT_FOUND;
    1308                 :      15888 :         it->node[i] = NULL;
    1309                 :      15888 :         it->addr[i] = NULL;
    1310                 :            :     }
    1311                 :      15783 :     it->bid[btree->height-1] = btree->root_bid;
    1312                 :      15783 :     it->flags = 0;
    1313                 :            : 
    1314                 :      15783 :     return BTREE_RESULT_SUCCESS;
    1315                 :            : }
    1316                 :            : 
    1317                 :      15783 : btree_result btree_iterator_free(struct btree_iterator *it)
    1318                 :            : {
    1319                 :            :     int i;
    1320         [ +  + ]:      15783 :     if (it->btree.kv_ops->free_kv_var) {
    1321                 :         35 :         it->btree.kv_ops->free_kv_var(&it->btree, it->curkey, NULL);
    1322                 :            :     }
    1323                 :      15783 :     mempool_free(it->curkey);
    1324                 :      15783 :     mempool_free(it->bid);
    1325                 :      15783 :     mempool_free(it->idx);
    1326         [ +  + ]:      31671 :     for (i=0;i<it->btree.height;++i){
    1327         [ +  + ]:      15888 :         if (it->node[i]) mempool_free(it->addr[i]);
    1328                 :            :     }
    1329                 :      15783 :     mempool_free(it->node);
    1330                 :      15783 :     mempool_free(it->addr);
    1331                 :      15783 :     return BTREE_RESULT_SUCCESS;
    1332                 :            : }
    1333                 :            : 
    1334                 :      33641 : btree_result _btree_prev(struct btree_iterator *it, void *key_buf,
    1335                 :            :                          void *value_buf, int depth)
    1336                 :            : {
    1337                 :            :     struct btree *btree;
    1338                 :      33641 :     btree = &it->btree;
    1339                 :            :     int i;
    1340                 :      33641 :     uint8_t *k = alca(uint8_t, btree->ksize);
    1341                 :      33641 :     uint8_t *v = alca(uint8_t, btree->vsize);
    1342                 :            :     void *addr;
    1343                 :            :     struct bnode *node;
    1344                 :            :     btree_result r;
    1345                 :            : 
    1346         [ +  - ]:      33641 :     if (it->btree.kv_ops->init_kv_var) {
    1347                 :      33641 :         it->btree.kv_ops->init_kv_var(&it->btree, k, v);
    1348                 :            :     }
    1349                 :            : 
    1350         [ +  + ]:      33641 :     if (it->node[depth] == NULL){
    1351                 :            :         size_t blksize;
    1352                 :       6620 :         addr = btree->blk_ops->blk_read(btree->blk_handle, it->bid[depth]);
    1353                 :       6620 :         it->addr[depth] = (void *)mempool_alloc(btree->blksize);
    1354                 :            :         blksize = btree->blk_ops->blk_get_size(btree->blk_handle,
    1355                 :       6620 :                                                it->bid[depth]);
    1356                 :       6620 :         memcpy(it->addr[depth], addr, blksize);
    1357                 :       6620 :         it->node[depth] = _fetch_bnode(&it->btree, it->addr[depth], depth+1);
    1358                 :            :     }
    1359                 :      33641 :     node = _fetch_bnode(&it->btree, it->addr[depth], depth+1);
    1360                 :            :     //assert(node->level == depth+1);
    1361                 :            : 
    1362         [ -  + ]:      33641 :     if (node->nentry <= 0) {
    1363         [ #  # ]:          0 :         if (it->btree.kv_ops->free_kv_var) {
    1364                 :          0 :             it->btree.kv_ops->free_kv_var(&it->btree, k, v);
    1365                 :            :         }
    1366         [ #  # ]:          0 :         if (it->node[depth] != NULL) mempool_free(it->addr[depth]);
    1367                 :          0 :         it->node[depth] = NULL;
    1368                 :          0 :         it->addr[depth] = NULL;
    1369                 :          0 :         return BTREE_RESULT_FAIL;
    1370                 :            :     }
    1371                 :            : 
    1372         [ +  + ]:      33641 :     if (it->idx[depth] == BTREE_IDX_NOT_FOUND) {
    1373                 :            :         // curkey: lastly returned key
    1374                 :       6620 :         it->idx[depth] = _btree_find_entry(btree, node, it->curkey);
    1375         [ +  + ]:       6620 :         if (it->idx[depth] == BTREE_IDX_NOT_FOUND) {
    1376                 :         38 :             it->idx[depth] = 0;
    1377                 :            :            // it->idx[depth] = node->nentry - 1;
    1378                 :            :         }
    1379                 :       6620 :         btree->kv_ops->get_kv(node, it->idx[depth], key_buf, value_buf);
    1380 [ +  + ][ +  + ]:       6620 :         if (btree->kv_ops->cmp(it->curkey, key_buf, btree->aux) < 0 &&
                 [ +  + ]
    1381                 :            :             depth == 0) {
    1382                 :            :             // in leaf node, prev key must be smaller than current key
    1383                 :         37 :             it->idx[depth] = it->idx[depth] ? it->idx[depth] - 1
    1384         [ -  + ]:         37 :                                             : BTREE_IDX_NOT_FOUND;
    1385                 :            :         } // else return the value at idx[depth] at this turn
    1386                 :            :     }
    1387                 :            : 
    1388 [ +  + ][ +  + ]:      33641 :     if (BTREE_ITR_IS_FWD(it) && depth ==0) {
    1389         [ +  + ]:       2401 :         if (it->idx[depth] >= 2) {
    1390                 :       1953 :             it->idx[depth] -= 2;
    1391                 :            :         } else {
    1392                 :            :             // out-of-bounds
    1393                 :        448 :             it->idx[depth] = node->nentry; // ending condition
    1394                 :            :             // we have to reset flag because _btree_prev will recursively
    1395                 :            :             // visit the left leaf node.
    1396                 :        448 :             BTREE_ITR_SET_NONE(it);
    1397                 :            :         }
    1398                 :            :     }
    1399                 :            : 
    1400         [ +  + ]:      33641 :     if (it->idx[depth] >= node->nentry) { // reused nentry for ending iteration
    1401                 :            :         // out of bound .. go up to parent node
    1402                 :       4764 :         it->idx[depth] = BTREE_IDX_NOT_FOUND; // reset for btree_next
    1403         [ +  - ]:       4764 :         if (it->node[depth] != NULL) mempool_free(it->addr[depth]);
    1404                 :       4764 :         it->node[depth] = NULL;
    1405                 :       4764 :         it->addr[depth] = NULL;
    1406                 :            : 
    1407         [ +  + ]:       4764 :         if (it->btree.kv_ops->free_kv_var) {
    1408                 :          2 :             it->btree.kv_ops->free_kv_var(&it->btree, k, v);
    1409                 :            :         }
    1410                 :       4764 :         return BTREE_RESULT_FAIL;
    1411                 :            :     }
    1412                 :            : 
    1413         [ +  + ]:      28877 :     if (depth > 0) {
    1414                 :            :         // index node
    1415         [ +  + ]:       1073 :         if (it->node[depth-1] == NULL) {
    1416                 :          4 :             btree->kv_ops->get_kv(node, it->idx[depth], k, v);
    1417                 :          4 :             it->bid[depth-1] = btree->kv_ops->value2bid(v);
    1418                 :          4 :             it->bid[depth-1] = _endian_decode(it->bid[depth-1]);
    1419                 :            :         }
    1420                 :       1073 :         r = _btree_prev(it, key_buf, value_buf, depth-1);
    1421                 :            : 
    1422         [ +  + ]:       1073 :         if (r == BTREE_RESULT_FAIL) {
    1423                 :            :             // move index to left
    1424                 :         31 :             it->idx[depth] = it->idx[depth] ? it->idx[depth] - 1
    1425         [ +  + ]:         18 :                                             : node->nentry; // ending condition
    1426                 :            : 
    1427         [ +  + ]:         18 :             if (it->idx[depth] >= node->nentry){
    1428                 :            :                 // out of bound .. go up to parent node
    1429                 :          5 :                 it->idx[depth] = BTREE_IDX_NOT_FOUND;
    1430         [ +  - ]:          5 :                 if (it->node[depth] != NULL) mempool_free(it->addr[depth]);
    1431                 :          5 :                 it->node[depth] = NULL;
    1432                 :          5 :                 it->addr[depth] = NULL;
    1433                 :            : 
    1434         [ -  + ]:          5 :                 if (it->btree.kv_ops->free_kv_var) {
    1435                 :          0 :                     it->btree.kv_ops->free_kv_var(&it->btree, k, v);
    1436                 :            :                 }
    1437                 :          5 :                 return BTREE_RESULT_FAIL;
    1438                 :            :             }else{
    1439                 :         13 :                 btree->kv_ops->get_kv(node, it->idx[depth], k, v);
    1440                 :         13 :                 it->bid[depth-1] = btree->kv_ops->value2bid(v);
    1441                 :         13 :                 it->bid[depth-1] = _endian_decode(it->bid[depth-1]);
    1442                 :            :                 // reset child index
    1443         [ +  + ]:         26 :                 for (i=depth-1; i>=0; --i) {
    1444                 :         13 :                     it->idx[i] = BTREE_IDX_NOT_FOUND;
    1445         [ -  + ]:         13 :                     if (it->node[i] != NULL) mempool_free(it->addr[i]);
    1446                 :         13 :                     it->node[i] = NULL;
    1447                 :         13 :                     it->addr[i] = NULL;
    1448                 :            :                 }
    1449                 :            :                 // retry
    1450                 :         13 :                 r = _btree_prev(it, key_buf, value_buf, depth-1);
    1451                 :            :             }
    1452                 :            :         }
    1453         [ -  + ]:       1068 :         if (it->btree.kv_ops->free_kv_var) {
    1454                 :          0 :             it->btree.kv_ops->free_kv_var(&it->btree, k, v);
    1455                 :            :         }
    1456                 :       1068 :         return r;
    1457                 :            :     }else{
    1458                 :            :         // leaf node
    1459                 :      27804 :         btree->kv_ops->get_kv(node, it->idx[depth], key_buf, value_buf);
    1460                 :            :         //memcpy(it->curkey, key_buf, btree->ksize);
    1461                 :      27804 :         btree->kv_ops->set_key(btree, it->curkey, key_buf);
    1462                 :      49221 :         it->idx[depth] = it->idx[depth] ? it->idx[depth] - 1
    1463         [ +  + ]:      27804 :                                         : node->nentry; // condition for ending
    1464         [ +  + ]:      27804 :         if (it->btree.kv_ops->free_kv_var) {
    1465                 :         51 :             it->btree.kv_ops->free_kv_var(&it->btree, k, v);
    1466                 :            :         }
    1467                 :      33641 :         return BTREE_RESULT_SUCCESS;
    1468                 :            :     }
    1469                 :            : }
    1470                 :            : 
    1471                 :      32555 : btree_result btree_prev(struct btree_iterator *it, void *key_buf,
    1472                 :            :                         void *value_buf)
    1473                 :            : {
    1474                 :      32555 :     btree_result br = _btree_prev(it, key_buf, value_buf, it->btree.height-1);
    1475         [ +  + ]:      32555 :     if (br == BTREE_RESULT_SUCCESS) {
    1476                 :      27804 :         BTREE_ITR_SET_REV(it);
    1477                 :            :     } else {
    1478                 :       4751 :         BTREE_ITR_SET_NONE(it);
    1479                 :            :     }
    1480                 :      32555 :     return br;
    1481                 :            : }
    1482                 :            : 
    1483                 :    6132666 : btree_result _btree_next(struct btree_iterator *it, void *key_buf,
    1484                 :            :                          void *value_buf, int depth)
    1485                 :            : {
    1486                 :            :     struct btree *btree;
    1487                 :    6132666 :     btree = &it->btree;
    1488                 :            :     int i;
    1489                 :    6132666 :     uint8_t *k = alca(uint8_t, btree->ksize);
    1490                 :    6132666 :     uint8_t *v = alca(uint8_t, btree->vsize);
    1491                 :            :     void *addr;
    1492                 :            :     struct bnode *node;
    1493                 :            :     btree_result r;
    1494                 :            : 
    1495         [ +  - ]:    6132666 :     if (it->btree.kv_ops->init_kv_var) {
    1496                 :    6132815 :         it->btree.kv_ops->init_kv_var(&it->btree, k, v);
    1497                 :            :     }
    1498                 :            : 
    1499         [ +  + ]:    6132606 :     if (it->node[depth] == NULL){
    1500                 :            :         size_t blksize;
    1501                 :      21333 :         addr = btree->blk_ops->blk_read(btree->blk_handle, it->bid[depth]);
    1502                 :      21333 :         it->addr[depth] = (void *)mempool_alloc(btree->blksize);
    1503                 :            :         blksize = btree->blk_ops->blk_get_size(btree->blk_handle,
    1504                 :      21333 :                                                it->bid[depth]);
    1505                 :      21333 :         memcpy(it->addr[depth], addr, blksize);
    1506                 :      21333 :         it->node[depth] = _fetch_bnode(&it->btree, it->addr[depth], depth+1);
    1507                 :            :     }
    1508                 :    6132606 :     node = _fetch_bnode(&it->btree, it->addr[depth], depth+1);
    1509                 :            :     //assert(node->level == depth+1);
    1510                 :            : 
    1511         [ -  + ]:    6133129 :     if (node->nentry <= 0) {
    1512         [ #  # ]:          0 :         if (it->btree.kv_ops->free_kv_var) it->btree.kv_ops->free_kv_var(
    1513                 :          0 :                                                              &it->btree, k, v);
    1514         [ #  # ]:          0 :         if (it->node[depth] != NULL) mempool_free(it->addr[depth]);
    1515                 :          0 :         it->node[depth] = NULL;
    1516                 :          0 :         it->addr[depth] = NULL;
    1517                 :          0 :         return BTREE_RESULT_FAIL;
    1518                 :            :     }
    1519                 :            : 
    1520         [ +  + ]:    6133129 :     if (it->idx[depth] == BTREE_IDX_NOT_FOUND) {
    1521                 :            :         // curkey: lastly returned key
    1522                 :       9281 :         it->idx[depth] = _btree_find_entry(btree, node, it->curkey);
    1523         [ +  + ]:       9281 :         if (it->idx[depth] == BTREE_IDX_NOT_FOUND) {
    1524                 :       2222 :             it->idx[depth] = 0;
    1525                 :            :         }
    1526                 :       9281 :         btree->kv_ops->get_kv(node, it->idx[depth], key_buf, value_buf);
    1527 [ +  + ][ +  + ]:       9281 :         if (btree->kv_ops->cmp(it->curkey, key_buf, btree->aux) > 0 &&
                 [ +  + ]
    1528                 :            :             depth == 0) {
    1529                 :            :             // in leaf node, next key must be larger than previous key
    1530                 :            :             // (i.e. it->curkey)
    1531                 :       1182 :             it->idx[depth]++;
    1532                 :            :         }
    1533                 :            :     }
    1534                 :            : 
    1535 [ +  + ][ +  + ]:    6133129 :     if (BTREE_ITR_IS_REV(it) && depth == 0) {
    1536         [ +  + ]:       1932 :         if (it->idx[depth] >= node->nentry) {
    1537                 :            :             // 'idx' becomes out-of-bounds by previous btree_prev() call.
    1538                 :            :             // this means that the last returned entry was the smallest entry.
    1539                 :            :             // set idx to the second smallest entry.
    1540                 :        400 :             it->idx[depth] = 1;
    1541                 :            :         } else {
    1542                 :       1532 :             it->idx[depth] += 2;
    1543                 :            :         }
    1544                 :            :     }
    1545                 :            : 
    1546         [ +  + ]:    6133129 :     if (it->idx[depth] >= node->nentry) {
    1547                 :            :         // out of bound .. go up to parent node
    1548                 :      17108 :         it->idx[depth] = BTREE_IDX_NOT_FOUND; // reset for btree_prev
    1549         [ +  - ]:      17108 :         if (it->node[depth] != NULL) mempool_free(it->addr[depth]);
    1550                 :      17108 :         it->node[depth] = NULL;
    1551                 :      17108 :         it->addr[depth] = NULL;
    1552                 :            : 
    1553         [ +  + ]:      17108 :         if (it->btree.kv_ops->free_kv_var) {
    1554                 :         73 :             it->btree.kv_ops->free_kv_var(&it->btree, k, v);
    1555                 :            :         }
    1556                 :      17108 :         return BTREE_RESULT_FAIL;
    1557                 :            :     }
    1558                 :            : 
    1559         [ +  + ]:    6116021 :     if (depth > 0) {
    1560                 :            :         // index node
    1561         [ +  + ]:    4021349 :         if (it->node[depth-1] == NULL) {
    1562                 :        157 :             btree->kv_ops->get_kv(node, it->idx[depth], k, v);
    1563                 :        157 :             it->bid[depth-1] = btree->kv_ops->value2bid(v);
    1564                 :        157 :             it->bid[depth-1] = _endian_decode(it->bid[depth-1]);
    1565                 :            :         }
    1566                 :    4021349 :         r = _btree_next(it, key_buf, value_buf, depth-1);
    1567                 :            : 
    1568         [ +  + ]:    4021253 :         if (r == BTREE_RESULT_FAIL) {
    1569                 :            :             // move index to right
    1570                 :      12148 :             it->idx[depth]++;
    1571                 :            : 
    1572         [ +  + ]:      12148 :             if (it->idx[depth] >= node->nentry){
    1573                 :            :                 // out of bound .. go up to parent node
    1574                 :        152 :                 it->idx[depth] = BTREE_IDX_NOT_FOUND;
    1575         [ +  - ]:        152 :                 if (it->node[depth] != NULL) mempool_free(it->addr[depth]);
    1576                 :        152 :                 it->node[depth] = NULL;
    1577                 :        152 :                 it->addr[depth] = NULL;
    1578                 :            : 
    1579         [ +  + ]:        152 :                 if (it->btree.kv_ops->free_kv_var) {
    1580                 :          6 :                     it->btree.kv_ops->free_kv_var(&it->btree, k, v);
    1581                 :            :                 }
    1582                 :        152 :                 return BTREE_RESULT_FAIL;
    1583                 :            :             }else{
    1584                 :      11996 :                 btree->kv_ops->get_kv(node, it->idx[depth], k, v);
    1585                 :      11996 :                 it->bid[depth-1] = btree->kv_ops->value2bid(v);
    1586                 :      11996 :                 it->bid[depth-1] = _endian_decode(it->bid[depth-1]);
    1587                 :            :                 // reset child index
    1588         [ +  + ]:      24048 :                 for (i=depth-1; i>=0; --i) {
    1589                 :      12052 :                     it->idx[i] = 0;
    1590         [ -  + ]:      12052 :                     if (it->node[i] != NULL) mempool_free(it->addr[i]);
    1591                 :      12052 :                     it->node[i] = NULL;
    1592                 :      12052 :                     it->addr[i] = NULL;
    1593                 :            :                 }
    1594                 :            :                 // retry
    1595                 :      11996 :                 r = _btree_next(it, key_buf, value_buf, depth-1);
    1596                 :            :             }
    1597                 :            :         }
    1598         [ +  + ]:    4021101 :         if (it->btree.kv_ops->free_kv_var) {
    1599                 :       4019 :             it->btree.kv_ops->free_kv_var(&it->btree, k, v);
    1600                 :            :         }
    1601                 :    4021275 :         return r;
    1602                 :            :     }else{
    1603                 :            :         // leaf node
    1604                 :    2094672 :         btree->kv_ops->get_kv(node, it->idx[depth], key_buf, value_buf);
    1605                 :            :         //memcpy(it->curkey, key_buf, btree->ksize);
    1606                 :    2094661 :         btree->kv_ops->set_key(btree, it->curkey, key_buf);
    1607                 :    2094640 :         it->idx[depth]++;
    1608         [ +  + ]:    2094640 :         if (it->btree.kv_ops->free_kv_var) {
    1609                 :       4441 :             it->btree.kv_ops->free_kv_var(&it->btree, k, v);
    1610                 :            :         }
    1611                 :    6133178 :         return BTREE_RESULT_SUCCESS;
    1612                 :            :     }
    1613                 :            : }
    1614                 :            : 
    1615                 :    2099802 : btree_result btree_next(struct btree_iterator *it, void *key_buf,
    1616                 :            :                         void *value_buf)
    1617                 :            : {
    1618                 :    2099802 :     btree_result br = _btree_next(it, key_buf, value_buf, it->btree.height-1);
    1619         [ +  + ]:    2099596 :     if (br == BTREE_RESULT_SUCCESS) {
    1620                 :    2094484 :         BTREE_ITR_SET_FWD(it);
    1621                 :            :     } else {
    1622                 :       5112 :         BTREE_ITR_SET_NONE(it);
    1623                 :            :     }
    1624                 :    2099596 :     return br;
    1625                 :            : }
    1626                 :            : 

Generated by: LCOV version 1.11