@@ -2284,6 +2284,14 @@ fdb_status _fdb_open(fdb_kvs_handle *handle,
22842284 }
22852285 }
22862286
2287+ if (config->bottom_up_index_build ) {
2288+ handle->bottom_up_build_entries = (struct list *)malloc (sizeof (struct list ));
2289+ list_init (handle->bottom_up_build_entries );
2290+ handle->num_bottom_up_build_entries = 0 ;
2291+ } else {
2292+ handle->bottom_up_build_entries = NULL ;
2293+ }
2294+
22872295 return status;
22882296}
22892297
@@ -4250,29 +4258,47 @@ fdb_status fdb_set(fdb_kvs_handle *handle, fdb_doc *doc)
42504258 if (!txn) {
42514259 txn = &file->global_txn ;
42524260 }
4253- if (handle->kvs ) {
4254- // multi KV instance mode
4255- fdb_doc kv_ins_doc = *doc;
4256- kv_ins_doc.key = _doc.key ;
4257- kv_ins_doc.keylen = _doc.length .keylen ;
4258- if (!immediate_remove) {
4259- wal_insert (txn, file, &cmp_info, &kv_ins_doc, offset,
4260- WAL_INS_WRITER);
4261- } else {
4262- wal_immediate_remove (txn, file, &cmp_info, &kv_ins_doc, offset,
4263- WAL_INS_WRITER);
4264- }
4261+
4262+ if (handle->config .bottom_up_index_build ) {
4263+ // Bottom-up build mode, bypass WAL.
4264+ struct bottom_up_build_entry * bub_entry =
4265+ (struct bottom_up_build_entry *)
4266+ malloc (sizeof (struct bottom_up_build_entry ));
4267+ bub_entry->keylen = _doc.length .keylen ;
4268+ bub_entry->key = (void *)malloc (_doc.length .keylen );
4269+ memcpy (bub_entry->key , _doc.key , _doc.length .keylen );
4270+ bub_entry->seqnum = doc->seqnum ;
4271+ bub_entry->offset = doc->offset ;
4272+
4273+ fdb_kvs_handle* root_handle = handle->fhandle ->root ;
4274+ list_push_back (root_handle->bottom_up_build_entries , &bub_entry->le );
4275+ root_handle->num_bottom_up_build_entries ++;
4276+
42654277 } else {
4266- if (!immediate_remove) {
4267- wal_insert (txn, file, &cmp_info, doc, offset, WAL_INS_WRITER);
4278+ if (handle->kvs ) {
4279+ // multi KV instance mode
4280+ fdb_doc kv_ins_doc = *doc;
4281+ kv_ins_doc.key = _doc.key ;
4282+ kv_ins_doc.keylen = _doc.length .keylen ;
4283+ if (!immediate_remove) {
4284+ wal_insert (txn, file, &cmp_info, &kv_ins_doc, offset,
4285+ WAL_INS_WRITER);
4286+ } else {
4287+ wal_immediate_remove (txn, file, &cmp_info, &kv_ins_doc, offset,
4288+ WAL_INS_WRITER);
4289+ }
42684290 } else {
4269- wal_immediate_remove (txn, file, &cmp_info, doc, offset,
4270- WAL_INS_WRITER);
4291+ if (!immediate_remove) {
4292+ wal_insert (txn, file, &cmp_info, doc, offset, WAL_INS_WRITER);
4293+ } else {
4294+ wal_immediate_remove (txn, file, &cmp_info, doc, offset,
4295+ WAL_INS_WRITER);
4296+ }
42714297 }
4272- }
42734298
4274- if (wal_get_dirty_status (file)== FDB_WAL_CLEAN) {
4275- wal_set_dirty_status (file, FDB_WAL_DIRTY);
4299+ if (wal_get_dirty_status (file)== FDB_WAL_CLEAN) {
4300+ wal_set_dirty_status (file, FDB_WAL_DIRTY);
4301+ }
42764302 }
42774303
42784304 if (handle->config .auto_commit &&
@@ -4648,11 +4674,11 @@ fdb_status fdb_commit_non_durable(fdb_file_handle *fhandle,
46484674
46494675void * _fdb_bottom_up_index_build_next (void * cur_entry, void * aux) {
46504676 if (!cur_entry) {
4651- struct avl_tree * tree = (struct avl_tree *)aux;
4652- return avl_first (tree );
4677+ struct list * ll = (struct list *)aux;
4678+ return list_begin (ll );
46534679 }
4654- struct avl_node * an = (struct avl_node *)cur_entry;
4655- return avl_next (an );
4680+ struct list_elem * le = (struct list_elem *)cur_entry;
4681+ return list_next (le );
46564682}
46574683
46584684void _fdb_bottom_up_index_build_get (void * cur_entry,
@@ -4661,15 +4687,13 @@ void _fdb_bottom_up_index_build_get(void* cur_entry,
46614687 void ** value_out,
46624688 void * aux)
46634689{
4664- struct wal_item_header * header =
4665- _get_entry (cur_entry, struct wal_item_header , avl_key );
4666- *key_out = header ->key ;
4667- *keylen_out = header ->keylen ;
4690+ struct bottom_up_build_entry * entry =
4691+ _get_entry (cur_entry, struct bottom_up_build_entry , le );
4692+ *key_out = entry ->key ;
4693+ *keylen_out = entry ->keylen ;
46684694
46694695 thread_local uint64_t enc_bid;
4670- struct list_elem * le = list_begin (&header->items );
4671- struct wal_item * first_item = _get_entry (le, struct wal_item , list_elem);
4672- enc_bid = _endian_encode (first_item->offset );
4696+ enc_bid = _endian_encode (entry->offset );
46734697 *value_out = &enc_bid;
46744698}
46754699
@@ -4683,27 +4707,23 @@ void _fdb_bottom_up_index_build_get_seq(void* cur_entry,
46834707 void ** value_out,
46844708 void * aux)
46854709{
4686- struct wal_item * elem =
4687- _get_entry (cur_entry, struct wal_item , avl_seq );
4710+ struct bottom_up_build_entry * entry =
4711+ _get_entry (cur_entry, struct bottom_up_build_entry , le );
46884712 thread_local uint64_t enc_seq;
4689- enc_seq = _endian_encode (elem ->seqnum );
4713+ enc_seq = _endian_encode (entry ->seqnum );
46904714 *key_out = &enc_seq;
46914715 *keylen_out = sizeof (enc_seq);
46924716
46934717 thread_local uint64_t enc_bid;
4694- enc_bid = _endian_encode (elem ->offset );
4718+ enc_bid = _endian_encode (entry ->offset );
46954719 *value_out = &enc_bid;
46964720}
46974721
46984722fdb_status _fdb_bottom_up_index_build (fdb_kvs_handle *handle)
46994723{
47004724 fdb_status fs = FDB_RESULT_SUCCESS;
47014725
4702- uint64_t num_entries = handle->file ->wal ->num_flushable ;
4703- struct avl_tree * avl_key = &handle->file ->wal ->key_shards [0 ]._map ;
4704- struct avl_tree * avl_seq =
4705- handle->file ->wal ->seq_shards
4706- ? &handle->file ->wal ->seq_shards [0 ]._map : NULL ;
4726+ uint64_t num_entries = handle->num_bottom_up_build_entries ;
47074727
47084728 // Build key-index first (tree is sorted by key).
47094729 struct hbtrie new_key_trie;
@@ -4717,7 +4737,7 @@ fdb_status _fdb_bottom_up_index_build(fdb_kvs_handle *handle)
47174737 _fdb_bottom_up_index_build_next,
47184738 _fdb_bottom_up_index_build_get,
47194739 _fdb_bottom_up_index_btreeblk_end,
4720- avl_key );
4740+ handle-> bottom_up_build_entries );
47214741 handle->trie ->root_bid = new_key_trie.root_bid ;
47224742
47234743 // Build seq-index next.
@@ -4733,7 +4753,7 @@ fdb_status _fdb_bottom_up_index_build(fdb_kvs_handle *handle)
47334753 _fdb_bottom_up_index_build_next,
47344754 _fdb_bottom_up_index_build_get_seq,
47354755 _fdb_bottom_up_index_btreeblk_end,
4736- avl_seq );
4756+ handle-> bottom_up_build_entries );
47374757 handle->seqtrie ->root_bid = new_seq_trie.root_bid ;
47384758 } else if (handle->seqtree ) {
47394759 // Not supported yet.
@@ -4842,33 +4862,35 @@ fdb_status _fdb_commit(fdb_kvs_handle *handle,
48424862 // (in this case, flush the rest of entries)
48434863 // 3. user forces to manually flush wal
48444864
4845- struct filemgr_dirty_update_node *prev_node = NULL , *new_node = NULL ;
4865+ if (handle->config .bottom_up_index_build ) {
4866+ _fdb_bottom_up_index_build (handle);
48464867
4847- _fdb_dirty_update_ready (handle, &prev_node, &new_node,
4848- &dirty_idtree_root, &dirty_seqtree_root, false ) ;
4868+ } else {
4869+ struct filemgr_dirty_update_node *prev_node = NULL , *new_node = NULL ;
48494870
4850- wr = wal_flush (handle->file , (void *)handle,
4851- _fdb_wal_flush_func, _fdb_wal_get_old_offset,
4852- _fdb_wal_flush_seq_purge, _fdb_wal_flush_kvs_delta_stats,
4853- &flush_items);
4871+ _fdb_dirty_update_ready (handle, &prev_node, &new_node,
4872+ &dirty_idtree_root, &dirty_seqtree_root, false );
48544873
4855- if (handle->config .bottom_up_index_build ) {
4856- _fdb_bottom_up_index_build (handle);
4857- }
4874+ wr = wal_flush (handle->file , (void *)handle,
4875+ _fdb_wal_flush_func, _fdb_wal_get_old_offset,
4876+ _fdb_wal_flush_seq_purge, _fdb_wal_flush_kvs_delta_stats,
4877+ &flush_items);
48584878
4859- if (wr != FDB_RESULT_SUCCESS) {
4860- btreeblk_clear_dirty_update (handle->bhandle );
4861- filemgr_dirty_update_close_node (handle->file , prev_node);
4862- filemgr_dirty_update_remove_node (handle->file , new_node);
4863- filemgr_mutex_unlock (handle->file );
4864- atomic_cas_uint8_t (&handle->handle_busy , 1 , 0 );
4865- return wr;
4866- }
4867- wal_set_dirty_status (handle->file , FDB_WAL_CLEAN);
4868- wal_flushed = true ;
48694879
4870- _fdb_dirty_update_finalize (handle, prev_node, new_node,
4871- &dirty_idtree_root, &dirty_seqtree_root, true );
4880+ if (wr != FDB_RESULT_SUCCESS) {
4881+ btreeblk_clear_dirty_update (handle->bhandle );
4882+ filemgr_dirty_update_close_node (handle->file , prev_node);
4883+ filemgr_dirty_update_remove_node (handle->file , new_node);
4884+ filemgr_mutex_unlock (handle->file );
4885+ atomic_cas_uint8_t (&handle->handle_busy , 1 , 0 );
4886+ return wr;
4887+ }
4888+ wal_set_dirty_status (handle->file , FDB_WAL_CLEAN);
4889+ wal_flushed = true ;
4890+
4891+ _fdb_dirty_update_finalize (handle, prev_node, new_node,
4892+ &dirty_idtree_root, &dirty_seqtree_root, true );
4893+ }
48724894 }
48734895
48744896 // Note: Appending KVS header must be done after flushing WAL
@@ -8182,6 +8204,21 @@ fdb_status _fdb_close_root(fdb_kvs_handle *handle)
81828204 return fs;
81838205}
81848206
8207+ void _destroy_bottom_up_build_entries (fdb_kvs_handle* handle) {
8208+ if (!handle->bottom_up_build_entries ) {
8209+ return ;
8210+ }
8211+ struct list_elem * le = list_begin (handle->bottom_up_build_entries );
8212+ while (le) {
8213+ struct bottom_up_build_entry * entry =
8214+ _get_entry (le, struct bottom_up_build_entry , le);
8215+ le = list_next (le);
8216+ free (entry->key );
8217+ free (entry);
8218+ }
8219+ free (handle->bottom_up_build_entries );
8220+ }
8221+
81858222fdb_status _fdb_close (fdb_kvs_handle *handle)
81868223{
81878224 fdb_status fs;
@@ -8235,6 +8272,8 @@ fdb_status _fdb_close(fdb_kvs_handle *handle)
82358272 handle->filename = NULL ;
82368273 }
82378274
8275+ _destroy_bottom_up_build_entries (handle);
8276+
82388277 return fs;
82398278}
82408279
0 commit comments