1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
7 #include <boost/iterator/counting_iterator.hpp>
9 #include "crimson/os/seastore/cache.h"
10 #include "crimson/os/seastore/extent_placement_manager.h"
11 #include "crimson/os/seastore/logging.h"
12 #include "crimson/os/seastore/transaction_manager.h"
13 #include "crimson/os/seastore/segment_manager/ephemeral.h"
14 #include "crimson/os/seastore/seastore.h"
15 #include "crimson/os/seastore/segment_manager.h"
16 #include "crimson/os/seastore/collection_manager/flat_collection_manager.h"
17 #include "crimson/os/seastore/onode_manager/staged-fltree/fltree_onode_manager.h"
18 #include "crimson/os/seastore/random_block_manager/rbm_device.h"
19 #include "crimson/os/seastore/journal/circular_bounded_journal.h"
20 #include "crimson/os/seastore/random_block_manager/block_rb_manager.h"
22 using namespace crimson
;
23 using namespace crimson::os
;
24 using namespace crimson::os::seastore
;
26 class EphemeralDevices
{
28 virtual seastar::future
<> setup() = 0;
29 virtual void remount() = 0;
30 virtual std::size_t get_num_devices() const = 0;
31 virtual void reset() = 0;
32 virtual std::vector
<Device
*> get_secondary_devices() = 0;
33 virtual ~EphemeralDevices() {}
34 virtual Device
* get_primary_device() = 0;
35 virtual DeviceRef
get_primary_device_ref() = 0;
36 virtual void set_primary_device_ref(DeviceRef
) = 0;
38 using EphemeralDevicesRef
= std::unique_ptr
<EphemeralDevices
>;
40 class EphemeralSegmentedDevices
: public EphemeralDevices
{
41 segment_manager::EphemeralSegmentManagerRef segment_manager
;
42 std::list
<segment_manager::EphemeralSegmentManagerRef
> secondary_segment_managers
;
43 std::size_t num_main_device_managers
;
44 std::size_t num_cold_device_managers
;
47 EphemeralSegmentedDevices(std::size_t num_main_devices
,
48 std::size_t num_cold_devices
)
49 : num_main_device_managers(num_main_devices
),
50 num_cold_device_managers(num_cold_devices
)
52 auto num_device_managers
= num_main_device_managers
+ num_cold_device_managers
;
53 assert(num_device_managers
> 0);
54 secondary_segment_managers
.resize(num_device_managers
- 1);
57 seastar::future
<> setup() final
{
58 segment_manager
= segment_manager::create_test_ephemeral();
59 for (auto &sec_sm
: secondary_segment_managers
) {
60 sec_sm
= segment_manager::create_test_ephemeral();
62 return segment_manager
->init(
64 return crimson::do_for_each(
65 secondary_segment_managers
.begin(),
66 secondary_segment_managers
.end(),
69 return sec_sm
->init();
72 return segment_manager
->mkfs(
73 segment_manager::get_ephemeral_device_config(
74 0, num_main_device_managers
, num_cold_device_managers
));
76 return seastar::do_with(std::size_t(0), [this](auto &cnt
) {
77 return crimson::do_for_each(
78 secondary_segment_managers
.begin(),
79 secondary_segment_managers
.end(),
80 [this, &cnt
](auto &sec_sm
)
84 segment_manager::get_ephemeral_device_config(
85 cnt
, num_main_device_managers
, num_cold_device_managers
));
89 crimson::ct_error::assert_all
{}
93 void remount() final
{
94 segment_manager
->remount();
95 for (auto &sec_sm
: secondary_segment_managers
) {
100 std::size_t get_num_devices() const final
{
101 return secondary_segment_managers
.size() + 1;
105 segment_manager
.reset();
106 for (auto &sec_sm
: secondary_segment_managers
) {
111 std::vector
<Device
*> get_secondary_devices() final
{
112 std::vector
<Device
*> sec_devices
;
113 for (auto &sec_sm
: secondary_segment_managers
) {
114 sec_devices
.emplace_back(sec_sm
.get());
119 Device
* get_primary_device() final
{
120 return segment_manager
.get();
122 DeviceRef
get_primary_device_ref() final
;
123 void set_primary_device_ref(DeviceRef
) final
;
126 class EphemeralRandomBlockDevices
: public EphemeralDevices
{
127 random_block_device::RBMDeviceRef rb_device
;
128 std::list
<random_block_device::RBMDeviceRef
> secondary_rb_devices
;
131 EphemeralRandomBlockDevices(std::size_t num_device_managers
) {
132 assert(num_device_managers
> 0);
133 secondary_rb_devices
.resize(num_device_managers
- 1);
136 seastar::future
<> setup() final
{
137 rb_device
= random_block_device::create_test_ephemeral();
138 device_config_t config
= get_rbm_ephemeral_device_config(0, 1);
139 return rb_device
->mkfs(config
).handle_error(crimson::ct_error::assert_all
{});
142 void remount() final
{}
144 std::size_t get_num_devices() const final
{
145 return secondary_rb_devices
.size() + 1;
150 for (auto &sec_rb
: secondary_rb_devices
) {
155 std::vector
<Device
*> get_secondary_devices() final
{
156 std::vector
<Device
*> sec_devices
;
157 for (auto &sec_rb
: secondary_rb_devices
) {
158 sec_devices
.emplace_back(sec_rb
.get());
163 Device
* get_primary_device() final
{
164 return rb_device
.get();
166 DeviceRef
get_primary_device_ref() final
;
167 void set_primary_device_ref(DeviceRef
) final
;
170 class EphemeralTestState
{
172 journal_type_t journal_type
;
173 size_t num_main_device_managers
= 0;
174 size_t num_cold_device_managers
= 0;
175 EphemeralDevicesRef devices
;
176 bool secondary_is_cold
;
177 EphemeralTestState(std::size_t num_main_device_managers
,
178 std::size_t num_cold_device_managers
) :
179 num_main_device_managers(num_main_device_managers
),
180 num_cold_device_managers(num_cold_device_managers
) {}
182 virtual seastar::future
<> _init() = 0;
184 virtual seastar::future
<> _destroy() = 0;
185 virtual seastar::future
<> _teardown() = 0;
186 seastar::future
<> teardown() {
187 return _teardown().then([this] {
192 virtual FuturizedStore::mkfs_ertr::future
<> _mkfs() = 0;
193 virtual FuturizedStore::mount_ertr::future
<> _mount() = 0;
195 seastar::future
<> restart_fut() {
196 LOG_PREFIX(EphemeralTestState::restart_fut
);
197 SUBINFO(test
, "begin ...");
198 return teardown().then([this] {
200 return _init().then([this] {
201 return _mount().handle_error(crimson::ct_error::assert_all
{});
204 SUBINFO(test
, "finish");
209 restart_fut().get0();
212 seastar::future
<> tm_setup(
213 journal_type_t type
= journal_type_t::SEGMENTED
) {
214 LOG_PREFIX(EphemeralTestState::tm_setup
);
216 if (journal_type
== journal_type_t::SEGMENTED
) {
218 EphemeralSegmentedDevices(
219 num_main_device_managers
, num_cold_device_managers
));
221 assert(journal_type
== journal_type_t::RANDOM_BLOCK
);
222 //TODO: multiple devices
223 ceph_assert(num_main_device_managers
== 1);
224 ceph_assert(num_cold_device_managers
== 0);
225 devices
.reset(new EphemeralRandomBlockDevices(1));
227 SUBINFO(test
, "begin with {} devices ...", devices
->get_num_devices());
228 return devices
->setup(
231 }).then([this, FNAME
] {
234 return restart_fut();
236 crimson::ct_error::assert_all
{}
238 SUBINFO(test
, "finish");
243 seastar::future
<> tm_teardown() {
244 LOG_PREFIX(EphemeralTestState::tm_teardown
);
245 SUBINFO(test
, "begin");
246 return teardown().then([this, FNAME
] {
248 SUBINFO(test
, "finish");
253 class TMTestState
: public EphemeralTestState
{
255 TransactionManagerRef tm
;
256 LBAManager
*lba_manager
;
258 ExtentPlacementManager
*epm
;
261 TMTestState() : EphemeralTestState(1, 0) {}
263 TMTestState(std::size_t num_main_devices
, std::size_t num_cold_devices
)
264 : EphemeralTestState(num_main_devices
, num_cold_devices
) {}
266 virtual seastar::future
<> _init() override
{
267 auto sec_devices
= devices
->get_secondary_devices();
268 auto p_dev
= devices
->get_primary_device();
269 tm
= make_transaction_manager(p_dev
, sec_devices
, true);
271 lba_manager
= tm
->get_lba_manager();
272 cache
= tm
->get_cache();
273 return seastar::now();
276 virtual seastar::future
<> _destroy() override
{
278 lba_manager
= nullptr;
281 return seastar::now();
284 virtual seastar::future
<> _teardown() {
285 return tm
->close().handle_error(
286 crimson::ct_error::assert_all
{"Error in teardown"}
290 virtual FuturizedStore::mount_ertr::future
<> _mount() {
293 crimson::ct_error::assert_all
{"Error in mount"}
295 return epm
->stop_background();
297 return epm
->run_background_work_until_halt();
301 virtual FuturizedStore::mkfs_ertr::future
<> _mkfs() {
304 crimson::ct_error::assert_all
{"Error in mkfs"}
308 auto create_mutate_transaction() {
309 return tm
->create_transaction(
310 Transaction::src_t::MUTATE
, "test_mutate");
313 auto create_read_transaction() {
314 return tm
->create_transaction(
315 Transaction::src_t::READ
, "test_read");
318 auto create_weak_transaction() {
319 return tm
->create_transaction(
320 Transaction::src_t::READ
, "test_read_weak", true);
323 auto submit_transaction_fut2(Transaction
& t
) {
324 return tm
->submit_transaction(t
);
327 auto submit_transaction_fut(Transaction
&t
) {
328 return with_trans_intr(
331 return tm
->submit_transaction(t
);
334 auto submit_transaction_fut_with_seq(Transaction
&t
) {
335 using ertr
= TransactionManager::base_iertr
;
336 return with_trans_intr(
339 return tm
->submit_transaction(t
341 return ertr::make_ready_future
<uint64_t>(seq
++);
346 void submit_transaction(TransactionRef t
) {
347 submit_transaction_fut(*t
).unsafe_get0();
348 epm
->run_background_work_until_halt().get0();
353 DeviceRef
EphemeralSegmentedDevices::get_primary_device_ref() {
354 return std::move(segment_manager
);
357 DeviceRef
EphemeralRandomBlockDevices::get_primary_device_ref() {
358 return std::move(rb_device
);
361 void EphemeralSegmentedDevices::set_primary_device_ref(DeviceRef dev
) {
363 segment_manager::EphemeralSegmentManagerRef(
364 static_cast<segment_manager::EphemeralSegmentManager
*>(dev
.release()));
367 void EphemeralRandomBlockDevices::set_primary_device_ref(DeviceRef dev
) {
369 random_block_device::RBMDeviceRef(
370 static_cast<random_block_device::RBMDevice
*>(dev
.release()));
373 class SeaStoreTestState
: public EphemeralTestState
{
374 class TestMDStoreState
{
375 std::map
<std::string
, std::string
> md
;
377 class Store final
: public SeaStore::MDStore
{
378 TestMDStoreState
&parent
;
380 Store(TestMDStoreState
&parent
) : parent(parent
) {}
382 write_meta_ret
write_meta(
383 const std::string
& key
, const std::string
& value
) final
{
384 parent
.md
[key
] = value
;
385 return seastar::now();
388 read_meta_ret
read_meta(const std::string
& key
) final
{
389 auto iter
= parent
.md
.find(key
);
390 if (iter
!= parent
.md
.end()) {
391 return read_meta_ret(
392 read_meta_ertr::ready_future_marker
{},
395 return read_meta_ret(
396 read_meta_ertr::ready_future_marker
{},
401 Store
get_mdstore() {
407 std::unique_ptr
<SeaStore
> seastore
;
408 FuturizedStore::Shard
*sharded_seastore
;
410 SeaStoreTestState() : EphemeralTestState(1, 0) {}
412 virtual seastar::future
<> _init() final
{
413 seastore
= make_test_seastore(
414 std::make_unique
<TestMDStoreState::Store
>(mdstore_state
.get_mdstore()));
415 return seastore
->test_start(devices
->get_primary_device_ref()
417 sharded_seastore
= &(seastore
->get_sharded_store());
421 virtual seastar::future
<> _destroy() final
{
422 devices
->set_primary_device_ref(seastore
->get_primary_device_ref());
423 return seastore
->stop().then([this] {
428 virtual seastar::future
<> _teardown() final
{
429 return seastore
->umount();
432 virtual FuturizedStore::mount_ertr::future
<> _mount() final
{
433 return seastore
->test_mount();
436 virtual FuturizedStore::mkfs_ertr::future
<> _mkfs() final
{
437 return seastore
->test_mkfs(uuid_d
{});