@@ -266,20 +266,28 @@ void db_lru_cleanup_percent(int* bytes_to_remove){
266266
267267static int db_expire_cursor_table (db_table* table){
268268 int ret = 0 ;
269- for (khiter_t ke = kh_begin (table->cache_hash_set ); ke != kh_end (table->cache_hash_set ); ++ke){
269+
270+ for (khiter_t ke = kh_begin (table->cache_hash_set ); ke < kh_end (table->cache_hash_set ); ++ke){
270271 if (kh_exist (table->cache_hash_set , ke)) {
271272 ret++;
272273 cache_entry* l = kh_value (table->cache_hash_set , ke);
273274 if (l->expires != 0 && l->expires < time_seconds){
275+ bool end_early = kh_size (table->cache_hash_set ) == 1 ;
274276 if (l->refs == 0 )
275277 {
276278 db_entry_incref (l);
277279 db_entry_handle_delete (l);
278280 db_entry_deref (l);
281+ end_early |= true ;
279282 }
280283 else
281284 {
282285 db_entry_handle_delete (l);
286+ end_early |= true ;
287+ }
288+
289+ if (end_early){
290+ break ;
283291 }
284292 }
285293 }
@@ -310,7 +318,7 @@ void db_expire_cursor(){
310318 done += db_expire_cursor_table (table);
311319 }
312320 db.table_gc ++;
313- if (db.table_gc = = kh_end (db.tables )){
321+ if (db.table_gc > = kh_end (db.tables )){
314322 db.table_gc = kh_begin (db.tables );
315323 }
316324 } while (db.table_gc != start && done < 1000 );
@@ -932,20 +940,23 @@ void db_target_write_allocate(struct cache_target* target, uint32_t data_length)
932940static void db_close_table_key_space (){
933941 db_table* table;
934942
935- // tables and key space
936- for (khiter_t ke = kh_begin (db.tables ); ke != kh_end (db.tables ); ++ke){
937- if (kh_exist (db.tables , ke)) {
938- table = kh_val (db.tables , ke);
943+ // make 128 attempts to clear the tablespace
944+ // table deletions can cause resizing and tables to be skipped in the iteration
945+ for (int i = 0 ; i < 128 && kh_size (db.tables ); i++){
946+ for (khiter_t ke = kh_begin (db.tables ); ke < kh_end (db.tables ); ++ke){
947+ if (kh_exist (db.tables , ke)) {
948+ table = kh_val (db.tables , ke);
939949
940- // All other refernces should have been de-refed before db_close is called
941- // and hence anything pending deletion will have been cleaned up already
942- assert (!table->deleted );
950+ // All other refernces should have been de-refed before db_close is called
951+ // and hence anything pending deletion will have been cleaned up already
952+ assert (!table->deleted );
943953
944- // Check reference count (should be 1)
945- assert (table->refs == 1 );
954+ // Check reference count (should be 1)
955+ assert (table->refs == 1 );
946956
947- // Actually delete
948- db_table_handle_delete (table);
957+ // Actually delete
958+ db_table_handle_delete (table);
959+ }
949960 }
950961 }
951962 kh_destroy (table, db.tables );
0 commit comments