diff --git a/configure.py b/configure.py index e35baaa114..c5f66888b7 100755 --- a/configure.py +++ b/configure.py @@ -791,6 +791,7 @@ scylla_tests_dependencies = scylla_core + idls + [ 'tests/result_set_assertions.cc', 'tests/mutation_source_test.cc', 'tests/data_model.cc', + 'tests/test_services.cc', ] deps = { diff --git a/dht/i_partitioner.hh b/dht/i_partitioner.hh index 7d2ccecd8b..3a240a5623 100644 --- a/dht/i_partitioner.hh +++ b/dht/i_partitioner.hh @@ -808,6 +808,8 @@ public: std::unique_ptr make_partitioner(sstring name, unsigned shard_count, unsigned sharding_ignore_msb_bits); +extern std::unique_ptr default_partitioner; + } // dht namespace std { diff --git a/tests/broken_sstable_test.cc b/tests/broken_sstable_test.cc index de37a38f26..9a6978ffb3 100644 --- a/tests/broken_sstable_test.cc +++ b/tests/broken_sstable_test.cc @@ -40,7 +40,8 @@ struct my_consumer { static void broken_sst(sstring dir, unsigned long generation, schema_ptr s, sstring msg, sstable_version_types version = la) { try { - sstable_ptr sstp = std::get<0>(reusable_sst(s, dir, generation, version).get()); + sstables::test_env env; + sstable_ptr sstp = std::get<0>(env.reusable_sst(s, dir, generation, version).get()); auto r = sstp->read_rows_flat(s); r.consume(my_consumer{}, db::no_timeout).get(); BOOST_FAIL("expecting exception"); @@ -63,7 +64,8 @@ SEASTAR_THREAD_TEST_CASE(test_empty_index) { .with_column("val", int32_type) .set_compressor_params(compression_parameters::no_compression()) .build(); - sstable_ptr sstp = std::get<0>(reusable_sst(s, "tests/sstables/empty_index", 36, sstable_version_types::mc).get()); + sstables::test_env env; + sstable_ptr sstp = std::get<0>(env.reusable_sst(s, "tests/sstables/empty_index", 36, sstable_version_types::mc).get()); sstp->load().get(); auto fut = sstables::test(sstp).read_indexes(); BOOST_REQUIRE_EXCEPTION(fut.get(), malformed_sstable_exception, [](auto&& e) { diff --git a/tests/memory_footprint.cc b/tests/memory_footprint.cc index 78943c4745..113d1e49d7 100644 --- a/tests/memory_footprint.cc +++ b/tests/memory_footprint.cc @@ -35,6 +35,7 @@ #include "canonical_mutation.hh" #include "sstable_utils.hh" #include "test_services.hh" +#include "sstable_test_env.hh" class size_calculator { class nest { @@ -187,7 +188,8 @@ static sizes calculate_sizes(const mutation& m) { result.query_result = m.query(partition_slice_builder(*s).build(), query::result_options::only_result()).buf().size(); tmpdir sstable_dir; - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, sstable_dir.path().string(), 1 /* generation */, sstables::sstable::version_types::la, diff --git a/tests/mutation_reader_test.cc b/tests/mutation_reader_test.cc index 58b893252f..c0cec5bed3 100644 --- a/tests/mutation_reader_test.cc +++ b/tests/mutation_reader_test.cc @@ -35,6 +35,7 @@ #include "tests/flat_mutation_reader_assertions.hh" #include "tests/tmpdir.hh" #include "tests/sstable_utils.hh" +#include "tests/sstable_test.hh" #include "tests/simple_schema.hh" #include "tests/test_services.hh" #include "tests/mutation_source_test.hh" @@ -384,6 +385,7 @@ SEASTAR_TEST_CASE(test_sm_fast_forwarding_combining_reader) { } struct sst_factory { + sstables::test_env env; schema_ptr s; sstring path; unsigned gen; @@ -397,7 +399,7 @@ struct sst_factory { {} sstables::shared_sstable operator()() { - auto sst = sstables::make_sstable(s, path, gen, sstables::sstable::version_types::la, sstables::sstable::format_types::big); + auto sst = env.make_sstable(s, path, gen, sstables::sstable::version_types::la, sstables::sstable::format_types::big); sst->set_unshared(); //sst->set_sstable_level(level); sst->get_metadata_collector().sstable_level(level); @@ -707,7 +709,7 @@ SEASTAR_TEST_CASE(reader_selector_fast_forwarding_test) { static const std::size_t new_reader_base_cost{16 * 1024}; -sstables::shared_sstable create_sstable(simple_schema& sschema, const sstring& path) { +sstables::shared_sstable create_sstable(sstables::test_env& env, simple_schema& sschema, const sstring& path) { std::vector mutations; mutations.reserve(1 << 14); @@ -724,17 +726,17 @@ sstables::shared_sstable create_sstable(simple_schema& sschema, const sstring& p } return make_sstable_containing([&] { - return make_lw_shared(sschema.schema(), path, 0, sstables::sstable::version_types::la, sstables::sstable::format_types::big); + return env.make_sstable(sschema.schema(), path, 0, sstables::sstable::version_types::la, sstables::sstable::format_types::big); } , mutations); } static -sstables::shared_sstable create_sstable(schema_ptr s, std::vector mutations) { +sstables::shared_sstable create_sstable(sstables::test_env& env, schema_ptr s, std::vector mutations) { static thread_local auto tmp = tmpdir(); static int gen = 0; return make_sstable_containing([&] { - return make_lw_shared(s, tmp.path().string(), gen++, sstables::sstable::version_types::la, sstables::sstable::format_types::big); + return env.make_sstable(s, tmp.path().string(), gen++, sstables::sstable::version_types::la, sstables::sstable::format_types::big); }, mutations); } @@ -973,14 +975,14 @@ SEASTAR_TEST_CASE(reader_restriction_file_tracking) { } SEASTAR_TEST_CASE(restricted_reader_reading) { - return async([&] { + return sstables::test_env::do_with_async([&] (sstables::test_env& env) { storage_service_for_tests ssft; reader_concurrency_semaphore semaphore(2, new_reader_base_cost); { simple_schema s; auto tmp = tmpdir(); - auto sst = create_sstable(s, tmp.path().string()); + auto sst = create_sstable(env, s, tmp.path().string()); auto reader1 = reader_wrapper(semaphore, s.schema(), sst); @@ -1044,14 +1046,14 @@ SEASTAR_TEST_CASE(restricted_reader_reading) { } SEASTAR_TEST_CASE(restricted_reader_timeout) { - return async([&] { + return sstables::test_env::do_with_async([&] (sstables::test_env& env) { storage_service_for_tests ssft; reader_concurrency_semaphore semaphore(2, new_reader_base_cost); { simple_schema s; auto tmp = tmpdir(); - auto sst = create_sstable(s, tmp.path().string()); + auto sst = create_sstable(env, s, tmp.path().string()); auto timeout = std::chrono::duration_cast(std::chrono::milliseconds{1}); @@ -1089,7 +1091,7 @@ SEASTAR_TEST_CASE(restricted_reader_timeout) { } SEASTAR_TEST_CASE(restricted_reader_max_queue_length) { - return async([&] { + return sstables::test_env::do_with_async([&] (sstables::test_env& env) { storage_service_for_tests ssft; struct queue_overloaded_exception {}; @@ -1099,7 +1101,7 @@ SEASTAR_TEST_CASE(restricted_reader_max_queue_length) { { simple_schema s; auto tmp = tmpdir(); - auto sst = create_sstable(s, tmp.path().string()); + auto sst = create_sstable(env, s, tmp.path().string()); auto reader1_ptr = std::make_unique(semaphore, s.schema(), sst); (*reader1_ptr)().get(); @@ -1128,14 +1130,14 @@ SEASTAR_TEST_CASE(restricted_reader_max_queue_length) { } SEASTAR_TEST_CASE(restricted_reader_create_reader) { - return async([&] { + return sstables::test_env::do_with_async([&] (sstables::test_env& env) { storage_service_for_tests ssft; reader_concurrency_semaphore semaphore(100, new_reader_base_cost); { simple_schema s; auto tmp = tmpdir(); - auto sst = create_sstable(s, tmp.path().string()); + auto sst = create_sstable(env, s, tmp.path().string()); { auto reader = reader_wrapper(semaphore, s.schema(), sst); @@ -1196,7 +1198,7 @@ static mutation compacted(const mutation& m) { } SEASTAR_TEST_CASE(test_fast_forwarding_combined_reader_is_consistent_with_slicing) { - return async([&] { + return sstables::test_env::do_with_async([&] (sstables::test_env& env) { storage_service_for_tests ssft; random_mutation_generator gen(random_mutation_generator::generate_counters::no); auto s = gen.schema(); @@ -1219,7 +1221,7 @@ SEASTAR_TEST_CASE(test_fast_forwarding_combined_reader_is_consistent_with_slicin combined[j++].apply(m); } } - mutation_source ds = create_sstable(s, muts)->as_mutation_source(); + mutation_source ds = create_sstable(env, s, muts)->as_mutation_source(); readers.push_back(ds.make_reader(s, dht::partition_range::make({keys[0]}, {keys[0]}), s->full_slice(), default_priority_class(), nullptr, @@ -1271,7 +1273,7 @@ SEASTAR_TEST_CASE(test_fast_forwarding_combined_reader_is_consistent_with_slicin } SEASTAR_TEST_CASE(test_combined_reader_slicing_with_overlapping_range_tombstones) { - return async([&] { + return sstables::test_env::do_with_async([&] (sstables::test_env& env) { storage_service_for_tests ssft; simple_schema ss; auto s = ss.schema(); @@ -1287,8 +1289,8 @@ SEASTAR_TEST_CASE(test_combined_reader_slicing_with_overlapping_range_tombstones std::vector readers; - mutation_source ds1 = create_sstable(s, {m1})->as_mutation_source(); - mutation_source ds2 = create_sstable(s, {m2})->as_mutation_source(); + mutation_source ds1 = create_sstable(env, s, {m1})->as_mutation_source(); + mutation_source ds2 = create_sstable(env, s, {m2})->as_mutation_source(); // upper bound ends before the row in m2, so that the raw is fetched after next fast forward. auto range = ss.make_ckey_range(0, 3); diff --git a/tests/perf/perf_sstable.cc b/tests/perf/perf_sstable.cc index 4d77f19ea5..288de55110 100644 --- a/tests/perf/perf_sstable.cc +++ b/tests/perf/perf_sstable.cc @@ -36,34 +36,34 @@ using namespace sstables; static unsigned iterations = 30; static unsigned parallelism = 1; -future<> test_write(distributed& dt) { +future<> test_write(distributed& dt) { return seastar::async([&dt] { storage_service_for_tests ssft; - dt.invoke_on_all([] (test_env &t) { + dt.invoke_on_all([] (perf_sstable_test_env &t) { return t.fill_memtable(); }).then([&dt] { - return time_runs(iterations, parallelism, dt, &test_env::flush_memtable); + return time_runs(iterations, parallelism, dt, &perf_sstable_test_env::flush_memtable); }).get(); }); } -future<> test_compaction(distributed& dt) { +future<> test_compaction(distributed& dt) { return seastar::async([&dt] { storage_service_for_tests ssft; - dt.invoke_on_all([] (test_env &t) { + dt.invoke_on_all([] (perf_sstable_test_env &t) { return t.fill_memtable(); }).then([&dt] { - return time_runs(iterations, parallelism, dt, &test_env::compaction); + return time_runs(iterations, parallelism, dt, &perf_sstable_test_env::compaction); }).get(); }); } -future<> test_index_read(distributed& dt) { - return time_runs(iterations, parallelism, dt, &test_env::read_all_indexes); +future<> test_index_read(distributed& dt) { + return time_runs(iterations, parallelism, dt, &perf_sstable_test_env::read_all_indexes); } -future<> test_sequential_read(distributed& dt) { - return time_runs(iterations, parallelism, dt, &test_env::read_sequential_partitions); +future<> test_sequential_read(distributed& dt) { + return time_runs(iterations, parallelism, dt, &perf_sstable_test_env::read_sequential_partitions); } enum class test_modes { @@ -98,9 +98,9 @@ int main(int argc, char** argv) { ("testdir", bpo::value()->default_value("/var/lib/scylla/perf-tests"), "directory in which to store the sstables"); return app.run_deprecated(argc, argv, [&app] { - auto test = make_lw_shared>(); + auto test = make_lw_shared>(); - auto cfg = test_env::conf(); + auto cfg = perf_sstable_test_env::conf(); iterations = app.configuration()["iterations"].as(); parallelism = app.configuration()["parallelism"].as(); cfg.partitions = app.configuration()["partitions"].as(); @@ -121,7 +121,7 @@ int main(int argc, char** argv) { engine().at_exit([test] { return test->stop(); }); if ((mode == test_modes::index_read) || (mode == test_modes::sequential_read)) { - return test->invoke_on_all([] (test_env &t) { + return test->invoke_on_all([] (perf_sstable_test_env &t) { return t.load_sstables(iterations); }).then_wrapped([] (future<> f) { try { diff --git a/tests/perf/perf_sstable.hh b/tests/perf/perf_sstable.hh index 3f8dd09dd9..043e3fa4b5 100644 --- a/tests/perf/perf_sstable.hh +++ b/tests/perf/perf_sstable.hh @@ -34,7 +34,9 @@ using namespace sstables; static db::nop_large_data_handler nop_lp_handler; -class test_env { +class perf_sstable_test_env { + test_env _env; + public: struct conf { unsigned partitions; @@ -99,7 +101,7 @@ private: } public: - test_env(conf cfg) : _cfg(std::move(cfg)) + perf_sstable_test_env(conf cfg) : _cfg(std::move(cfg)) , s(create_schema()) , _distribution('@', '~') , _mt(make_lw_shared(s)) @@ -122,7 +124,7 @@ public: } future<> load_sstables(unsigned iterations) { - _sst.push_back(make_sstable(s, this->dir(), 0, sstable::version_types::ka, sstable::format_types::big)); + _sst.push_back(_env.make_sstable(s, this->dir(), 0, sstable::version_types::ka, sstable::format_types::big)); return _sst.back()->load(); } @@ -138,11 +140,11 @@ public: size_t partitions = _mt->partition_count(); test_setup::create_empty_test_dir(dir()).get(); - auto sst = sstables::test::make_test_sstable(_cfg.buffer_size, s, dir(), idx, sstable::version_types::ka, sstable::format_types::big); + auto sst = _env.make_sstable(s, dir(), idx, sstable::version_types::ka, sstable::format_types::big, _cfg.buffer_size); - auto start = test_env::now(); + auto start = perf_sstable_test_env::now(); write_memtable_to_sstable_for_test(*_mt, sst).get(); - auto end = test_env::now(); + auto end = perf_sstable_test_env::now(); _mt->revert_flushed_memory(); @@ -155,7 +157,7 @@ public: return test_setup::create_empty_test_dir(dir()).then([this, idx] { return seastar::async([this, idx] { auto sst_gen = [this, gen = make_lw_shared(idx)] () mutable { - return sstables::test::make_test_sstable(_cfg.buffer_size, s, dir(), (*gen)++, sstable::version_types::ka, sstable::format_types::big); + return _env.make_sstable(s, dir(), (*gen)++, sstable::version_types::ka, sstable::format_types::big, _cfg.buffer_size); }; std::vector ssts; @@ -174,9 +176,9 @@ public: cfg.large_data_handler = &nop_lp_handler; auto cf = make_lw_shared(s, cfg, column_family::no_commitlog(), *cm, cl_stats, tracker); - auto start = test_env::now(); + auto start = perf_sstable_test_env::now(); auto ret = sstables::compact_sstables(sstables::compaction_descriptor(std::move(ssts)), *cf, sst_gen, sstables::replacer_fn_no_op()).get0(); - auto end = test_env::now(); + auto end = perf_sstable_test_env::now(); auto partitions_per_sstable = _cfg.partitions / _cfg.sstables; assert(ret.total_keys_written == partitions_per_sstable); @@ -189,10 +191,10 @@ public: future read_all_indexes(int idx) { return do_with(test(_sst[0]), [] (auto& sst) { - const auto start = test_env::now(); + const auto start = perf_sstable_test_env::now(); return sst.read_indexes().then([start] (const auto& indexes) { - auto end = test_env::now(); + auto end = perf_sstable_test_env::now(); auto duration = std::chrono::duration(end - start).count(); return indexes.size() / duration; }); @@ -201,7 +203,7 @@ public: future read_sequential_partitions(int idx) { return do_with(_sst[0]->read_rows_flat(s), [this] (flat_mutation_reader& r) { - auto start = test_env::now(); + auto start = perf_sstable_test_env::now(); auto total = make_lw_shared(0); auto done = make_lw_shared(false); return do_until([done] { return *done; }, [this, done, total, &r] { @@ -218,7 +220,7 @@ public: } }); }).then([total, start] { - auto end = test_env::now(); + auto end = perf_sstable_test_env::now(); auto duration = std::chrono::duration(end - start).count(); return *total / duration; }); @@ -229,7 +231,7 @@ public: // The function func should carry on with the test, and return the number of partitions processed. // time_runs will then map reduce it, and return the aggregate partitions / sec for the whole system. template -future<> time_runs(unsigned iterations, unsigned parallelism, distributed& dt, Func func) { +future<> time_runs(unsigned iterations, unsigned parallelism, distributed& dt, Func func) { using namespace boost::accumulators; auto acc = make_lw_shared>>>(); auto idx = boost::irange(0, int(iterations)); diff --git a/tests/sstable_3_x_test.cc b/tests/sstable_3_x_test.cc index ecd8a9d37e..c34d836ff1 100644 --- a/tests/sstable_3_x_test.cc +++ b/tests/sstable_3_x_test.cc @@ -37,7 +37,6 @@ #include "schema_builder.hh" #include "sstable_test.hh" #include "flat_mutation_reader_assertions.hh" -#include "sstable_test.hh" #include "tests/test_services.hh" #include "tests/tmpdir.hh" #include "tests/sstable_utils.hh" @@ -56,18 +55,22 @@ using namespace sstables; class sstable_assertions final { + test_env _env; shared_sstable _sst; public: sstable_assertions(schema_ptr schema, const sstring& path, int generation = 1) - : _sst(make_sstable(std::move(schema), + : _env() + , _sst(_env.make_sstable(std::move(schema), path, generation, sstable_version_types::mc, sstable_format_types::big, - gc_clock::now(), - default_io_error_handler_gen(), 1)) { } + + test_env& get_env() { + return _env; + } void read_toc() { _sst->read_toc().get(); } @@ -2855,30 +2858,20 @@ SEASTAR_THREAD_TEST_CASE(test_uncompressed_collections_read) { .produces_end_of_stream(); } -static sstables::shared_sstable open_sstable(schema_ptr schema, sstring dir, unsigned long generation) { - auto sst = sstables::make_sstable(std::move(schema), dir, generation, - sstables::sstable::version_types::mc, - sstables::sstable::format_types::big); - sst->load().get(); - return sst; +static sstables::shared_sstable open_sstable(test_env& env, schema_ptr schema, sstring dir, unsigned long generation) { + return env.reusable_sst(std::move(schema), dir, generation, sstables::sstable::version_types::mc).get0(); } -static std::vector open_sstables(schema_ptr s, sstring dir, std::vector generations) { +static std::vector open_sstables(test_env& env, schema_ptr s, sstring dir, std::vector generations) { std::vector result; for(auto generation: generations) { - result.push_back(open_sstable(s, dir, generation)); + result.push_back(open_sstable(env, s, dir, generation)); } return result; } -static flat_mutation_reader compacted_sstable_reader(schema_ptr s, +static flat_mutation_reader compacted_sstable_reader(test_env& env, schema_ptr s, sstring table_name, std::vector generations) { - auto column_family_test_config = [] { - static db::nop_large_data_handler nop_lp_handler; - column_family::config cfg; - cfg.large_data_handler = &nop_lp_handler; - return cfg; - }; storage_service_for_tests ssft; auto cm = make_lw_shared(); @@ -2889,16 +2882,16 @@ static flat_mutation_reader compacted_sstable_reader(schema_ptr s, lw_shared_ptr mt = make_lw_shared(s); tmpdir tmp; - auto sstables = open_sstables(s, format("tests/sstables/3.x/uncompressed/{}", table_name), generations); + auto sstables = open_sstables(env, s, format("tests/sstables/3.x/uncompressed/{}", table_name), generations); auto new_generation = generations.back() + 1; - auto new_sstable = [s, &tmp, new_generation] { - return sstables::test::make_test_sstable(4096, s, tmp.path().string(), new_generation, - sstables::sstable_version_types::mc, sstable::format_types::big); + auto new_sstable = [s, &tmp, &env, new_generation] { + return env.make_sstable(s, tmp.path().string(), new_generation, + sstables::sstable_version_types::mc, sstable::format_types::big, 4096); }; sstables::compact_sstables(sstables::compaction_descriptor(std::move(sstables)), *cf, new_sstable, replacer_fn_no_op()).get(); - auto compacted_sst = open_sstable(s, tmp.path().string(), new_generation); + auto compacted_sst = open_sstable(env, s, tmp.path().string(), new_generation); return compacted_sst->as_mutation_source().make_reader(s, query::full_partition_range, s->full_slice()); } @@ -2955,7 +2948,8 @@ SEASTAR_THREAD_TEST_CASE(compact_deleted_row) { * } * ] */ - auto reader = compacted_sstable_reader(s, table_name, {1, 2}); + test_env env; + auto reader = compacted_sstable_reader(env, s, table_name, {1, 2}); mutation_opt m = read_mutation_from_flat_mutation_reader(reader, db::no_timeout).get0(); BOOST_REQUIRE(m); BOOST_REQUIRE(m->key().equal(*s, partition_key::from_singular(*s, data_value(sstring("key"))))); @@ -3025,7 +3019,8 @@ SEASTAR_THREAD_TEST_CASE(compact_deleted_cell) { *] * */ - auto reader = compacted_sstable_reader(s, table_name, {1, 2}); + test_env env; + auto reader = compacted_sstable_reader(env, s, table_name, {1, 2}); mutation_opt m = read_mutation_from_flat_mutation_reader(reader, db::no_timeout).get0(); BOOST_REQUIRE(m); BOOST_REQUIRE(m->key().equal(*s, partition_key::from_singular(*s, data_value(sstring("key"))))); @@ -3071,11 +3066,11 @@ static void compare_sstables(const seastar::compat::filesystem::path& result_pat } } -static tmpdir write_sstables(schema_ptr s, lw_shared_ptr mt1, lw_shared_ptr mt2) { +static tmpdir write_sstables(test_env& env, schema_ptr s, lw_shared_ptr mt1, lw_shared_ptr mt2) { static db::nop_large_data_handler nop_lp_handler; storage_service_for_tests ssft; tmpdir tmp; - auto sst = sstables::test::make_test_sstable(4096, s, tmp.path().string(), 1, sstables::sstable_version_types::mc, sstable::format_types::big); + auto sst = env.make_sstable(s, tmp.path().string(), 1, sstables::sstable_version_types::mc, sstable::format_types::big, 4096); sstable_writer_config cfg; cfg.large_data_handler = &nop_lp_handler; sst->write_components(make_combined_reader(s, @@ -3088,27 +3083,29 @@ static tmpdir write_sstables(schema_ptr s, lw_shared_ptr mt1, lw_share // that otherwise takes place for RTs put into one and the same memtable static tmpdir write_and_compare_sstables(schema_ptr s, lw_shared_ptr mt1, lw_shared_ptr mt2, sstring table_name) { - auto tmp = write_sstables(std::move(s), std::move(mt1), std::move(mt2)); + test_env env; + auto tmp = write_sstables(env, std::move(s), std::move(mt1), std::move(mt2)); compare_sstables(tmp.path(), table_name); return tmp; } -static tmpdir write_sstables(schema_ptr s, lw_shared_ptr mt) { +static tmpdir write_sstables(test_env& env, schema_ptr s, lw_shared_ptr mt) { storage_service_for_tests ssft; tmpdir tmp; - auto sst = sstables::test::make_test_sstable(4096, s, tmp.path().string(), 1, sstables::sstable_version_types::mc, sstable::format_types::big); + auto sst = env.make_sstable(s, tmp.path().string(), 1, sstables::sstable_version_types::mc, sstable::format_types::big, 4096); write_memtable_to_sstable_for_test(*mt, sst).get(); return tmp; } static tmpdir write_and_compare_sstables(schema_ptr s, lw_shared_ptr mt, sstring table_name) { - auto tmp = write_sstables(std::move(s), std::move(mt)); + test_env env; + auto tmp = write_sstables(env, std::move(s), std::move(mt)); compare_sstables(tmp.path(), table_name); return tmp; } static sstable_assertions validate_read(schema_ptr s, const seastar::compat::filesystem::path& path, std::vector mutations) { - sstable_assertions sst(s, path.string()); + sstable_assertions sst(s, path.string(), 1); sst.load(); auto assertions = assert_that(sst.read_rows_flat()); @@ -3124,8 +3121,7 @@ static constexpr api::timestamp_type write_timestamp = 1525385507816568; static constexpr gc_clock::time_point write_time_point = gc_clock::time_point{} + gc_clock::duration{1525385507}; static void validate_stats_metadata(schema_ptr s, sstable_assertions written_sst, sstring table_name) { - auto orig_sst = sstables::make_sstable(s, get_write_test_path(table_name), 1, sstable_version_types::mc, big); - orig_sst->load().get(); + auto orig_sst = written_sst.get_env().reusable_sst(s, get_write_test_path(table_name), 1, sstable_version_types::mc).get0(); const auto& orig_stats = orig_sst->get_stats_metadata(); const auto& written_stats = written_sst.get_stats_metadata(); @@ -3520,7 +3516,8 @@ static void test_write_many_partitions(sstring table_name, tombstone partition_t } bool compressed = cp.get_compressor() != nullptr; - tmpdir tmp = compressed ? write_sstables(s, mt) : write_and_compare_sstables(s, mt, table_name); + test_env env; + tmpdir tmp = compressed ? write_sstables(env, s, mt) : write_and_compare_sstables(s, mt, table_name); boost::sort(muts, mutation_decorated_key_less_comparator()); validate_read(s, tmp.path(), muts); } @@ -4406,6 +4403,10 @@ static std::unique_ptr get_index_reader(shared_sstable sst) { return std::make_unique(sst, default_priority_class()); } +shared_sstable make_test_sstable(test_env& env, schema_ptr schema, const sstring& table_name, int64_t gen = 1) { + return env.reusable_sst(schema, get_read_index_test_path(table_name), gen, sstable_version_types::mc).get0(); +} + /* * The SSTables read is generated using the following queries: * @@ -4421,8 +4422,8 @@ SEASTAR_THREAD_TEST_CASE(test_read_empty_index) { builder.set_compressor_params(compression_parameters::no_compression()); schema_ptr s = builder.build(schema_builder::compact_storage::no); - auto sst = sstables::make_sstable(s, get_read_index_test_path(table_name), 1, sstable_version_types::mc , sstable_format_types::big); - sst->load().get0(); + test_env env; + auto sst = make_test_sstable(env, s, table_name); assert_that(get_index_reader(sst)).is_empty(*s); } @@ -4441,8 +4442,8 @@ SEASTAR_THREAD_TEST_CASE(test_read_rows_only_index) { builder.set_compressor_params(compression_parameters::no_compression()); schema_ptr s = builder.build(schema_builder::compact_storage::no); - auto sst = sstables::make_sstable(s, get_read_index_test_path(table_name), 1, sstable_version_types::mc , sstable_format_types::big); - sst->load().get0(); + test_env env; + auto sst = make_test_sstable(env, s, table_name); assert_that(get_index_reader(sst)).has_monotonic_positions(*s); } @@ -4460,8 +4461,8 @@ SEASTAR_THREAD_TEST_CASE(test_read_range_tombstones_only_index) { builder.set_compressor_params(compression_parameters::no_compression()); schema_ptr s = builder.build(schema_builder::compact_storage::no); - auto sst = sstables::make_sstable(s, get_read_index_test_path(table_name), 1, sstable_version_types::mc , sstable_format_types::big); - sst->load().get0(); + test_env env; + auto sst = make_test_sstable(env, s, table_name); assert_that(get_index_reader(sst)).has_monotonic_positions(*s); } @@ -4487,8 +4488,8 @@ SEASTAR_THREAD_TEST_CASE(test_read_range_tombstone_boundaries_index) { builder.set_compressor_params(compression_parameters::no_compression()); schema_ptr s = builder.build(schema_builder::compact_storage::no); - auto sst = sstables::make_sstable(s, get_read_index_test_path(table_name), 1, sstable_version_types::mc , sstable_format_types::big); - sst->load().get0(); + test_env env; + auto sst = make_test_sstable(env, s, table_name); assert_that(get_index_reader(sst)).has_monotonic_positions(*s); } @@ -4945,7 +4946,8 @@ SEASTAR_THREAD_TEST_CASE(test_sstable_reader_on_unknown_column) { sstable_writer_config cfg; cfg.promoted_index_block_size = index_block_size; cfg.large_data_handler = &nop_lp_handler; - auto sst = sstables::make_sstable(write_schema, + test_env env; + auto sst = env.make_sstable(write_schema, dir.path().string(), 1 /* generation */, sstable_version_types::mc, @@ -4998,7 +5000,8 @@ struct large_row_handler : public db::large_data_handler { static void test_sstable_write_large_row_f(schema_ptr s, memtable& mt, const partition_key& pk, std::vector expected, uint64_t threshold) { tmpdir dir; - auto sst = sstables::make_sstable( + test_env env; + auto sst = env.make_sstable( s, dir.path().string(), 1 /* generation */, sstable_version_types::mc, sstables::sstable::format_types::big); unsigned i = 0; diff --git a/tests/sstable_datafile_test.cc b/tests/sstable_datafile_test.cc index 970992632b..ba96000991 100644 --- a/tests/sstable_datafile_test.cc +++ b/tests/sstable_datafile_test.cc @@ -68,17 +68,11 @@ using namespace sstables; -static sstring some_keyspace("ks"); -static sstring some_column_family("cf"); +static const sstring some_keyspace("ks"); +static const sstring some_column_family("cf"); static db::nop_large_data_handler nop_lp_handler; -static column_family::config column_family_test_config() { - column_family::config cfg; - cfg.large_data_handler = &nop_lp_handler; - return cfg; -} - atomic_cell make_atomic_cell(data_type dt, bytes_view value, uint32_t ttl = 0, uint32_t expiration = 0) { if (ttl) { return atomic_cell::make_live(*dt, 0, value, @@ -101,7 +95,7 @@ SEASTAR_TEST_CASE(datafile_generation_01) { // ) WITH compression = {}; // INSERT INTO test (p1, c1, r1) VALUES ('key1', 'abc', 1); - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { schema_builder builder(make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}, {"r2", int32_type}}, {}, utf8_type))); builder.set_compressor_params(compression_parameters::no_compression()); @@ -118,7 +112,7 @@ SEASTAR_TEST_CASE(datafile_generation_01) { m.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 1, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 1, la, big); auto fname = sstable::filename(tmpdir_path, "ks", "cf", la, 1, big, component_type::Data); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, fname] { @@ -157,7 +151,7 @@ SEASTAR_TEST_CASE(datafile_generation_01) { }); } SEASTAR_TEST_CASE(datafile_generation_02) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { // Data file with compound partition key and clustering key // // Respective CQL table and CQL insert: @@ -186,7 +180,7 @@ SEASTAR_TEST_CASE(datafile_generation_02) { m.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 2, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 2, la, big); auto fname = sstable::filename(tmpdir_path, "ks", "cf", la, 2, big, component_type::Data); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, fname] { @@ -239,7 +233,7 @@ SEASTAR_TEST_CASE(datafile_generation_03) { // PRIMARY KEY (p1, c1, c2) // ) WITH compression = {}; // INSERT INTO table (p1, c1, c2, r1) VALUES ('key1', 'abc', 'cde', 1); - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { schema_builder builder(make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}, {"c2", utf8_type}}, {{"r1", int32_type}}, {}, utf8_type))); builder.set_compressor_params(compression_parameters::no_compression()); @@ -256,7 +250,7 @@ SEASTAR_TEST_CASE(datafile_generation_03) { m.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 3, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 3, la, big); auto fname = sstable::filename(tmpdir_path, "ks", "cf", la, 3, big, component_type::Data); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, fname] { @@ -310,7 +304,7 @@ SEASTAR_TEST_CASE(datafile_generation_04) { // ) WITH compression = {}; // INSERT INTO test (p1, s1) VALUES ('key1', 10); // INSERT INTO test (p1, c1, r1) VALUES ('key1', 'abc', 1); - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { schema_builder builder(make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}}, {{"s1", int32_type}}, utf8_type))); builder.set_compressor_params(compression_parameters::no_compression()); @@ -329,7 +323,7 @@ SEASTAR_TEST_CASE(datafile_generation_04) { m.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 4, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 4, la, big); auto fname = sstable::filename(tmpdir_path, "ks", "cf", la, 4, big, component_type::Data); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, fname] { @@ -384,7 +378,7 @@ SEASTAR_TEST_CASE(datafile_generation_05) { // PRIMARY KEY (p1, c1) // ) WITH compression = {}; // INSERT INTO test (p1, c1, r1) VALUES ('key1', 'abc', 1) USING TTL 3600; - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { schema_builder builder(make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}}, {}, utf8_type))); builder.set_compressor_params(compression_parameters::no_compression()); @@ -402,7 +396,7 @@ SEASTAR_TEST_CASE(datafile_generation_05) { mt->apply(std::move(m)); auto now = to_gc_clock(db_clock::from_time_t(0)); - auto sst = make_sstable(s, tmpdir_path, 5, la, big, now); + auto sst = env.make_sstable(s, tmpdir_path, 5, la, big, default_sstable_buffer_size(), now); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, tmpdir_path] { auto fname = sstable::filename(tmpdir_path, "ks", "cf", la, 5, big, component_type::Data); @@ -459,7 +453,7 @@ SEASTAR_TEST_CASE(datafile_generation_06) { // INSERT INTO test (p1, c1, r1) VALUES ('key1', 'abc', 1); // after flushed: // DELETE r1 FROM test WHERE p1 = 'key1' AND c1 = 'abc'; - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { schema_builder builder(make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}}, {}, utf8_type))); builder.set_compressor_params(compression_parameters::no_compression()); @@ -476,7 +470,7 @@ SEASTAR_TEST_CASE(datafile_generation_06) { m.set_clustered_cell(c_key, r1_col, make_dead_atomic_cell(3600)); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 6, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 6, la, big); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, tmpdir_path] { auto fname = sstable::filename(tmpdir_path, "ks", "cf", la, 6, big, component_type::Data); @@ -530,7 +524,7 @@ SEASTAR_TEST_CASE(datafile_generation_07) { // ) WITH compression = {}; // INSERT INTO test (p1, c1, r1) VALUES ('key1', 'abc', 1); // INSERT INTO test (p1, c1, r1) VALUES ('key2', 'cde', 1); - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}}, {}, utf8_type)); @@ -552,7 +546,7 @@ SEASTAR_TEST_CASE(datafile_generation_07) { m2.set_clustered_cell(c_key2, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m2)); - auto sst = make_sstable(s, tmpdir_path, 7, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 7, la, big); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, tmpdir_path] { auto fname = sstable::filename(tmpdir_path, "ks", "cf", la, 7, big, component_type::Index); @@ -590,7 +584,7 @@ SEASTAR_TEST_CASE(datafile_generation_08) { // r1 int, // PRIMARY KEY (p1, c1) // ) WITH compression = {}; - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", int32_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}}, {}, utf8_type)); @@ -608,7 +602,7 @@ SEASTAR_TEST_CASE(datafile_generation_08) { mt->apply(std::move(m)); } - auto sst = make_sstable(s, tmpdir_path, 8, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 8, la, big); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, tmpdir_path] { auto fname = sstable::filename(tmpdir_path, "ks", "cf", la, 8, big, component_type::Summary); @@ -652,7 +646,7 @@ SEASTAR_TEST_CASE(datafile_generation_08) { SEASTAR_TEST_CASE(datafile_generation_09) { // Test that generated sstable components can be successfully loaded. - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}}, {}, utf8_type)); @@ -667,10 +661,10 @@ SEASTAR_TEST_CASE(datafile_generation_09) { m.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 9, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 9, la, big); - return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, tmpdir_path] { - auto sst2 = make_sstable(s, tmpdir_path, 9, la, big); + return write_memtable_to_sstable_for_test(*mt, sst).then([&env, mt, sst, s, tmpdir_path] { + auto sst2 = env.make_sstable(s, tmpdir_path, 9, la, big); return sstables::test(sst2).read_summary().then([sst, sst2] { summary& sst1_s = sstables::test(sst).get_summary(); @@ -697,7 +691,7 @@ template static future<> test_digest_and_checksum(sstable_version_types version) { // Check that the component Digest was properly generated by using the // approach described above. - return test_setup::do_with_tmp_directory([version] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([version] (test_env& env, sstring tmpdir_path) { schema_builder builder(make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}}, {}, utf8_type))); builder.set_compressor_params(compression_parameters::no_compression()); @@ -714,7 +708,7 @@ static future<> test_digest_and_checksum(sstable_version_types version) { m.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 10, version, big); + auto sst = env.make_sstable(s, tmpdir_path, 10, version, big); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, version, tmpdir_path] { auto fname = sstable::filename(tmpdir_path, "ks", "cf", version, 10, big, component_type::Data); @@ -780,7 +774,7 @@ SEASTAR_TEST_CASE(datafile_generation_10) { } SEASTAR_TEST_CASE(datafile_generation_11) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = complex_schema(); auto mt = make_lw_shared(s); @@ -830,9 +824,9 @@ SEASTAR_TEST_CASE(datafile_generation_11) { return t->deserialize_mutation_form(bv).materialize(*t); }; - auto sst = make_sstable(s, tmpdir_path, 11, la, big); - return write_memtable_to_sstable_for_test(*mt, sst).then([s, sst, mt, verifier, tomb, &static_set_col, tmpdir_path] { - return reusable_sst(s, tmpdir_path, 11).then([s, verifier, tomb, &static_set_col] (auto sstp) mutable { + auto sst = env.make_sstable(s, tmpdir_path, 11, la, big); + return write_memtable_to_sstable_for_test(*mt, sst).then([&env, s, sst, mt, verifier, tomb, &static_set_col, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, 11).then([s, verifier, tomb, &static_set_col] (auto sstp) mutable { return do_with(make_dkey(s, "key1"), [sstp, s, verifier, tomb, &static_set_col] (auto& key) { auto rd = make_lw_shared(sstp->read_row_flat(s, key)); return read_mutation_from_flat_mutation_reader(*rd, db::no_timeout).then([sstp, s, verifier, tomb, &static_set_col, rd] (auto mutation) { @@ -878,7 +872,7 @@ SEASTAR_TEST_CASE(datafile_generation_11) { } SEASTAR_TEST_CASE(datafile_generation_12) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = complex_schema(); auto mt = make_lw_shared(s); @@ -892,9 +886,9 @@ SEASTAR_TEST_CASE(datafile_generation_12) { m.partition().apply_delete(*s, cp, tomb); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 12, la, big); - return write_memtable_to_sstable_for_test(*mt, sst).then([s, tomb, tmpdir_path] { - return reusable_sst(s, tmpdir_path, 12).then([s, tomb] (auto sstp) mutable { + auto sst = env.make_sstable(s, tmpdir_path, 12, la, big); + return write_memtable_to_sstable_for_test(*mt, sst).then([&env, s, tomb, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, 12).then([s, tomb] (auto sstp) mutable { return do_with(make_dkey(s, "key1"), [sstp, s, tomb] (auto& key) { auto rd = make_lw_shared(sstp->read_row_flat(s, key)); return read_mutation_from_flat_mutation_reader(*rd, db::no_timeout).then([sstp, s, tomb, rd] (auto mutation) { @@ -911,7 +905,7 @@ SEASTAR_TEST_CASE(datafile_generation_12) { } static future<> sstable_compression_test(compressor_ptr c, unsigned generation) { - return test_setup::do_with_tmp_directory([c, generation] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([c, generation] (test_env& env, sstring tmpdir_path) { // NOTE: set a given compressor algorithm to schema. schema_builder builder(complex_schema()); builder.set_compressor_params(c); @@ -928,9 +922,9 @@ static future<> sstable_compression_test(compressor_ptr c, unsigned generation) m.partition().apply_delete(*s, cp, tomb); mtp->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, generation, la, big); - return write_memtable_to_sstable_for_test(*mtp, sst).then([s, tomb, generation, tmpdir_path] { - return reusable_sst(s, tmpdir_path, generation).then([s, tomb] (auto sstp) mutable { + auto sst = env.make_sstable(s, tmpdir_path, generation, la, big); + return write_memtable_to_sstable_for_test(*mtp, sst).then([&env, s, tomb, generation, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, generation).then([s, tomb] (auto sstp) mutable { return do_with(make_dkey(s, "key1"), [sstp, s, tomb] (auto& key) { auto rd = make_lw_shared(sstp->read_row_flat(s, key)); return read_mutation_from_flat_mutation_reader(*rd, db::no_timeout).then([sstp, s, tomb, rd] (auto mutation) { @@ -959,7 +953,7 @@ SEASTAR_TEST_CASE(datafile_generation_15) { } SEASTAR_TEST_CASE(datafile_generation_16) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = uncompressed_schema(); auto mtp = make_lw_shared(s); @@ -974,9 +968,9 @@ SEASTAR_TEST_CASE(datafile_generation_16) { mtp->apply(std::move(m)); } - auto sst = make_sstable(s, tmpdir_path, 16, la, big); - return write_memtable_to_sstable_for_test(*mtp, sst).then([s, tmpdir_path] { - return reusable_sst(s, tmpdir_path, 16).then([] (auto s) { + auto sst = env.make_sstable(s, tmpdir_path, 16, la, big); + return write_memtable_to_sstable_for_test(*mtp, sst).then([&env, s, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, 16).then([] (auto s) { // Not crashing is enough return make_ready_future<>(); }); @@ -992,21 +986,17 @@ SEASTAR_TEST_CASE(datafile_generation_16) { // therefore may block. The future value is a shared sstable - a reference- // counting pointer to an sstable - allowing for the returned handle to // be passed around until no longer needed. -static future open_sstable(schema_ptr schema, sstring dir, unsigned long generation) { - auto sst = sstables::make_sstable(std::move(schema), dir, generation, - sstables::sstable::version_types::la, - sstables::sstable::format_types::big); - auto fut = sst->load(); - return fut.then([sst = std::move(sst)] { return std::move(sst); }); +static future open_sstable(test_env& env, schema_ptr schema, sstring dir, unsigned long generation) { + return env.reusable_sst(std::move(schema), dir, generation); } // open_sstables() opens several generations of the same sstable, returning, // after all the tables have been open, their vector. -static future> open_sstables(schema_ptr s, sstring dir, std::vector generations) { +static future> open_sstables(test_env& env, schema_ptr s, sstring dir, std::vector generations) { return do_with(std::vector(), - [dir = std::move(dir), generations = std::move(generations), s] (auto& ret) mutable { - return parallel_for_each(generations, [&ret, &dir, s] (unsigned long generation) { - return open_sstable(s, dir, generation).then([&ret] (sstables::shared_sstable sst) { + [&env, dir = std::move(dir), generations = std::move(generations), s] (auto& ret) mutable { + return parallel_for_each(generations, [&env, &ret, &dir, s] (unsigned long generation) { + return open_sstable(env, s, dir, generation).then([&ret] (sstables::shared_sstable sst) { ret.push_back(std::move(sst)); }); }).then([&ret] { @@ -1042,7 +1032,7 @@ static flat_mutation_reader make_normalizing_sstable_reader(shared_sstable sst, } SEASTAR_TEST_CASE(compaction_manager_test) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; BOOST_REQUIRE(smp::count == 1); auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, @@ -1052,7 +1042,6 @@ SEASTAR_TEST_CASE(compaction_manager_test) { cm->start(); auto tmp = tmpdir(); - column_family::config cfg; cfg.datadir = tmp.path().string(); cfg.enable_commitlog = false; @@ -1067,7 +1056,7 @@ SEASTAR_TEST_CASE(compaction_manager_test) { auto generations = make_lw_shared>({1, 2, 3, 4}); - do_for_each(*generations, [generations, cf, cm, s, &tmp] (unsigned long generation) { + do_for_each(*generations, [&env, generations, cf, cm, s, &tmp] (unsigned long generation) { // create 4 sstables of similar size to be compacted later on. auto mt = make_lw_shared(s); @@ -1082,7 +1071,7 @@ SEASTAR_TEST_CASE(compaction_manager_test) { m.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmp.path().string(), column_family_test::calculate_generation_for_new_table(*cf), la, big); + auto sst = env.make_sstable(s, tmp.path().string(), column_family_test::calculate_generation_for_new_table(*cf), la, big); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, cf] { return sst->load().then([sst, cf] { @@ -1090,7 +1079,7 @@ SEASTAR_TEST_CASE(compaction_manager_test) { return make_ready_future<>(); }); }); - }).then([cf, cm, generations] { + }).then([&env, cf, cm, generations] { // submit cf to compaction manager and then check that cf's sstables // were compacted. @@ -1118,8 +1107,8 @@ SEASTAR_TEST_CASE(compaction_manager_test) { }); }); }); - }).finally([s, cm, cl_stats, tracker] { - return cm->stop().then([cm] {}); + }).finally([&env, s, cm, cl_stats, tracker] { + return cm->stop().then([&env, cm] {}); }).get(); }); } @@ -1147,13 +1136,13 @@ SEASTAR_TEST_CASE(compact) { auto cf = make_lw_shared(s, column_family_test_config(), column_family::no_commitlog(), *cm, *cl_stats, *tracker); cf->mark_ready_for_writes(); - return open_sstables(s, "tests/sstables/compaction", {1,2,3}).then([s, cf, cm, generation] (auto sstables) { - return test_setup::do_with_tmp_directory([sstables, s, generation, cf, cm] (sstring tmpdir_path) { - auto new_sstable = [generation, s, tmpdir_path] { - return sstables::make_sstable(s, tmpdir_path, + return test_setup::do_with_tmp_directory([s, generation, cf, cm] (test_env& env, sstring tmpdir_path) { + return open_sstables(env, s, "tests/sstables/compaction", {1,2,3}).then([&env, tmpdir_path, s, cf, cm, generation] (auto sstables) { + auto new_sstable = [&env, generation, s, tmpdir_path] { + return env.make_sstable(s, tmpdir_path, generation, sstables::sstable::version_types::la, sstables::sstable::format_types::big); }; - return sstables::compact_sstables(sstables::compaction_descriptor(std::move(sstables)), *cf, new_sstable, replacer_fn_no_op()).then([s, generation, cf, cm, tmpdir_path] (auto) { + return sstables::compact_sstables(sstables::compaction_descriptor(std::move(sstables)), *cf, new_sstable, replacer_fn_no_op()).then([&env, s, generation, cf, cm, tmpdir_path] (auto) { // Verify that the compacted sstable has the right content. We expect to see: // name | age | height // -------+-----+-------- @@ -1161,7 +1150,7 @@ SEASTAR_TEST_CASE(compact) { // tom | 20 | 180 // john | 20 | deleted // nadav - deleted partition - return open_sstable(s, tmpdir_path, generation).then([s] (shared_sstable sst) { + return open_sstable(env, s, tmpdir_path, generation).then([s] (shared_sstable sst) { auto reader = make_lw_shared(sstable_reader(sst, s)); // reader holds sst and s alive. return read_mutation_from_flat_mutation_reader(*reader, db::no_timeout).then([reader, s] (mutation_opt m) { BOOST_REQUIRE(m); @@ -1232,46 +1221,8 @@ static std::vector get_candidates_for_leveled_strategy return candidates; } -struct column_family_for_tests { - struct data { - schema_ptr s; - cache_tracker tracker; - column_family::config cfg; - cell_locker_stats cl_stats; - compaction_manager cm; - lw_shared_ptr cf; - }; - lw_shared_ptr _data; - - column_family_for_tests() - : column_family_for_tests( - schema_builder(some_keyspace, some_column_family) - .with_column(utf8_type->decompose("p1"), utf8_type, column_kind::partition_key) - .build() - ) - { } - - explicit column_family_for_tests(schema_ptr s) - : _data(make_lw_shared()) - { - _data->s = s; - _data->cfg.enable_disk_writes = false; - _data->cfg.enable_commitlog = false; - _data->cfg.large_data_handler = &nop_lp_handler; - _data->cf = make_lw_shared(_data->s, _data->cfg, column_family::no_commitlog(), _data->cm, _data->cl_stats, _data->tracker); - _data->cf->mark_ready_for_writes(); - } - - schema_ptr schema() { return _data->s; } - - operator lw_shared_ptr() { return _data->cf; } - - column_family& operator*() { return *_data->cf; } - column_family* operator->() { return _data->cf.get(); } -}; - // Return vector of sstables generated by compaction. Only relevant for leveled one. -static future> compact_sstables(sstring tmpdir_path, std::vector generations_to_compact, +static future> compact_sstables(test_env& env, sstring tmpdir_path, std::vector generations_to_compact, unsigned long new_generation, bool create_sstables, uint64_t min_sstable_size, compaction_strategy_type strategy) { BOOST_REQUIRE(smp::count == 1); schema_builder builder(make_lw_shared(schema({}, some_keyspace, some_column_family, @@ -1288,16 +1239,16 @@ static future> compact_sstables(sstring tmpdir_path, auto f = make_ready_future<>(); - return f.then([generations, sstables, s, create_sstables, min_sstable_size, tmpdir_path] () mutable { + return f.then([&env, generations, sstables, s, create_sstables, min_sstable_size, tmpdir_path] () mutable { if (!create_sstables) { - return open_sstables(s, tmpdir_path, *generations).then([sstables] (auto opened_sstables) mutable { + return open_sstables(env, s, tmpdir_path, *generations).then([sstables] (auto opened_sstables) mutable { for (auto& sst : opened_sstables) { sstables->push_back(sst); } return make_ready_future<>(); }); } - return do_for_each(*generations, [generations, sstables, s, min_sstable_size, tmpdir_path] (unsigned long generation) { + return do_for_each(*generations, [&env, generations, sstables, s, min_sstable_size, tmpdir_path] (unsigned long generation) { auto mt = make_lw_shared(s); const column_definition& r1_col = *s->get_column_definition("r1"); @@ -1310,7 +1261,7 @@ static future> compact_sstables(sstring tmpdir_path, m.set_clustered_cell(c_key, r1_col, make_atomic_cell(utf8_type, bytes(min_sstable_size, 'a'))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, generation, la, big); + auto sst = env.make_sstable(s, tmpdir_path, generation, la, big); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, sstables] { return sst->load().then([sst, sstables] { @@ -1319,12 +1270,12 @@ static future> compact_sstables(sstring tmpdir_path, }); }); }); - }).then([cf, sstables, new_generation, generations, strategy, created, min_sstable_size, s, tmpdir_path] () mutable { + }).then([&env, cf, sstables, new_generation, generations, strategy, created, min_sstable_size, s, tmpdir_path] () mutable { auto generation = make_lw_shared(new_generation); - auto new_sstable = [generation, created, s, tmpdir_path] { + auto new_sstable = [&env, generation, created, s, tmpdir_path] { auto gen = (*generation)++; created->push_back(gen); - return sstables::make_sstable(s, tmpdir_path, + return env.make_sstable(s, tmpdir_path, gen, sstables::sstable::version_types::la, sstables::sstable::format_types::big); }; // We must have opened at least all original candidates. @@ -1365,9 +1316,9 @@ static future> compact_sstables(sstring tmpdir_path, }); } -static future<> compact_sstables(sstring tmpdir_path, std::vector generations_to_compact, unsigned long new_generation, bool create_sstables = true) { +static future<> compact_sstables(test_env& env, sstring tmpdir_path, std::vector generations_to_compact, unsigned long new_generation, bool create_sstables = true) { uint64_t min_sstable_size = 50; - return compact_sstables(tmpdir_path, std::move(generations_to_compact), new_generation, create_sstables, min_sstable_size, + return compact_sstables(env, tmpdir_path, std::move(generations_to_compact), new_generation, create_sstables, min_sstable_size, compaction_strategy_type::size_tiered).then([new_generation] (auto ret) { // size tiered compaction will output at most one sstable, let's assert that. BOOST_REQUIRE(ret.size() == 1); @@ -1376,13 +1327,13 @@ static future<> compact_sstables(sstring tmpdir_path, std::vector }); } -static future<> check_compacted_sstables(sstring tmpdir_path, unsigned long generation, std::vector compacted_generations) { +static future<> check_compacted_sstables(test_env& env, sstring tmpdir_path, unsigned long generation, std::vector compacted_generations) { auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}}, {}, utf8_type)); auto generations = make_lw_shared>(std::move(compacted_generations)); - return open_sstable(s, tmpdir_path, generation).then([s, generations] (shared_sstable sst) { + return open_sstable(env, s, tmpdir_path, generation).then([s, generations] (shared_sstable sst) { auto reader = sstable_reader(sst, s); // reader holds sst and s alive. auto keys = make_lw_shared>(); @@ -1420,29 +1371,29 @@ SEASTAR_TEST_CASE(compact_02) { // By the way, automatic compaction isn't tested here, instead the // strategy algorithm that selects candidates for compaction. - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { // Compact 4 sstables into 1 using size-tiered strategy to select sstables. // E.g.: generations 18, 19, 20 and 21 will be compacted into generation 22. - return compact_sstables(tmpdir_path, { 18, 19, 20, 21 }, 22).then([tmpdir_path] { + return compact_sstables(env, tmpdir_path, { 18, 19, 20, 21 }, 22).then([&env, tmpdir_path] { // Check that generation 22 contains all keys of generations 18, 19, 20 and 21. - return check_compacted_sstables(tmpdir_path, 22, { 18, 19, 20, 21 }); - }).then([tmpdir_path] { - return compact_sstables(tmpdir_path, { 23, 24, 25, 26 }, 27).then([tmpdir_path] { - return check_compacted_sstables(tmpdir_path, 27, { 23, 24, 25, 26 }); + return check_compacted_sstables(env, tmpdir_path, 22, { 18, 19, 20, 21 }); + }).then([&env, tmpdir_path] { + return compact_sstables(env, tmpdir_path, { 23, 24, 25, 26 }, 27).then([&env, tmpdir_path] { + return check_compacted_sstables(env, tmpdir_path, 27, { 23, 24, 25, 26 }); }); - }).then([tmpdir_path] { - return compact_sstables(tmpdir_path, { 28, 29, 30, 31 }, 32).then([tmpdir_path] { - return check_compacted_sstables(tmpdir_path, 32, { 28, 29, 30, 31 }); + }).then([&env, tmpdir_path] { + return compact_sstables(env, tmpdir_path, { 28, 29, 30, 31 }, 32).then([&env, tmpdir_path] { + return check_compacted_sstables(env, tmpdir_path, 32, { 28, 29, 30, 31 }); }); - }).then([tmpdir_path] { - return compact_sstables(tmpdir_path, { 33, 34, 35, 36 }, 37).then([tmpdir_path] { - return check_compacted_sstables(tmpdir_path, 37, { 33, 34, 35, 36 }); + }).then([&env, tmpdir_path] { + return compact_sstables(env, tmpdir_path, { 33, 34, 35, 36 }, 37).then([&env, tmpdir_path] { + return check_compacted_sstables(env, tmpdir_path, 37, { 33, 34, 35, 36 }); }); - }).then([tmpdir_path] { + }).then([&env, tmpdir_path] { // In this step, we compact 4 compacted sstables. - return compact_sstables(tmpdir_path, { 22, 27, 32, 37 }, 38, false).then([tmpdir_path] { + return compact_sstables(env, tmpdir_path, { 22, 27, 32, 37 }, 38, false).then([&env, tmpdir_path] { // Check that the compacted sstable contains all keys. - return check_compacted_sstables(tmpdir_path, 38, + return check_compacted_sstables(env, tmpdir_path, 38, { 18, 19, 20, 21, 23, 24, 25, 26, 28, 29, 30, 31, 33, 34, 35, 36 }); }); }); @@ -1450,7 +1401,7 @@ SEASTAR_TEST_CASE(compact_02) { } SEASTAR_TEST_CASE(datafile_generation_37) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = compact_simple_dense_schema(); auto mtp = make_lw_shared(s); @@ -1464,9 +1415,9 @@ SEASTAR_TEST_CASE(datafile_generation_37) { m.set_clustered_cell(c_key, cl2, make_atomic_cell(bytes_type, bytes_type->decompose(data_value(to_bytes("cl2"))))); mtp->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 37, la, big); - return write_memtable_to_sstable_for_test(*mtp, sst).then([s, tmpdir_path] { - return reusable_sst(s, tmpdir_path, 37).then([s, tmpdir_path] (auto sstp) { + auto sst = env.make_sstable(s, tmpdir_path, 37, la, big); + return write_memtable_to_sstable_for_test(*mtp, sst).then([&env, s, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, 37).then([s, tmpdir_path] (auto sstp) { return do_with(make_dkey(s, "key1"), [sstp, s] (auto& key) { auto rd = make_lw_shared(sstp->read_row_flat(s, key)); return read_mutation_from_flat_mutation_reader(*rd, db::no_timeout).then([sstp, s, rd] (auto mutation) { @@ -1485,7 +1436,7 @@ SEASTAR_TEST_CASE(datafile_generation_37) { } SEASTAR_TEST_CASE(datafile_generation_38) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = compact_dense_schema(); auto mtp = make_lw_shared(s); @@ -1499,9 +1450,9 @@ SEASTAR_TEST_CASE(datafile_generation_38) { m.set_clustered_cell(c_key, cl3, make_atomic_cell(bytes_type, bytes_type->decompose(data_value(to_bytes("cl3"))))); mtp->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 38, la, big); - return write_memtable_to_sstable_for_test(*mtp, sst).then([s, tmpdir_path] { - return reusable_sst(s, tmpdir_path, 38).then([s] (auto sstp) { + auto sst = env.make_sstable(s, tmpdir_path, 38, la, big); + return write_memtable_to_sstable_for_test(*mtp, sst).then([&env, s, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, 38).then([s] (auto sstp) { return do_with(make_dkey(s, "key1"), [sstp, s] (auto& key) { auto rd = make_lw_shared(sstp->read_row_flat(s, key)); return read_mutation_from_flat_mutation_reader(*rd, db::no_timeout).then([sstp, s, rd] (auto mutation) { @@ -1519,7 +1470,7 @@ SEASTAR_TEST_CASE(datafile_generation_38) { } SEASTAR_TEST_CASE(datafile_generation_39) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = compact_sparse_schema(); auto mtp = make_lw_shared(s); @@ -1535,9 +1486,9 @@ SEASTAR_TEST_CASE(datafile_generation_39) { m.set_clustered_cell(c_key, cl2, make_atomic_cell(bytes_type, bytes_type->decompose(data_value(to_bytes("cl2"))))); mtp->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 39, la, big); - return write_memtable_to_sstable_for_test(*mtp, sst).then([s, tmpdir_path] { - return reusable_sst(s, tmpdir_path, 39).then([s] (auto sstp) { + auto sst = env.make_sstable(s, tmpdir_path, 39, la, big); + return write_memtable_to_sstable_for_test(*mtp, sst).then([&env, s, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, 39).then([s] (auto sstp) { return do_with(make_dkey(s, "key1"), [sstp, s] (auto& key) { auto rd = make_lw_shared(sstp->read_row_flat(s, key)); return read_mutation_from_flat_mutation_reader(*rd, db::no_timeout).then([sstp, s, rd] (auto mutation) { @@ -1554,7 +1505,7 @@ SEASTAR_TEST_CASE(datafile_generation_39) { } SEASTAR_TEST_CASE(datafile_generation_40) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { // Data file with clustering key sorted in descending order // // Respective CQL table and CQL insert: @@ -1588,7 +1539,7 @@ SEASTAR_TEST_CASE(datafile_generation_40) { m.set_clustered_cell(cb, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 40, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 40, la, big); return write_memtable_to_sstable_for_test(*mt, sst).then([mt, sst, s, tmpdir_path] { auto fname = sstable::filename(tmpdir_path, "ks", "cf", la, 40, big, component_type::Data); @@ -1617,7 +1568,7 @@ SEASTAR_TEST_CASE(datafile_generation_40) { } SEASTAR_TEST_CASE(datafile_generation_41) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}, {"r2", int32_type}}, {}, utf8_type)); @@ -1631,9 +1582,9 @@ SEASTAR_TEST_CASE(datafile_generation_41) { m.partition().apply_delete(*s, std::move(c_key), tomb); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 41, la, big); - return write_memtable_to_sstable_for_test(*mt, sst).then([s, tomb, tmpdir_path] { - return reusable_sst(s, tmpdir_path, 41).then([s, tomb] (auto sstp) mutable { + auto sst = env.make_sstable(s, tmpdir_path, 41, la, big); + return write_memtable_to_sstable_for_test(*mt, sst).then([&env, s, tomb, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, 41).then([s, tomb] (auto sstp) mutable { return do_with(make_dkey(s, "key1"), [sstp, s, tomb] (auto& key) { auto rd = make_lw_shared(sstp->read_row_flat(s, key)); return read_mutation_from_flat_mutation_reader(*rd, db::no_timeout).then([sstp, s, tomb, rd] (auto mutation) { @@ -1653,11 +1604,11 @@ SEASTAR_TEST_CASE(check_compaction_ancestor_metadata) { // check that ancestors list of compacted sstable is correct. - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { - return compact_sstables(tmpdir_path, { 42, 43, 44, 45 }, 46).then([tmpdir_path] { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { + return compact_sstables(env, tmpdir_path, { 42, 43, 44, 45 }, 46).then([&env, tmpdir_path] { auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", utf8_type}}, {}, utf8_type)); - return open_sstable(s, tmpdir_path, 46).then([] (shared_sstable sst) { + return open_sstable(env, s, tmpdir_path, 46).then([] (shared_sstable sst) { std::set ancestors; const compaction_metadata& cm = sst->get_compaction_metadata(); for (auto& ancestor : cm.ancestors.elements) { @@ -1676,7 +1627,7 @@ SEASTAR_TEST_CASE(check_compaction_ancestor_metadata) { SEASTAR_TEST_CASE(datafile_generation_47) { // Tests the problem in which the sstable row parser would hang. - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", utf8_type}}, {}, utf8_type)); @@ -1690,9 +1641,9 @@ SEASTAR_TEST_CASE(datafile_generation_47) { m.set_clustered_cell(c_key, r1_col, make_atomic_cell(utf8_type, bytes(512*1024, 'a'))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmpdir_path, 47, la, big); - return write_memtable_to_sstable_for_test(*mt, sst).then([s, tmpdir_path] { - return reusable_sst(s, tmpdir_path, 47).then([s] (auto sstp) mutable { + auto sst = env.make_sstable(s, tmpdir_path, 47, la, big); + return write_memtable_to_sstable_for_test(*mt, sst).then([&env, s, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, 47).then([s] (auto sstp) mutable { auto reader = make_lw_shared(sstable_reader(sstp, s)); return repeat([reader] { return (*reader)(db::no_timeout).then([] (mutation_fragment_opt m) { @@ -1708,8 +1659,8 @@ SEASTAR_TEST_CASE(datafile_generation_47) { } SEASTAR_TEST_CASE(test_counter_write) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { - return seastar::async([tmpdir_path] { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { + return seastar::async([&env, tmpdir_path] { auto s = schema_builder(some_keyspace, some_column_family) .with_column("p1", utf8_type, column_kind::partition_key) .with_column("c1", utf8_type, column_kind::clustering_key) @@ -1747,10 +1698,10 @@ SEASTAR_TEST_CASE(test_counter_write) { mt->apply(m); - auto sst = make_sstable(s, tmpdir_path, 900, la, big); + auto sst = env.make_sstable(s, tmpdir_path, 900, la, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - auto sstp = reusable_sst(s, tmpdir_path, 900).get0(); + auto sstp = env.reusable_sst(s, tmpdir_path, 900).get0(); assert_that(sstable_reader(sstp, s)) .produces(m) .produces_end_of_stream(); @@ -1760,26 +1711,6 @@ SEASTAR_TEST_CASE(test_counter_write) { // Leveled compaction strategy tests -static dht::token create_token_from_key(sstring key) { - sstables::key_view key_view = sstables::key_view(bytes_view(reinterpret_cast(key.c_str()), key.size())); - dht::token token = dht::global_partitioner().get_token(key_view); - assert(token == dht::global_partitioner().get_token(key_view)); - return token; -} - -static range create_token_range_from_keys(sstring start_key, sstring end_key) { - dht::token start = create_token_from_key(start_key); - assert(engine().cpu_id() == dht::global_partitioner().shard_of(start)); - dht::token end = create_token_from_key(end_key); - assert(engine().cpu_id() == dht::global_partitioner().shard_of(end)); - assert(end >= start); - return range::make(start, end); -} - -namespace dht { - extern std::unique_ptr default_partitioner; -} - static std::vector> token_generation_for_shard(unsigned tokens_to_generate, unsigned shard, unsigned ignore_msb = 0, unsigned smp_count = smp::count) { unsigned tokens = 0; @@ -1811,9 +1742,9 @@ static std::vector> token_generation_for_current_ return token_generation_for_shard(tokens_to_generate, engine().cpu_id()); } -static void add_sstable_for_leveled_test(lw_shared_ptr cf, int64_t gen, uint64_t fake_data_size, +static void add_sstable_for_leveled_test(test_env& env, lw_shared_ptr cf, int64_t gen, uint64_t fake_data_size, uint32_t sstable_level, sstring first_key, sstring last_key, int64_t max_timestamp = 0) { - auto sst = make_sstable(cf->schema(), "", gen, la, big); + auto sst = env.make_sstable(cf->schema(), "", gen, la, big); sstables::test(sst).set_values_for_leveled_strategy(fake_data_size, sstable_level, max_timestamp, std::move(first_key), std::move(last_key)); assert(sst->data_size() == fake_data_size); assert(sst->get_sstable_level() == sstable_level); @@ -1822,14 +1753,14 @@ static void add_sstable_for_leveled_test(lw_shared_ptr cf, int64_ column_family_test(cf).add_sstable(sst); } -static shared_sstable add_sstable_for_overlapping_test(lw_shared_ptr cf, int64_t gen, sstring first_key, sstring last_key, stats_metadata stats = {}) { - auto sst = make_sstable(cf->schema(), "", gen, la, big); +static shared_sstable add_sstable_for_overlapping_test(test_env& env, lw_shared_ptr cf, int64_t gen, sstring first_key, sstring last_key, stats_metadata stats = {}) { + auto sst = env.make_sstable(cf->schema(), "", gen, la, big); sstables::test(sst).set_values(std::move(first_key), std::move(last_key), std::move(stats)); column_family_test(cf).add_sstable(sst); return sst; } -static shared_sstable sstable_for_overlapping_test(const schema_ptr& schema, int64_t gen, sstring first_key, sstring last_key, uint32_t level = 0) { - auto sst = make_sstable(schema, "", gen, la, big); +static shared_sstable sstable_for_overlapping_test(test_env& env, const schema_ptr& schema, int64_t gen, sstring first_key, sstring last_key, uint32_t level = 0) { + auto sst = env.make_sstable(schema, "", gen, la, big); sstables::test(sst).set_values_for_leveled_strategy(0, level, 0, std::move(first_key), std::move(last_key)); return sst; } @@ -1859,6 +1790,7 @@ static bool sstable_overlaps(const lw_shared_ptr& cf, int64_t gen } SEASTAR_TEST_CASE(leveled_01) { + test_env env; column_family_for_tests cf; auto key_and_token_pair = token_generation_for_current_shard(50); @@ -1868,10 +1800,10 @@ SEASTAR_TEST_CASE(leveled_01) { auto max_sstable_size = max_sstable_size_in_mb*1024*1024; // Creating two sstables which key range overlap. - add_sstable_for_leveled_test(cf, /*gen*/1, max_sstable_size, /*level*/0, min_key, max_key); + add_sstable_for_leveled_test(env, cf, /*gen*/1, max_sstable_size, /*level*/0, min_key, max_key); BOOST_REQUIRE(cf->get_sstables()->size() == 1); - add_sstable_for_leveled_test(cf, /*gen*/2, max_sstable_size, /*level*/0, key_and_token_pair[1].first, max_key); + add_sstable_for_leveled_test(env, cf, /*gen*/2, max_sstable_size, /*level*/0, key_and_token_pair[1].first, max_key); BOOST_REQUIRE(cf->get_sstables()->size() == 2); BOOST_REQUIRE(key_range_overlaps(min_key, max_key, key_and_token_pair[1].first, max_key) == true); @@ -1900,6 +1832,7 @@ SEASTAR_TEST_CASE(leveled_01) { } SEASTAR_TEST_CASE(leveled_02) { + test_env env; column_family_for_tests cf; auto key_and_token_pair = token_generation_for_current_shard(50); @@ -1911,13 +1844,13 @@ SEASTAR_TEST_CASE(leveled_02) { // Generation 1 will overlap only with generation 2. // Remember that for level0, leveled strategy prefer choosing older sstables as candidates. - add_sstable_for_leveled_test(cf, /*gen*/1, max_sstable_size, /*level*/0, min_key, key_and_token_pair[10].first); + add_sstable_for_leveled_test(env, cf, /*gen*/1, max_sstable_size, /*level*/0, min_key, key_and_token_pair[10].first); BOOST_REQUIRE(cf->get_sstables()->size() == 1); - add_sstable_for_leveled_test(cf, /*gen*/2, max_sstable_size, /*level*/0, min_key, key_and_token_pair[20].first); + add_sstable_for_leveled_test(env, cf, /*gen*/2, max_sstable_size, /*level*/0, min_key, key_and_token_pair[20].first); BOOST_REQUIRE(cf->get_sstables()->size() == 2); - add_sstable_for_leveled_test(cf, /*gen*/3, max_sstable_size, /*level*/0, key_and_token_pair[30].first, max_key); + add_sstable_for_leveled_test(env, cf, /*gen*/3, max_sstable_size, /*level*/0, key_and_token_pair[30].first, max_key); BOOST_REQUIRE(cf->get_sstables()->size() == 3); BOOST_REQUIRE(key_range_overlaps(min_key, key_and_token_pair[10].first, min_key, key_and_token_pair[20].first) == true); @@ -1951,6 +1884,7 @@ SEASTAR_TEST_CASE(leveled_02) { } SEASTAR_TEST_CASE(leveled_03) { + test_env env; column_family_for_tests cf; auto key_and_token_pair = token_generation_for_current_shard(50); @@ -1958,12 +1892,12 @@ SEASTAR_TEST_CASE(leveled_03) { auto max_key = key_and_token_pair[key_and_token_pair.size()-1].first; // Creating two sstables of level 0 which overlap - add_sstable_for_leveled_test(cf, /*gen*/1, /*data_size*/1024*1024, /*level*/0, min_key, key_and_token_pair[10].first); - add_sstable_for_leveled_test(cf, /*gen*/2, /*data_size*/1024*1024, /*level*/0, min_key, key_and_token_pair[20].first); + add_sstable_for_leveled_test(env, cf, /*gen*/1, /*data_size*/1024*1024, /*level*/0, min_key, key_and_token_pair[10].first); + add_sstable_for_leveled_test(env, cf, /*gen*/2, /*data_size*/1024*1024, /*level*/0, min_key, key_and_token_pair[20].first); // Creating a sstable of level 1 which overlap with two sstables above. - add_sstable_for_leveled_test(cf, /*gen*/3, /*data_size*/1024*1024, /*level*/1, min_key, key_and_token_pair[30].first); + add_sstable_for_leveled_test(env, cf, /*gen*/3, /*data_size*/1024*1024, /*level*/1, min_key, key_and_token_pair[30].first); // Creating a sstable of level 1 which doesn't overlap with any sstable. - add_sstable_for_leveled_test(cf, /*gen*/4, /*data_size*/1024*1024, /*level*/1, key_and_token_pair[40].first, max_key); + add_sstable_for_leveled_test(env, cf, /*gen*/4, /*data_size*/1024*1024, /*level*/1, key_and_token_pair[40].first, max_key); BOOST_REQUIRE(cf->get_sstables()->size() == 4); @@ -2005,6 +1939,7 @@ SEASTAR_TEST_CASE(leveled_03) { } SEASTAR_TEST_CASE(leveled_04) { + test_env env; column_family_for_tests cf; auto key_and_token_pair = token_generation_for_current_shard(50); @@ -2015,18 +1950,18 @@ SEASTAR_TEST_CASE(leveled_04) { auto max_sstable_size_in_bytes = max_sstable_size_in_mb*1024*1024; // add 1 level-0 sstable to cf. - add_sstable_for_leveled_test(cf, /*gen*/1, /*data_size*/max_sstable_size_in_bytes, /*level*/0, min_key, max_key); + add_sstable_for_leveled_test(env, cf, /*gen*/1, /*data_size*/max_sstable_size_in_bytes, /*level*/0, min_key, max_key); // create two big sstables in level1 to force leveled compaction on it. auto max_bytes_for_l1 = leveled_manifest::max_bytes_for_level(1, max_sstable_size_in_bytes); // NOTE: SSTables in level1 cannot overlap. - add_sstable_for_leveled_test(cf, /*gen*/2, /*data_size*/max_bytes_for_l1, /*level*/1, min_key, key_and_token_pair[25].first); - add_sstable_for_leveled_test(cf, /*gen*/3, /*data_size*/max_bytes_for_l1, /*level*/1, key_and_token_pair[26].first, max_key); + add_sstable_for_leveled_test(env, cf, /*gen*/2, /*data_size*/max_bytes_for_l1, /*level*/1, min_key, key_and_token_pair[25].first); + add_sstable_for_leveled_test(env, cf, /*gen*/3, /*data_size*/max_bytes_for_l1, /*level*/1, key_and_token_pair[26].first, max_key); // Create SSTable in level2 that overlaps with the ones in level1, // so compaction in level1 will select overlapping sstables in // level2. - add_sstable_for_leveled_test(cf, /*gen*/4, /*data_size*/max_sstable_size_in_bytes, /*level*/2, min_key, max_key); + add_sstable_for_leveled_test(env, cf, /*gen*/4, /*data_size*/max_sstable_size_in_bytes, /*level*/2, min_key, max_key); BOOST_REQUIRE(cf->get_sstables()->size() == 4); @@ -2069,10 +2004,10 @@ SEASTAR_TEST_CASE(leveled_04) { SEASTAR_TEST_CASE(leveled_05) { // NOTE: Generations from 48 to 51 are used here. - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { // Check compaction code with leveled strategy. In this test, two sstables of level 0 will be created. - return compact_sstables(tmpdir_path, { 48, 49 }, 50, true, 1024*1024, compaction_strategy_type::leveled).then([tmpdir_path] (auto generations) { + return compact_sstables(env, tmpdir_path, { 48, 49 }, 50, true, 1024*1024, compaction_strategy_type::leveled).then([tmpdir_path] (auto generations) { BOOST_REQUIRE(generations.size() == 2); BOOST_REQUIRE(generations[0] == 50); BOOST_REQUIRE(generations[1] == 51); @@ -2089,7 +2024,7 @@ SEASTAR_TEST_CASE(leveled_05) { SEASTAR_TEST_CASE(leveled_06) { // Test that we can compact a single L1 compaction into an empty L2. - + test_env env; column_family_for_tests cf; auto max_sstable_size_in_mb = 1; @@ -2097,7 +2032,7 @@ SEASTAR_TEST_CASE(leveled_06) { auto max_bytes_for_l1 = leveled_manifest::max_bytes_for_level(1, max_sstable_size_in_bytes); // Create fake sstable that will be compacted into L2. - add_sstable_for_leveled_test(cf, /*gen*/1, /*data_size*/max_bytes_for_l1*2, /*level*/1, "a", "a"); + add_sstable_for_leveled_test(env, cf, /*gen*/1, /*data_size*/max_bytes_for_l1*2, /*level*/1, "a", "a"); BOOST_REQUIRE(cf->get_sstables()->size() == 1); auto candidates = get_candidates_for_leveled_strategy(*cf); @@ -2120,10 +2055,11 @@ SEASTAR_TEST_CASE(leveled_06) { } SEASTAR_TEST_CASE(leveled_07) { + test_env env; column_family_for_tests cf; for (auto i = 0; i < leveled_manifest::MAX_COMPACTING_L0*2; i++) { - add_sstable_for_leveled_test(cf, i, 1024*1024, /*level*/0, "a", "a", i /* max timestamp */); + add_sstable_for_leveled_test(env, cf, i, 1024*1024, /*level*/0, "a", "a", i /* max timestamp */); } auto candidates = get_candidates_for_leveled_strategy(*cf); sstables::size_tiered_compaction_strategy_options stcs_options; @@ -2142,6 +2078,7 @@ SEASTAR_TEST_CASE(leveled_07) { } SEASTAR_TEST_CASE(leveled_invariant_fix) { + test_env env; column_family_for_tests cf; auto sstables_no = cf.schema()->max_compaction_threshold(); @@ -2151,13 +2088,13 @@ SEASTAR_TEST_CASE(leveled_invariant_fix) { auto sstable_max_size = 1024*1024; // add non overlapping with min token to be discarded by strategy - add_sstable_for_leveled_test(cf, 0, sstable_max_size, /*level*/1, min_key, min_key); + add_sstable_for_leveled_test(env, cf, 0, sstable_max_size, /*level*/1, min_key, min_key); for (auto i = 1; i < sstables_no-1; i++) { - add_sstable_for_leveled_test(cf, i, sstable_max_size, /*level*/1, key_and_token_pair[i].first, key_and_token_pair[i].first); + add_sstable_for_leveled_test(env, cf, i, sstable_max_size, /*level*/1, key_and_token_pair[i].first, key_and_token_pair[i].first); } // add large token span sstable into level 1, which overlaps with all sstables added in loop above. - add_sstable_for_leveled_test(cf, sstables_no, sstable_max_size, 1, key_and_token_pair[1].first, max_key); + add_sstable_for_leveled_test(env, cf, sstables_no, sstable_max_size, 1, key_and_token_pair[1].first, max_key); auto candidates = get_candidates_for_leveled_strategy(*cf); sstables::size_tiered_compaction_strategy_options stcs_options; @@ -2176,6 +2113,7 @@ SEASTAR_TEST_CASE(leveled_invariant_fix) { } SEASTAR_TEST_CASE(leveled_stcs_on_L0) { + test_env env; schema_builder builder(make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {}, {}, {}, utf8_type))); builder.set_min_compaction_threshold(4); @@ -2189,9 +2127,9 @@ SEASTAR_TEST_CASE(leveled_stcs_on_L0) { // we don't want level 0 to be worth promoting. auto l0_sstables_size = (sstable_max_size_in_mb*1024*1024)/(l0_sstables_no+1); - add_sstable_for_leveled_test(cf, 0, sstable_max_size_in_mb*1024*1024, /*level*/1, key_and_token_pair[0].first, key_and_token_pair[0].first); + add_sstable_for_leveled_test(env, cf, 0, sstable_max_size_in_mb*1024*1024, /*level*/1, key_and_token_pair[0].first, key_and_token_pair[0].first); for (auto gen = 0; gen < l0_sstables_no; gen++) { - add_sstable_for_leveled_test(cf, gen+1, l0_sstables_size, /*level*/0, key_and_token_pair[0].first, key_and_token_pair[0].first); + add_sstable_for_leveled_test(env, cf, gen+1, l0_sstables_size, /*level*/0, key_and_token_pair[0].first, key_and_token_pair[0].first); } auto candidates = get_candidates_for_leveled_strategy(*cf); BOOST_REQUIRE(candidates.size() == size_t(l0_sstables_no+1)); @@ -2223,6 +2161,7 @@ SEASTAR_TEST_CASE(leveled_stcs_on_L0) { } SEASTAR_TEST_CASE(overlapping_starved_sstables_test) { + test_env env; column_family_for_tests cf; auto key_and_token_pair = token_generation_for_current_shard(5); @@ -2234,9 +2173,9 @@ SEASTAR_TEST_CASE(overlapping_starved_sstables_test) { // to bring a sstable from level 3 that theoretically wasn't compacted // for many rounds and won't introduce an overlap. auto max_bytes_for_l1 = leveled_manifest::max_bytes_for_level(1, max_sstable_size_in_bytes); - add_sstable_for_leveled_test(cf, /*gen*/1, max_bytes_for_l1*1.1, /*level*/1, min_key, key_and_token_pair[2].first); - add_sstable_for_leveled_test(cf, /*gen*/2, max_sstable_size_in_bytes, /*level*/2, min_key, key_and_token_pair[1].first); - add_sstable_for_leveled_test(cf, /*gen*/3, max_sstable_size_in_bytes, /*level*/3, min_key, key_and_token_pair[1].first); + add_sstable_for_leveled_test(env, cf, /*gen*/1, max_bytes_for_l1*1.1, /*level*/1, min_key, key_and_token_pair[2].first); + add_sstable_for_leveled_test(env, cf, /*gen*/2, max_sstable_size_in_bytes, /*level*/2, min_key, key_and_token_pair[1].first); + add_sstable_for_leveled_test(env, cf, /*gen*/3, max_sstable_size_in_bytes, /*level*/3, min_key, key_and_token_pair[1].first); std::vector> last_compacted_keys(leveled_manifest::MAX_LEVELS); std::vector compaction_counter(leveled_manifest::MAX_LEVELS); @@ -2254,16 +2193,17 @@ SEASTAR_TEST_CASE(overlapping_starved_sstables_test) { } SEASTAR_TEST_CASE(check_overlapping) { + test_env env; column_family_for_tests cf; auto key_and_token_pair = token_generation_for_current_shard(4); auto min_key = key_and_token_pair[0].first; auto max_key = key_and_token_pair[key_and_token_pair.size()-1].first; - auto sst1 = add_sstable_for_overlapping_test(cf, /*gen*/1, min_key, key_and_token_pair[1].first); - auto sst2 = add_sstable_for_overlapping_test(cf, /*gen*/2, min_key, key_and_token_pair[2].first); - auto sst3 = add_sstable_for_overlapping_test(cf, /*gen*/3, key_and_token_pair[3].first, max_key); - auto sst4 = add_sstable_for_overlapping_test(cf, /*gen*/4, min_key, max_key); + auto sst1 = add_sstable_for_overlapping_test(env, cf, /*gen*/1, min_key, key_and_token_pair[1].first); + auto sst2 = add_sstable_for_overlapping_test(env, cf, /*gen*/2, min_key, key_and_token_pair[2].first); + auto sst3 = add_sstable_for_overlapping_test(env, cf, /*gen*/3, key_and_token_pair[3].first, max_key); + auto sst4 = add_sstable_for_overlapping_test(env, cf, /*gen*/4, min_key, max_key); BOOST_REQUIRE(cf->get_sstables()->size() == 4); std::vector compacting = { sst1, sst2 }; @@ -2277,13 +2217,14 @@ SEASTAR_TEST_CASE(check_overlapping) { } SEASTAR_TEST_CASE(check_read_indexes) { - return for_each_sstable_version([] (const sstables::sstable::version_types version) { + test_env env; + return for_each_sstable_version([&env] (const sstables::sstable::version_types version) { auto builder = schema_builder("test", "summary_test") .with_column("a", int32_type, column_kind::partition_key); builder.set_min_index_interval(256); auto s = builder.build(); - auto sst = make_sstable(s, get_test_dir("summary_test", s), 1, version, big); + auto sst = env.make_sstable(s, get_test_dir("summary_test", s), 1, version, big); auto fut = sst->load(); return fut.then([sst] { @@ -2297,7 +2238,7 @@ SEASTAR_TEST_CASE(check_read_indexes) { SEASTAR_TEST_CASE(tombstone_purge_test) { BOOST_REQUIRE(smp::count == 1); - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; cell_locker_stats cl_stats; @@ -2310,8 +2251,8 @@ SEASTAR_TEST_CASE(tombstone_purge_test) { auto s = builder.build(); auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); }; auto compact = [&, s] (std::vector all, std::vector to_compact) -> std::vector { @@ -2511,7 +2452,8 @@ SEASTAR_TEST_CASE(check_multi_schema) { // d int, // e blob //); - return for_each_sstable_version([] (const sstables::sstable::version_types version) { + test_env env; + return for_each_sstable_version([&env] (const sstables::sstable::version_types version) { auto set_of_ints_type = set_type_impl::get_instance(int32_type, true); auto builder = schema_builder("test", "test_multi_schema") .with_column("a", int32_type, column_kind::partition_key) @@ -2520,7 +2462,7 @@ SEASTAR_TEST_CASE(check_multi_schema) { .with_column("e", bytes_type); auto s = builder.build(); - auto sst = make_sstable(s, get_test_dir("multi_schema_test", s), 1, version, big); + auto sst = env.make_sstable(s, get_test_dir("multi_schema_test", s), 1, version, big); auto f = sst->load(); return f.then([sst, s] { auto reader = make_lw_shared(sstable_reader(sst, s)); @@ -2546,7 +2488,7 @@ SEASTAR_TEST_CASE(check_multi_schema) { SEASTAR_TEST_CASE(sstable_rewrite) { BOOST_REQUIRE(smp::count == 1); - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {{"c1", utf8_type}}, {{"r1", utf8_type}}, {}, utf8_type)); @@ -2564,13 +2506,13 @@ SEASTAR_TEST_CASE(sstable_rewrite) { }; apply_key(key_for_this_shard[0].first); - auto sst = make_sstable(s, tmpdir_path, 51, la, big); - return write_memtable_to_sstable_for_test(*mt, sst).then([s, sst, tmpdir_path] { - return reusable_sst(s, tmpdir_path, 51); - }).then([s, key = key_for_this_shard[0].first, tmpdir_path] (auto sstp) mutable { + auto sst = env.make_sstable(s, tmpdir_path, 51, la, big); + return write_memtable_to_sstable_for_test(*mt, sst).then([&env, s, sst, tmpdir_path] { + return env.reusable_sst(s, tmpdir_path, 51); + }).then([&env, s, key = key_for_this_shard[0].first, tmpdir_path] (auto sstp) mutable { auto new_tables = make_lw_shared>(); - auto creator = [new_tables, s, tmpdir_path] { - auto sst = sstables::make_sstable(s, tmpdir_path, 52, la, big); + auto creator = [&env, new_tables, s, tmpdir_path] { + auto sst = env.make_sstable(s, tmpdir_path, 52, la, big); sst->set_unshared(); new_tables->emplace_back(sst); return sst; @@ -2658,7 +2600,7 @@ SEASTAR_TEST_CASE(test_sliced_mutation_reads) { // insert into sliced_mutation_reads_test (pk, ck, v1) values (1, 1, 1); // insert into sliced_mutation_reads_test (pk, ck, v1) values (1, 3, 1); // insert into sliced_mutation_reads_test (pk, ck, v1) values (1, 5, 1); - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (auto version : all_sstable_versions) { auto set_of_ints_type = set_type_impl::get_instance(int32_type, true); auto builder = schema_builder("ks", "sliced_mutation_reads_test") @@ -2668,7 +2610,7 @@ SEASTAR_TEST_CASE(test_sliced_mutation_reads) { .with_column("v2", set_of_ints_type); auto s = builder.build(); - auto sst = make_sstable(s, get_test_dir("sliced_mutation_reads", s), 1, version, big); + auto sst = env.make_sstable(s, get_test_dir("sliced_mutation_reads", s), 1, version, big); sst->load().get0(); { @@ -2750,7 +2692,7 @@ SEASTAR_TEST_CASE(test_wrong_range_tombstone_order) { // delete from wrong_range_tombstone_order where p = 0 and a = 2 and b = 1; // delete from wrong_range_tombstone_order where p = 0 and a = 2 and b = 2; - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (const auto version : all_sstable_versions) { auto s = schema_builder("ks", "wrong_range_tombstone_order") .with(schema_builder::compact_storage::yes) @@ -2764,7 +2706,7 @@ SEASTAR_TEST_CASE(test_wrong_range_tombstone_order) { auto pkey = partition_key::from_exploded(*s, { int32_type->decompose(0) }); auto dkey = dht::global_partitioner().decorate_key(*s, std::move(pkey)); - auto sst = make_sstable(s, get_test_dir("wrong_range_tombstone_order", s), 1, version, big); + auto sst = env.make_sstable(s, get_test_dir("wrong_range_tombstone_order", s), 1, version, big); sst->load().get0(); auto reader = make_normalizing_sstable_reader(sst, s); @@ -2819,7 +2761,7 @@ SEASTAR_TEST_CASE(test_counter_read) { // ----+----+----+----- // 0 | 0 | 13 | -92 - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (const auto version : all_sstable_versions) { auto s = schema_builder("ks", "counter_test") .with_column("pk", int32_type, column_kind::partition_key) @@ -2831,7 +2773,7 @@ SEASTAR_TEST_CASE(test_counter_read) { auto node1 = counter_id(utils::UUID("8379ab99-4507-4ab1-805d-ac85a863092b")); auto node2 = counter_id(utils::UUID("b8a6c3f3-e222-433f-9ce9-de56a8466e07")); - auto sst = make_sstable(s, get_test_dir("counter_test", s), 5, version, big); + auto sst = env.make_sstable(s, get_test_dir("counter_test", s), 5, version, big); sst->load().get(); auto reader = sstable_reader(sst, s); @@ -2892,8 +2834,8 @@ SEASTAR_TEST_CASE(test_counter_read) { } SEASTAR_TEST_CASE(test_sstable_max_local_deletion_time) { - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { - return seastar::async([tmpdir_path] { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { + return seastar::async([&env, tmpdir_path] { for (const auto version : all_sstable_versions) { schema_builder builder(some_keyspace, some_column_family); builder.with_column("p1", utf8_type, column_kind::partition_key); @@ -2911,9 +2853,9 @@ SEASTAR_TEST_CASE(test_sstable_max_local_deletion_time) { make_atomic_cell(utf8_type, bytes("a"), 3600 + i, last_expiry)); mt->apply(std::move(m)); } - auto sst = make_sstable(s, tmpdir_path, 53, version, big); + auto sst = env.make_sstable(s, tmpdir_path, 53, version, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - auto sstp = reusable_sst(s, tmpdir_path, 53, version).get0(); + auto sstp = env.reusable_sst(s, tmpdir_path, 53, version).get0(); BOOST_REQUIRE(last_expiry == sstp->get_stats_metadata().max_local_deletion_time); } }); @@ -2924,8 +2866,8 @@ SEASTAR_TEST_CASE(test_sstable_max_local_deletion_time_2) { // Create sstable A with 5x column with TTL 100 and 1x column with TTL 1000 // Create sstable B with tombstone for column in sstable A with TTL 1000. // Compact them and expect that maximum deletion time is that of column with TTL 100. - return test_setup::do_with_tmp_directory([] (sstring tmpdir_path) { - return seastar::async([tmpdir_path] { + return test_setup::do_with_tmp_directory([] (test_env& env, sstring tmpdir_path) { + return seastar::async([&env, tmpdir_path] { for (auto version : all_sstable_versions) { schema_builder builder(some_keyspace, some_column_family); builder.with_column("p1", utf8_type, column_kind::partition_key); @@ -2943,10 +2885,10 @@ SEASTAR_TEST_CASE(test_sstable_max_local_deletion_time_2) { make_atomic_cell(utf8_type, bytes(""), ttl, last_expiry)); mt->apply(std::move(m)); }; - auto get_usable_sst = [s, tmpdir_path, version](memtable &mt, int64_t gen) -> future { - auto sst = make_sstable(s, tmpdir_path, gen, version, big); - return write_memtable_to_sstable_for_test(mt, sst).then([sst, gen, s, tmpdir_path, version] { - return reusable_sst(s, tmpdir_path, gen, version); + auto get_usable_sst = [&env, s, tmpdir_path, version](memtable &mt, int64_t gen) -> future { + auto sst = env.make_sstable(s, tmpdir_path, gen, version, big); + return write_memtable_to_sstable_for_test(mt, sst).then([&env, sst, gen, s, tmpdir_path, version] { + return env.reusable_sst(s, tmpdir_path, gen, version); }); }; @@ -2966,7 +2908,7 @@ SEASTAR_TEST_CASE(test_sstable_max_local_deletion_time_2) { auto sst2 = get_usable_sst(*mt, 55).get0(); BOOST_REQUIRE(now.time_since_epoch().count() == sst2->get_stats_metadata().max_local_deletion_time); - auto creator = [s, tmpdir_path, version] { return sstables::make_sstable(s, tmpdir_path, 56, version, big); }; + auto creator = [&env, s, tmpdir_path, version] { return env.make_sstable(s, tmpdir_path, 56, version, big); }; auto info = sstables::compact_sstables(sstables::compaction_descriptor({sst1, sst2}), *cf, creator, replacer_fn_no_op()).get0(); BOOST_REQUIRE(info.new_sstables.size() == 1); @@ -2986,6 +2928,7 @@ static stats_metadata build_stats(int64_t min_timestamp, int64_t max_timestamp, } SEASTAR_TEST_CASE(get_fully_expired_sstables_test) { + test_env env; auto key_and_token_pair = token_generation_for_current_shard(4); auto min_key = key_and_token_pair[0].first; auto max_key = key_and_token_pair[key_and_token_pair.size()-1].first; @@ -2998,9 +2941,9 @@ SEASTAR_TEST_CASE(get_fully_expired_sstables_test) { { column_family_for_tests cf; - auto sst1 = add_sstable_for_overlapping_test(cf, /*gen*/1, min_key, key_and_token_pair[1].first, build_stats(t0, t1, t1)); - auto sst2 = add_sstable_for_overlapping_test(cf, /*gen*/2, min_key, key_and_token_pair[2].first, build_stats(t0, t1, std::numeric_limits::max())); - auto sst3 = add_sstable_for_overlapping_test(cf, /*gen*/3, min_key, max_key, build_stats(t3, t4, std::numeric_limits::max())); + auto sst1 = add_sstable_for_overlapping_test(env, cf, /*gen*/1, min_key, key_and_token_pair[1].first, build_stats(t0, t1, t1)); + auto sst2 = add_sstable_for_overlapping_test(env, cf, /*gen*/2, min_key, key_and_token_pair[2].first, build_stats(t0, t1, std::numeric_limits::max())); + auto sst3 = add_sstable_for_overlapping_test(env, cf, /*gen*/3, min_key, max_key, build_stats(t3, t4, std::numeric_limits::max())); std::vector compacting = { sst1, sst2 }; auto expired = get_fully_expired_sstables(*cf, compacting, /*gc before*/gc_clock::from_time_t(15)); BOOST_REQUIRE(expired.size() == 0); @@ -3009,9 +2952,9 @@ SEASTAR_TEST_CASE(get_fully_expired_sstables_test) { { column_family_for_tests cf; - auto sst1 = add_sstable_for_overlapping_test(cf, /*gen*/1, min_key, key_and_token_pair[1].first, build_stats(t0, t1, t1)); - auto sst2 = add_sstable_for_overlapping_test(cf, /*gen*/2, min_key, key_and_token_pair[2].first, build_stats(t2, t3, std::numeric_limits::max())); - auto sst3 = add_sstable_for_overlapping_test(cf, /*gen*/3, min_key, max_key, build_stats(t3, t4, std::numeric_limits::max())); + auto sst1 = add_sstable_for_overlapping_test(env, cf, /*gen*/1, min_key, key_and_token_pair[1].first, build_stats(t0, t1, t1)); + auto sst2 = add_sstable_for_overlapping_test(env, cf, /*gen*/2, min_key, key_and_token_pair[2].first, build_stats(t2, t3, std::numeric_limits::max())); + auto sst3 = add_sstable_for_overlapping_test(env, cf, /*gen*/3, min_key, max_key, build_stats(t3, t4, std::numeric_limits::max())); std::vector compacting = { sst1, sst2 }; auto expired = get_fully_expired_sstables(*cf, compacting, /*gc before*/gc_clock::from_time_t(25)); BOOST_REQUIRE(expired.size() == 1); @@ -3023,20 +2966,21 @@ SEASTAR_TEST_CASE(get_fully_expired_sstables_test) { } SEASTAR_TEST_CASE(compaction_with_fully_expired_table) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; auto builder = schema_builder("la", "cf") .with_column("pk", utf8_type, column_kind::partition_key) .with_column("ck1", utf8_type, column_kind::clustering_key) .with_column("r1", int32_type); + builder.set_gc_grace_seconds(0); auto s = builder.build(); auto tmp = tmpdir(); auto key = partition_key::from_exploded(*s, {to_bytes("key1")}); auto c_key = clustering_key_prefix::from_exploded(*s, {to_bytes("c1")}); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); }; auto mt = make_lw_shared(s); @@ -3046,7 +2990,7 @@ SEASTAR_TEST_CASE(compaction_with_fully_expired_table) { mt->apply(std::move(m)); auto sst = sst_gen(); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 1).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 1).get0(); column_family_for_tests cf; @@ -3058,7 +3002,7 @@ SEASTAR_TEST_CASE(compaction_with_fully_expired_table) { // check that sstable will auto correct potentially bad max_deletion_time and thus sstable will not be fully expired sstables::test(sst).rewrite_toc_without_scylla_component(); - sst = reusable_sst(s, tmp.path().string(), 1).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 1).get0(); ssts = std::vector{ sst }; expired = get_fully_expired_sstables(*cf, ssts, gc_clock::now()); BOOST_REQUIRE(expired.size() == 0); @@ -3075,7 +3019,7 @@ SEASTAR_TEST_CASE(basic_date_tiered_strategy_test) { {{"p1", utf8_type}}, {}, {}, {}, utf8_type))); builder.set_min_compaction_threshold(4); auto s = builder.build(schema_builder::compact_storage::no); - + test_env env; column_family_for_tests cf(s); std::vector candidates; @@ -3086,12 +3030,12 @@ SEASTAR_TEST_CASE(basic_date_tiered_strategy_test) { int64_t timestamp_for_past_hour = past_hour.time_since_epoch().count() * 1000; for (auto i = 1; i <= min_threshold; i++) { - auto sst = add_sstable_for_overlapping_test(cf, /*gen*/i, "a", "a", + auto sst = add_sstable_for_overlapping_test(env, cf, /*gen*/i, "a", "a", build_stats(timestamp_for_now, timestamp_for_now, std::numeric_limits::max())); candidates.push_back(sst); } // add sstable that belong to a different time tier. - auto sst = add_sstable_for_overlapping_test(cf, /*gen*/min_threshold + 1, "a", "a", + auto sst = add_sstable_for_overlapping_test(env, cf, /*gen*/min_threshold + 1, "a", "a", build_stats(timestamp_for_past_hour, timestamp_for_past_hour, std::numeric_limits::max())); candidates.push_back(sst); @@ -3112,7 +3056,7 @@ SEASTAR_TEST_CASE(date_tiered_strategy_test_2) { {{"p1", utf8_type}}, {}, {}, {}, utf8_type))); builder.set_min_compaction_threshold(4); auto s = builder.build(schema_builder::compact_storage::no); - + test_env env; column_family_for_tests cf(s); // deterministic timestamp for Fri, 01 Jan 2016 00:00:00 GMT. @@ -3124,21 +3068,21 @@ SEASTAR_TEST_CASE(date_tiered_strategy_test_2) { // add sstables that belong to same time window until min threshold is satisfied. for (auto i = 1; i <= min_threshold; i++) { - auto sst = add_sstable_for_overlapping_test(cf, /*gen*/i, "a", "a", + auto sst = add_sstable_for_overlapping_test(env, cf, /*gen*/i, "a", "a", build_stats(timestamp, timestamp, std::numeric_limits::max())); candidates.push_back(sst); } // belongs to the time window auto tp2 = tp + std::chrono::seconds(1800); timestamp = tp2.time_since_epoch().count() * 1000; - auto sst = add_sstable_for_overlapping_test(cf, /*gen*/min_threshold + 1, "a", "a", + auto sst = add_sstable_for_overlapping_test(env, cf, /*gen*/min_threshold + 1, "a", "a", build_stats(timestamp, timestamp, std::numeric_limits::max())); candidates.push_back(sst); // doesn't belong to the time window above auto tp3 = tp + std::chrono::seconds(4000); timestamp = tp3.time_since_epoch().count() * 1000; - auto sst2 = add_sstable_for_overlapping_test(cf, /*gen*/min_threshold + 2, "a", "a", + auto sst2 = add_sstable_for_overlapping_test(env, cf, /*gen*/min_threshold + 2, "a", "a", build_stats(timestamp, timestamp, std::numeric_limits::max())); candidates.push_back(sst2); @@ -3191,12 +3135,13 @@ SEASTAR_TEST_CASE(time_window_strategy_ts_resolution_check) { auto s = schema_builder("tests", "time_window_strategy") .with_column("id", utf8_type, column_kind::partition_key) .with_column("value", int32_type).build(); + test_env env; { std::map opts = { { time_window_compaction_strategy_options::TIMESTAMP_RESOLUTION_KEY, "MILLISECONDS" }, }; time_window_compaction_strategy_options options(opts); - auto sst = make_sstable(s, "", 1, la, big); + auto sst = env.make_sstable(s, "", 1, la, big); sstables::test(sst).set_values("key1", "key1", build_stats(ts_in_ms.count(), ts_in_ms.count(), std::numeric_limits::max())); auto ret = time_window_compaction_strategy::get_buckets({ sst }, options); @@ -3209,7 +3154,7 @@ SEASTAR_TEST_CASE(time_window_strategy_ts_resolution_check) { std::map opts = { { time_window_compaction_strategy_options::TIMESTAMP_RESOLUTION_KEY, "MICROSECONDS" }, }; time_window_compaction_strategy_options options(opts); - auto sst = make_sstable(s, "", 1, la, big); + auto sst = env.make_sstable(s, "", 1, la, big); sstables::test(sst).set_values("key1", "key1", build_stats(ts_in_us.count(), ts_in_us.count(), std::numeric_limits::max())); auto ret = time_window_compaction_strategy::get_buckets({ sst }, options); @@ -3223,15 +3168,15 @@ SEASTAR_TEST_CASE(time_window_strategy_ts_resolution_check) { SEASTAR_TEST_CASE(time_window_strategy_correctness_test) { using namespace std::chrono; - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; auto s = schema_builder("tests", "time_window_strategy") .with_column("id", utf8_type, column_kind::partition_key) .with_column("value", int32_type).build(); auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); }; auto make_insert = [&] (partition_key key, api::timestamp_type t) { @@ -3345,7 +3290,7 @@ SEASTAR_TEST_CASE(test_promoted_index_read) { // ["0:1:v","1",1468923311744298]]} // ] - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (const auto version : all_sstable_versions) { auto s = schema_builder("ks", "promoted_index_read") .with_column("pk", int32_type, column_kind::partition_key) @@ -3353,8 +3298,7 @@ SEASTAR_TEST_CASE(test_promoted_index_read) { .with_column("ck2", int32_type, column_kind::clustering_key) .with_column("v", int32_type) .build(); - - auto sst = make_sstable(s, get_test_dir("promoted_index_read", s), 1, version, big); + auto sst = env.make_sstable(s, get_test_dir("promoted_index_read", s), 1, version, big); sst->load().get0(); auto pkey = partition_key::from_exploded(*s, { int32_type->decompose(0) }); @@ -3419,15 +3363,16 @@ static void test_min_max_clustering_key(schema_ptr s, std::vector explode } } } + test_env env; auto tmp = tmpdir(); - auto sst = make_sstable(s, tmp.path().string(), 1, version, big); + auto sst = env.make_sstable(s, tmp.path().string(), 1, version, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 1, version).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 1, version).get0(); check_min_max_column_names(sst, std::move(min_components), std::move(max_components)); } SEASTAR_TEST_CASE(min_max_clustering_key_test) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; for (auto version : all_sstable_versions) { { @@ -3481,7 +3426,7 @@ SEASTAR_TEST_CASE(min_max_clustering_key_test) { } SEASTAR_TEST_CASE(min_max_clustering_key_test_2) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; for (const auto version : all_sstable_versions) { auto s = schema_builder("ks", "cf") @@ -3503,9 +3448,9 @@ SEASTAR_TEST_CASE(min_max_clustering_key_test_2) { } mt->apply(std::move(m)); } - auto sst = make_sstable(s, tmp.path().string(), 1, version, big); + auto sst = env.make_sstable(s, tmp.path().string(), 1, version, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 1, version).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 1, version).get0(); check_min_max_column_names(sst, {"0ck100"}, {"7ck149"}); mt = make_lw_shared(s); @@ -3516,12 +3461,12 @@ SEASTAR_TEST_CASE(min_max_clustering_key_test_2) { m.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); } mt->apply(std::move(m)); - auto sst2 = make_sstable(s, tmp.path().string(), 2, version, big); + auto sst2 = env.make_sstable(s, tmp.path().string(), 2, version, big); write_memtable_to_sstable_for_test(*mt, sst2).get(); - sst2 = reusable_sst(s, tmp.path().string(), 2, version).get0(); + sst2 = env.reusable_sst(s, tmp.path().string(), 2, version).get0(); check_min_max_column_names(sst2, {"9ck101"}, {"9ck298"}); - auto creator = [s, &tmp, version] { return sstables::make_sstable(s, tmp.path().string(), 3, version, big); }; + auto creator = [&env, s, &tmp, version] { return env.make_sstable(s, tmp.path().string(), 3, version, big); }; auto info = sstables::compact_sstables(sstables::compaction_descriptor({sst, sst2}), *cf, creator, replacer_fn_no_op()).get0(); BOOST_REQUIRE(info.new_sstables.size() == 1); check_min_max_column_names(info.new_sstables.front(), {"0ck100"}, {"9ck298"}); @@ -3530,7 +3475,7 @@ SEASTAR_TEST_CASE(min_max_clustering_key_test_2) { } SEASTAR_TEST_CASE(sstable_tombstone_metadata_check) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; for (const auto version : all_sstable_versions) { auto s = schema_builder("ks", "cf") @@ -3549,9 +3494,9 @@ SEASTAR_TEST_CASE(sstable_tombstone_metadata_check) { tombstone tomb(api::new_timestamp(), gc_clock::now()); m.partition().apply_delete(*s, c_key, tomb); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmp.path().string(), 1, version, big); + auto sst = env.make_sstable(s, tmp.path().string(), 1, version, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 1, version).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 1, version).get0(); sstables::sstlog.warn("Version {}", (int)version); BOOST_REQUIRE(sst->get_stats_metadata().estimated_tombstone_drop_time.bin.size()); } @@ -3561,9 +3506,9 @@ SEASTAR_TEST_CASE(sstable_tombstone_metadata_check) { mutation m(s, key); m.set_clustered_cell(c_key, r1_col, make_dead_atomic_cell(3600)); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmp.path().string(), 2, version, big); + auto sst = env.make_sstable(s, tmp.path().string(), 2, version, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 2, version).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 2, version).get0(); BOOST_REQUIRE(sst->get_stats_metadata().estimated_tombstone_drop_time.bin.size()); } @@ -3572,9 +3517,9 @@ SEASTAR_TEST_CASE(sstable_tombstone_metadata_check) { mutation m(s, key); m.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmp.path().string(), 3, version, big); + auto sst = env.make_sstable(s, tmp.path().string(), 3, version, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 3, version).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 3, version).get0(); BOOST_REQUIRE(!sst->get_stats_metadata().estimated_tombstone_drop_time.bin.size()); } @@ -3591,9 +3536,9 @@ SEASTAR_TEST_CASE(sstable_tombstone_metadata_check) { m2.set_clustered_cell(c_key, r1_col, make_atomic_cell(int32_type, int32_type->decompose(1))); mt->apply(std::move(m2)); - auto sst = make_sstable(s, tmp.path().string(), 4, version, big); + auto sst = env.make_sstable(s, tmp.path().string(), 4, version, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 4, version).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 4, version).get0(); BOOST_REQUIRE(sst->get_stats_metadata().estimated_tombstone_drop_time.bin.size()); } @@ -3603,9 +3548,9 @@ SEASTAR_TEST_CASE(sstable_tombstone_metadata_check) { tombstone tomb(api::new_timestamp(), gc_clock::now()); m.partition().apply(tomb); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmp.path().string(), 5, version, big); + auto sst = env.make_sstable(s, tmp.path().string(), 5, version, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 5, version).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 5, version).get0(); BOOST_REQUIRE(sst->get_stats_metadata().estimated_tombstone_drop_time.bin.size()); } @@ -3617,9 +3562,9 @@ SEASTAR_TEST_CASE(sstable_tombstone_metadata_check) { "a")), clustering_key_prefix::from_single_value(*s, bytes("a")), tomb); m.partition().apply_delete(*s, std::move(rt)); mt->apply(std::move(m)); - auto sst = make_sstable(s, tmp.path().string(), 6, version, big); + auto sst = env.make_sstable(s, tmp.path().string(), 6, version, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 6, version).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 6, version).get0(); BOOST_REQUIRE(sst->get_stats_metadata().estimated_tombstone_drop_time.bin.size()); } } @@ -3627,14 +3572,14 @@ SEASTAR_TEST_CASE(sstable_tombstone_metadata_check) { } SEASTAR_TEST_CASE(test_partition_skipping) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (const auto version : all_sstable_versions) { auto s = schema_builder("ks", "test_skipping_partitions") .with_column("pk", int32_type, column_kind::partition_key) .with_column("v", int32_type) .build(); - auto sst = make_sstable(s, get_test_dir("partition_skipping",s), 1, version, big); + auto sst = env.make_sstable(s, get_test_dir("partition_skipping",s), 1, version, big); sst->load().get0(); std::vector keys; @@ -3691,16 +3636,16 @@ SEASTAR_TEST_CASE(test_partition_skipping) { // Must be run in a seastar thread static -shared_sstable make_sstable_easy(const seastar::compat::filesystem::path& path, flat_mutation_reader rd, sstable_writer_config cfg, const sstables::sstable::version_types version) { +shared_sstable make_sstable_easy(test_env& env, const seastar::compat::filesystem::path& path, flat_mutation_reader rd, sstable_writer_config cfg, const sstables::sstable::version_types version) { auto s = rd.schema(); - auto sst = make_sstable(s, path.string(), 1, version, big); + auto sst = env.make_sstable(s, path.string(), 1, version, big); sst->write_components(std::move(rd), 1, s, cfg, encoding_stats{}).get(); sst->load().get(); return sst; } SEASTAR_TEST_CASE(test_repeated_tombstone_skipping) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (const auto version : all_sstable_versions) { storage_service_for_tests ssft; simple_schema table; @@ -3739,7 +3684,7 @@ SEASTAR_TEST_CASE(test_repeated_tombstone_skipping) { for (auto&& mf : fragments) { mut.apply(mf); } - auto sst = make_sstable_easy(dir.path(), flat_mutation_reader_from_mutations({ std::move(mut) }), cfg, version); + auto sst = make_sstable_easy(env, dir.path(), flat_mutation_reader_from_mutations({ std::move(mut) }), cfg, version); auto ms = as_mutation_source(sst); for (uint32_t i = 3; i < seq; i++) { @@ -3760,7 +3705,7 @@ SEASTAR_TEST_CASE(test_repeated_tombstone_skipping) { } SEASTAR_TEST_CASE(test_skipping_using_index) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (const auto version : all_sstable_versions) { storage_service_for_tests ssft; simple_schema table; @@ -3790,7 +3735,7 @@ SEASTAR_TEST_CASE(test_skipping_using_index) { sstable_writer_config cfg; cfg.promoted_index_block_size = 1; // So that every fragment is indexed cfg.large_data_handler = &nop_lp_handler; - auto sst = make_sstable_easy(dir.path(), flat_mutation_reader_from_mutations(partitions), cfg, version); + auto sst = make_sstable_easy(env, dir.path(), flat_mutation_reader_from_mutations(partitions), cfg, version); auto ms = as_mutation_source(sst); auto rd = ms.make_reader(table.schema(), @@ -3895,15 +3840,15 @@ static void copy_directory(boost::filesystem::path src_dir, boost::filesystem::p } SEASTAR_TEST_CASE(test_unknown_component) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { auto tmp = tmpdir(); copy_directory("tests/sstables/unknown_component", std::string(tmp.path().string()) + "/unknown_component"); - auto sstp = reusable_sst(uncompressed_schema(), tmp.path().string() + "/unknown_component", 1).get0(); + auto sstp = env.reusable_sst(uncompressed_schema(), tmp.path().string() + "/unknown_component", 1).get0(); sstp->create_links(tmp.path().string()).get(); // check that create_links() moved unknown component to new dir BOOST_REQUIRE(file_exists(tmp.path().string() + "/la-1-big-UNKNOWN.txt").get0()); - sstp = reusable_sst(uncompressed_schema(), tmp.path().string(), 1).get0(); + sstp = env.reusable_sst(uncompressed_schema(), tmp.path().string(), 1).get0(); sstp->set_generation(2).get(); BOOST_REQUIRE(!file_exists(tmp.path().string() + "/la-1-big-UNKNOWN.txt").get0()); BOOST_REQUIRE(file_exists(tmp.path().string() + "/la-2-big-UNKNOWN.txt").get0()); @@ -3915,6 +3860,7 @@ SEASTAR_TEST_CASE(test_unknown_component) { } SEASTAR_TEST_CASE(size_tiered_beyond_max_threshold_test) { + test_env env; column_family_for_tests cf; auto cs = sstables::make_compaction_strategy(sstables::compaction_strategy_type::size_tiered, cf.schema()->compaction_strategy_options()); @@ -3922,7 +3868,7 @@ SEASTAR_TEST_CASE(size_tiered_beyond_max_threshold_test) { int max_threshold = cf->schema()->max_compaction_threshold(); candidates.reserve(max_threshold+1); for (auto i = 0; i < (max_threshold+1); i++) { // (max_threshold+1) sstables of similar size - auto sst = make_sstable(cf.schema(), "", i, la, big); + auto sst = env.make_sstable(cf.schema(), "", i, la, big); sstables::test(sst).set_data_file_size(1); candidates.push_back(std::move(sst)); } @@ -3932,6 +3878,7 @@ SEASTAR_TEST_CASE(size_tiered_beyond_max_threshold_test) { } SEASTAR_TEST_CASE(sstable_set_incremental_selector) { + test_env env; auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {}, {}, {}, utf8_type)); auto cs = sstables::make_compaction_strategy(sstables::compaction_strategy_type::leveled, s->compaction_strategy_options()); @@ -3953,11 +3900,11 @@ SEASTAR_TEST_CASE(sstable_set_incremental_selector) { { sstable_set set = cs.make_sstable_set(s); - set.insert(sstable_for_overlapping_test(s, 1, key_and_token_pair[0].first, key_and_token_pair[1].first, 1)); - set.insert(sstable_for_overlapping_test(s, 2, key_and_token_pair[0].first, key_and_token_pair[1].first, 1)); - set.insert(sstable_for_overlapping_test(s, 3, key_and_token_pair[3].first, key_and_token_pair[4].first, 1)); - set.insert(sstable_for_overlapping_test(s, 4, key_and_token_pair[4].first, key_and_token_pair[4].first, 1)); - set.insert(sstable_for_overlapping_test(s, 5, key_and_token_pair[4].first, key_and_token_pair[5].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 1, key_and_token_pair[0].first, key_and_token_pair[1].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 2, key_and_token_pair[0].first, key_and_token_pair[1].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 3, key_and_token_pair[3].first, key_and_token_pair[4].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 4, key_and_token_pair[4].first, key_and_token_pair[4].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 5, key_and_token_pair[4].first, key_and_token_pair[5].first, 1)); sstable_set::incremental_selector sel = set.make_incremental_selector(); check(sel, decorated_keys[0], {1, 2}); @@ -3972,12 +3919,12 @@ SEASTAR_TEST_CASE(sstable_set_incremental_selector) { { sstable_set set = cs.make_sstable_set(s); - set.insert(sstable_for_overlapping_test(s, 0, key_and_token_pair[0].first, key_and_token_pair[1].first, 0)); - set.insert(sstable_for_overlapping_test(s, 1, key_and_token_pair[0].first, key_and_token_pair[1].first, 1)); - set.insert(sstable_for_overlapping_test(s, 2, key_and_token_pair[0].first, key_and_token_pair[1].first, 1)); - set.insert(sstable_for_overlapping_test(s, 3, key_and_token_pair[3].first, key_and_token_pair[4].first, 1)); - set.insert(sstable_for_overlapping_test(s, 4, key_and_token_pair[4].first, key_and_token_pair[4].first, 1)); - set.insert(sstable_for_overlapping_test(s, 5, key_and_token_pair[4].first, key_and_token_pair[5].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 0, key_and_token_pair[0].first, key_and_token_pair[1].first, 0)); + set.insert(sstable_for_overlapping_test(env, s, 1, key_and_token_pair[0].first, key_and_token_pair[1].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 2, key_and_token_pair[0].first, key_and_token_pair[1].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 3, key_and_token_pair[3].first, key_and_token_pair[4].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 4, key_and_token_pair[4].first, key_and_token_pair[4].first, 1)); + set.insert(sstable_for_overlapping_test(env, s, 5, key_and_token_pair[4].first, key_and_token_pair[5].first, 1)); sstable_set::incremental_selector sel = set.make_incremental_selector(); check(sel, decorated_keys[0], {0, 1, 2}); @@ -3994,6 +3941,7 @@ SEASTAR_TEST_CASE(sstable_set_incremental_selector) { } SEASTAR_TEST_CASE(sstable_set_erase) { + test_env env; auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", utf8_type}}, {}, {}, {}, utf8_type)); auto key_and_token_pair = token_generation_for_current_shard(1); @@ -4003,12 +3951,12 @@ SEASTAR_TEST_CASE(sstable_set_erase) { auto cs = sstables::make_compaction_strategy(sstables::compaction_strategy_type::leveled, s->compaction_strategy_options()); sstable_set set = cs.make_sstable_set(s); - auto sst = sstable_for_overlapping_test(s, 0, key_and_token_pair[0].first, key_and_token_pair[0].first, 0); + auto sst = sstable_for_overlapping_test(env, s, 0, key_and_token_pair[0].first, key_and_token_pair[0].first, 0); set.insert(sst); BOOST_REQUIRE(set.all()->size() == 1); - auto unleveled_sst = sstable_for_overlapping_test(s, 1, key_and_token_pair[0].first, key_and_token_pair[0].first, 0); - auto leveled_sst = sstable_for_overlapping_test(s, 2, key_and_token_pair[0].first, key_and_token_pair[0].first, 1); + auto unleveled_sst = sstable_for_overlapping_test(env, s, 1, key_and_token_pair[0].first, key_and_token_pair[0].first, 0); + auto leveled_sst = sstable_for_overlapping_test(env, s, 2, key_and_token_pair[0].first, key_and_token_pair[0].first, 1); set.erase(unleveled_sst); set.erase(leveled_sst); BOOST_REQUIRE(set.all()->size() == 1); @@ -4019,11 +3967,11 @@ SEASTAR_TEST_CASE(sstable_set_erase) { auto cs = sstables::make_compaction_strategy(sstables::compaction_strategy_type::size_tiered, s->compaction_strategy_options()); sstable_set set = cs.make_sstable_set(s); - auto sst = sstable_for_overlapping_test(s, 0, key_and_token_pair[0].first, key_and_token_pair[0].first, 0); + auto sst = sstable_for_overlapping_test(env, s, 0, key_and_token_pair[0].first, key_and_token_pair[0].first, 0); set.insert(sst); BOOST_REQUIRE(set.all()->size() == 1); - auto sst2 = sstable_for_overlapping_test(s, 1, key_and_token_pair[0].first, key_and_token_pair[0].first, 0); + auto sst2 = sstable_for_overlapping_test(env, s, 1, key_and_token_pair[0].first, key_and_token_pair[0].first, 0); set.erase(sst2); BOOST_REQUIRE(set.all()->size() == 1); BOOST_REQUIRE(set.all()->count(sst)); @@ -4032,48 +3980,8 @@ SEASTAR_TEST_CASE(sstable_set_erase) { return make_ready_future<>(); } -SEASTAR_TEST_CASE(sstable_resharding_strategy_tests) { - // TODO: move it to sstable_resharding_test.cc. Unable to do so now because of linking issues - // when using sstables::stats_metadata at sstable_resharding_test.cc. - - for (const auto version : all_sstable_versions) { - auto s = make_lw_shared(schema({}, "ks", "cf", {{"p1", utf8_type}}, {}, {}, {}, utf8_type)); - auto get_sstable = [&] (int64_t gen, sstring first_key, sstring last_key) mutable { - auto sst = make_sstable(s, "", gen, version, sstables::sstable::format_types::big); - stats_metadata stats = {}; - stats.sstable_level = 1; - sstables::test(sst).set_values(std::move(first_key), std::move(last_key), std::move(stats)); - return sst; - }; - - column_family_for_tests cf; - - auto tokens = token_generation_for_current_shard(2); - auto stcs = sstables::make_compaction_strategy(sstables::compaction_strategy_type::size_tiered, s->compaction_strategy_options()); - auto lcs = sstables::make_compaction_strategy(sstables::compaction_strategy_type::leveled, s->compaction_strategy_options()); - - auto sst1 = get_sstable(1, tokens[0].first, tokens[1].first); - auto sst2 = get_sstable(2, tokens[1].first, tokens[1].first); - - { - // TODO: sstable_test runs with smp::count == 1, thus we will not be able to stress it more - // until we move this test case to sstable_resharding_test. - auto descriptors = stcs.get_resharding_jobs(*cf, { sst1, sst2 }); - BOOST_REQUIRE(descriptors.size() == 2); - } - { - auto ssts = std::vector{ sst1, sst2 }; - auto descriptors = lcs.get_resharding_jobs(*cf, ssts); - auto expected_jobs = ssts.size()/smp::count + ssts.size()%smp::count; - BOOST_REQUIRE(descriptors.size() == expected_jobs); - } - } - - return make_ready_future<>(); -} - SEASTAR_TEST_CASE(sstable_tombstone_histogram_test) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; for (auto version : all_sstable_versions) { auto builder = schema_builder("tests", "tombstone_histogram_test") @@ -4082,8 +3990,8 @@ SEASTAR_TEST_CASE(sstable_tombstone_histogram_test) { auto s = builder.build(); auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1), version]() mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, version, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1), version]() mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, version, big); }; auto next_timestamp = [] { @@ -4106,7 +4014,7 @@ SEASTAR_TEST_CASE(sstable_tombstone_histogram_test) { } auto sst = make_sstable_containing(sst_gen, mutations); auto histogram = sst->get_stats_metadata().estimated_tombstone_drop_time; - sst = reusable_sst(s, tmp.path().string(), sst->generation(), version).get0(); + sst = env.reusable_sst(s, tmp.path().string(), sst->generation(), version).get0(); auto histogram2 = sst->get_stats_metadata().estimated_tombstone_drop_time; // check that histogram respected limit @@ -4118,12 +4026,12 @@ SEASTAR_TEST_CASE(sstable_tombstone_histogram_test) { } SEASTAR_TEST_CASE(sstable_bad_tombstone_histogram_test) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { auto builder = schema_builder("tests", "tombstone_histogram_test") .with_column("id", utf8_type, column_kind::partition_key) .with_column("value", int32_type); auto s = builder.build(); - auto sst = reusable_sst(s, "tests/sstables/bad_tombstone_histogram", 1).get0(); + auto sst = env.reusable_sst(s, "tests/sstables/bad_tombstone_histogram", 1).get0(); auto histogram = sst->get_stats_metadata().estimated_tombstone_drop_time; BOOST_REQUIRE(histogram.max_bin_size == sstables::TOMBSTONE_HISTOGRAM_BIN_SIZE); // check that bad histogram was discarded @@ -4132,7 +4040,7 @@ SEASTAR_TEST_CASE(sstable_bad_tombstone_histogram_test) { } SEASTAR_TEST_CASE(sstable_expired_data_ratio) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; auto tmp = tmpdir(); auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, @@ -4165,9 +4073,9 @@ SEASTAR_TEST_CASE(sstable_expired_data_ratio) { for (auto i = 0; i < remaining; i++) { insert_key(to_bytes("key" + to_sstring(i)), 3600, expiration_time); } - auto sst = make_sstable(s, tmp.path().string(), 1, la, big); + auto sst = env.make_sstable(s, tmp.path().string(), 1, la, big); write_memtable_to_sstable_for_test(*mt, sst).get(); - sst = reusable_sst(s, tmp.path().string(), 1).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 1).get0(); const auto& stats = sst->get_stats_metadata(); BOOST_REQUIRE(stats.estimated_tombstone_drop_time.bin.size() == sstables::TOMBSTONE_HISTOGRAM_BIN_SIZE); auto gc_before = gc_clock::now() - s->gc_grace_seconds(); @@ -4177,7 +4085,7 @@ SEASTAR_TEST_CASE(sstable_expired_data_ratio) { column_family_for_tests cf(s); auto creator = [&] { - auto sst = sstables::make_sstable(s, tmp.path().string(), 2, la, big); + auto sst = env.make_sstable(s, tmp.path().string(), 2, la, big); sst->set_unshared(); return sst; }; @@ -4234,7 +4142,7 @@ SEASTAR_TEST_CASE(sstable_expired_data_ratio) { } SEASTAR_TEST_CASE(sstable_owner_shards) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; cell_locker_stats cl_stats; @@ -4244,8 +4152,8 @@ SEASTAR_TEST_CASE(sstable_owner_shards) { auto s = builder.build(); auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - auto sst = make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + auto sst = env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); sst->set_unshared(); return sst; }; @@ -4267,7 +4175,7 @@ SEASTAR_TEST_CASE(sstable_owner_shards) { dht::default_partitioner = std::make_unique(1, ignore_msb); auto sst = make_sstable_containing(sst_gen, std::move(muts)); dht::default_partitioner = std::make_unique(smp_count, ignore_msb); - sst = reusable_sst(s, tmp.path().string(), sst->generation()).get0(); + sst = env.reusable_sst(s, tmp.path().string(), sst->generation()).get0(); // restore partitioner dht::default_partitioner = std::make_unique(smp::count); return sst; @@ -4306,7 +4214,7 @@ SEASTAR_TEST_CASE(sstable_owner_shards) { } SEASTAR_TEST_CASE(test_summary_entry_spanning_more_keys_than_min_interval) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; auto s = make_lw_shared(schema({}, some_keyspace, some_column_family, {{"p1", int32_type}}, {{"c1", utf8_type}}, {{"r1", int32_type}}, {}, utf8_type)); @@ -4324,11 +4232,11 @@ SEASTAR_TEST_CASE(test_summary_entry_spanning_more_keys_than_min_interval) { } auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); }; auto sst = make_sstable_containing(sst_gen, mutations); - sst = reusable_sst(s, tmp.path().string(), sst->generation()).get0(); + sst = env.reusable_sst(s, tmp.path().string(), sst->generation()).get0(); summary& sum = sstables::test(sst).get_summary(); BOOST_REQUIRE(sum.entries.size() == 1); @@ -4367,7 +4275,7 @@ SEASTAR_TEST_CASE(test_wrong_counter_shard_order) { // scylla-bench -mode counter_update -workload uniform -duration 15s // -replication-factor 3 -partition-count 2 -clustering-row-count 4 // on a three-node Scylla 1.7.4 cluster. - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (const auto version : all_sstable_versions) { auto s = schema_builder("scylla_bench", "test_counters") .with_column("pk", long_type, column_kind::partition_key) @@ -4379,7 +4287,7 @@ SEASTAR_TEST_CASE(test_wrong_counter_shard_order) { .with_column("c5", counter_type) .build(); - auto sst = make_lw_shared(s, get_test_dir("wrong_counter_shard_order", s), 2, version, big); + auto sst = env.make_sstable(s, get_test_dir("wrong_counter_shard_order", s), 2, version, big); sst->load().get0(); auto reader = sstable_reader(sst, s); @@ -4433,7 +4341,7 @@ SEASTAR_TEST_CASE(test_wrong_counter_shard_order) { } SEASTAR_TEST_CASE(compaction_correctness_with_partitioned_sstable_set) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; cell_locker_stats cl_stats; @@ -4445,8 +4353,8 @@ SEASTAR_TEST_CASE(compaction_correctness_with_partitioned_sstable_set) { auto s = builder.build(); auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - auto sst = make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + auto sst = env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); sst->set_unshared(); return sst; }; @@ -4559,7 +4467,7 @@ SEASTAR_TEST_CASE(test_broken_promoted_index_is_skipped) { // insert into ks.test (pk, ck, v) values (1, 2, 1); // insert into ks.test (pk, ck, v) values (1, 3, 1); // delete from ks.test where pk = 1 and ck = 2; - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (const auto version : all_sstable_versions) { auto s = schema_builder("ks", "test") .with_column("pk", int32_type, column_kind::partition_key) @@ -4567,7 +4475,7 @@ SEASTAR_TEST_CASE(test_broken_promoted_index_is_skipped) { .with_column("v", int32_type) .build(schema_builder::compact_storage::yes); - auto sst = sstables::make_sstable(s, get_test_dir("broken_non_compound_pi_and_range_tombstone", s), 1, version, big); + auto sst = env.make_sstable(s, get_test_dir("broken_non_compound_pi_and_range_tombstone", s), 1, version, big); sst->load().get0(); { @@ -4586,7 +4494,7 @@ SEASTAR_TEST_CASE(test_old_format_non_compound_range_tombstone_is_read) { // insert into ks.test (pk, ck, v) values (1, 2, 1); // insert into ks.test (pk, ck, v) values (1, 3, 1); // delete from ks.test where pk = 1 and ck = 2; - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { for (const auto version : all_sstable_versions) { if (version != sstables::sstable::version_types::mc) { // Does not apply to 'mc' format auto s = schema_builder("ks", "test") @@ -4595,7 +4503,7 @@ SEASTAR_TEST_CASE(test_old_format_non_compound_range_tombstone_is_read) { .with_column("v", int32_type) .build(schema_builder::compact_storage::yes); - auto sst = sstables::make_sstable(s, get_test_dir("broken_non_compound_pi_and_range_tombstone", s), 1, version, big); + auto sst = env.make_sstable(s, get_test_dir("broken_non_compound_pi_and_range_tombstone", s), 1, version, big); sst->load().get0(); auto pk = partition_key::from_exploded(*s, { int32_type->decompose(1) }); @@ -4617,7 +4525,7 @@ SEASTAR_TEST_CASE(test_old_format_non_compound_range_tombstone_is_read) { } SEASTAR_TEST_CASE(summary_rebuild_sanity) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; auto builder = schema_builder("tests", "test") .with_column("id", utf8_type, column_kind::partition_key) @@ -4639,8 +4547,8 @@ SEASTAR_TEST_CASE(summary_rebuild_sanity) { } auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); }; auto sst = make_sstable_containing(sst_gen, mutations); @@ -4648,7 +4556,7 @@ SEASTAR_TEST_CASE(summary_rebuild_sanity) { BOOST_REQUIRE(s1.entries.size() > 1); sstables::test(sst).remove_component(component_type::Summary).get(); - sst = reusable_sst(s, tmp.path().string(), 1).get0(); + sst = env.reusable_sst(s, tmp.path().string(), 1).get0(); summary& s2 = sstables::test(sst).get_summary(); BOOST_REQUIRE(::memcmp(&s1.header, &s2.header, sizeof(summary::header)) == 0); @@ -4661,7 +4569,7 @@ SEASTAR_TEST_CASE(summary_rebuild_sanity) { SEASTAR_TEST_CASE(sstable_cleanup_correctness_test) { return do_with_cql_env([] (auto& e) { - return seastar::async([&db = e.local_db()] () mutable { + return test_env::do_with_async([&db = e.local_db()] (test_env& env) { cell_locker_stats cl_stats; auto s = schema_builder("ks" /* single_node_cql_env::ks_name */, "correcness_test") @@ -4669,8 +4577,8 @@ SEASTAR_TEST_CASE(sstable_cleanup_correctness_test) { .with_column("value", int32_type).build(); auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); }; auto make_insert = [&] (partition_key key) { @@ -4701,7 +4609,7 @@ SEASTAR_TEST_CASE(sstable_cleanup_correctness_test) { } SEASTAR_TEST_CASE(sstable_partition_estimation_sanity_test) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; auto builder = schema_builder("tests", "test") .with_column("id", utf8_type, column_kind::partition_key) @@ -4725,8 +4633,8 @@ SEASTAR_TEST_CASE(sstable_partition_estimation_sanity_test) { }; auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); }; { @@ -4759,7 +4667,7 @@ SEASTAR_TEST_CASE(sstable_partition_estimation_sanity_test) { SEASTAR_TEST_CASE(sstable_timestamp_metadata_correcness_with_negative) { BOOST_REQUIRE(smp::count == 1); - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; for (auto version : all_sstable_versions) { cell_locker_stats cl_stats; @@ -4769,8 +4677,8 @@ SEASTAR_TEST_CASE(sstable_timestamp_metadata_correcness_with_negative) { .with_column("value", int32_type).build(); auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1), version]() mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, version, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1), version]() mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, version, big); }; auto make_insert = [&](partition_key key, api::timestamp_type ts) { @@ -4795,7 +4703,7 @@ SEASTAR_TEST_CASE(sstable_timestamp_metadata_correcness_with_negative) { SEASTAR_TEST_CASE(sstable_run_identifier_correctness) { BOOST_REQUIRE(smp::count == 1); - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; cell_locker_stats cl_stats; @@ -4810,14 +4718,14 @@ SEASTAR_TEST_CASE(sstable_run_identifier_correctness) { sstable_writer_config cfg; cfg.run_identifier = utils::make_random_uuid(); cfg.large_data_handler = &nop_lp_handler; - auto sst = make_sstable_easy(tmp.path(), flat_mutation_reader_from_mutations({ std::move(mut) }), cfg, la); + auto sst = make_sstable_easy(env, tmp.path(), flat_mutation_reader_from_mutations({ std::move(mut) }), cfg, la); BOOST_REQUIRE(sst->run_identifier() == cfg.run_identifier); }); } SEASTAR_TEST_CASE(sstable_run_based_compaction_test) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; cell_locker_stats cl_stats; @@ -4827,8 +4735,8 @@ SEASTAR_TEST_CASE(sstable_run_based_compaction_test) { auto s = builder.build(); auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - auto sst = make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + auto sst = env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); sst->set_unshared(); return sst; }; @@ -4929,7 +4837,7 @@ SEASTAR_TEST_CASE(sstable_run_based_compaction_test) { } SEASTAR_TEST_CASE(compaction_strategy_aware_major_compaction_test) { - return seastar::async([] { + return test_env::do_with_async([] (test_env& env) { storage_service_for_tests ssft; cell_locker_stats cl_stats; @@ -4938,8 +4846,8 @@ SEASTAR_TEST_CASE(compaction_strategy_aware_major_compaction_test) { .with_column("value", int32_type).build(); auto tmp = tmpdir(); - auto sst_gen = [s, &tmp, gen = make_lw_shared(1)] () mutable { - return make_sstable(s, tmp.path().string(), (*gen)++, la, big); + auto sst_gen = [&env, s, &tmp, gen = make_lw_shared(1)] () mutable { + return env.make_sstable(s, tmp.path().string(), (*gen)++, la, big); }; auto make_insert = [&] (partition_key key) { mutation m(s, key); diff --git a/tests/sstable_mutation_test.cc b/tests/sstable_mutation_test.cc index 2d0ff396af..223b6227f1 100644 --- a/tests/sstable_mutation_test.cc +++ b/tests/sstable_mutation_test.cc @@ -53,7 +53,8 @@ static db::nop_large_data_handler nop_lp_handler; SEASTAR_THREAD_TEST_CASE(nonexistent_key) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([] (auto sstp) { + sstables::test_env env; + env.reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([] (auto sstp) { return do_with(make_dkey(uncompressed_schema(), "invalid_key"), [sstp] (auto& key) { auto s = uncompressed_schema(); auto rd = make_lw_shared(sstp->read_row_flat(s, key)); @@ -65,8 +66,8 @@ SEASTAR_THREAD_TEST_CASE(nonexistent_key) { }).get(); } -future<> test_no_clustered(bytes&& key, std::unordered_map &&map) { - return reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([k = std::move(key), map = std::move(map)] (auto sstp) mutable { +future<> test_no_clustered(sstables::test_env& env, bytes&& key, std::unordered_map &&map) { + return env.reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([k = std::move(key), map = std::move(map)] (auto sstp) mutable { return do_with(make_dkey(uncompressed_schema(), std::move(k)), [sstp, map = std::move(map)] (auto& key) { auto s = uncompressed_schema(); auto rd = make_lw_shared(sstp->read_row_flat(s, key)); @@ -90,22 +91,26 @@ future<> test_no_clustered(bytes&& key, std::unordered_map && SEASTAR_THREAD_TEST_CASE(uncompressed_1) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - test_no_clustered("vinna", {{ "col1", to_sstring("daughter") }, { "col2", 3 }}).get(); + sstables::test_env env; + test_no_clustered(env, "vinna", {{ "col1", to_sstring("daughter") }, { "col2", 3 }}).get(); } SEASTAR_THREAD_TEST_CASE(uncompressed_2) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - test_no_clustered("gustaf", {{ "col1", to_sstring("son") }, { "col2", 0 }}).get(); + sstables::test_env env; + test_no_clustered(env, "gustaf", {{ "col1", to_sstring("son") }, { "col2", 0 }}).get(); } SEASTAR_THREAD_TEST_CASE(uncompressed_3) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - test_no_clustered("isak", {{ "col1", to_sstring("son") }, { "col2", 1 }}).get(); + sstables::test_env env; + test_no_clustered(env, "isak", {{ "col1", to_sstring("son") }, { "col2", 1 }}).get(); } SEASTAR_THREAD_TEST_CASE(uncompressed_4) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - test_no_clustered("finna", {{ "col1", to_sstring("daughter") }, { "col2", 2 }}).get(); + sstables::test_env env; + test_no_clustered(env, "finna", {{ "col1", to_sstring("daughter") }, { "col2", 2 }}).get(); } /* @@ -136,8 +141,8 @@ SEASTAR_THREAD_TEST_CASE(uncompressed_4) { // FIXME: we are lacking a full deletion test template -future generate_clustered(bytes&& key) { - return reusable_sst(complex_schema(), "tests/sstables/complex", Generation).then([k = std::move(key)] (auto sstp) mutable { +future generate_clustered(sstables::test_env& env, bytes&& key) { + return env.reusable_sst(complex_schema(), "tests/sstables/complex", Generation).then([k = std::move(key)] (auto sstp) mutable { return do_with(make_dkey(complex_schema(), std::move(k)), [sstp] (auto& key) { auto s = complex_schema(); auto rd = make_lw_shared(sstp->read_row_flat(s, key)); @@ -157,7 +162,8 @@ inline auto clustered_row(mutation& mutation, const schema& s, std::vector("key1").then([] (auto&& mutation) { + sstables::test_env env; + generate_clustered<1>(env, "key1").then([] (auto&& mutation) { auto s = complex_schema(); auto& sr = mutation.partition().static_row(); @@ -187,7 +193,8 @@ SEASTAR_THREAD_TEST_CASE(complex_sst1_k1) { SEASTAR_THREAD_TEST_CASE(complex_sst1_k2) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - generate_clustered<1>("key2").then([] (auto&& mutation) { + sstables::test_env env; + generate_clustered<1>(env, "key2").then([] (auto&& mutation) { auto s = complex_schema(); auto& sr = mutation.partition().static_row(); @@ -219,7 +226,8 @@ SEASTAR_THREAD_TEST_CASE(complex_sst1_k2) { SEASTAR_THREAD_TEST_CASE(complex_sst2_k1) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - generate_clustered<2>("key1").then([] (auto&& mutation) { + sstables::test_env env; + generate_clustered<2>(env, "key1").then([] (auto&& mutation) { auto s = complex_schema(); auto exploded = exploded_clustering_prefix({"cl1.1", "cl2.1"}); @@ -238,7 +246,8 @@ SEASTAR_THREAD_TEST_CASE(complex_sst2_k1) { SEASTAR_THREAD_TEST_CASE(complex_sst2_k2) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - generate_clustered<2>("key2").then([] (auto&& mutation) { + sstables::test_env env; + generate_clustered<2>(env, "key2").then([] (auto&& mutation) { auto s = complex_schema(); auto& sr = mutation.partition().static_row(); @@ -268,7 +277,8 @@ SEASTAR_THREAD_TEST_CASE(complex_sst2_k2) { SEASTAR_THREAD_TEST_CASE(complex_sst2_k3) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - generate_clustered<2>("key3").then([] (auto&& mutation) { + sstables::test_env env; + generate_clustered<2>(env, "key3").then([] (auto&& mutation) { auto s = complex_schema(); auto& sr = mutation.partition().static_row(); @@ -287,7 +297,8 @@ SEASTAR_THREAD_TEST_CASE(complex_sst2_k3) { SEASTAR_THREAD_TEST_CASE(complex_sst3_k1) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - generate_clustered<3>("key1").then([] (auto&& mutation) { + sstables::test_env env; + generate_clustered<3>(env, "key1").then([] (auto&& mutation) { auto s = complex_schema(); auto row = clustered_row(mutation, *s, {"cl1.2", "cl2.2"}); @@ -308,7 +319,8 @@ SEASTAR_THREAD_TEST_CASE(complex_sst3_k1) { SEASTAR_THREAD_TEST_CASE(complex_sst3_k2) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - generate_clustered<3>("key2").then([] (auto&& mutation) { + sstables::test_env env; + generate_clustered<3>(env, "key2").then([] (auto&& mutation) { auto s = complex_schema(); auto& sr = mutation.partition().static_row(); @@ -325,8 +337,8 @@ SEASTAR_THREAD_TEST_CASE(complex_sst3_k2) { }).get(); } -future<> test_range_reads(const dht::token& min, const dht::token& max, std::vector& expected) { - return reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([min, max, &expected] (auto sstp) mutable { +future<> test_range_reads(sstables::test_env& env, const dht::token& min, const dht::token& max, std::vector& expected) { + return env.reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([min, max, &expected] (auto sstp) mutable { auto s = uncompressed_schema(); auto count = make_lw_shared(0); auto expected_size = expected.size(); @@ -361,31 +373,31 @@ future<> test_range_reads(const dht::token& min, const dht::token& max, std::vec SEASTAR_THREAD_TEST_CASE(read_range) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); std::vector expected = { to_bytes("finna"), to_bytes("isak"), to_bytes("gustaf"), to_bytes("vinna") }; - do_with(std::move(expected), [] (auto& expected) { - return test_range_reads(dht::minimum_token(), dht::maximum_token(), expected); + do_with(sstables::test_env(), std::move(expected), [] (auto& env, auto& expected) { + return test_range_reads(env, dht::minimum_token(), dht::maximum_token(), expected); }).get(); } SEASTAR_THREAD_TEST_CASE(read_partial_range) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); std::vector expected = { to_bytes("finna"), to_bytes("isak") }; - do_with(std::move(expected), [] (auto& expected) { - return test_range_reads(dht::global_partitioner().get_token(key_view(bytes_view(expected.back()))), dht::maximum_token(), expected); + do_with(sstables::test_env(), std::move(expected), [] (auto& env, auto& expected) { + return test_range_reads(env, dht::global_partitioner().get_token(key_view(bytes_view(expected.back()))), dht::maximum_token(), expected); }).get(); } SEASTAR_THREAD_TEST_CASE(read_partial_range_2) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); std::vector expected = { to_bytes("gustaf"), to_bytes("vinna") }; - do_with(std::move(expected), [] (auto& expected) { - return test_range_reads(dht::minimum_token(), dht::global_partitioner().get_token(key_view(bytes_view(expected.front()))), expected); + do_with(sstables::test_env(), std::move(expected), [] (auto& env, auto& expected) { + return test_range_reads(env, dht::minimum_token(), dht::global_partitioner().get_token(key_view(bytes_view(expected.front()))), expected); }).get(); } static -mutation_source make_sstable_mutation_source(schema_ptr s, sstring dir, std::vector mutations, +mutation_source make_sstable_mutation_source(sstables::test_env& env, schema_ptr s, sstring dir, std::vector mutations, sstable_writer_config cfg, sstables::sstable::version_types version) { - auto sst = sstables::make_sstable(s, + auto sst = env.make_sstable(s, dir, 1 /* generation */, version, @@ -405,11 +417,11 @@ mutation_source make_sstable_mutation_source(schema_ptr s, sstring dir, std::vec // Must be run in a seastar thread static -void test_mutation_source(sstable_writer_config cfg, sstables::sstable::version_types version) { +void test_mutation_source(sstables::test_env& env, sstable_writer_config cfg, sstables::sstable::version_types version) { std::vector dirs; - run_mutation_source_tests([&dirs, &cfg, version] (schema_ptr s, const std::vector& partitions) -> mutation_source { + run_mutation_source_tests([&env, &dirs, &cfg, version] (schema_ptr s, const std::vector& partitions) -> mutation_source { dirs.emplace_back(); - return make_sstable_mutation_source(s, dirs.back().path().string(), partitions, cfg, version); + return make_sstable_mutation_source(env, s, dirs.back().path().string(), partitions, cfg, version); }); } @@ -418,12 +430,13 @@ SEASTAR_TEST_CASE(test_sstable_conforms_to_mutation_source) { return seastar::async([] { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); storage_service_for_tests ssft; + sstables::test_env env; for (auto version : all_sstable_versions) { for (auto index_block_size : {1, 128, 64*1024}) { sstable_writer_config cfg; cfg.promoted_index_block_size = index_block_size; cfg.large_data_handler = &nop_lp_handler; - test_mutation_source(cfg, version); + test_mutation_source(env, cfg, version); } } }); @@ -448,7 +461,8 @@ SEASTAR_TEST_CASE(test_sstable_can_write_and_read_range_tombstone) { auto mt = make_lw_shared(s); mt->apply(std::move(m)); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, sstables::sstable::version_types::la, @@ -472,7 +486,8 @@ SEASTAR_TEST_CASE(test_sstable_can_write_and_read_range_tombstone) { SEASTAR_THREAD_TEST_CASE(compact_storage_sparse_read) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - reusable_sst(compact_sparse_schema(), "tests/sstables/compact_sparse", 1).then([] (auto sstp) { + sstables::test_env env; + env.reusable_sst(compact_sparse_schema(), "tests/sstables/compact_sparse", 1).then([] (auto sstp) { return do_with(make_dkey(compact_sparse_schema(), "first_row"), [sstp] (auto& key) { auto s = compact_sparse_schema(); auto rd = make_lw_shared(sstp->read_row_flat(s, key)); @@ -490,7 +505,8 @@ SEASTAR_THREAD_TEST_CASE(compact_storage_sparse_read) { SEASTAR_THREAD_TEST_CASE(compact_storage_simple_dense_read) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - reusable_sst(compact_simple_dense_schema(), "tests/sstables/compact_simple_dense", 1).then([] (auto sstp) { + sstables::test_env env; + env.reusable_sst(compact_simple_dense_schema(), "tests/sstables/compact_simple_dense", 1).then([] (auto sstp) { return do_with(make_dkey(compact_simple_dense_schema(), "first_row"), [sstp] (auto& key) { auto s = compact_simple_dense_schema(); auto rd = make_lw_shared(sstp->read_row_flat(s, key)); @@ -510,7 +526,8 @@ SEASTAR_THREAD_TEST_CASE(compact_storage_simple_dense_read) { SEASTAR_THREAD_TEST_CASE(compact_storage_dense_read) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - reusable_sst(compact_dense_schema(), "tests/sstables/compact_dense", 1).then([] (auto sstp) { + sstables::test_env env; + env.reusable_sst(compact_dense_schema(), "tests/sstables/compact_dense", 1).then([] (auto sstp) { return do_with(make_dkey(compact_dense_schema(), "first_row"), [sstp] (auto& key) { auto s = compact_dense_schema(); auto rd = make_lw_shared(sstp->read_row_flat(s, key)); @@ -534,7 +551,8 @@ SEASTAR_THREAD_TEST_CASE(compact_storage_dense_read) { // Make sure we don't regress on that. SEASTAR_THREAD_TEST_CASE(broken_ranges_collection) { auto wait_bg = seastar::defer([] { sstables::await_background_jobs().get(); }); - reusable_sst(peers_schema(), "tests/sstables/broken_ranges", 2).then([] (auto sstp) { + sstables::test_env env; + env.reusable_sst(peers_schema(), "tests/sstables/broken_ranges", 2).then([] (auto sstp) { auto s = peers_schema(); auto reader = make_lw_shared(sstp->as_mutation_source().make_reader(s, query::full_partition_range)); return repeat([s, reader] { @@ -586,7 +604,8 @@ static schema_ptr tombstone_overlap_schema() { static future ka_sst(schema_ptr schema, sstring dir, unsigned long generation) { - auto sst = make_sstable(std::move(schema), dir, generation, sstables::sstable::version_types::ka, big); + sstables::test_env env; + auto sst = env.make_sstable(std::move(schema), dir, generation, sstables::sstable::version_types::ka, big); auto fut = sst->load(); return std::move(fut).then([sst = std::move(sst)] { return make_ready_future(std::move(sst)); @@ -823,7 +842,8 @@ SEASTAR_TEST_CASE(test_non_compound_table_row_is_not_marked_as_static) { auto mt = make_lw_shared(s); mt->apply(std::move(m)); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, version, @@ -859,7 +879,8 @@ SEASTAR_TEST_CASE(test_has_partition_key) { auto mt = make_lw_shared(s); mt->apply(std::move(m)); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, version, @@ -922,7 +943,8 @@ SEASTAR_TEST_CASE(test_promoted_index_blocks_are_monotonic) { auto mt = make_lw_shared(s); mt->apply(std::move(m)); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, sstables::sstable::version_types::ka, @@ -975,7 +997,8 @@ SEASTAR_TEST_CASE(test_promoted_index_blocks_are_monotonic_compound_dense) { auto mt = make_lw_shared(s); mt->apply(std::move(m)); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, version, @@ -1035,7 +1058,8 @@ SEASTAR_TEST_CASE(test_promoted_index_blocks_are_monotonic_non_compound_dense) { auto mt = make_lw_shared(s); mt->apply(std::move(m)); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, version, @@ -1092,7 +1116,8 @@ SEASTAR_TEST_CASE(test_promoted_index_repeats_open_tombstones) { auto mt = make_lw_shared(s); mt->apply(m); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), generation, version, @@ -1139,7 +1164,8 @@ SEASTAR_TEST_CASE(test_range_tombstones_are_correctly_seralized_for_non_compound auto mt = make_lw_shared(s); mt->apply(m); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, version, @@ -1179,7 +1205,8 @@ SEASTAR_TEST_CASE(test_promoted_index_is_absent_for_schemas_without_clustering_k auto mt = make_lw_shared(s); mt->apply(m); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, version, @@ -1220,7 +1247,8 @@ SEASTAR_TEST_CASE(test_can_write_and_read_non_compound_range_tombstone_as_compou auto mt = make_lw_shared(s); mt->apply(m); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, version, @@ -1274,7 +1302,8 @@ SEASTAR_TEST_CASE(test_writing_combined_stream_with_tombstones_at_the_same_posit auto mt2 = make_lw_shared(s); mt2->apply(m2); - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, version, @@ -1319,7 +1348,8 @@ SEASTAR_TEST_CASE(test_no_index_reads_when_rows_fall_into_range_boundaries) { cfg.large_data_handler = &nop_lp_handler; tmpdir dir; - auto ms = make_sstable_mutation_source(s, dir.path().string(), {m1, m2}, cfg, version); + sstables::test_env env; + auto ms = make_sstable_mutation_source(env, s, dir.path().string(), {m1, m2}, cfg, version); auto index_accesses = [] { auto&& stats = sstables::shared_index_lists::shard_stats(); @@ -1396,7 +1426,8 @@ SEASTAR_THREAD_TEST_CASE(test_large_index_pages_do_not_cause_large_allocations) mt->apply(m); } - auto sst = sstables::make_sstable(s, + sstables::test_env env; + auto sst = env.make_sstable(s, dir.path().string(), 1 /* generation */, sstable_version_types::ka, @@ -1438,18 +1469,19 @@ SEASTAR_THREAD_TEST_CASE(test_schema_changes) { shared_sstable created_with_base_schema; shared_sstable created_with_changed_schema; + sstables::test_env env; if (it == cache.end()) { auto mt = make_lw_shared(base); for (auto& m : base_mutations) { mt->apply(m); } - created_with_base_schema = sstables::make_sstable(base, dir.path().string(), gen, version, sstables::sstable::format_types::big); + created_with_base_schema = env.make_sstable(base, dir.path().string(), gen, version, sstables::sstable::format_types::big); sstable_writer_config cfg; cfg.large_data_handler = &nop_lp_handler; created_with_base_schema->write_components(mt->make_flat_reader(base), base_mutations.size(), base, cfg, mt->get_encoding_stats()).get(); created_with_base_schema->load().get(); - created_with_changed_schema = sstables::make_sstable(changed, dir.path().string(), gen, version, sstables::sstable::format_types::big); + created_with_changed_schema = env.make_sstable(changed, dir.path().string(), gen, version, sstables::sstable::format_types::big); created_with_changed_schema->load().get(); cache.emplace(std::tuple { version, base }, std::tuple { created_with_base_schema, gen }); @@ -1457,7 +1489,7 @@ SEASTAR_THREAD_TEST_CASE(test_schema_changes) { } else { created_with_base_schema = std::get(it->second); - created_with_changed_schema = sstables::make_sstable(changed, dir.path().string(), std::get(it->second), version, sstables::sstable::format_types::big); + created_with_changed_schema = env.make_sstable(changed, dir.path().string(), std::get(it->second), version, sstables::sstable::format_types::big); created_with_changed_schema->load().get(); } @@ -1518,17 +1550,18 @@ SEASTAR_THREAD_TEST_CASE(test_reading_serialization_header) { auto m1ow = md1_overwrite.build(s); mt->apply(m1ow); + sstables::test_env env; { // SSTable class has way too many responsibilities. In particular, it mixes the reading and // writting parts. Let's use a separate objects for writing and reading to ensure that nothing // carries over that wouldn't normally be read from disk. - auto sst = sstables::make_sstable(s, dir.path().string(), 1, sstable::version_types::mc, sstables::sstable::format_types::big); + auto sst = env.make_sstable(s, dir.path().string(), 1, sstable::version_types::mc, sstables::sstable::format_types::big); sstable_writer_config cfg; cfg.large_data_handler = &nop_lp_handler; sst->write_components(mt->make_flat_reader(s), 2, s, cfg, mt->get_encoding_stats()).get(); } - auto sst = sstables::make_sstable(s, dir.path().string(), 1, sstable::version_types::mc, sstables::sstable::format_types::big); + auto sst = env.make_sstable(s, dir.path().string(), 1, sstable::version_types::mc, sstables::sstable::format_types::big); sst->load().get(); auto hdr = sst->get_serialization_header(); @@ -1617,8 +1650,9 @@ SEASTAR_THREAD_TEST_CASE(test_counter_header_size) { auto mt = make_lw_shared(s); mt->apply(m); + sstables::test_env env; for (const auto version : all_sstable_versions) { - auto sst = sstables::make_sstable(s, dir.path().string(), 1, version, sstables::sstable::format_types::big); + auto sst = env.make_sstable(s, dir.path().string(), 1, version, sstables::sstable::format_types::big); sstable_writer_config cfg; cfg.large_data_handler = &nop_lp_handler; sst->write_components(mt->make_flat_reader(s), 1, s, cfg, mt->get_encoding_stats()).get(); diff --git a/tests/sstable_resharding_test.cc b/tests/sstable_resharding_test.cc index 58757fbd79..45875c00a5 100644 --- a/tests/sstable_resharding_test.cc +++ b/tests/sstable_resharding_test.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include "sstables/compaction_manager.hh" #include "mutation_reader.hh" #include "sstable_test.hh" +#include "test_services.hh" #include "tmpdir.hh" #include "cell_locking.hh" #include "flat_mutation_reader_assertions.hh" @@ -23,13 +25,6 @@ using namespace sstables; static db::nop_large_data_handler nop_lp_handler; -static inline dht::token create_token_from_key(sstring key) { - sstables::key_view key_view = sstables::key_view(bytes_view(reinterpret_cast(key.c_str()), key.size())); - dht::token token = dht::global_partitioner().get_token(key_view); - assert(token == dht::global_partitioner().get_token(key_view)); - return token; -} - static inline std::vector> token_generation_for_shard(shard_id shard, unsigned tokens_to_generate) { unsigned tokens = 0; unsigned key_id = 0; @@ -56,6 +51,10 @@ static inline std::vector> token_generation_for_s return key_and_token_pair; } +static std::vector> token_generation_for_current_shard(unsigned tokens_to_generate) { + return token_generation_for_shard(engine().cpu_id(), tokens_to_generate); +} + static schema_ptr get_schema() { auto builder = schema_builder("tests", "sstable_resharding_test") .with_column("id", utf8_type, column_kind::partition_key) @@ -64,6 +63,7 @@ static schema_ptr get_schema() { } void run_sstable_resharding_test() { + test_env env; cache_tracker tracker; for (const auto version : all_sstable_versions) { storage_service_for_tests ssft; @@ -97,11 +97,10 @@ void run_sstable_resharding_test() { mt->apply(std::move(m)); } } - auto sst = sstables::make_sstable(s, tmp.path().string(), 0, version, sstables::sstable::format_types::big); + auto sst = env.make_sstable(s, tmp.path().string(), 0, version, sstables::sstable::format_types::big); write_memtable_to_sstable_for_test(*mt, sst).get(); } - auto sst = sstables::make_sstable(s, tmp.path().string(), 0, version, sstables::sstable::format_types::big); - sst->load().get(); + auto sst = env.reusable_sst(s, tmp.path().string(), 0, version, sstables::sstable::format_types::big).get0(); // FIXME: sstable write has a limitation in which it will generate sharding metadata only // for a single shard. workaround that by setting shards manually. from this test perspective, @@ -112,17 +111,15 @@ void run_sstable_resharding_test() { auto filter_fname = sstables::test(sst).filename(component_type::Filter); uint64_t bloom_filter_size_before = file_size(filter_fname).get0(); - auto creator = [&cf, &tmp, version] (shard_id shard) mutable { + auto creator = [&env, &cf, &tmp, version] (shard_id shard) mutable { // we need generation calculated by instance of cf at requested shard, // or resource usage wouldn't be fairly distributed among shards. auto gen = smp::submit_to(shard, [&cf] () { return column_family_test::calculate_generation_for_new_table(*cf); }).get0(); - auto sst = sstables::make_sstable(cf->schema(), tmp.path().string(), gen, - version, sstables::sstable::format_types::big, - gc_clock::now(), default_io_error_handler_gen()); - return sst; + return env.make_sstable(cf->schema(), tmp.path().string(), gen, + version, sstables::sstable::format_types::big); }; auto new_sstables = sstables::reshard_sstables({ sst }, *cf, creator, std::numeric_limits::max(), 0).get0(); BOOST_REQUIRE(new_sstables.size() == smp::count); @@ -130,9 +127,8 @@ void run_sstable_resharding_test() { uint64_t bloom_filter_size_after = 0; for (auto& sstable : new_sstables) { - auto new_sst = sstables::make_sstable(s, tmp.path().string(), sstable->generation(), - version, sstables::sstable::format_types::big); - new_sst->load().get(); + auto new_sst = env.reusable_sst(s, tmp.path().string(), sstable->generation(), + version, sstables::sstable::format_types::big).get0(); filter_fname = sstables::test(new_sst).filename(component_type::Filter); bloom_filter_size_after += file_size(filter_fname).get0(); auto shards = new_sst->get_shards_for_this_sstable(); @@ -156,3 +152,40 @@ SEASTAR_TEST_CASE(sstable_resharding_test) { run_sstable_resharding_test(); }); } + +SEASTAR_THREAD_TEST_CASE(sstable_resharding_strategy_tests) { + test_env env; + + for (const auto version : all_sstable_versions) { + auto s = make_lw_shared(schema({}, "ks", "cf", {{"p1", utf8_type}}, {}, {}, {}, utf8_type)); + auto get_sstable = [&] (int64_t gen, sstring first_key, sstring last_key) mutable { + auto sst = env.make_sstable(s, "", gen, version, sstables::sstable::format_types::big); + stats_metadata stats = {}; + stats.sstable_level = 1; + sstables::test(sst).set_values(std::move(first_key), std::move(last_key), std::move(stats)); + return sst; + }; + + column_family_for_tests cf; + + auto tokens = token_generation_for_current_shard(2); + auto stcs = sstables::make_compaction_strategy(sstables::compaction_strategy_type::size_tiered, s->compaction_strategy_options()); + auto lcs = sstables::make_compaction_strategy(sstables::compaction_strategy_type::leveled, s->compaction_strategy_options()); + + auto sst1 = get_sstable(1, tokens[0].first, tokens[1].first); + auto sst2 = get_sstable(2, tokens[1].first, tokens[1].first); + + { + // TODO: sstable_test runs with smp::count == 1, thus we will not be able to stress it more + // until we move this test case to sstable_resharding_test. + auto descriptors = stcs.get_resharding_jobs(*cf, { sst1, sst2 }); + BOOST_REQUIRE(descriptors.size() == 2); + } + { + auto ssts = std::vector{ sst1, sst2 }; + auto descriptors = lcs.get_resharding_jobs(*cf, ssts); + auto expected_jobs = ssts.size()/smp::count + ssts.size()%smp::count; + BOOST_REQUIRE(descriptors.size() == expected_jobs); + } + } +} diff --git a/tests/sstable_test.cc b/tests/sstable_test.cc index a3636d80e4..a223eb3666 100644 --- a/tests/sstable_test.cc +++ b/tests/sstable_test.cc @@ -48,21 +48,37 @@ bytes as_bytes(const sstring& s) { return { reinterpret_cast(s.begin()), s.size() }; } +future<> test_using_working_sst(schema_ptr s, sstring dir, int64_t gen) { + return test_env::do_with([s = std::move(s), dir = std::move(dir), gen] (test_env& env) { + return env.working_sst(std::move(s), std::move(dir), gen); + }); +} + SEASTAR_TEST_CASE(uncompressed_data) { - return working_sst(uncompressed_schema(), uncompressed_dir(), 1); + return test_using_working_sst(uncompressed_schema(), uncompressed_dir(), 1); } SEASTAR_TEST_CASE(compressed_data) { auto s = make_lw_shared(schema({}, "ks", "cf", {}, {}, {}, {}, utf8_type)); - return working_sst(std::move(s), "tests/sstables/compressed", 1); + return test_using_working_sst(std::move(s), "tests/sstables/compressed", 1); } SEASTAR_TEST_CASE(composite_index) { - return working_sst(composite_schema(), "tests/sstables/composite", 1); + return test_using_working_sst(composite_schema(), "tests/sstables/composite", 1); +} + +template +inline auto +test_using_reusable_sst(schema_ptr s, sstring dir, unsigned long gen, Func&& func) { + return test_env::do_with([s = std::move(s), dir = std::move(dir), gen, func = std::move(func)] (test_env& env) { + return env.reusable_sst(std::move(s), std::move(dir), gen).then([func = std::move(func)] (sstable_ptr sst) { + return func(std::move(sst)); + }); + }); } future index_read(schema_ptr schema, sstring path) { - return reusable_sst(std::move(schema), path, 1).then([] (sstable_ptr ptr) { + return test_using_reusable_sst(std::move(schema), std::move(path), 1, [] (sstable_ptr ptr) { return sstables::test(ptr).read_indexes(); }); } @@ -81,7 +97,7 @@ SEASTAR_TEST_CASE(composite_index_read) { template future<> summary_query(schema_ptr schema, sstring path, int generation) { - return reusable_sst(std::move(schema), path, generation).then([] (sstable_ptr ptr) { + return test_using_reusable_sst(std::move(schema), path, generation, [] (sstable_ptr ptr) { return sstables::test(ptr).read_summary_entry(Position).then([ptr] (auto entry) { BOOST_REQUIRE(entry.position == EntryPosition); BOOST_REQUIRE(entry.key.size() == EntryKeySize); @@ -146,7 +162,7 @@ SEASTAR_TEST_CASE(missing_summary_interval_1_query_ok) { #endif SEASTAR_TEST_CASE(missing_summary_first_last_sane) { - return reusable_sst(uncompressed_schema(), uncompressed_dir(), 2).then([] (sstable_ptr ptr) { + return test_using_reusable_sst(uncompressed_schema(), uncompressed_dir(), 2, [] (shared_sstable ptr) { auto& summary = sstables::test(ptr).get_summary(); BOOST_REQUIRE(summary.header.size == 1); BOOST_REQUIRE(summary.positions.size() == 1); @@ -157,9 +173,8 @@ SEASTAR_TEST_CASE(missing_summary_first_last_sane) { }); } -static future do_write_sst(schema_ptr schema, sstring load_dir, sstring write_dir, unsigned long generation) { - auto sst = sstables::make_sstable(std::move(schema), load_dir, generation, la, big); - return sst->load().then([sst, write_dir, generation] { +static future do_write_sst(test_env& env, schema_ptr schema, sstring load_dir, sstring write_dir, unsigned long generation) { + return env.reusable_sst(std::move(schema), load_dir, generation, la).then([write_dir, generation] (sstable_ptr sst) { sstables::test(sst).change_generation_number(generation + 1); sstables::test(sst).change_dir(write_dir); auto fut = sstables::test(sst).store(); @@ -169,6 +184,12 @@ static future do_write_sst(schema_ptr schema, sstring load_dir, sst }); } +static future do_write_sst(schema_ptr schema, sstring load_dir, sstring write_dir, unsigned long generation) { + return test_env::do_with([schema = std::move(schema), load_dir = std::move(load_dir), write_dir = std::move(write_dir), generation] (test_env& env) { + return do_write_sst(env, std::move(schema), std::move(load_dir), std::move(write_dir), generation); + }); +} + static future<> write_sst_info(schema_ptr schema, sstring load_dir, sstring write_dir, unsigned long generation) { return do_write_sst(std::move(schema), load_dir, write_dir, generation).then([] (auto ptr) { return make_ready_future<>(); }); } @@ -225,11 +246,20 @@ SEASTAR_TEST_CASE(check_compressed_info_func) { return check_component_integrity(component_type::CompressionInfo); } +template +inline auto +write_and_validate_sst(schema_ptr s, sstring dir, Func&& func) { + return test_env::do_with(tmpdir(), [s = std::move(s), dir = std::move(dir), func = std::move(func)] (test_env& env, tmpdir& tmp) { + return do_write_sst(env, s, dir, tmp.path().string(), 1).then([&env, &tmp, s = std::move(s), func = std::move(func)] (auto sst1) { + auto sst2 = env.make_sstable(s, tmp.path().string(), 2, la, big); + return func(std::move(sst1), std::move(sst2)); + }); + }); +} + SEASTAR_TEST_CASE(check_summary_func) { - auto tmp = make_lw_shared(); auto s = make_lw_shared(schema({}, "ks", "cf", {}, {}, {}, {}, utf8_type)); - return do_write_sst(s, "tests/sstables/compressed", tmp->path().string(), 1).then([tmp, s] (auto sst1) { - auto sst2 = make_sstable(s, tmp->path().string(), 2, la, big); + return write_and_validate_sst(std::move(s), "tests/sstables/compressed", [] (shared_sstable sst1, shared_sstable sst2) { return sstables::test(sst2).read_summary().then([sst1, sst2] { summary& sst1_s = sstables::test(sst1).get_summary(); summary& sst2_s = sstables::test(sst2).get_summary(); @@ -239,8 +269,9 @@ SEASTAR_TEST_CASE(check_summary_func) { BOOST_REQUIRE(sst1_s.entries == sst2_s.entries); BOOST_REQUIRE(sst1_s.first_key.value == sst2_s.first_key.value); BOOST_REQUIRE(sst1_s.last_key.value == sst2_s.last_key.value); + return make_ready_future<>(); }); - }).then([tmp] {}); + }); } SEASTAR_TEST_CASE(check_filter_func) { @@ -248,10 +279,8 @@ SEASTAR_TEST_CASE(check_filter_func) { } SEASTAR_TEST_CASE(check_statistics_func) { - auto tmp = make_lw_shared(); auto s = make_lw_shared(schema({}, "ks", "cf", {}, {}, {}, {}, utf8_type)); - return do_write_sst(s, "tests/sstables/compressed", tmp->path().string(), 1).then([tmp, s] (auto sst1) { - auto sst2 = make_sstable(s, tmp->path().string(), 2, la, big); + return write_and_validate_sst(std::move(s), "tests/sstables/compressed", [] (shared_sstable sst1, shared_sstable sst2) { return sstables::test(sst2).read_statistics().then([sst1, sst2] { statistics& sst1_s = sstables::test(sst1).get_statistics(); statistics& sst2_s = sstables::test(sst2).get_statistics(); @@ -263,26 +292,26 @@ SEASTAR_TEST_CASE(check_statistics_func) { BOOST_REQUIRE(boost::get<0>(e).second == boost::get<1>(e).second); } // TODO: compare the field contents from both sstables. + return make_ready_future<>(); }); - }).then([tmp] {}); + }); } SEASTAR_TEST_CASE(check_toc_func) { - auto tmp = make_lw_shared(); auto s = make_lw_shared(schema({}, "ks", "cf", {}, {}, {}, {}, utf8_type)); - return do_write_sst(s, "tests/sstables/compressed", tmp->path().string(), 1).then([tmp, s] (auto sst1) { - auto sst2 = sstables::make_sstable(s, tmp->path().string(), 2, la, big); + return write_and_validate_sst(std::move(s), "tests/sstables/compressed", [] (shared_sstable sst1, shared_sstable sst2) { return sstables::test(sst2).read_toc().then([sst1, sst2] { auto& sst1_c = sstables::test(sst1).get_components(); auto& sst2_c = sstables::test(sst2).get_components(); BOOST_REQUIRE(sst1_c == sst2_c); + return make_ready_future<>(); }); - }).then([tmp] {}); + }); } SEASTAR_TEST_CASE(uncompressed_random_access_read) { - return reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([] (auto sstp) { + return test_using_reusable_sst(uncompressed_schema(), uncompressed_dir(), 1, [] (auto sstp) { // note: it's important to pass on a shared copy of sstp to prevent its // destruction until the continuation finishes reading! return sstables::test(sstp).data_read(97, 6).then([sstp] (temporary_buffer buf) { @@ -294,7 +323,7 @@ SEASTAR_TEST_CASE(uncompressed_random_access_read) { SEASTAR_TEST_CASE(compressed_random_access_read) { auto s = make_lw_shared(schema({}, "ks", "cf", {}, {}, {}, {}, utf8_type)); - return reusable_sst(std::move(s), "tests/sstables/compressed", 1).then([] (auto sstp) { + return test_using_reusable_sst(std::move(s), "tests/sstables/compressed", 1, [] (auto sstp) { return sstables::test(sstp).data_read(97, 6).then([sstp] (temporary_buffer buf) { BOOST_REQUIRE(sstring(buf.get(), buf.size()) == "gustaf"); return make_ready_future<>(); @@ -388,7 +417,7 @@ public: }; SEASTAR_TEST_CASE(uncompressed_rows_read_one) { - return reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([] (auto sstp) { + return test_using_reusable_sst(uncompressed_schema(), uncompressed_dir(), 1, [] (auto sstp) { return do_with(test_row_consumer(1418656871665302), [sstp] (auto& c) { auto context = data_consume_rows(*uncompressed_schema(), sstp, c, {0, 95}, 95); auto fut = context.read(); @@ -406,7 +435,7 @@ SEASTAR_TEST_CASE(uncompressed_rows_read_one) { SEASTAR_TEST_CASE(compressed_rows_read_one) { auto s = make_lw_shared(schema({}, "ks", "cf", {}, {}, {}, {}, utf8_type)); - return reusable_sst(std::move(s), "tests/sstables/compressed", 1).then([] (auto sstp) { + return test_using_reusable_sst(std::move(s), "tests/sstables/compressed", 1, [] (auto sstp) { return do_with(test_row_consumer(1418654707438005), [sstp] (auto& c) { auto context = data_consume_rows(*uncompressed_schema(), sstp, c, {0, 95}, 95); auto fut = context.read(); @@ -472,7 +501,7 @@ public: SEASTAR_TEST_CASE(uncompressed_rows_read_all) { - return reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([] (auto sstp) { + return test_using_reusable_sst(uncompressed_schema(), uncompressed_dir(), 1, [] (auto sstp) { return do_with(count_row_consumer(), [sstp] (auto& c) { auto context = data_consume_rows(*uncompressed_schema(), sstp, c); auto fut = context.read(); @@ -490,7 +519,7 @@ SEASTAR_TEST_CASE(uncompressed_rows_read_all) { SEASTAR_TEST_CASE(compressed_rows_read_all) { auto s = make_lw_shared(schema({}, "ks", "cf", {}, {}, {}, {}, utf8_type)); - return reusable_sst(std::move(s), "tests/sstables/compressed", 1).then([] (auto sstp) { + return test_using_reusable_sst(std::move(s), "tests/sstables/compressed", 1, [] (auto sstp) { return do_with(count_row_consumer(), [sstp] (auto& c) { auto context = data_consume_rows(*uncompressed_schema(), sstp, c); auto fut = context.read(); @@ -517,7 +546,7 @@ public: }; SEASTAR_TEST_CASE(pausable_uncompressed_rows_read_all) { - return reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([] (auto sstp) { + return test_using_reusable_sst(uncompressed_schema(), uncompressed_dir(), 1, [] (auto sstp) { return do_with(pausable_count_row_consumer(), [sstp] (auto& c) { auto context = data_consume_rows(*uncompressed_schema(), sstp, c); auto fut = context.read(); @@ -564,7 +593,7 @@ public: }; SEASTAR_TEST_CASE(read_set) { - return reusable_sst(set_schema(), "tests/sstables/set", 1).then([] (auto sstp) { + return test_using_reusable_sst(set_schema(), "tests/sstables/set", 1, [] (auto sstp) { return do_with(set_consumer(), [sstp] (auto& c) { auto context = data_consume_rows(*uncompressed_schema(), sstp, c); auto fut = context.read(); @@ -621,7 +650,7 @@ public: }; SEASTAR_TEST_CASE(ttl_read) { - return reusable_sst(uncompressed_schema(), "tests/sstables/ttl", 1).then([] (auto sstp) { + return test_using_reusable_sst(uncompressed_schema(), "tests/sstables/ttl", 1, [] (auto sstp) { return do_with(ttl_row_consumer(1430151018675502), [sstp] (auto& c) { auto context = data_consume_rows(*uncompressed_schema(), sstp, c); auto fut = context.read(); @@ -660,7 +689,7 @@ public: }; SEASTAR_TEST_CASE(deleted_cell_read) { - return reusable_sst(uncompressed_schema(), "tests/sstables/deleted_cell", 2).then([] (auto sstp) { + return test_using_reusable_sst(uncompressed_schema(), "tests/sstables/deleted_cell", 2, [] (auto sstp) { return do_with(deleted_cell_row_consumer(), [sstp] (auto& c) { auto context = data_consume_rows(*uncompressed_schema(), sstp, c); auto fut = context.read(); @@ -678,7 +707,7 @@ SEASTAR_TEST_CASE(deleted_cell_read) { SEASTAR_TEST_CASE(find_key_map) { - return reusable_sst(map_schema(), "tests/sstables/map_pk", 1).then([] (auto sstp) { + return test_using_reusable_sst(map_schema(), "tests/sstables/map_pk", 1, [] (auto sstp) { schema_ptr s = map_schema(); auto& summary = sstables::test(sstp)._summary(); std::vector kk; @@ -695,11 +724,12 @@ SEASTAR_TEST_CASE(find_key_map) { auto key = sstables::key::from_deeply_exploded(*s, kk); BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == 0); + return make_ready_future<>(); }); } SEASTAR_TEST_CASE(find_key_set) { - return reusable_sst(set_schema(), "tests/sstables/set_pk", 1).then([] (auto sstp) { + return test_using_reusable_sst(set_schema(), "tests/sstables/set_pk", 1, [] (auto sstp) { schema_ptr s = set_schema(); auto& summary = sstables::test(sstp)._summary(); std::vector kk; @@ -716,11 +746,12 @@ SEASTAR_TEST_CASE(find_key_set) { auto key = sstables::key::from_deeply_exploded(*s, kk); BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == 0); + return make_ready_future<>(); }); } SEASTAR_TEST_CASE(find_key_list) { - return reusable_sst(list_schema(), "tests/sstables/list_pk", 1).then([] (auto sstp) { + return test_using_reusable_sst(list_schema(), "tests/sstables/list_pk", 1, [] (auto sstp) { schema_ptr s = set_schema(); auto& summary = sstables::test(sstp)._summary(); std::vector kk; @@ -737,12 +768,13 @@ SEASTAR_TEST_CASE(find_key_list) { auto key = sstables::key::from_deeply_exploded(*s, kk); BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == 0); + return make_ready_future<>(); }); } SEASTAR_TEST_CASE(find_key_composite) { - return reusable_sst(composite_schema(), "tests/sstables/composite", 1).then([] (auto sstp) { + return test_using_reusable_sst(composite_schema(), "tests/sstables/composite", 1, [] (auto sstp) { schema_ptr s = composite_schema(); auto& summary = sstables::test(sstp)._summary(); std::vector kk; @@ -755,11 +787,12 @@ SEASTAR_TEST_CASE(find_key_composite) { auto key = sstables::key::from_deeply_exploded(*s, kk); BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == 0); + return make_ready_future<>(); }); } SEASTAR_TEST_CASE(all_in_place) { - return reusable_sst(uncompressed_schema(), "tests/sstables/bigsummary", 76).then([] (auto sstp) { + return test_using_reusable_sst(uncompressed_schema(), "tests/sstables/bigsummary", 76, [] (auto sstp) { auto& summary = sstables::test(sstp)._summary(); int idx = 0; @@ -767,11 +800,12 @@ SEASTAR_TEST_CASE(all_in_place) { auto key = sstables::key::from_bytes(bytes(e.key)); BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == idx++); } + return make_ready_future<>(); }); } SEASTAR_TEST_CASE(full_index_search) { - return reusable_sst(uncompressed_schema(), uncompressed_dir(), 1).then([] (auto sstp) { + return test_using_reusable_sst(uncompressed_schema(), uncompressed_dir(), 1, [] (auto sstp) { return sstables::test(sstp).read_indexes().then([sstp] (auto index_list) { int idx = 0; for (auto& ie: index_list) { @@ -783,7 +817,7 @@ SEASTAR_TEST_CASE(full_index_search) { } SEASTAR_TEST_CASE(not_find_key_composite_bucket0) { - return reusable_sst(composite_schema(), "tests/sstables/composite", 1).then([] (auto sstp) { + return test_using_reusable_sst(composite_schema(), "tests/sstables/composite", 1, [] (auto sstp) { schema_ptr s = composite_schema(); auto& summary = sstables::test(sstp)._summary(); std::vector kk; @@ -797,12 +831,13 @@ SEASTAR_TEST_CASE(not_find_key_composite_bucket0) { auto key = sstables::key::from_deeply_exploded(*s, kk); // (result + 1) * -1 -1 = 0 BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == -2); + return make_ready_future<>(); }); } // See CASSANDRA-7593. This sstable writes 0 in the range_start. We need to handle that case as well SEASTAR_TEST_CASE(wrong_range) { - return reusable_sst(uncompressed_schema(), "tests/sstables/wrongrange", 114).then([] (auto sstp) { + return test_using_reusable_sst(uncompressed_schema(), "tests/sstables/wrongrange", 114, [] (auto sstp) { return do_with(make_dkey(uncompressed_schema(), "todata"), [sstp] (auto& key) { auto s = columns_schema(); auto rd = make_lw_shared(sstp->read_row_flat(s, key)); @@ -830,11 +865,11 @@ test_sstable_exists(sstring dir, unsigned long generation, bool exists) { // We will therefore run it in an empty directory, and first link a known SSTable from another // directory to it. SEASTAR_TEST_CASE(set_generation) { - return test_setup::do_with_cloned_tmp_directory(uncompressed_dir(), [] (sstring uncompressed_dir, sstring generation_dir) { - return reusable_sst(uncompressed_schema(), uncompressed_dir, 1).then([generation_dir] (auto sstp) { + return test_setup::do_with_cloned_tmp_directory(uncompressed_dir(), [] (test_env& env, sstring uncompressed_dir, sstring generation_dir) { + return env.reusable_sst(uncompressed_schema(), uncompressed_dir, 1).then([generation_dir] (auto sstp) { return sstp->create_links(generation_dir).then([sstp] {}); - }).then([generation_dir] { - return reusable_sst(uncompressed_schema(), generation_dir, 1).then([] (auto sstp) { + }).then([&env, generation_dir] { + return env.reusable_sst(uncompressed_schema(), generation_dir, 1).then([] (auto sstp) { return sstp->set_generation(2).then([sstp] {}); }); }).then([generation_dir] { @@ -848,8 +883,8 @@ SEASTAR_TEST_CASE(set_generation) { } SEASTAR_TEST_CASE(reshuffle) { - return test_setup::do_with_cloned_tmp_directory(uncompressed_dir(), [] (sstring uncompressed_dir, sstring generation_dir) { - return reusable_sst(uncompressed_schema(), uncompressed_dir, 1).then([generation_dir] (auto sstp) { + return test_setup::do_with_cloned_tmp_directory(uncompressed_dir(), [] (test_env& env, sstring uncompressed_dir, sstring generation_dir) { + return env.reusable_sst(uncompressed_schema(), uncompressed_dir, 1).then([generation_dir] (auto sstp) { return sstp->create_links(generation_dir, 1).then([sstp, generation_dir] { return sstp->create_links(generation_dir, 5).then([sstp, generation_dir] { return sstp->create_links(generation_dir, 10); @@ -892,19 +927,20 @@ SEASTAR_TEST_CASE(reshuffle) { } SEASTAR_TEST_CASE(statistics_rewrite) { - return test_setup::do_with_cloned_tmp_directory(uncompressed_dir(), [] (sstring uncompressed_dir, sstring generation_dir) { - return reusable_sst(uncompressed_schema(), uncompressed_dir, 1).then([generation_dir] (auto sstp) { + return test_setup::do_with_cloned_tmp_directory(uncompressed_dir(), [] (test_env& env, sstring uncompressed_dir, sstring generation_dir) { + return env.reusable_sst(uncompressed_schema(), uncompressed_dir, 1).then([generation_dir] (auto sstp) { return sstp->create_links(generation_dir).then([sstp] {}); }).then([generation_dir] { return test_sstable_exists(generation_dir, 1, true); - }).then([generation_dir] { - return reusable_sst(uncompressed_schema(), generation_dir, 1).then([] (auto sstp) { + }).then([&env, generation_dir] { + return env.reusable_sst(uncompressed_schema(), generation_dir, 1).then([] (auto sstp) { // mutate_sstable_level results in statistics rewrite return sstp->mutate_sstable_level(10).then([sstp] {}); }); - }).then([generation_dir] { - return reusable_sst(uncompressed_schema(), generation_dir, 1).then([] (auto sstp) { + }).then([&env, generation_dir] { + return env.reusable_sst(uncompressed_schema(), generation_dir, 1).then([] (auto sstp) { BOOST_REQUIRE(sstp->get_sstable_level() == 10); + return make_ready_future<>(); }); }); }); @@ -938,14 +974,10 @@ static schema_ptr large_partition_schema() { return s; } -static future load_large_partition_sst(const sstables::sstable::version_types version) { +static future load_large_partition_sst(test_env& env, const sstables::sstable::version_types version) { auto s = large_partition_schema(); - auto sst = make_sstable(s, get_test_dir("large_partition", s), 3, - version, big); - auto fut = sst->load(); - return std::move(fut).then([sst = std::move(sst)] { - return std::move(sst); - }); + auto dir = get_test_dir("large_partition", s); + return env.reusable_sst(std::move(s), std::move(dir), 3, version); } // This is a rudimentary test that reads an sstable exported from Cassandra @@ -954,12 +986,14 @@ static future load_large_partition_sst(const sstables::sstable:: // search for anything. SEASTAR_TEST_CASE(promoted_index_read) { return for_each_sstable_version([] (const sstables::sstable::version_types version) { - return load_large_partition_sst(version).then([] (auto sstp) { + return test_env::do_with([version] (test_env& env) { + return load_large_partition_sst(env, version).then([] (auto sstp) { schema_ptr s = large_partition_schema(); return sstables::test(sstp).read_indexes().then([sstp] (index_list vec) { BOOST_REQUIRE(vec.size() == 1); BOOST_REQUIRE(vec.front().get_promoted_index_size() > 0); }); + }); }); }); } @@ -1061,7 +1095,8 @@ static future count_rows(sstable_ptr sstp, schema_ptr s, sstring ck1, sstri SEASTAR_TEST_CASE(sub_partition_read) { schema_ptr s = large_partition_schema(); return for_each_sstable_version([s] (const sstables::sstable::version_types version) { - return load_large_partition_sst(version).then([s] (auto sstp) { + return test_env::do_with([s, version] (test_env& env) { + return load_large_partition_sst(env, version).then([s] (auto sstp) { return count_rows(sstp, s, "v1", "18wX", "18xB").then([] (int nrows) { // there should be 5 rows (out of 13520 = 20*26*26) in this range: // 18wX, 18wY, 18wZ, 18xA, 18xB. @@ -1119,6 +1154,7 @@ SEASTAR_TEST_CASE(sub_partition_read) { }); }); }); + }); }); } @@ -1128,11 +1164,13 @@ SEASTAR_TEST_CASE(sub_partition_read) { SEASTAR_TEST_CASE(sub_partitions_read) { schema_ptr s = large_partition_schema(); return for_each_sstable_version([s] (const sstables::sstable::version_types version) { - return load_large_partition_sst(version).then([s] (auto sstp) { + return test_env::do_with([s, version] (test_env& env) { + return load_large_partition_sst(env, version).then([s] (auto sstp) { return count_rows(sstp, s, "18wX", "18xB").then([] (int nrows) { BOOST_REQUIRE(nrows == 5); }); }); + }); }); } @@ -1158,7 +1196,7 @@ static future<> compare_files(sstring file1, sstring file2) { // writing code, because the promoted index points to offsets in the data). SEASTAR_TEST_CASE(promoted_index_write) { auto s = large_partition_schema(); - return test_setup::do_with_tmp_directory([s] (auto dirname) { + return test_setup::do_with_tmp_directory([s] (test_env& env, auto dirname) { auto mtp = make_lw_shared(s); auto key = partition_key::from_exploded(*s, {to_bytes("v1")}); mutation m(s, key); @@ -1178,7 +1216,7 @@ SEASTAR_TEST_CASE(promoted_index_write) { } } mtp->apply(std::move(m)); - auto sst = make_sstable(s, dirname, 100, + auto sst = env.make_sstable(s, dirname, 100, sstables::sstable::version_types::la, big); return write_memtable_to_sstable_for_test(*mtp, sst).then([s, dirname] { auto large_partition_file = seastar::format("{}/la-3-big-Index.db", get_test_dir("large_partition", s)); diff --git a/tests/sstable_test.hh b/tests/sstable_test.hh index 51ad719f47..bcde6e3a09 100644 --- a/tests/sstable_test.hh +++ b/tests/sstable_test.hh @@ -31,12 +31,13 @@ #include #include "sstables/index_reader.hh" #include "tests/test_services.hh" +#include "tests/sstable_test_env.hh" #include "tmpdir.hh" #include #include -static auto la = sstables::sstable::version_types::la; -static auto big = sstables::sstable::format_types::big; +constexpr auto la = sstables::sstable::version_types::la; +constexpr auto big = sstables::sstable::format_types::big; class column_family_test { lw_shared_ptr _cf; @@ -171,11 +172,6 @@ public: }); } - static sstable_ptr make_test_sstable(size_t buffer_size, schema_ptr schema, sstring dir, unsigned long generation, sstable::version_types v, - sstable::format_types f, gc_clock::time_point now = gc_clock::now()) { - return sstables::make_sstable(std::move(schema), dir, generation, v, f, now, default_io_error_handler_gen(), buffer_size); - } - // Used to create synthetic sstables for testing leveled compaction strategy. void set_values_for_leveled_strategy(uint64_t fake_data_size, uint32_t sstable_level, int64_t max_timestamp, sstring first_key, sstring last_key) { _sst->_data_file_size = fake_data_size; @@ -249,19 +245,6 @@ future<> for_each_sstable_version(AsyncAction action) { return seastar::do_for_each(all_sstable_versions, std::move(action)); } -inline future reusable_sst(schema_ptr schema, sstring dir, - unsigned long generation, sstable_version_types version = la) { - auto sst = sstables::make_sstable(std::move(schema), dir, generation, version, big); - auto fut = sst->load(); - return std::move(fut).then([sst = std::move(sst)] { - return make_ready_future(std::move(sst)); - }); -} - -inline future<> working_sst(schema_ptr schema, sstring dir, unsigned long generation) { - return reusable_sst(std::move(schema), dir, generation).then([] (auto ptr) { return make_ready_future<>(); }); -} - inline schema_ptr composite_schema() { static thread_local auto s = [] { schema_builder builder(make_lw_shared(schema({}, "tests", "composite", @@ -692,26 +675,16 @@ public: }); } - static future<> do_with_test_directory(std::function ()>&& fut, sstring p = path()) { - return seastar::async([p, fut = std::move(fut)] { - storage_service_for_tests ssft; - boost::filesystem::create_directories(std::string(p)); - fut().get(); - test_setup::empty_test_dir(p).get(); - // FIXME: this removes only the last component in the path that often contains: `test-name/ks/cf-uuid' - engine().remove_file(p).get(); - }); - } - - static future<> do_with_tmp_directory(std::function (sstring tmpdir_path)>&& fut) { + static future<> do_with_tmp_directory(std::function (test_env&, sstring tmpdir_path)>&& fut) { return seastar::async([fut = std::move(fut)] { storage_service_for_tests ssft; auto tmp = tmpdir(); - fut(tmp.path().string()).get(); + test_env env; + fut(env, tmp.path().string()).get(); }); } - static future<> do_with_cloned_tmp_directory(sstring src, std::function (sstring srcdir_path, sstring destdir_path)>&& fut) { + static future<> do_with_cloned_tmp_directory(sstring src, std::function (test_env&, sstring srcdir_path, sstring destdir_path)>&& fut) { return seastar::async([fut = std::move(fut), src = std::move(src)] { storage_service_for_tests ssft; auto src_dir = tmpdir(); @@ -721,7 +694,8 @@ public: } auto dest_path = dest_dir.path() / src.c_str(); seastar::compat::filesystem::create_directories(dest_path); - fut(src_dir.path().string(), dest_path.string()).get(); + test_env env; + fut(env, src_dir.path().string(), dest_path.string()).get(); }); } }; diff --git a/tests/sstable_test_env.hh b/tests/sstable_test_env.hh new file mode 100644 index 0000000000..bfb08126b2 --- /dev/null +++ b/tests/sstable_test_env.hh @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 ScyllaDB + */ + +/* + * This file is part of Scylla. + * + * Scylla is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Scylla is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Scylla. If not, see . + */ + +#pragma once + +#include + +#include "sstables/sstables.hh" +#include "tests/tmpdir.hh" + +namespace sstables { + +class test_env { +public: + test_env() = default; + + shared_sstable make_sstable(schema_ptr schema, sstring dir, unsigned long generation, + sstable::version_types v, sstable::format_types f = sstable::format_types::big, + size_t buffer_size = default_sstable_buffer_size(), gc_clock::time_point now = gc_clock::now()) { + return sstables::make_sstable(std::move(schema), dir, generation, v, f, now, default_io_error_handler_gen(), buffer_size); + } + + future reusable_sst(schema_ptr schema, sstring dir, unsigned long generation, + sstable::version_types version = sstable::version_types::la, sstable::format_types f = sstable::format_types::big) { + auto sst = make_sstable(std::move(schema), dir, generation, version, f); + return sst->load().then([sst = std::move(sst)] { + return make_ready_future(std::move(sst)); + }); + } + + future<> working_sst(schema_ptr schema, sstring dir, unsigned long generation) { + return reusable_sst(std::move(schema), dir, generation).then([] (auto ptr) { return make_ready_future<>(); }); + } + + template + static inline auto do_with(Func&& func) { + return seastar::do_with(test_env(), [func = std::move(func)] (test_env& env) mutable { + return func(env); + }); + } + + template + static inline auto do_with(T&& rval, Func&& func) { + return seastar::do_with(test_env(), std::forward(rval), [func = std::move(func)] (test_env& env, T& val) mutable { + return func(env, val); + }); + } + + template + static inline auto do_with_async(Func&& func) { + return seastar::async([func = std::move(func)] { + test_env env; + func(env); + }); + } +}; + +} // namespace sstables diff --git a/tests/test_services.cc b/tests/test_services.cc new file mode 100644 index 0000000000..29206d972e --- /dev/null +++ b/tests/test_services.cc @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019 ScyllaDB + */ + +/* + * This file is part of Scylla. + * + * Scylla is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Scylla is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Scylla. If not, see . + */ + +#include "tests/test_services.hh" +#include "dht/i_partitioner.hh" +#include "dht/murmur3_partitioner.hh" + +dht::token create_token_from_key(sstring key) { + sstables::key_view key_view = sstables::key_view(bytes_view(reinterpret_cast(key.c_str()), key.size())); + dht::token token = dht::global_partitioner().get_token(key_view); + assert(token == dht::global_partitioner().get_token(key_view)); + return token; +} + +range create_token_range_from_keys(sstring start_key, sstring end_key) { + dht::token start = create_token_from_key(start_key); + assert(engine().cpu_id() == dht::global_partitioner().shard_of(start)); + dht::token end = create_token_from_key(end_key); + assert(engine().cpu_id() == dht::global_partitioner().shard_of(end)); + assert(end >= start); + return range::make(start, end); +} + +static db::nop_large_data_handler nop_lp_handler; + +static const sstring some_keyspace("ks"); +static const sstring some_column_family("cf"); + +column_family::config column_family_test_config() { + column_family::config cfg; + cfg.large_data_handler = &nop_lp_handler; + return cfg; +} + +column_family_for_tests::column_family_for_tests() + : column_family_for_tests( + schema_builder(some_keyspace, some_column_family) + .with_column(utf8_type->decompose("p1"), utf8_type, column_kind::partition_key) + .build() + ) +{ } + +column_family_for_tests::column_family_for_tests(schema_ptr s) + : _data(make_lw_shared()) +{ + _data->s = s; + _data->cfg.enable_disk_writes = false; + _data->cfg.enable_commitlog = false; + _data->cfg.large_data_handler = &nop_lp_handler; + _data->cf = make_lw_shared(_data->s, _data->cfg, column_family::no_commitlog(), _data->cm, _data->cl_stats, _data->tracker); + _data->cf->mark_ready_for_writes(); +} diff --git a/tests/test_services.hh b/tests/test_services.hh index b774e5b318..f9fe27d615 100644 --- a/tests/test_services.hh +++ b/tests/test_services.hh @@ -23,6 +23,14 @@ #pragma once #include +#include + +#include "schema.hh" +#include "schema_builder.hh" +#include "row_cache.hh" +#include "database.hh" +#include "cell_locking.hh" +#include "sstables/compaction_manager.hh" // Includes: database, auth, storage_service class storage_service_for_tests { @@ -32,3 +40,31 @@ public: storage_service_for_tests(); ~storage_service_for_tests(); }; + +column_family::config column_family_test_config(); + +struct column_family_for_tests { + struct data { + schema_ptr s; + cache_tracker tracker; + column_family::config cfg; + cell_locker_stats cl_stats; + compaction_manager cm; + lw_shared_ptr cf; + }; + lw_shared_ptr _data; + + column_family_for_tests(); + + explicit column_family_for_tests(schema_ptr s); + + schema_ptr schema() { return _data->s; } + + operator lw_shared_ptr() { return _data->cf; } + + column_family& operator*() { return *_data->cf; } + column_family* operator->() { return _data->cf.get(); } +}; + +dht::token create_token_from_key(sstring key); +range create_token_range_from_keys(sstring start_key, sstring end_key);