@@ -236,6 +236,10 @@ class SequenceGenerator {
236236
237237 void reset () { keyStates.clear (); }
238238
239+ std::map< uint64_t , bool >& getKeyStates () { return keyStates; }
240+ std::atomic< uint64_t >& getInUseKeyCount () { return in_use_key_cnt_; }
241+ std::uniform_int_distribution<>& getKeyDistribution () { return keyDist_; }
242+
239243private:
240244 int putFreq_;
241245 int removeFreq_;
@@ -264,6 +268,7 @@ struct long_running_crash_options {
264268 uint32_t num_entries_per_rounds{SISL_OPTIONS[" num_entries_per_rounds" ].as < uint32_t >()};
265269 bool load_mode{SISL_OPTIONS.count (" load_from_file" ) > 0 };
266270 bool save_mode{SISL_OPTIONS.count (" save_to_file" ) > 0 };
271+ bool range_remove_{false };
267272};
268273
269274template < typename TestType >
@@ -545,6 +550,13 @@ struct IndexCrashTest : public test_common::HSTestHelper, BtreeTestHelper< TestT
545550
546551 uint32_t tree_key_count () { return this ->m_bt ->count_keys (this ->m_bt ->root_node_id ()); }
547552
553+ std::pair<uint32_t , uint32_t > range_remove_op (SequenceGenerator& generator, uint32_t range_remove_count) {
554+ uint32_t key = generator.getKeyDistribution ()(g_re);
555+ auto [start_key, end_key] = this ->m_shadow_map .pick_existing_range (K{key}, range_remove_count,
556+ [&generator](const K& key) { generator.getKeyStates ()[key.key ()] = false ; generator.getInUseKeyCount ().fetch_sub (1 ); });
557+ return {start_key.key (), end_key.key ()};
558+ }
559+
548560 void long_running_crash (long_running_crash_options const & crash_test_options) {
549561 // set putFreq 100 for the initial load
550562 SequenceGenerator generator (100 /* putFreq*/ , 0 /* removeFreq*/ , 0 /* start_range*/ ,
@@ -719,6 +731,12 @@ struct IndexCrashTest : public test_common::HSTestHelper, BtreeTestHelper< TestT
719731 }
720732 }
721733 }
734+ if (crash_test_options.range_remove_ ) {
735+ // add one range remove operation
736+ auto op = this ->range_remove_op (generator, crash_test_options.num_entries_per_rounds );
737+ LOGDEBUG (" Range removing keys [{}, {})" , op.first , op.second );
738+ this ->range_remove_all (op.first , op.second );
739+ }
722740 if (normal_execution) {
723741 if (clean_shutdown) {
724742 this ->m_shadow_map .save (this ->m_shadow_filename );
@@ -881,6 +899,19 @@ TYPED_TEST(IndexCrashTest, long_running_put_remove_crash) {
881899 this ->long_running_crash (crash_test_options);
882900}
883901
902+ TYPED_TEST (IndexCrashTest, long_running_put_range_remove_crash) {
903+ long_running_crash_options crash_test_options{
904+ // put freq should be 100 for range remove test
905+ .put_freq = 100 ,
906+ .put_flips = {" crash_flush_on_split_at_parent" , " crash_flush_on_split_at_left_child" ,
907+ " crash_flush_on_split_at_right_child" },
908+ .remove_flips = {" crash_flush_on_merge_at_parent" , " crash_flush_on_merge_at_left_child"
909+ /* , "crash_flush_on_freed_child"*/ },
910+ .range_remove_ = true ,
911+ };
912+ this ->long_running_crash (crash_test_options);
913+ }
914+
884915// Basic reverse and forward order remove with different flip points
885916TYPED_TEST (IndexCrashTest, MergeRemoveBasic) {
886917 vector< std::string > flip_points = {
0 commit comments