]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/cls_journal/test_cls_journal.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / test / cls_journal / test_cls_journal.cc
1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "cls/journal/cls_journal_client.h"
5 #include "include/stringify.h"
6 #include "common/Cond.h"
7 #include "test/librados/test_cxx.h"
8 #include "gtest/gtest.h"
9 #include <errno.h>
10 #include <set>
11 #include <string>
12
13 using namespace cls::journal;
14
15 static bool is_sparse_read_supported(librados::IoCtx &ioctx,
16 const std::string &oid) {
17 EXPECT_EQ(0, ioctx.create(oid, true));
18 bufferlist inbl;
19 inbl.append(std::string(1, 'X'));
20 EXPECT_EQ(0, ioctx.write(oid, inbl, inbl.length(), 1));
21 EXPECT_EQ(0, ioctx.write(oid, inbl, inbl.length(), 3));
22
23 std::map<uint64_t, uint64_t> m;
24 bufferlist outbl;
25 int r = ioctx.sparse_read(oid, m, outbl, 4, 0);
26 ioctx.remove(oid);
27
28 int expected_r = 2;
29 std::map<uint64_t, uint64_t> expected_m = {{1, 1}, {3, 1}};
30 bufferlist expected_outbl;
31 expected_outbl.append(std::string(2, 'X'));
32
33 return (r == expected_r && m == expected_m &&
34 outbl.contents_equal(expected_outbl));
35 }
36
37 class TestClsJournal : public ::testing::Test {
38 public:
39
40 static void SetUpTestCase() {
41 _pool_name = get_temp_pool_name();
42 ASSERT_EQ("", create_one_pool_pp(_pool_name, _rados));
43 }
44
45 static void TearDownTestCase() {
46 ASSERT_EQ(0, destroy_one_pool_pp(_pool_name, _rados));
47 }
48
49 std::string get_temp_image_name() {
50 ++_image_number;
51 return "image" + stringify(_image_number);
52 }
53
54 static std::string _pool_name;
55 static librados::Rados _rados;
56 static uint64_t _image_number;
57
58 };
59
60 std::string TestClsJournal::_pool_name;
61 librados::Rados TestClsJournal::_rados;
62 uint64_t TestClsJournal::_image_number = 0;
63
64 TEST_F(TestClsJournal, Create) {
65 librados::IoCtx ioctx;
66 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
67
68 std::string oid = get_temp_image_name();
69
70 uint8_t order = 1;
71 uint8_t splay_width = 2;
72 int64_t pool_id = ioctx.get_id();
73 ASSERT_EQ(0, client::create(ioctx, oid, order, splay_width, pool_id));
74
75 uint8_t read_order;
76 uint8_t read_splay_width;
77 int64_t read_pool_id;
78 C_SaferCond cond;
79 client::get_immutable_metadata(ioctx, oid, &read_order, &read_splay_width,
80 &read_pool_id, &cond);
81 ASSERT_EQ(0, cond.wait());
82 ASSERT_EQ(order, read_order);
83 ASSERT_EQ(splay_width, read_splay_width);
84 ASSERT_EQ(pool_id, read_pool_id);
85 }
86
87 TEST_F(TestClsJournal, MinimumSet) {
88 librados::IoCtx ioctx;
89 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
90
91 std::string oid = get_temp_image_name();
92
93 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
94
95 librados::ObjectWriteOperation op1;
96 client::set_active_set(&op1, 300);
97 ASSERT_EQ(0, ioctx.operate(oid, &op1));
98
99 uint64_t minimum_set = 123;
100 librados::ObjectWriteOperation op2;
101 client::set_minimum_set(&op2, minimum_set);
102 ASSERT_EQ(0, ioctx.operate(oid, &op2));
103
104 C_SaferCond cond;
105 uint64_t read_minimum_set;
106 uint64_t read_active_set;
107 std::set<cls::journal::Client> read_clients;
108 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
109 &read_clients, &cond);
110 ASSERT_EQ(0, cond.wait());
111 ASSERT_EQ(minimum_set, read_minimum_set);
112 }
113
114 TEST_F(TestClsJournal, MinimumSetStale) {
115 librados::IoCtx ioctx;
116 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
117
118 std::string oid = get_temp_image_name();
119
120 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
121
122 librados::ObjectWriteOperation op1;
123 client::set_active_set(&op1, 300);
124 ASSERT_EQ(0, ioctx.operate(oid, &op1));
125
126 uint64_t minimum_set = 123;
127 librados::ObjectWriteOperation op2;
128 client::set_minimum_set(&op2, minimum_set);
129 ASSERT_EQ(0, ioctx.operate(oid, &op2));
130
131 librados::ObjectWriteOperation op3;
132 client::set_minimum_set(&op3, 1);
133 ASSERT_EQ(-ESTALE, ioctx.operate(oid, &op3));
134
135 C_SaferCond cond;
136 uint64_t read_minimum_set;
137 uint64_t read_active_set;
138 std::set<cls::journal::Client> read_clients;
139 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
140 &read_clients, &cond);
141 ASSERT_EQ(0, cond.wait());
142 ASSERT_EQ(minimum_set, read_minimum_set);
143 }
144
145 TEST_F(TestClsJournal, MinimumSetOrderConstraint) {
146 librados::IoCtx ioctx;
147 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
148
149 std::string oid = get_temp_image_name();
150
151 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
152
153 librados::ObjectWriteOperation op1;
154 client::set_minimum_set(&op1, 123);
155 ASSERT_EQ(-EINVAL, ioctx.operate(oid, &op1));
156
157 C_SaferCond cond;
158 uint64_t read_minimum_set;
159 uint64_t read_active_set;
160 std::set<cls::journal::Client> read_clients;
161 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
162 &read_clients, &cond);
163 ASSERT_EQ(0, cond.wait());
164 ASSERT_EQ(0U, read_minimum_set);
165 }
166
167 TEST_F(TestClsJournal, ActiveSet) {
168 librados::IoCtx ioctx;
169 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
170
171 std::string oid = get_temp_image_name();
172
173 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
174
175 uint64_t active_set = 234;
176 librados::ObjectWriteOperation op1;
177 client::set_active_set(&op1, active_set);
178 ASSERT_EQ(0, ioctx.operate(oid, &op1));
179
180 C_SaferCond cond;
181 uint64_t read_minimum_set;
182 uint64_t read_active_set;
183 std::set<cls::journal::Client> read_clients;
184 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
185 &read_clients, &cond);
186 ASSERT_EQ(0, cond.wait());
187 ASSERT_EQ(active_set, read_active_set);
188 }
189
190 TEST_F(TestClsJournal, ActiveSetStale) {
191 librados::IoCtx ioctx;
192 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
193
194 std::string oid = get_temp_image_name();
195
196 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
197
198 librados::ObjectWriteOperation op1;
199 client::set_active_set(&op1, 345);
200 ASSERT_EQ(0, ioctx.operate(oid, &op1));
201
202 librados::ObjectWriteOperation op2;
203 client::set_active_set(&op2, 3);
204 ASSERT_EQ(-ESTALE, ioctx.operate(oid, &op2));
205 }
206
207 TEST_F(TestClsJournal, CreateDuplicate) {
208 librados::IoCtx ioctx;
209 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
210
211 std::string oid = get_temp_image_name();
212
213 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
214 ASSERT_EQ(-EEXIST, client::create(ioctx, oid, 3, 5, ioctx.get_id()));
215 }
216
217 TEST_F(TestClsJournal, GetClient) {
218 librados::IoCtx ioctx;
219 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
220
221 std::string oid = get_temp_image_name();
222 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
223
224 Client client;
225 ASSERT_EQ(-ENOENT, client::get_client(ioctx, oid, "id", &client));
226
227 bufferlist data;
228 data.append(std::string(128, '1'));
229 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", data));
230
231 ASSERT_EQ(0, client::get_client(ioctx, oid, "id1", &client));
232 Client expected_client("id1", data);
233 ASSERT_EQ(expected_client, client);
234 }
235
236 TEST_F(TestClsJournal, ClientRegister) {
237 librados::IoCtx ioctx;
238 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
239
240 std::string oid = get_temp_image_name();
241 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
242
243 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
244
245 std::set<Client> clients;
246 ASSERT_EQ(0, client::client_list(ioctx, oid, &clients));
247
248 std::set<Client> expected_clients = {Client("id1", bufferlist())};
249 ASSERT_EQ(expected_clients, clients);
250 }
251
252 TEST_F(TestClsJournal, ClientRegisterDuplicate) {
253 librados::IoCtx ioctx;
254 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
255
256 std::string oid = get_temp_image_name();
257 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
258
259 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
260 ASSERT_EQ(-EEXIST, client::client_register(ioctx, oid, "id1", bufferlist()));
261 }
262
263 TEST_F(TestClsJournal, ClientUpdateData) {
264 librados::IoCtx ioctx;
265 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
266
267 std::string oid = get_temp_image_name();
268 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
269
270 ASSERT_EQ(-ENOENT, client::client_update_data(ioctx, oid, "id1",
271 bufferlist()));
272
273 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
274
275 bufferlist data;
276 data.append(std::string(128, '1'));
277 ASSERT_EQ(0, client::client_update_data(ioctx, oid, "id1", data));
278
279 Client client;
280 ASSERT_EQ(0, client::get_client(ioctx, oid, "id1", &client));
281 Client expected_client("id1", data);
282 ASSERT_EQ(expected_client, client);
283 }
284
285 TEST_F(TestClsJournal, ClientUpdateState) {
286 librados::IoCtx ioctx;
287 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
288
289 std::string oid = get_temp_image_name();
290 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
291
292 ASSERT_EQ(-ENOENT, client::client_update_state(ioctx, oid, "id1",
293 CLIENT_STATE_DISCONNECTED));
294
295 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
296
297 bufferlist data;
298 data.append(std::string(128, '1'));
299 ASSERT_EQ(0, client::client_update_state(ioctx, oid, "id1",
300 CLIENT_STATE_DISCONNECTED));
301
302 Client client;
303 ASSERT_EQ(0, client::get_client(ioctx, oid, "id1", &client));
304 Client expected_client;
305 expected_client.id = "id1";
306 expected_client.state = CLIENT_STATE_DISCONNECTED;
307 ASSERT_EQ(expected_client, client);
308 }
309
310 TEST_F(TestClsJournal, ClientUnregister) {
311 librados::IoCtx ioctx;
312 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
313
314 std::string oid = get_temp_image_name();
315 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
316
317 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
318 ASSERT_EQ(0, client::client_unregister(ioctx, oid, "id1"));
319 }
320
321 TEST_F(TestClsJournal, ClientUnregisterDNE) {
322 librados::IoCtx ioctx;
323 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
324
325 std::string oid = get_temp_image_name();
326 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
327
328 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
329 ASSERT_EQ(0, client::client_unregister(ioctx, oid, "id1"));
330 ASSERT_EQ(-ENOENT, client::client_unregister(ioctx, oid, "id1"));
331 }
332
333 TEST_F(TestClsJournal, ClientUnregisterPruneTags) {
334 librados::IoCtx ioctx;
335 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
336
337 std::string oid = get_temp_image_name();
338
339 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
340 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
341 ASSERT_EQ(0, client::client_register(ioctx, oid, "id2", bufferlist()));
342
343 ASSERT_EQ(0, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
344 bufferlist()));
345 ASSERT_EQ(0, client::tag_create(ioctx, oid, 1, Tag::TAG_CLASS_NEW,
346 bufferlist()));
347
348 for (uint32_t i = 2; i <= 96; ++i) {
349 ASSERT_EQ(0, client::tag_create(ioctx, oid, i, 1, bufferlist()));
350 }
351
352 librados::ObjectWriteOperation op1;
353 client::client_commit(&op1, "id1", {{{1, 32, 120}}});
354 ASSERT_EQ(0, ioctx.operate(oid, &op1));
355
356 ASSERT_EQ(0, client::client_unregister(ioctx, oid, "id2"));
357
358 std::set<Tag> expected_tags = {{0, 0, {}}};
359 for (uint32_t i = 32; i <= 96; ++i) {
360 expected_tags.insert({i, 1, {}});
361 }
362 std::set<Tag> tags;
363 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1",
364 boost::optional<uint64_t>(), &tags));
365 ASSERT_EQ(expected_tags, tags);
366 }
367
368 TEST_F(TestClsJournal, ClientCommit) {
369 librados::IoCtx ioctx;
370 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
371
372 std::string oid = get_temp_image_name();
373
374 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
375 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
376
377 cls::journal::ObjectPositions object_positions;
378 object_positions = {
379 cls::journal::ObjectPosition(0, 234, 120),
380 cls::journal::ObjectPosition(3, 235, 121)};
381 cls::journal::ObjectSetPosition object_set_position(
382 object_positions);
383
384 librados::ObjectWriteOperation op2;
385 client::client_commit(&op2, "id1", object_set_position);
386 ASSERT_EQ(0, ioctx.operate(oid, &op2));
387
388 std::set<Client> clients;
389 ASSERT_EQ(0, client::client_list(ioctx, oid, &clients));
390
391 std::set<Client> expected_clients = {
392 Client("id1", bufferlist(), object_set_position)};
393 ASSERT_EQ(expected_clients, clients);
394 }
395
396 TEST_F(TestClsJournal, ClientCommitInvalid) {
397 librados::IoCtx ioctx;
398 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
399
400 std::string oid = get_temp_image_name();
401
402 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
403 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
404
405 cls::journal::ObjectPositions object_positions;
406 object_positions = {
407 cls::journal::ObjectPosition(0, 234, 120),
408 cls::journal::ObjectPosition(4, 234, 121),
409 cls::journal::ObjectPosition(5, 235, 121)};
410 cls::journal::ObjectSetPosition object_set_position(
411 object_positions);
412
413 librados::ObjectWriteOperation op2;
414 client::client_commit(&op2, "id1", object_set_position);
415 ASSERT_EQ(-EINVAL, ioctx.operate(oid, &op2));
416 }
417
418 TEST_F(TestClsJournal, ClientCommitDNE) {
419 librados::IoCtx ioctx;
420 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
421
422 std::string oid = get_temp_image_name();
423
424 cls::journal::ObjectSetPosition object_set_position;
425
426 librados::ObjectWriteOperation op1;
427 client::client_commit(&op1, "id1", object_set_position);
428 ASSERT_EQ(-ENOENT, ioctx.operate(oid, &op1));
429 }
430
431 TEST_F(TestClsJournal, ClientList) {
432 librados::IoCtx ioctx;
433 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
434
435 std::string oid = get_temp_image_name();
436
437 ASSERT_EQ(0, client::create(ioctx, oid, 12, 5, ioctx.get_id()));
438
439 std::set<Client> expected_clients;
440 librados::ObjectWriteOperation op1;
441 for (uint32_t i = 0; i < 512; ++i) {
442 std::string id = "id" + stringify(i + 1);
443 expected_clients.insert(Client(id, bufferlist()));
444 client::client_register(&op1, id, bufferlist());
445 }
446 ASSERT_EQ(0, ioctx.operate(oid, &op1));
447
448 std::set<Client> clients;
449 ASSERT_EQ(0, client::client_list(ioctx, oid, &clients));
450 ASSERT_EQ(expected_clients, clients);
451
452 C_SaferCond cond;
453 uint64_t read_minimum_set;
454 uint64_t read_active_set;
455 std::set<cls::journal::Client> read_clients;
456 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
457 &read_clients, &cond);
458 ASSERT_EQ(0, cond.wait());
459 ASSERT_EQ(expected_clients, read_clients);
460 }
461
462 TEST_F(TestClsJournal, GetNextTagTid) {
463 librados::IoCtx ioctx;
464 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
465
466 std::string oid = get_temp_image_name();
467
468 uint64_t tag_tid;
469 ASSERT_EQ(-ENOENT, client::get_next_tag_tid(ioctx, oid, &tag_tid));
470
471 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
472 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
473
474 ASSERT_EQ(0, client::get_next_tag_tid(ioctx, oid, &tag_tid));
475 ASSERT_EQ(0U, tag_tid);
476
477 ASSERT_EQ(0, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
478 bufferlist()));
479 ASSERT_EQ(0, client::get_next_tag_tid(ioctx, oid, &tag_tid));
480 ASSERT_EQ(1U, tag_tid);
481 }
482
483 TEST_F(TestClsJournal, TagCreate) {
484 librados::IoCtx ioctx;
485 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
486
487 std::string oid = get_temp_image_name();
488
489 ASSERT_EQ(-ENOENT, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
490 bufferlist()));
491
492 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
493 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
494
495 ASSERT_EQ(-ESTALE, client::tag_create(ioctx, oid, 1, Tag::TAG_CLASS_NEW,
496 bufferlist()));
497 ASSERT_EQ(-EINVAL, client::tag_create(ioctx, oid, 0, 1, bufferlist()));
498
499 ASSERT_EQ(0, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
500 bufferlist()));
501 ASSERT_EQ(-EEXIST, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
502 bufferlist()));
503 ASSERT_EQ(0, client::tag_create(ioctx, oid, 1, Tag::TAG_CLASS_NEW,
504 bufferlist()));
505 ASSERT_EQ(0, client::tag_create(ioctx, oid, 2, 1, bufferlist()));
506
507 std::set<Tag> expected_tags = {
508 {0, 0, {}}, {1, 1, {}}, {2, 1, {}}};
509 std::set<Tag> tags;
510 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1",
511 boost::optional<uint64_t>(), &tags));
512 ASSERT_EQ(expected_tags, tags);
513 }
514
515 TEST_F(TestClsJournal, TagCreatePrunesTags) {
516 librados::IoCtx ioctx;
517 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
518
519 std::string oid = get_temp_image_name();
520
521 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
522 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
523
524 ASSERT_EQ(0, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
525 bufferlist()));
526 ASSERT_EQ(0, client::tag_create(ioctx, oid, 1, Tag::TAG_CLASS_NEW,
527 bufferlist()));
528 ASSERT_EQ(0, client::tag_create(ioctx, oid, 2, 1, bufferlist()));
529
530 librados::ObjectWriteOperation op1;
531 client::client_commit(&op1, "id1", {{{1, 2, 120}}});
532 ASSERT_EQ(0, ioctx.operate(oid, &op1));
533
534 ASSERT_EQ(0, client::tag_create(ioctx, oid, 3, 0, bufferlist()));
535
536 std::set<Tag> expected_tags = {
537 {0, 0, {}}, {2, 1, {}}, {3, 0, {}}};
538 std::set<Tag> tags;
539 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1",
540 boost::optional<uint64_t>(), &tags));
541 ASSERT_EQ(expected_tags, tags);
542 }
543
544 TEST_F(TestClsJournal, TagList) {
545 librados::IoCtx ioctx;
546 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
547
548 std::string oid = get_temp_image_name();
549
550 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
551 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
552
553 std::set<Tag> expected_all_tags;
554 std::set<Tag> expected_filtered_tags;
555 for (uint32_t i = 0; i < 96; ++i) {
556 uint64_t tag_class = Tag::TAG_CLASS_NEW;
557 if (i > 1) {
558 tag_class = i % 2 == 0 ? 0 : 1;
559 }
560
561 Tag tag(i, i % 2 == 0 ? 0 : 1, bufferlist());
562 expected_all_tags.insert(tag);
563 if (i % 2 == 0) {
564 expected_filtered_tags.insert(tag);
565 }
566 ASSERT_EQ(0, client::tag_create(ioctx, oid, i, tag_class,
567 bufferlist()));
568 }
569
570 std::set<Tag> tags;
571 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1", boost::optional<uint64_t>(),
572 &tags));
573 ASSERT_EQ(expected_all_tags, tags);
574
575 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1", boost::optional<uint64_t>(0),
576 &tags));
577 ASSERT_EQ(expected_filtered_tags, tags);
578
579 librados::ObjectWriteOperation op1;
580 client::client_commit(&op1, "id1", {{{96, 0, 120}}});
581 ASSERT_EQ(0, ioctx.operate(oid, &op1));
582
583 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1", boost::optional<uint64_t>(),
584 &tags));
585 ASSERT_EQ(expected_all_tags, tags);
586 }
587
588 TEST_F(TestClsJournal, GuardAppend) {
589 librados::IoCtx ioctx;
590 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
591
592 std::string oid = get_temp_image_name();
593
594 bufferlist bl;
595 bl.append("journal entry!");
596
597 librados::ObjectWriteOperation op1;
598 op1.append(bl);
599 ASSERT_EQ(0, ioctx.operate(oid, &op1));
600
601 librados::ObjectWriteOperation op2;
602 client::guard_append(&op2, 1024);
603 ASSERT_EQ(0, ioctx.operate(oid, &op2));
604 }
605
606 TEST_F(TestClsJournal, GuardAppendDNE) {
607 librados::IoCtx ioctx;
608 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
609
610 std::string oid = get_temp_image_name();
611
612 librados::ObjectWriteOperation op2;
613 client::guard_append(&op2, 1024);
614 ASSERT_EQ(0, ioctx.operate(oid, &op2));
615 }
616
617 TEST_F(TestClsJournal, GuardAppendOverflow) {
618 librados::IoCtx ioctx;
619 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
620
621 std::string oid = get_temp_image_name();
622
623 bufferlist bl;
624 bl.append("journal entry!");
625
626 librados::ObjectWriteOperation op1;
627 op1.append(bl);
628 ASSERT_EQ(0, ioctx.operate(oid, &op1));
629
630 librados::ObjectWriteOperation op2;
631 client::guard_append(&op2, 1);
632 ASSERT_EQ(-EOVERFLOW, ioctx.operate(oid, &op2));
633 }
634
635 TEST_F(TestClsJournal, Append) {
636 librados::IoCtx ioctx;
637 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
638
639 std::string oid = get_temp_image_name();
640 ioctx.remove(oid);
641
642 bool sparse_read_supported = is_sparse_read_supported(ioctx, oid);
643
644 bufferlist bl;
645 bl.append("journal entry!");
646
647 librados::ObjectWriteOperation op1;
648 client::append(&op1, 1, bl);
649 ASSERT_EQ(0, ioctx.operate(oid, &op1));
650
651 librados::ObjectWriteOperation op2;
652 client::append(&op2, 1, bl);
653 ASSERT_EQ(-EOVERFLOW, ioctx.operate(oid, &op2));
654
655 bufferlist outbl;
656 ASSERT_LE(bl.length(), ioctx.read(oid, outbl, 0, 0));
657
658 bufferlist tmpbl;
659 tmpbl.substr_of(outbl, 0, bl.length());
660 ASSERT_TRUE(bl.contents_equal(tmpbl));
661
662 if (outbl.length() == bl.length()) {
663 std::cout << "padding is not enabled" << std::endl;
664 return;
665 }
666
667 tmpbl.clear();
668 tmpbl.substr_of(outbl, bl.length(), outbl.length() - bl.length());
669 ASSERT_TRUE(tmpbl.is_zero());
670
671 if (!sparse_read_supported) {
672 std::cout << "sparse_read is not supported" << std::endl;
673 return;
674 }
675
676 librados::ObjectWriteOperation op3;
677 client::append(&op3, 1 << 24, bl);
678 ASSERT_EQ(0, ioctx.operate(oid, &op3));
679
680 std::map<uint64_t, uint64_t> m;
681 uint64_t pad_len = outbl.length();
682 outbl.clear();
683 std::map<uint64_t, uint64_t> expected_m =
684 {{0, bl.length()}, {pad_len, bl.length()}};
685 ASSERT_EQ(expected_m.size(), ioctx.sparse_read(oid, m, outbl, 2 * pad_len, 0));
686 ASSERT_EQ(m, expected_m);
687
688 uint64_t buffer_offset = 0;
689 for (auto &it : m) {
690 tmpbl.clear();
691 tmpbl.substr_of(outbl, buffer_offset, it.second);
692 ASSERT_TRUE(bl.contents_equal(tmpbl));
693 buffer_offset += it.second;
694 }
695 }