]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/crimson/seastore/transaction_manager_test_state.h
add stop-gap to fix compat with CPUs not supporting SSE 4.1
[ceph.git] / ceph / src / test / crimson / seastore / transaction_manager_test_state.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #pragma once
5
6 #include <random>
7 #include <boost/iterator/counting_iterator.hpp>
8
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"
21
22 using namespace crimson;
23 using namespace crimson::os;
24 using namespace crimson::os::seastore;
25
26 class EphemeralDevices {
27 public:
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;
37 };
38 using EphemeralDevicesRef = std::unique_ptr<EphemeralDevices>;
39
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;
45
46 public:
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)
51 {
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);
55 }
56
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();
61 }
62 return segment_manager->init(
63 ).safe_then([this] {
64 return crimson::do_for_each(
65 secondary_segment_managers.begin(),
66 secondary_segment_managers.end(),
67 [](auto &sec_sm)
68 {
69 return sec_sm->init();
70 });
71 }).safe_then([this] {
72 return segment_manager->mkfs(
73 segment_manager::get_ephemeral_device_config(
74 0, num_main_device_managers, num_cold_device_managers));
75 }).safe_then([this] {
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)
81 {
82 ++cnt;
83 return sec_sm->mkfs(
84 segment_manager::get_ephemeral_device_config(
85 cnt, num_main_device_managers, num_cold_device_managers));
86 });
87 });
88 }).handle_error(
89 crimson::ct_error::assert_all{}
90 );
91 }
92
93 void remount() final {
94 segment_manager->remount();
95 for (auto &sec_sm : secondary_segment_managers) {
96 sec_sm->remount();
97 }
98 }
99
100 std::size_t get_num_devices() const final {
101 return secondary_segment_managers.size() + 1;
102 }
103
104 void reset() final {
105 segment_manager.reset();
106 for (auto &sec_sm : secondary_segment_managers) {
107 sec_sm.reset();
108 }
109 }
110
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());
115 }
116 return sec_devices;
117 }
118
119 Device* get_primary_device() final {
120 return segment_manager.get();
121 }
122 DeviceRef get_primary_device_ref() final;
123 void set_primary_device_ref(DeviceRef) final;
124 };
125
126 class EphemeralRandomBlockDevices : public EphemeralDevices {
127 random_block_device::RBMDeviceRef rb_device;
128 std::list<random_block_device::RBMDeviceRef> secondary_rb_devices;
129
130 public:
131 EphemeralRandomBlockDevices(std::size_t num_device_managers) {
132 assert(num_device_managers > 0);
133 secondary_rb_devices.resize(num_device_managers - 1);
134 }
135
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{});
140 }
141
142 void remount() final {}
143
144 std::size_t get_num_devices() const final {
145 return secondary_rb_devices.size() + 1;
146 }
147
148 void reset() final {
149 rb_device.reset();
150 for (auto &sec_rb : secondary_rb_devices) {
151 sec_rb.reset();
152 }
153 }
154
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());
159 }
160 return sec_devices;
161 }
162
163 Device* get_primary_device() final {
164 return rb_device.get();
165 }
166 DeviceRef get_primary_device_ref() final;
167 void set_primary_device_ref(DeviceRef) final;
168 };
169
170 class EphemeralTestState {
171 protected:
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) {}
181
182 virtual seastar::future<> _init() = 0;
183
184 virtual seastar::future<> _destroy() = 0;
185 virtual seastar::future<> _teardown() = 0;
186 seastar::future<> teardown() {
187 return _teardown().then([this] {
188 return _destroy();
189 });
190 }
191
192 virtual FuturizedStore::mkfs_ertr::future<> _mkfs() = 0;
193 virtual FuturizedStore::mount_ertr::future<> _mount() = 0;
194
195 seastar::future<> restart_fut() {
196 LOG_PREFIX(EphemeralTestState::restart_fut);
197 SUBINFO(test, "begin ...");
198 return teardown().then([this] {
199 devices->remount();
200 return _init().then([this] {
201 return _mount().handle_error(crimson::ct_error::assert_all{});
202 });
203 }).then([FNAME] {
204 SUBINFO(test, "finish");
205 });
206 }
207
208 void restart() {
209 restart_fut().get0();
210 }
211
212 seastar::future<> tm_setup(
213 journal_type_t type = journal_type_t::SEGMENTED) {
214 LOG_PREFIX(EphemeralTestState::tm_setup);
215 journal_type = type;
216 if (journal_type == journal_type_t::SEGMENTED) {
217 devices.reset(new
218 EphemeralSegmentedDevices(
219 num_main_device_managers, num_cold_device_managers));
220 } else {
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));
226 }
227 SUBINFO(test, "begin with {} devices ...", devices->get_num_devices());
228 return devices->setup(
229 ).then([this] {
230 return _init();
231 }).then([this, FNAME] {
232 return _mkfs(
233 ).safe_then([this] {
234 return restart_fut();
235 }).handle_error(
236 crimson::ct_error::assert_all{}
237 ).then([FNAME] {
238 SUBINFO(test, "finish");
239 });
240 });
241 }
242
243 seastar::future<> tm_teardown() {
244 LOG_PREFIX(EphemeralTestState::tm_teardown);
245 SUBINFO(test, "begin");
246 return teardown().then([this, FNAME] {
247 devices->reset();
248 SUBINFO(test, "finish");
249 });
250 }
251 };
252
253 class TMTestState : public EphemeralTestState {
254 protected:
255 TransactionManagerRef tm;
256 LBAManager *lba_manager;
257 Cache* cache;
258 ExtentPlacementManager *epm;
259 uint64_t seq = 0;
260
261 TMTestState() : EphemeralTestState(1, 0) {}
262
263 TMTestState(std::size_t num_main_devices, std::size_t num_cold_devices)
264 : EphemeralTestState(num_main_devices, num_cold_devices) {}
265
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);
270 epm = tm->get_epm();
271 lba_manager = tm->get_lba_manager();
272 cache = tm->get_cache();
273 return seastar::now();
274 }
275
276 virtual seastar::future<> _destroy() override {
277 epm = nullptr;
278 lba_manager = nullptr;
279 cache = nullptr;
280 tm.reset();
281 return seastar::now();
282 }
283
284 virtual seastar::future<> _teardown() {
285 return tm->close().handle_error(
286 crimson::ct_error::assert_all{"Error in teardown"}
287 );
288 }
289
290 virtual FuturizedStore::mount_ertr::future<> _mount() {
291 return tm->mount(
292 ).handle_error(
293 crimson::ct_error::assert_all{"Error in mount"}
294 ).then([this] {
295 return epm->stop_background();
296 }).then([this] {
297 return epm->run_background_work_until_halt();
298 });
299 }
300
301 virtual FuturizedStore::mkfs_ertr::future<> _mkfs() {
302 return tm->mkfs(
303 ).handle_error(
304 crimson::ct_error::assert_all{"Error in mkfs"}
305 );
306 }
307
308 auto create_mutate_transaction() {
309 return tm->create_transaction(
310 Transaction::src_t::MUTATE, "test_mutate");
311 }
312
313 auto create_read_transaction() {
314 return tm->create_transaction(
315 Transaction::src_t::READ, "test_read");
316 }
317
318 auto create_weak_transaction() {
319 return tm->create_transaction(
320 Transaction::src_t::READ, "test_read_weak", true);
321 }
322
323 auto submit_transaction_fut2(Transaction& t) {
324 return tm->submit_transaction(t);
325 }
326
327 auto submit_transaction_fut(Transaction &t) {
328 return with_trans_intr(
329 t,
330 [this](auto &t) {
331 return tm->submit_transaction(t);
332 });
333 }
334 auto submit_transaction_fut_with_seq(Transaction &t) {
335 using ertr = TransactionManager::base_iertr;
336 return with_trans_intr(
337 t,
338 [this](auto &t) {
339 return tm->submit_transaction(t
340 ).si_then([this] {
341 return ertr::make_ready_future<uint64_t>(seq++);
342 });
343 });
344 }
345
346 void submit_transaction(TransactionRef t) {
347 submit_transaction_fut(*t).unsafe_get0();
348 epm->run_background_work_until_halt().get0();
349 }
350 };
351
352
353 DeviceRef EphemeralSegmentedDevices::get_primary_device_ref() {
354 return std::move(segment_manager);
355 }
356
357 DeviceRef EphemeralRandomBlockDevices::get_primary_device_ref() {
358 return std::move(rb_device);
359 }
360
361 void EphemeralSegmentedDevices::set_primary_device_ref(DeviceRef dev) {
362 segment_manager =
363 segment_manager::EphemeralSegmentManagerRef(
364 static_cast<segment_manager::EphemeralSegmentManager*>(dev.release()));
365 }
366
367 void EphemeralRandomBlockDevices::set_primary_device_ref(DeviceRef dev) {
368 rb_device =
369 random_block_device::RBMDeviceRef(
370 static_cast<random_block_device::RBMDevice*>(dev.release()));
371 }
372
373 class SeaStoreTestState : public EphemeralTestState {
374 class TestMDStoreState {
375 std::map<std::string, std::string> md;
376 public:
377 class Store final : public SeaStore::MDStore {
378 TestMDStoreState &parent;
379 public:
380 Store(TestMDStoreState &parent) : parent(parent) {}
381
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();
386 }
387
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{},
393 iter->second);
394 } else {
395 return read_meta_ret(
396 read_meta_ertr::ready_future_marker{},
397 std::nullopt);
398 }
399 }
400 };
401 Store get_mdstore() {
402 return Store(*this);
403 }
404 } mdstore_state;
405
406 protected:
407 std::unique_ptr<SeaStore> seastore;
408 FuturizedStore::Shard *sharded_seastore;
409
410 SeaStoreTestState() : EphemeralTestState(1, 0) {}
411
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()
416 ).then([this] {
417 sharded_seastore = &(seastore->get_sharded_store());
418 });
419 }
420
421 virtual seastar::future<> _destroy() final {
422 devices->set_primary_device_ref(seastore->get_primary_device_ref());
423 return seastore->stop().then([this] {
424 seastore.reset();
425 });
426 }
427
428 virtual seastar::future<> _teardown() final {
429 return seastore->umount();
430 }
431
432 virtual FuturizedStore::mount_ertr::future<> _mount() final {
433 return seastore->test_mount();
434 }
435
436 virtual FuturizedStore::mkfs_ertr::future<> _mkfs() final {
437 return seastore->test_mkfs(uuid_d{});
438 }
439 };