]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/osd/TestPGLog.cc
8e10c7532f3a2190149299b21e0d03d797723cc2
[ceph.git] / ceph / src / test / osd / TestPGLog.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
7 *
8 * Author: Loic Dachary <loic@dachary.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Library Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library Public License for more details.
19 *
20 */
21
22 #include <stdio.h>
23 #include <signal.h>
24 #include "gtest/gtest.h"
25 #include "osd/PGLog.h"
26 #include "osd/OSDMap.h"
27 #include "include/coredumpctl.h"
28
29 class PGLogTest : public ::testing::Test, protected PGLog {
30 public:
31 PGLogTest() : PGLog(g_ceph_context) {}
32 void SetUp() override { }
33
34 void TearDown() override {
35 clear();
36 }
37
38 static hobject_t mk_obj(unsigned id) {
39 hobject_t hoid;
40 stringstream ss;
41 ss << "obj_" << id;
42 hoid.oid = ss.str();
43 hoid.set_hash(id);
44 return hoid;
45 }
46 static eversion_t mk_evt(unsigned ep, unsigned v) {
47 return eversion_t(ep, v);
48 }
49 static pg_log_entry_t mk_ple_mod(
50 const hobject_t &hoid, eversion_t v, eversion_t pv) {
51 pg_log_entry_t e;
52 e.mark_unrollbackable();
53 e.op = pg_log_entry_t::MODIFY;
54 e.soid = hoid;
55 e.version = v;
56 e.prior_version = pv;
57 return e;
58 }
59 static pg_log_entry_t mk_ple_dt(
60 const hobject_t &hoid, eversion_t v, eversion_t pv) {
61 pg_log_entry_t e;
62 e.mark_unrollbackable();
63 e.op = pg_log_entry_t::DELETE;
64 e.soid = hoid;
65 e.version = v;
66 e.prior_version = pv;
67 return e;
68 }
69 static pg_log_entry_t mk_ple_mod_rb(
70 const hobject_t &hoid, eversion_t v, eversion_t pv) {
71 pg_log_entry_t e;
72 e.op = pg_log_entry_t::MODIFY;
73 e.soid = hoid;
74 e.version = v;
75 e.prior_version = pv;
76 return e;
77 }
78 static pg_log_entry_t mk_ple_dt_rb(
79 const hobject_t &hoid, eversion_t v, eversion_t pv) {
80 pg_log_entry_t e;
81 e.op = pg_log_entry_t::DELETE;
82 e.soid = hoid;
83 e.version = v;
84 e.prior_version = pv;
85 return e;
86 }
87
88 struct TestCase {
89 list<pg_log_entry_t> base;
90 list<pg_log_entry_t> auth;
91 list<pg_log_entry_t> div;
92
93 pg_missing_t init;
94 pg_missing_t final;
95
96 set<hobject_t> toremove;
97 list<pg_log_entry_t> torollback;
98
99 private:
100 IndexedLog fullauth;
101 IndexedLog fulldiv;
102 pg_info_t authinfo;
103 pg_info_t divinfo;
104 public:
105 void setup() {
106 fullauth.log.insert(fullauth.log.end(), base.begin(), base.end());
107 fullauth.log.insert(fullauth.log.end(), auth.begin(), auth.end());
108 fulldiv.log.insert(fulldiv.log.end(), base.begin(), base.end());
109 fulldiv.log.insert(fulldiv.log.end(), div.begin(), div.end());
110
111 fullauth.head = authinfo.last_update = fullauth.log.rbegin()->version;
112 authinfo.last_complete = fullauth.log.rbegin()->version;
113 authinfo.log_tail = fullauth.log.begin()->version;
114 authinfo.log_tail.version--;
115 fullauth.tail = authinfo.log_tail;
116 authinfo.last_backfill = hobject_t::get_max();
117
118 fulldiv.head = divinfo.last_update = fulldiv.log.rbegin()->version;
119 divinfo.last_complete = eversion_t();
120 divinfo.log_tail = fulldiv.log.begin()->version;
121 divinfo.log_tail.version--;
122 fulldiv.tail = divinfo.log_tail;
123 divinfo.last_backfill = hobject_t::get_max();
124
125 if (init.get_items().empty()) {
126 divinfo.last_complete = divinfo.last_update;
127 } else {
128 eversion_t fmissing = init.get_items().at(init.get_rmissing().begin()->second).need;
129 for (list<pg_log_entry_t>::const_iterator i = fulldiv.log.begin();
130 i != fulldiv.log.end();
131 ++i) {
132 if (i->version < fmissing)
133 divinfo.last_complete = i->version;
134 else
135 break;
136 }
137 }
138
139 fullauth.index();
140 fulldiv.index();
141 }
142 void set_div_bounds(eversion_t head, eversion_t tail) {
143 fulldiv.tail = divinfo.log_tail = tail;
144 fulldiv.head = divinfo.last_update = head;
145 }
146 void set_auth_bounds(eversion_t head, eversion_t tail) {
147 fullauth.tail = authinfo.log_tail = tail;
148 fullauth.head = authinfo.last_update = head;
149 }
150 const IndexedLog &get_fullauth() const { return fullauth; }
151 const IndexedLog &get_fulldiv() const { return fulldiv; }
152 const pg_info_t &get_authinfo() const { return authinfo; }
153 const pg_info_t &get_divinfo() const { return divinfo; }
154 };
155
156 struct LogHandler : public PGLog::LogEntryHandler {
157 set<hobject_t> removed;
158 list<pg_log_entry_t> rolledback;
159
160 void rollback(
161 const pg_log_entry_t &entry) override {
162 rolledback.push_back(entry);
163 }
164 void rollforward(
165 const pg_log_entry_t &entry) override {}
166 void remove(
167 const hobject_t &hoid) override {
168 removed.insert(hoid);
169 }
170 void try_stash(const hobject_t &, version_t) override {
171 // lost/unfound cases are not tested yet
172 }
173 void trim(
174 const pg_log_entry_t &entry) override {}
175 };
176
177 template <typename missing_t>
178 void verify_missing(
179 const TestCase &tcase,
180 const missing_t &missing) {
181 ASSERT_EQ(tcase.final.get_items().size(), missing.get_items().size());
182 for (auto i = missing.get_items().begin();
183 i != missing.get_items().end();
184 ++i) {
185 EXPECT_TRUE(tcase.final.get_items().count(i->first));
186 EXPECT_EQ(tcase.final.get_items().find(i->first)->second.need, i->second.need);
187 EXPECT_EQ(tcase.final.get_items().find(i->first)->second.have, i->second.have);
188 }
189 bool correct = missing.debug_verify_from_init(tcase.init, &(std::cout));
190 ASSERT_TRUE(correct);
191 }
192
193 void verify_sideeffects(
194 const TestCase &tcase,
195 const LogHandler &handler) {
196 ASSERT_EQ(tcase.toremove.size(), handler.removed.size());
197 ASSERT_EQ(tcase.torollback.size(), handler.rolledback.size());
198
199 {
200 list<pg_log_entry_t>::const_iterator titer = tcase.torollback.begin();
201 list<pg_log_entry_t>::const_iterator hiter = handler.rolledback.begin();
202 for (; titer != tcase.torollback.end(); ++titer, ++hiter) {
203 EXPECT_EQ(titer->version, hiter->version);
204 }
205 }
206
207 {
208 set<hobject_t>::const_iterator titer = tcase.toremove.begin();
209 set<hobject_t>::const_iterator hiter = handler.removed.begin();
210 for (; titer != tcase.toremove.end(); ++titer, ++hiter) {
211 EXPECT_EQ(*titer, *hiter);
212 }
213 }
214 }
215
216 void test_merge_log(const TestCase &tcase) {
217 clear();
218 log = tcase.get_fulldiv();
219 pg_info_t info = tcase.get_divinfo();
220
221 missing = tcase.init;
222 missing.flush();
223
224 IndexedLog olog;
225 olog = tcase.get_fullauth();
226 pg_info_t oinfo = tcase.get_authinfo();
227
228 LogHandler h;
229 bool dirty_info = false;
230 bool dirty_big_info = false;
231 merge_log(
232 oinfo, olog, pg_shard_t(1, shard_id_t(0)), info,
233 &h, dirty_info, dirty_big_info);
234
235 ASSERT_EQ(info.last_update, oinfo.last_update);
236 verify_missing(tcase, missing);
237 verify_sideeffects(tcase, h);
238 };
239 void test_proc_replica_log(const TestCase &tcase) {
240 clear();
241 log = tcase.get_fullauth();
242 pg_info_t info = tcase.get_authinfo();
243
244 pg_missing_t omissing = tcase.init;
245
246 IndexedLog olog;
247 olog = tcase.get_fulldiv();
248 pg_info_t oinfo = tcase.get_divinfo();
249
250 proc_replica_log(
251 oinfo, olog, omissing, pg_shard_t(1, shard_id_t(0)));
252
253 assert(oinfo.last_update >= log.tail);
254
255 if (!tcase.base.empty()) {
256 ASSERT_EQ(tcase.base.rbegin()->version, oinfo.last_update);
257 }
258
259 for (list<pg_log_entry_t>::const_iterator i = tcase.auth.begin();
260 i != tcase.auth.end();
261 ++i) {
262 if (i->version > oinfo.last_update)
263 omissing.add_next_event(*i);
264 }
265 verify_missing(tcase, omissing);
266 }
267 void run_test_case(const TestCase &tcase) {
268 test_merge_log(tcase);
269 test_proc_replica_log(tcase);
270 }
271 };
272
273 struct TestHandler : public PGLog::LogEntryHandler {
274 list<hobject_t> &removed;
275 explicit TestHandler(list<hobject_t> &removed) : removed(removed) {}
276
277 void rollback(
278 const pg_log_entry_t &entry) override {}
279 void rollforward(
280 const pg_log_entry_t &entry) override {}
281 void remove(
282 const hobject_t &hoid) override {
283 removed.push_back(hoid);
284 }
285 void cant_rollback(const pg_log_entry_t &entry) {}
286 void try_stash(const hobject_t &, version_t) override {
287 // lost/unfound cases are not tested yet
288 }
289 void trim(
290 const pg_log_entry_t &entry) override {}
291 };
292
293 TEST_F(PGLogTest, rewind_divergent_log) {
294 /* +----------------+
295 | log |
296 +--------+-------+
297 | |object |
298 |version | hash |
299 | | |
300 tail > (1,1) | x5 |
301 | | |
302 | | |
303 | (1,4) | x9 < newhead
304 | MODIFY | |
305 | | |
306 head > (1,5) | x9 |
307 | DELETE | |
308 | | |
309 +--------+-------+
310
311 */
312 {
313 clear();
314
315 pg_info_t info;
316 list<hobject_t> remove_snap;
317 bool dirty_info = false;
318 bool dirty_big_info = false;
319
320 hobject_t divergent_object;
321 eversion_t divergent_version;
322 eversion_t newhead;
323
324 hobject_t divergent;
325 divergent.set_hash(0x9);
326
327 {
328 pg_log_entry_t e;
329 e.mark_unrollbackable();
330
331 e.version = eversion_t(1, 1);
332 e.soid.set_hash(0x5);
333 log.tail = e.version;
334 log.log.push_back(e);
335 e.version = newhead = eversion_t(1, 4);
336 e.soid = divergent;
337 e.op = pg_log_entry_t::MODIFY;
338 log.log.push_back(e);
339 e.version = divergent_version = eversion_t(1, 5);
340 e.prior_version = eversion_t(1, 4);
341 e.soid = divergent;
342 divergent_object = e.soid;
343 e.op = pg_log_entry_t::DELETE;
344 log.log.push_back(e);
345 log.head = e.version;
346 log.index();
347
348 info.last_update = log.head;
349 info.last_complete = log.head;
350 }
351
352 EXPECT_FALSE(missing.have_missing());
353 EXPECT_EQ(3U, log.log.size());
354 EXPECT_TRUE(remove_snap.empty());
355 EXPECT_EQ(log.head, info.last_update);
356 EXPECT_EQ(log.head, info.last_complete);
357 EXPECT_FALSE(is_dirty());
358 EXPECT_FALSE(dirty_info);
359 EXPECT_FALSE(dirty_big_info);
360
361 TestHandler h(remove_snap);
362 rewind_divergent_log(newhead, info, &h,
363 dirty_info, dirty_big_info);
364
365 EXPECT_TRUE(log.objects.count(divergent));
366 EXPECT_TRUE(missing.is_missing(divergent_object));
367 EXPECT_EQ(1U, log.objects.count(divergent_object));
368 EXPECT_EQ(2U, log.log.size());
369 EXPECT_TRUE(remove_snap.empty());
370 EXPECT_EQ(newhead, info.last_update);
371 EXPECT_EQ(newhead, info.last_complete);
372 EXPECT_TRUE(is_dirty());
373 EXPECT_TRUE(dirty_info);
374 EXPECT_TRUE(dirty_big_info);
375 }
376
377 /* +----------------+
378 | log |
379 +--------+-------+
380 | |object |
381 |version | hash |
382 | | |
383 tail > (1,1) | NULL |
384 | | |
385 | (1,4) | NULL < newhead
386 | | |
387 head > (1,5) | x9 |
388 | | |
389 +--------+-------+
390
391 */
392 {
393 clear();
394
395 pg_info_t info;
396 list<hobject_t> remove_snap;
397 bool dirty_info = false;
398 bool dirty_big_info = false;
399
400 hobject_t divergent_object;
401 eversion_t divergent_version;
402 eversion_t prior_version;
403 eversion_t newhead;
404 {
405 pg_log_entry_t e;
406 e.mark_unrollbackable();
407
408 info.log_tail = log.tail = eversion_t(1, 1);
409 newhead = eversion_t(1, 3);
410 e.version = divergent_version = eversion_t(1, 5);
411 e.soid.set_hash(0x9);
412 divergent_object = e.soid;
413 e.op = pg_log_entry_t::DELETE;
414 e.prior_version = prior_version = eversion_t(0, 2);
415 log.log.push_back(e);
416 log.head = e.version;
417 }
418
419 EXPECT_FALSE(missing.have_missing());
420 EXPECT_EQ(1U, log.log.size());
421 EXPECT_TRUE(remove_snap.empty());
422 EXPECT_FALSE(is_dirty());
423 EXPECT_FALSE(dirty_info);
424 EXPECT_FALSE(dirty_big_info);
425
426 TestHandler h(remove_snap);
427 rewind_divergent_log(newhead, info, &h,
428 dirty_info, dirty_big_info);
429
430 EXPECT_TRUE(missing.is_missing(divergent_object));
431 EXPECT_EQ(0U, log.objects.count(divergent_object));
432 EXPECT_TRUE(log.empty());
433 EXPECT_TRUE(remove_snap.empty());
434 EXPECT_TRUE(is_dirty());
435 EXPECT_TRUE(dirty_info);
436 EXPECT_TRUE(dirty_big_info);
437 }
438
439 // Test for 13965
440 {
441 clear();
442
443 list<hobject_t> remove_snap;
444 pg_info_t info;
445 info.log_tail = log.tail = eversion_t(1, 5);
446 info.last_update = eversion_t(1, 6);
447 bool dirty_info = false;
448 bool dirty_big_info = false;
449
450 {
451 pg_log_entry_t e;
452 e.mark_unrollbackable();
453 e.version = eversion_t(1, 5);
454 e.soid.set_hash(0x9);
455 add(e);
456 }
457 {
458 pg_log_entry_t e;
459 e.mark_unrollbackable();
460 e.version = eversion_t(1, 6);
461 e.soid.set_hash(0x10);
462 add(e);
463 }
464 TestHandler h(remove_snap);
465 roll_forward_to(eversion_t(1, 6), &h);
466 rewind_divergent_log(eversion_t(1, 5), info, &h,
467 dirty_info, dirty_big_info);
468 pg_log_t log;
469 reset_backfill_claim_log(log, &h);
470 }
471 }
472
473 TEST_F(PGLogTest, merge_old_entry) {
474 // entries > last_backfill are silently ignored
475 {
476 clear();
477
478 ObjectStore::Transaction t;
479 pg_log_entry_t oe;
480 oe.mark_unrollbackable();
481 pg_info_t info;
482 list<hobject_t> remove_snap;
483
484 info.last_backfill = hobject_t();
485 info.last_backfill.set_hash(100);
486 oe.soid.set_hash(2);
487 ASSERT_GT(oe.soid, info.last_backfill);
488
489 EXPECT_FALSE(is_dirty());
490 EXPECT_TRUE(remove_snap.empty());
491 EXPECT_TRUE(t.empty());
492 EXPECT_FALSE(missing.have_missing());
493 EXPECT_TRUE(log.empty());
494
495 TestHandler h(remove_snap);
496 merge_old_entry(t, oe, info, &h);
497
498 EXPECT_FALSE(is_dirty());
499 EXPECT_TRUE(remove_snap.empty());
500 EXPECT_TRUE(t.empty());
501 EXPECT_FALSE(missing.have_missing());
502 EXPECT_TRUE(log.empty());
503 }
504
505 // the new entry (from the logs) has a version that is higher than
506 // the old entry (from the log entry given in argument) : do
507 // nothing and return false
508 {
509 clear();
510
511 ObjectStore::Transaction t;
512 pg_info_t info;
513 list<hobject_t> remove_snap;
514
515 pg_log_entry_t ne;
516 ne.mark_unrollbackable();
517 ne.version = eversion_t(2,1);
518 log.add(ne);
519
520 EXPECT_FALSE(is_dirty());
521 EXPECT_TRUE(remove_snap.empty());
522 EXPECT_TRUE(t.empty());
523 EXPECT_FALSE(missing.have_missing());
524 EXPECT_EQ(1U, log.log.size());
525 EXPECT_EQ(ne.version, log.log.front().version);
526
527 // the newer entry ( from the logs ) can be DELETE
528 {
529 log.log.front().op = pg_log_entry_t::DELETE;
530 pg_log_entry_t oe;
531 oe.mark_unrollbackable();
532 oe.version = eversion_t(1,1);
533
534 TestHandler h(remove_snap);
535 merge_old_entry(t, oe, info, &h);
536 }
537
538 // if the newer entry is not DELETE, the object must be in missing
539 {
540 pg_log_entry_t &ne = log.log.front();
541 ne.op = pg_log_entry_t::MODIFY;
542 missing.add_next_event(ne);
543 pg_log_entry_t oe;
544 oe.mark_unrollbackable();
545 oe.version = eversion_t(1,1);
546
547 TestHandler h(remove_snap);
548 merge_old_entry(t, oe, info, &h);
549
550 missing.rm(ne.soid, ne.version);
551 }
552
553 missing.flush();
554 EXPECT_FALSE(is_dirty());
555 EXPECT_FALSE(remove_snap.empty());
556 EXPECT_TRUE(t.empty());
557 EXPECT_FALSE(missing.have_missing());
558 EXPECT_EQ(1U, log.log.size());
559 EXPECT_EQ(ne.version, log.log.front().version);
560
561 }
562
563 // the new entry (from the logs) has a version that is lower than
564 // the old entry (from the log entry given in argument) and
565 // old and new are delete : do nothing and return false
566 {
567 clear();
568
569 ObjectStore::Transaction t;
570 pg_log_entry_t oe;
571 oe.mark_unrollbackable();
572 pg_info_t info;
573 list<hobject_t> remove_snap;
574
575 pg_log_entry_t ne;
576 ne.mark_unrollbackable();
577 ne.version = eversion_t(1,1);
578 ne.op = pg_log_entry_t::DELETE;
579 log.add(ne);
580
581 oe.version = eversion_t(2,1);
582 oe.op = pg_log_entry_t::DELETE;
583
584 EXPECT_FALSE(is_dirty());
585 EXPECT_TRUE(remove_snap.empty());
586 EXPECT_TRUE(t.empty());
587 EXPECT_FALSE(missing.have_missing());
588 EXPECT_EQ(1U, log.log.size());
589
590 TestHandler h(remove_snap);
591 merge_old_entry(t, oe, info, &h);
592
593 EXPECT_FALSE(is_dirty());
594 EXPECT_TRUE(remove_snap.empty());
595 EXPECT_TRUE(t.empty());
596 EXPECT_FALSE(missing.have_missing());
597 EXPECT_EQ(1U, log.log.size());
598 }
599
600 // the new entry (from the logs) has a version that is lower than
601 // the old entry (from the log entry given in argument) and
602 // old is update and new is DELETE :
603 // if the object is in missing, it is removed
604 {
605 clear();
606
607 ObjectStore::Transaction t;
608 pg_log_entry_t oe;
609 oe.mark_unrollbackable();
610 pg_info_t info;
611 list<hobject_t> remove_snap;
612
613 pg_log_entry_t ne;
614 ne.mark_unrollbackable();
615 ne.version = eversion_t(1,1);
616 ne.op = pg_log_entry_t::DELETE;
617 log.add(ne);
618
619 oe.version = eversion_t(2,1);
620 oe.op = pg_log_entry_t::MODIFY;
621 missing.add_next_event(oe);
622
623 missing.flush();
624 EXPECT_FALSE(is_dirty());
625 EXPECT_TRUE(remove_snap.empty());
626 EXPECT_TRUE(t.empty());
627 EXPECT_TRUE(missing.is_missing(oe.soid));
628 EXPECT_EQ(1U, log.log.size());
629
630 TestHandler h(remove_snap);
631 merge_old_entry(t, oe, info, &h);
632
633 missing.flush();
634 EXPECT_FALSE(is_dirty());
635 EXPECT_TRUE(remove_snap.size() > 0);
636 EXPECT_TRUE(t.empty());
637 EXPECT_FALSE(missing.have_missing());
638 EXPECT_EQ(1U, log.log.size());
639 }
640
641 // there is no new entry (from the logs) and
642 // the old entry (from the log entry given in argument) is not a CLONE and
643 // the old entry prior_version is greater than the tail of the log :
644 // do nothing and return false
645 {
646 clear();
647
648 ObjectStore::Transaction t;
649 pg_log_entry_t oe;
650 oe.mark_unrollbackable();
651 pg_info_t info;
652 list<hobject_t> remove_snap;
653
654 info.log_tail = eversion_t(1,1);
655 oe.op = pg_log_entry_t::MODIFY;
656 oe.prior_version = eversion_t(2,1);
657 missing_add(oe.soid, oe.prior_version, eversion_t());
658
659 missing.flush();
660 EXPECT_FALSE(is_dirty());
661 EXPECT_TRUE(remove_snap.empty());
662 EXPECT_TRUE(t.empty());
663 EXPECT_TRUE(log.empty());
664
665 TestHandler h(remove_snap);
666 merge_old_entry(t, oe, info, &h);
667
668 missing.flush();
669 EXPECT_FALSE(is_dirty());
670 EXPECT_TRUE(remove_snap.empty());
671 EXPECT_TRUE(t.empty());
672 EXPECT_TRUE(log.empty());
673 }
674
675 // there is no new entry (from the logs) and
676 // the old entry (from the log entry given in argument) is not a CLONE and
677 // the old entry (from the log entry given in argument) is not a DELETE and
678 // the old entry prior_version is lower than the tail of the log :
679 // add the old object to the remove_snap list and
680 // add the old object to divergent priors and
681 // add or update the prior_version of the object to missing and
682 // return false
683 {
684 clear();
685
686 ObjectStore::Transaction t;
687 pg_log_entry_t oe;
688 oe.mark_unrollbackable();
689 pg_info_t info;
690 list<hobject_t> remove_snap;
691
692 info.log_tail = eversion_t(2,1);
693 oe.soid.set_hash(1);
694 oe.op = pg_log_entry_t::MODIFY;
695 oe.prior_version = eversion_t(1,1);
696
697 EXPECT_FALSE(is_dirty());
698 EXPECT_TRUE(remove_snap.empty());
699 EXPECT_TRUE(t.empty());
700 EXPECT_FALSE(missing.have_missing());
701 EXPECT_TRUE(log.empty());
702
703 TestHandler h(remove_snap);
704 merge_old_entry(t, oe, info, &h);
705
706 EXPECT_TRUE(is_dirty());
707 EXPECT_EQ(oe.soid, remove_snap.front());
708 EXPECT_TRUE(t.empty());
709 EXPECT_TRUE(missing.is_missing(oe.soid));
710 EXPECT_TRUE(log.empty());
711 }
712
713 // there is no new entry (from the logs) and
714 // the old entry (from the log entry given in argument) is not a CLONE and
715 // the old entry (from the log entry given in argument) is a DELETE and
716 // the old entry prior_version is lower than the tail of the log :
717 // add the old object to divergent priors and
718 // add or update the prior_version of the object to missing and
719 // return false
720 {
721 clear();
722
723 ObjectStore::Transaction t;
724 pg_log_entry_t oe;
725 oe.mark_unrollbackable();
726 pg_info_t info;
727 list<hobject_t> remove_snap;
728
729 info.log_tail = eversion_t(2,1);
730 oe.soid.set_hash(1);
731 oe.op = pg_log_entry_t::DELETE;
732 oe.prior_version = eversion_t(1,1);
733
734 EXPECT_FALSE(is_dirty());
735 EXPECT_TRUE(remove_snap.empty());
736 EXPECT_TRUE(t.empty());
737 EXPECT_FALSE(missing.have_missing());
738 EXPECT_TRUE(log.empty());
739
740 TestHandler h(remove_snap);
741 merge_old_entry(t, oe, info, &h);
742
743 EXPECT_TRUE(is_dirty());
744 EXPECT_TRUE(remove_snap.empty());
745 EXPECT_TRUE(t.empty());
746 EXPECT_TRUE(missing.is_missing(oe.soid));
747 EXPECT_TRUE(log.empty());
748 }
749
750
751 // there is no new entry (from the logs) and
752 // the old entry (from the log entry given in argument) is not a CLONE and
753 // the old entry (from the log entry given in argument) is not a DELETE and
754 // the old entry prior_version is eversion_t() :
755 // add the old object to the remove_snap list and
756 // remove the prior_version of the object from missing, if any and
757 // return false
758 {
759 clear();
760
761 ObjectStore::Transaction t;
762 pg_log_entry_t oe;
763 oe.mark_unrollbackable();
764 pg_info_t info;
765 list<hobject_t> remove_snap;
766
767 info.log_tail = eversion_t(10,1);
768 oe.soid.set_hash(1);
769 oe.op = pg_log_entry_t::MODIFY;
770 oe.prior_version = eversion_t();
771
772 missing.add(oe.soid, eversion_t(1,1), eversion_t());
773
774 missing.flush();
775 EXPECT_FALSE(is_dirty());
776 EXPECT_TRUE(remove_snap.empty());
777 EXPECT_TRUE(t.empty());
778 EXPECT_TRUE(missing.is_missing(oe.soid));
779 EXPECT_TRUE(log.empty());
780
781 TestHandler h(remove_snap);
782 merge_old_entry(t, oe, info, &h);
783
784 missing.flush();
785 EXPECT_FALSE(is_dirty());
786 EXPECT_EQ(oe.soid, remove_snap.front());
787 EXPECT_TRUE(t.empty());
788 EXPECT_FALSE(missing.have_missing());
789 EXPECT_TRUE(log.empty());
790 }
791
792 }
793
794 TEST_F(PGLogTest, merge_log) {
795 // head and tail match, last_backfill is set:
796 // noop
797 {
798 clear();
799
800 pg_log_t olog;
801 pg_info_t oinfo;
802 pg_shard_t fromosd;
803 pg_info_t info;
804 list<hobject_t> remove_snap;
805 bool dirty_info = false;
806 bool dirty_big_info = false;
807
808 hobject_t last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
809 info.last_backfill = last_backfill;
810 eversion_t stat_version(10, 1);
811 info.stats.version = stat_version;
812 log.tail = olog.tail = eversion_t(1, 1);
813 log.head = olog.head = eversion_t(2, 1);
814
815 EXPECT_FALSE(missing.have_missing());
816 EXPECT_EQ(0U, log.log.size());
817 EXPECT_EQ(stat_version, info.stats.version);
818 EXPECT_TRUE(remove_snap.empty());
819 EXPECT_EQ(last_backfill, info.last_backfill);
820 EXPECT_TRUE(info.purged_snaps.empty());
821 EXPECT_FALSE(is_dirty());
822 EXPECT_FALSE(dirty_info);
823 EXPECT_FALSE(dirty_big_info);
824
825 TestHandler h(remove_snap);
826 merge_log(oinfo, olog, fromosd, info, &h,
827 dirty_info, dirty_big_info);
828
829 EXPECT_FALSE(missing.have_missing());
830 EXPECT_EQ(0U, log.log.size());
831 EXPECT_EQ(stat_version, info.stats.version);
832 EXPECT_TRUE(remove_snap.empty());
833 EXPECT_TRUE(info.purged_snaps.empty());
834 EXPECT_FALSE(is_dirty());
835 EXPECT_FALSE(dirty_info);
836 EXPECT_FALSE(dirty_big_info);
837 }
838
839 // head and tail match, last_backfill is not set: info.stats is
840 // copied from oinfo.stats but info.stats.reported_* is guaranteed to
841 // never be replaced by a lower version
842 {
843 clear();
844
845 pg_log_t olog;
846 pg_info_t oinfo;
847 pg_shard_t fromosd;
848 pg_info_t info;
849 list<hobject_t> remove_snap;
850 bool dirty_info = false;
851 bool dirty_big_info = false;
852
853 eversion_t stat_version(10, 1);
854 oinfo.stats.version = stat_version;
855 info.stats.reported_seq = 1;
856 info.stats.reported_epoch = 10;
857 oinfo.stats.reported_seq = 1;
858 oinfo.stats.reported_epoch = 1;
859 log.tail = olog.tail = eversion_t(1, 1);
860 log.head = olog.head = eversion_t(2, 1);
861
862 EXPECT_FALSE(missing.have_missing());
863 EXPECT_EQ(0U, log.log.size());
864 EXPECT_EQ(eversion_t(), info.stats.version);
865 EXPECT_EQ(1ull, info.stats.reported_seq);
866 EXPECT_EQ(10u, info.stats.reported_epoch);
867 EXPECT_TRUE(remove_snap.empty());
868 EXPECT_TRUE(info.last_backfill.is_max());
869 EXPECT_TRUE(info.purged_snaps.empty());
870 EXPECT_FALSE(is_dirty());
871 EXPECT_FALSE(dirty_info);
872 EXPECT_FALSE(dirty_big_info);
873
874 TestHandler h(remove_snap);
875 merge_log(oinfo, olog, fromosd, info, &h,
876 dirty_info, dirty_big_info);
877
878 EXPECT_FALSE(missing.have_missing());
879 EXPECT_EQ(0U, log.log.size());
880 EXPECT_EQ(stat_version, info.stats.version);
881 EXPECT_EQ(1ull, info.stats.reported_seq);
882 EXPECT_EQ(10u, info.stats.reported_epoch);
883 EXPECT_TRUE(remove_snap.empty());
884 EXPECT_TRUE(info.purged_snaps.empty());
885 EXPECT_FALSE(is_dirty());
886 EXPECT_FALSE(dirty_info);
887 EXPECT_FALSE(dirty_big_info);
888 }
889
890 /* Before
891 +--------------------------+
892 | log olog |
893 +--------+-------+---------+
894 | |object | |
895 |version | hash | version |
896 | | | |
897 | | x5 | (1,1) < tail
898 | | | |
899 | | | |
900 tail > (1,4) | x7 | |
901 | | | |
902 | | | |
903 head > (1,5) | x9 | (1,5) < head
904 | | | |
905 | | | |
906 +--------+-------+---------+
907
908 After
909 +-----------------
910 | log |
911 +--------+-------+
912 | |object |
913 |version | hash |
914 | | |
915 tail > (1,1) | x5 |
916 | | |
917 | | |
918 | (1,4) | x7 |
919 | | |
920 | | |
921 head > (1,5) | x9 |
922 | | |
923 | | |
924 +--------+-------+
925 */
926 {
927 clear();
928
929 pg_log_t olog;
930 pg_info_t oinfo;
931 pg_shard_t fromosd;
932 pg_info_t info;
933 list<hobject_t> remove_snap;
934 bool dirty_info = false;
935 bool dirty_big_info = false;
936
937 {
938 pg_log_entry_t e;
939 e.mark_unrollbackable();
940
941 e.version = eversion_t(1, 4);
942 e.soid.set_hash(0x5);
943 log.tail = e.version;
944 log.log.push_back(e);
945 e.version = eversion_t(1, 5);
946 e.soid.set_hash(0x9);
947 log.log.push_back(e);
948 log.head = e.version;
949 log.index();
950
951 info.last_update = log.head;
952
953 e.version = eversion_t(1, 1);
954 e.soid.set_hash(0x5);
955 olog.tail = e.version;
956 olog.log.push_back(e);
957 e.version = eversion_t(1, 5);
958 e.soid.set_hash(0x9);
959 olog.log.push_back(e);
960 olog.head = e.version;
961 }
962
963 hobject_t last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
964 info.last_backfill = last_backfill;
965 eversion_t stat_version(10, 1);
966 info.stats.version = stat_version;
967
968 EXPECT_FALSE(missing.have_missing());
969 EXPECT_EQ(2U, log.log.size());
970 EXPECT_EQ(stat_version, info.stats.version);
971 EXPECT_TRUE(remove_snap.empty());
972 EXPECT_EQ(last_backfill, info.last_backfill);
973 EXPECT_TRUE(info.purged_snaps.empty());
974 EXPECT_FALSE(is_dirty());
975 EXPECT_FALSE(dirty_info);
976 EXPECT_FALSE(dirty_big_info);
977
978 TestHandler h(remove_snap);
979 merge_log(oinfo, olog, fromosd, info, &h,
980 dirty_info, dirty_big_info);
981
982 EXPECT_FALSE(missing.have_missing());
983 EXPECT_EQ(3U, log.log.size());
984 EXPECT_EQ(stat_version, info.stats.version);
985 EXPECT_TRUE(remove_snap.empty());
986 EXPECT_TRUE(info.purged_snaps.empty());
987 EXPECT_TRUE(is_dirty());
988 EXPECT_TRUE(dirty_info);
989 EXPECT_TRUE(dirty_big_info);
990 }
991
992 /* +--------------------------+
993 | log olog |
994 +--------+-------+---------+
995 | |object | |
996 |version | hash | version |
997 | | | |
998 tail > (1,1) | x5 | (1,1) < tail
999 | | | |
1000 | | | |
1001 | (1,2) | x3 | (1,2) < lower_bound
1002 | | | |
1003 | | | |
1004 head > (1,3) | x9 | |
1005 | DELETE | | |
1006 | | | |
1007 | | x9 | (2,3) |
1008 | | | MODIFY |
1009 | | | |
1010 | | x7 | (2,4) < head
1011 | | | DELETE |
1012 +--------+-------+---------+
1013
1014 The log entry (1,3) deletes the object x9 but the olog entry (2,3) modifies
1015 it and is authoritative : the log entry (1,3) is divergent.
1016
1017 */
1018 {
1019 clear();
1020
1021 pg_log_t olog;
1022 pg_info_t oinfo;
1023 pg_shard_t fromosd;
1024 pg_info_t info;
1025 list<hobject_t> remove_snap;
1026 bool dirty_info = false;
1027 bool dirty_big_info = false;
1028
1029 hobject_t divergent_object;
1030
1031 {
1032 pg_log_entry_t e;
1033 e.mark_unrollbackable();
1034
1035 e.version = eversion_t(1, 1);
1036 e.soid.set_hash(0x5);
1037 log.tail = e.version;
1038 log.log.push_back(e);
1039 e.version = eversion_t(1, 2);
1040 e.soid.set_hash(0x3);
1041 log.log.push_back(e);
1042 e.version = eversion_t(1,3);
1043 e.soid.set_hash(0x9);
1044 divergent_object = e.soid;
1045 e.op = pg_log_entry_t::DELETE;
1046 log.log.push_back(e);
1047 log.head = e.version;
1048 log.index();
1049
1050 info.last_update = log.head;
1051
1052 e.version = eversion_t(1, 1);
1053 e.soid.set_hash(0x5);
1054 olog.tail = e.version;
1055 olog.log.push_back(e);
1056 e.version = eversion_t(1, 2);
1057 e.soid.set_hash(0x3);
1058 olog.log.push_back(e);
1059 e.version = eversion_t(2, 3);
1060 e.soid.set_hash(0x9);
1061 e.op = pg_log_entry_t::MODIFY;
1062 olog.log.push_back(e);
1063 e.version = eversion_t(2, 4);
1064 e.soid.set_hash(0x7);
1065 e.op = pg_log_entry_t::DELETE;
1066 olog.log.push_back(e);
1067 olog.head = e.version;
1068 }
1069
1070 snapid_t purged_snap(1);
1071 {
1072 oinfo.last_update = olog.head;
1073 oinfo.purged_snaps.insert(purged_snap);
1074 }
1075
1076 EXPECT_FALSE(missing.have_missing());
1077 EXPECT_EQ(1U, log.objects.count(divergent_object));
1078 EXPECT_EQ(3U, log.log.size());
1079 EXPECT_TRUE(remove_snap.empty());
1080 EXPECT_EQ(log.head, info.last_update);
1081 EXPECT_TRUE(info.purged_snaps.empty());
1082 EXPECT_FALSE(is_dirty());
1083 EXPECT_FALSE(dirty_info);
1084 EXPECT_FALSE(dirty_big_info);
1085
1086 TestHandler h(remove_snap);
1087 merge_log(oinfo, olog, fromosd, info, &h,
1088 dirty_info, dirty_big_info);
1089
1090 /* When the divergent entry is a DELETE and the authoritative
1091 entry is a MODIFY, the object will be added to missing : it is
1092 a verifiable side effect proving the entry was identified
1093 to be divergent.
1094 */
1095 EXPECT_TRUE(missing.is_missing(divergent_object));
1096 EXPECT_EQ(1U, log.objects.count(divergent_object));
1097 EXPECT_EQ(4U, log.log.size());
1098 /* DELETE entries from olog that are appended to the hed of the
1099 log are also added to remove_snap.
1100 */
1101 EXPECT_EQ(0x7U, remove_snap.front().get_hash());
1102 EXPECT_EQ(log.head, info.last_update);
1103 EXPECT_TRUE(info.purged_snaps.contains(purged_snap));
1104 EXPECT_TRUE(is_dirty());
1105 EXPECT_TRUE(dirty_info);
1106 EXPECT_TRUE(dirty_big_info);
1107 }
1108
1109 /* +--------------------------+
1110 | log olog |
1111 +--------+-------+---------+
1112 | |object | |
1113 |version | hash | version |
1114 | | | |
1115 tail > (1,1) | x5 | (1,1) < tail
1116 | | | |
1117 | | | |
1118 | (1,4) | x7 | (1,4) < head
1119 | | | |
1120 | | | |
1121 head > (1,5) | x9 | |
1122 | | | |
1123 | | | |
1124 +--------+-------+---------+
1125
1126 The head of the log entry (1,5) is divergent because it is greater than the
1127 head of olog.
1128
1129 */
1130 {
1131 clear();
1132
1133 pg_log_t olog;
1134 pg_info_t oinfo;
1135 pg_shard_t fromosd;
1136 pg_info_t info;
1137 list<hobject_t> remove_snap;
1138 bool dirty_info = false;
1139 bool dirty_big_info = false;
1140
1141 {
1142 pg_log_entry_t e;
1143 e.mark_unrollbackable();
1144
1145 e.version = eversion_t(1, 1);
1146 e.soid.set_hash(0x5);
1147 log.tail = e.version;
1148 log.log.push_back(e);
1149 e.version = eversion_t(1, 4);
1150 e.soid.set_hash(0x7);
1151 log.log.push_back(e);
1152 e.version = eversion_t(1, 5);
1153 e.soid.set_hash(0x9);
1154 log.log.push_back(e);
1155 log.head = e.version;
1156 log.index();
1157
1158 info.last_update = log.head;
1159
1160 e.version = eversion_t(1, 1);
1161 e.soid.set_hash(0x5);
1162 olog.tail = e.version;
1163 olog.log.push_back(e);
1164 e.version = eversion_t(1, 4);
1165 e.soid.set_hash(0x7);
1166 olog.log.push_back(e);
1167 olog.head = e.version;
1168 }
1169
1170 hobject_t last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
1171 info.last_backfill = last_backfill;
1172 eversion_t stat_version(10, 1);
1173 info.stats.version = stat_version;
1174
1175 EXPECT_FALSE(missing.have_missing());
1176 EXPECT_EQ(3U, log.log.size());
1177 EXPECT_EQ(stat_version, info.stats.version);
1178 EXPECT_TRUE(remove_snap.empty());
1179 EXPECT_EQ(last_backfill, info.last_backfill);
1180 EXPECT_TRUE(info.purged_snaps.empty());
1181 EXPECT_FALSE(is_dirty());
1182 EXPECT_FALSE(dirty_info);
1183 EXPECT_FALSE(dirty_big_info);
1184
1185 TestHandler h(remove_snap);
1186 merge_log(oinfo, olog, fromosd, info, &h,
1187 dirty_info, dirty_big_info);
1188
1189 EXPECT_FALSE(missing.have_missing());
1190 EXPECT_EQ(2U, log.log.size());
1191 EXPECT_EQ(stat_version, info.stats.version);
1192 EXPECT_EQ(0x9U, remove_snap.front().get_hash());
1193 EXPECT_TRUE(info.purged_snaps.empty());
1194 EXPECT_TRUE(is_dirty());
1195 EXPECT_TRUE(dirty_info);
1196 EXPECT_TRUE(dirty_big_info);
1197 }
1198
1199 // If our log is empty, the incoming log needs to have not been trimmed.
1200 {
1201 clear();
1202
1203 pg_log_t olog;
1204 pg_info_t oinfo;
1205 pg_shard_t fromosd;
1206 pg_info_t info;
1207 list<hobject_t> remove_snap;
1208 bool dirty_info = false;
1209 bool dirty_big_info = false;
1210
1211 // olog has been trimmed
1212 olog.tail = eversion_t(1, 1);
1213
1214 TestHandler h(remove_snap);
1215 PrCtl unset_dumpable;
1216 ASSERT_DEATH(merge_log(oinfo, olog, fromosd, info, &h,
1217 dirty_info, dirty_big_info), "");
1218 }
1219
1220 }
1221
1222 TEST_F(PGLogTest, proc_replica_log) {
1223 // empty log : no side effect
1224 {
1225 clear();
1226
1227 pg_log_t olog;
1228 pg_info_t oinfo;
1229 pg_missing_t omissing;
1230 pg_shard_t from;
1231
1232 eversion_t last_update(1, 1);
1233 log.head = olog.head = oinfo.last_update = last_update;
1234 eversion_t last_complete(1, 1);
1235 oinfo.last_complete = last_complete;
1236
1237 EXPECT_FALSE(omissing.have_missing());
1238 EXPECT_EQ(last_update, oinfo.last_update);
1239 EXPECT_EQ(last_complete, oinfo.last_complete);
1240
1241 proc_replica_log(oinfo, olog, omissing, from);
1242
1243 EXPECT_FALSE(omissing.have_missing());
1244 EXPECT_EQ(last_update, oinfo.last_update);
1245 EXPECT_EQ(last_update, oinfo.last_complete);
1246 }
1247
1248 /* +--------------------------+
1249 | log olog |
1250 +--------+-------+---------+
1251 | |object | |
1252 |version | hash | version |
1253 | | | |
1254 | | x3 | (1,1) < tail
1255 | | | |
1256 | | | |
1257 tail > (1,2) | x5 | |
1258 | | | |
1259 | | | |
1260 head > (1,3) | x9 | |
1261 | DELETE | | |
1262 | | | |
1263 | | x9 | (2,3) < head
1264 | | | DELETE |
1265 | | | |
1266 +--------+-------+---------+
1267
1268 The log entry (1,3) deletes the object x9 and the olog entry
1269 (2,3) also deletes it : do nothing. The olog tail is ignored
1270 because it is before the log tail.
1271
1272 */
1273 {
1274 clear();
1275
1276 pg_log_t olog;
1277 pg_info_t oinfo;
1278 pg_missing_t omissing;
1279 pg_shard_t from;
1280
1281 {
1282 pg_log_entry_t e;
1283 e.mark_unrollbackable();
1284
1285 e.version = eversion_t(1, 2);
1286 e.soid.set_hash(0x5);
1287 log.tail = e.version;
1288 log.log.push_back(e);
1289 e.version = eversion_t(1, 3);
1290 e.soid.set_hash(0x9);
1291 e.op = pg_log_entry_t::DELETE;
1292 log.log.push_back(e);
1293 log.head = e.version;
1294 log.index();
1295
1296 e.version = eversion_t(1, 1);
1297 e.soid.set_hash(0x3);
1298 olog.tail = e.version;
1299 olog.log.push_back(e);
1300 e.version = eversion_t(2, 3);
1301 e.soid.set_hash(0x9);
1302 e.op = pg_log_entry_t::DELETE;
1303 olog.log.push_back(e);
1304 olog.head = e.version;
1305
1306 oinfo.last_update = olog.head;
1307 oinfo.last_complete = olog.head;
1308 }
1309
1310 EXPECT_FALSE(omissing.have_missing());
1311 EXPECT_EQ(olog.head, oinfo.last_update);
1312 EXPECT_EQ(olog.head, oinfo.last_complete);
1313
1314 proc_replica_log(oinfo, olog, omissing, from);
1315
1316 EXPECT_FALSE(omissing.have_missing());
1317 }
1318
1319 {
1320 clear();
1321
1322 pg_log_t olog;
1323 pg_info_t oinfo;
1324 pg_missing_t omissing;
1325 pg_shard_t from;
1326
1327 hobject_t divergent_object;
1328
1329 {
1330 pg_log_entry_t e;
1331 e.mark_unrollbackable();
1332
1333 {
1334 e.soid = divergent_object;
1335 e.soid.set_hash(0x1);
1336 e.version = eversion_t(1, 1);
1337 log.tail = e.version;
1338 log.log.push_back(e);
1339
1340 e.soid = divergent_object;
1341 e.prior_version = eversion_t(1, 1);
1342 e.version = eversion_t(1, 2);
1343 log.tail = e.version;
1344 log.log.push_back(e);
1345
1346 e.soid.set_hash(0x3);
1347 e.version = eversion_t(1, 4);
1348 log.log.push_back(e);
1349
1350 e.soid.set_hash(0x7);
1351 e.version = eversion_t(1, 5);
1352 log.log.push_back(e);
1353
1354 e.soid.set_hash(0x8);
1355 e.version = eversion_t(1, 6);
1356 log.log.push_back(e);
1357
1358 e.soid.set_hash(0x9);
1359 e.op = pg_log_entry_t::DELETE;
1360 e.version = eversion_t(2, 7);
1361 log.log.push_back(e);
1362
1363 e.soid.set_hash(0xa);
1364 e.version = eversion_t(2, 8);
1365 log.head = e.version;
1366 log.log.push_back(e);
1367 }
1368 log.index();
1369
1370 {
1371 e.soid = divergent_object;
1372 e.soid.set_hash(0x1);
1373 e.version = eversion_t(1, 1);
1374 olog.tail = e.version;
1375 olog.log.push_back(e);
1376
1377 e.soid = divergent_object;
1378 e.prior_version = eversion_t(1, 1);
1379 e.version = eversion_t(1, 2);
1380 olog.log.push_back(e);
1381
1382 e.prior_version = eversion_t(0, 0);
1383 e.soid.set_hash(0x3);
1384 e.version = eversion_t(1, 4);
1385 olog.log.push_back(e);
1386
1387 e.soid.set_hash(0x7);
1388 e.version = eversion_t(1, 5);
1389 olog.log.push_back(e);
1390
1391 e.soid.set_hash(0x8);
1392 e.version = eversion_t(1, 6);
1393 olog.log.push_back(e);
1394
1395 e.soid.set_hash(0x9); // should not be added to missing, create
1396 e.op = pg_log_entry_t::MODIFY;
1397 e.version = eversion_t(1, 7);
1398 olog.log.push_back(e);
1399
1400 e.soid = divergent_object; // should be added to missing at 1,2
1401 e.op = pg_log_entry_t::MODIFY;
1402 e.version = eversion_t(1, 8);
1403 e.prior_version = eversion_t(1, 2);
1404 olog.log.push_back(e);
1405 olog.head = e.version;
1406 }
1407 oinfo.last_update = olog.head;
1408 oinfo.last_complete = olog.head;
1409 }
1410
1411 EXPECT_FALSE(omissing.have_missing());
1412 EXPECT_EQ(olog.head, oinfo.last_update);
1413 EXPECT_EQ(olog.head, oinfo.last_complete);
1414
1415 proc_replica_log(oinfo, olog, omissing, from);
1416
1417 EXPECT_TRUE(omissing.have_missing());
1418 EXPECT_TRUE(omissing.is_missing(divergent_object));
1419 EXPECT_EQ(eversion_t(1, 2), omissing.get_items().at(divergent_object).need);
1420 EXPECT_EQ(eversion_t(1, 6), oinfo.last_update);
1421 EXPECT_EQ(eversion_t(1, 1), oinfo.last_complete);
1422 }
1423
1424 /* +--------------------------+
1425 | olog log |
1426 +--------+-------+---------+
1427 | |object | |
1428 |version | hash | version |
1429 | | | |
1430 tail > (1,1) | x9 | (1,1) < tail
1431 | | | |
1432 | | | |
1433 | (1,2) | x3 | (1,2) |
1434 | | | |
1435 | | | |
1436 head > (1,3) | x9 | |
1437 | DELETE | | |
1438 | | | |
1439 | | x9 | (2,3) < head
1440 | | | DELETE |
1441 | | | |
1442 +--------+-------+---------+
1443
1444 The log entry (1,3) deletes the object x9 and the olog entry
1445 (2,3) also deletes it : do nothing.
1446
1447 */
1448 {
1449 clear();
1450
1451 pg_log_t olog;
1452 pg_info_t oinfo;
1453 pg_missing_t omissing;
1454 pg_shard_t from;
1455
1456 eversion_t last_update(1, 2);
1457 hobject_t divergent_object;
1458 divergent_object.set_hash(0x9);
1459
1460 {
1461 pg_log_entry_t e;
1462 e.mark_unrollbackable();
1463
1464 e.version = eversion_t(1, 1);
1465 e.soid = divergent_object;
1466 log.tail = e.version;
1467 log.log.push_back(e);
1468 e.version = last_update;
1469 e.soid.set_hash(0x3);
1470 log.log.push_back(e);
1471 e.version = eversion_t(2, 3);
1472 e.prior_version = eversion_t(1, 1);
1473 e.soid = divergent_object;
1474 e.op = pg_log_entry_t::DELETE;
1475 log.log.push_back(e);
1476 log.head = e.version;
1477 log.index();
1478
1479 e.version = eversion_t(1, 1);
1480 e.soid = divergent_object;
1481 olog.tail = e.version;
1482 olog.log.push_back(e);
1483 e.version = last_update;
1484 e.soid.set_hash(0x3);
1485 olog.log.push_back(e);
1486 e.version = eversion_t(1, 3);
1487 e.prior_version = eversion_t(1, 1);
1488 e.soid = divergent_object;
1489 e.op = pg_log_entry_t::DELETE;
1490 olog.log.push_back(e);
1491 olog.head = e.version;
1492
1493 oinfo.last_update = olog.head;
1494 oinfo.last_complete = olog.head;
1495 }
1496
1497 EXPECT_FALSE(omissing.have_missing());
1498 EXPECT_EQ(olog.head, oinfo.last_update);
1499 EXPECT_EQ(olog.head, oinfo.last_complete);
1500
1501 proc_replica_log(oinfo, olog, omissing, from);
1502
1503 EXPECT_TRUE(omissing.have_missing());
1504 EXPECT_TRUE(omissing.is_missing(divergent_object));
1505 EXPECT_EQ(omissing.get_items().at(divergent_object).have, eversion_t(0, 0));
1506 EXPECT_EQ(omissing.get_items().at(divergent_object).need, eversion_t(1, 1));
1507 EXPECT_EQ(last_update, oinfo.last_update);
1508 }
1509
1510 /* +--------------------------+
1511 | olog log |
1512 +--------+-------+---------+
1513 | |object | |
1514 |version | hash | version |
1515 | | | |
1516 tail > (1,1) | x9 | (1,1) < tail
1517 | | | |
1518 | | | |
1519 | (1,2) | x3 | (1,2) |
1520 | | | |
1521 | | | |
1522 head > (1,3) | x9 | |
1523 | MODIFY | | |
1524 | | | |
1525 | | x9 | (2,3) < head
1526 | | | DELETE |
1527 | | | |
1528 +--------+-------+---------+
1529
1530 The log entry (1,3) deletes the object x9 but the olog entry
1531 (2,3) modifies it : remove it from omissing.
1532
1533 */
1534 {
1535 clear();
1536
1537 pg_log_t olog;
1538 pg_info_t oinfo;
1539 pg_missing_t omissing;
1540 pg_shard_t from;
1541
1542 eversion_t last_update(1, 2);
1543 hobject_t divergent_object;
1544
1545 {
1546 pg_log_entry_t e;
1547 e.mark_unrollbackable();
1548
1549 e.version = eversion_t(1, 1);
1550 e.soid = divergent_object;
1551 log.tail = e.version;
1552 log.log.push_back(e);
1553 e.version = last_update;
1554 e.soid.set_hash(0x3);
1555 log.log.push_back(e);
1556 e.version = eversion_t(2, 3);
1557 e.prior_version = eversion_t(1, 1);
1558 e.soid = divergent_object;
1559 e.op = pg_log_entry_t::DELETE;
1560 log.log.push_back(e);
1561 log.head = e.version;
1562 log.index();
1563
1564 e.version = eversion_t(1, 1);
1565 e.soid = divergent_object;
1566 olog.tail = e.version;
1567 olog.log.push_back(e);
1568 e.version = last_update;
1569 e.soid.set_hash(0x3);
1570 olog.log.push_back(e);
1571 e.version = eversion_t(1, 3);
1572 e.prior_version = eversion_t(1, 1);
1573 e.soid = divergent_object;
1574 divergent_object = e.soid;
1575 omissing.add(divergent_object, e.version, eversion_t());
1576 e.op = pg_log_entry_t::MODIFY;
1577 olog.log.push_back(e);
1578 olog.head = e.version;
1579
1580 oinfo.last_update = olog.head;
1581 oinfo.last_complete = olog.head;
1582 }
1583
1584 EXPECT_TRUE(omissing.have_missing());
1585 EXPECT_TRUE(omissing.is_missing(divergent_object));
1586 EXPECT_EQ(eversion_t(1, 3), omissing.get_items().at(divergent_object).need);
1587 EXPECT_EQ(olog.head, oinfo.last_update);
1588 EXPECT_EQ(olog.head, oinfo.last_complete);
1589
1590 proc_replica_log(oinfo, olog, omissing, from);
1591
1592 EXPECT_TRUE(omissing.have_missing());
1593 EXPECT_TRUE(omissing.is_missing(divergent_object));
1594 EXPECT_EQ(omissing.get_items().at(divergent_object).have, eversion_t(0, 0));
1595 EXPECT_EQ(omissing.get_items().at(divergent_object).need, eversion_t(1, 1));
1596 EXPECT_EQ(last_update, oinfo.last_update);
1597 }
1598
1599 /* +--------------------------+
1600 | log olog |
1601 +--------+-------+---------+
1602 | |object | |
1603 |version | hash | version |
1604 | | | |
1605 tail > (1,1) | x9 | (1,1) < tail
1606 | | | |
1607 | | | |
1608 | (1,2) | x3 | (1,2) |
1609 | | | |
1610 | | | |
1611 | | x9 | (1,3) < head
1612 | | | MODIFY |
1613 | | | |
1614 head > (2,3) | x9 | |
1615 | DELETE | | |
1616 | | | |
1617 +--------+-------+---------+
1618
1619 The log entry (2,3) deletes the object x9 but the olog entry
1620 (1,3) modifies it : proc_replica_log should adjust missing to
1621 1,1 for that object until add_next_event in PG::activate processes
1622 the delete.
1623 */
1624 {
1625 clear();
1626
1627 pg_log_t olog;
1628 pg_info_t oinfo;
1629 pg_missing_t omissing;
1630 pg_shard_t from;
1631
1632 eversion_t last_update(1, 2);
1633 hobject_t divergent_object;
1634 eversion_t new_version(2, 3);
1635 eversion_t divergent_version(1, 3);
1636
1637 {
1638 pg_log_entry_t e;
1639 e.mark_unrollbackable();
1640
1641 e.version = eversion_t(1, 1);
1642 e.soid.set_hash(0x9);
1643 log.tail = e.version;
1644 log.log.push_back(e);
1645 e.version = last_update;
1646 e.soid.set_hash(0x3);
1647 log.log.push_back(e);
1648 e.version = new_version;
1649 e.prior_version = eversion_t(1, 1);
1650 e.soid.set_hash(0x9);
1651 e.op = pg_log_entry_t::DELETE;
1652 log.log.push_back(e);
1653 log.head = e.version;
1654 log.index();
1655
1656 e.op = pg_log_entry_t::MODIFY;
1657 e.version = eversion_t(1, 1);
1658 e.soid.set_hash(0x9);
1659 olog.tail = e.version;
1660 olog.log.push_back(e);
1661 e.version = last_update;
1662 e.soid.set_hash(0x3);
1663 olog.log.push_back(e);
1664 e.version = divergent_version;
1665 e.prior_version = eversion_t(1, 1);
1666 e.soid.set_hash(0x9);
1667 divergent_object = e.soid;
1668 omissing.add(divergent_object, e.version, eversion_t());
1669 e.op = pg_log_entry_t::MODIFY;
1670 olog.log.push_back(e);
1671 olog.head = e.version;
1672
1673 oinfo.last_update = olog.head;
1674 oinfo.last_complete = olog.head;
1675 }
1676
1677 EXPECT_TRUE(omissing.have_missing());
1678 EXPECT_TRUE(omissing.is_missing(divergent_object));
1679 EXPECT_EQ(divergent_version, omissing.get_items().at(divergent_object).need);
1680 EXPECT_EQ(olog.head, oinfo.last_update);
1681 EXPECT_EQ(olog.head, oinfo.last_complete);
1682
1683 proc_replica_log(oinfo, olog, omissing, from);
1684
1685 EXPECT_TRUE(omissing.have_missing());
1686 EXPECT_TRUE(omissing.get_items().begin()->second.need == eversion_t(1, 1));
1687 EXPECT_EQ(last_update, oinfo.last_update);
1688 EXPECT_EQ(eversion_t(0, 0), oinfo.last_complete);
1689 }
1690
1691 }
1692
1693 TEST_F(PGLogTest, merge_log_1) {
1694 TestCase t;
1695 t.base.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1696
1697 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1698
1699 t.final.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0));
1700
1701 t.toremove.insert(mk_obj(1));
1702
1703 t.setup();
1704 run_test_case(t);
1705 }
1706
1707 TEST_F(PGLogTest, merge_log_2) {
1708 TestCase t;
1709 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1710
1711 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1712 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1713
1714 t.torollback.insert(
1715 t.torollback.begin(), t.div.rbegin(), t.div.rend());
1716
1717 t.setup();
1718 run_test_case(t);
1719 }
1720
1721 TEST_F(PGLogTest, merge_log_3) {
1722 TestCase t;
1723 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1724
1725 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1726 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1727
1728 t.final.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0));
1729
1730 t.toremove.insert(mk_obj(1));
1731
1732 t.setup();
1733 run_test_case(t);
1734 }
1735
1736 TEST_F(PGLogTest, merge_log_4) {
1737 TestCase t;
1738 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1739
1740 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1741 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1742
1743 t.init.add(mk_obj(1), mk_evt(10, 102), mk_evt(0, 0));
1744 t.final.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0));
1745
1746 t.setup();
1747 run_test_case(t);
1748 }
1749
1750 TEST_F(PGLogTest, merge_log_5) {
1751 TestCase t;
1752 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1753
1754 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1755 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1756
1757 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1758
1759 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(0, 0));
1760
1761 t.toremove.insert(mk_obj(1));
1762
1763 t.setup();
1764 run_test_case(t);
1765 }
1766
1767 TEST_F(PGLogTest, merge_log_6) {
1768 TestCase t;
1769 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1770
1771 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1772
1773 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100));
1774
1775 t.setup();
1776 run_test_case(t);
1777 }
1778
1779 TEST_F(PGLogTest, merge_log_7) {
1780 TestCase t;
1781 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1782
1783 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1784
1785 t.init.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80));
1786 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80));
1787
1788 t.setup();
1789 run_test_case(t);
1790 }
1791
1792 TEST_F(PGLogTest, merge_log_8) {
1793 TestCase t;
1794 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1795
1796 t.auth.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1797
1798 t.init.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80));
1799
1800 t.toremove.insert(mk_obj(1));
1801
1802 t.setup();
1803 run_test_case(t);
1804 }
1805
1806 TEST_F(PGLogTest, merge_log_prior_version_have) {
1807 TestCase t;
1808 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1809
1810 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1811
1812 t.init.add(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100));
1813
1814 t.setup();
1815 run_test_case(t);
1816 }
1817
1818 TEST_F(PGLogTest, merge_log_split_missing_entries_at_head) {
1819 TestCase t;
1820 t.auth.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
1821 t.auth.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
1822
1823 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(8, 70), mk_evt(8, 65)));
1824
1825 t.setup();
1826 t.set_div_bounds(mk_evt(9, 79), mk_evt(8, 69));
1827 t.set_auth_bounds(mk_evt(15, 160), mk_evt(9, 77));
1828 t.final.add(mk_obj(1), mk_evt(15, 150), mk_evt(8, 70));
1829 run_test_case(t);
1830 }
1831
1832 TEST_F(PGLogTest, olog_tail_gt_log_tail_split) {
1833 TestCase t;
1834 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
1835 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
1836 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150)));
1837
1838 t.setup();
1839 t.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
1840 t.set_auth_bounds(mk_evt(15, 156), mk_evt(10, 99));
1841 t.final.add(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150));
1842 run_test_case(t);
1843 }
1844
1845 TEST_F(PGLogTest, olog_tail_gt_log_tail_split2) {
1846 TestCase t;
1847 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
1848 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
1849 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(16, 155), mk_evt(15, 150)));
1850 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 153), mk_evt(15, 150)));
1851
1852 t.setup();
1853 t.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
1854 t.set_auth_bounds(mk_evt(16, 156), mk_evt(10, 99));
1855 t.final.add(mk_obj(1), mk_evt(16, 155), mk_evt(0, 0));
1856 t.toremove.insert(mk_obj(1));
1857 run_test_case(t);
1858 }
1859
1860 TEST_F(PGLogTest, filter_log_1) {
1861 {
1862 clear();
1863
1864 int osd_id = 1;
1865 epoch_t epoch = 40;
1866 int64_t pool_id = 0;
1867 int bits = 2;
1868 int max_osd = 4;
1869 int pg_num = max_osd << bits;
1870 int num_objects = 1000;
1871 int num_internal = 10;
1872
1873 // Set up splitting map
1874 OSDMap *osdmap = new OSDMap;
1875 uuid_d test_uuid;
1876 test_uuid.generate_random();
1877 osdmap->build_simple(g_ceph_context, epoch, test_uuid, max_osd, bits, bits);
1878 osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
1879
1880 const string hit_set_namespace("internal");
1881
1882 {
1883 pg_log_entry_t e;
1884 e.mark_unrollbackable();
1885 e.op = pg_log_entry_t::MODIFY;
1886 e.soid.pool = pool_id;
1887
1888 uuid_d uuid_name;
1889 int i;
1890 for (i = 1; i <= num_objects; ++i) {
1891 e.version = eversion_t(epoch, i);
1892 // Use this to generate random file names
1893 uuid_name.generate_random();
1894 ostringstream name;
1895 name << uuid_name;
1896 e.soid.oid.name = name.str();
1897 // First has no namespace
1898 if (i != 1) {
1899 // num_internal have the internal namspace
1900 if (i <= num_internal + 1) {
1901 e.soid.nspace = hit_set_namespace;
1902 } else { // rest have different namespaces
1903 ostringstream ns;
1904 ns << "ns" << i;
1905 e.soid.nspace = ns.str();
1906 }
1907 }
1908 log.log.push_back(e);
1909 if (i == 1)
1910 log.tail = e.version;
1911 }
1912 log.head = e.version;
1913 log.index();
1914 }
1915
1916 spg_t pgid(pg_t(2, pool_id), shard_id_t::NO_SHARD);
1917
1918 // See if we created the right number of entries
1919 int total = log.log.size();
1920 ASSERT_EQ(total, num_objects);
1921
1922 // Some should be removed
1923 {
1924 pg_log_t filtered, reject;
1925 pg_log_t::filter_log(
1926 pgid, *osdmap, hit_set_namespace, log, filtered, reject);
1927 log = IndexedLog(filtered);
1928 }
1929 EXPECT_LE(log.log.size(), (size_t)total);
1930
1931 // If we filter a second time, there should be the same total
1932 total = log.log.size();
1933 {
1934 pg_log_t filtered, reject;
1935 pg_log_t::filter_log(
1936 pgid, *osdmap, hit_set_namespace, log, filtered, reject);
1937 log = IndexedLog(filtered);
1938 }
1939 EXPECT_EQ(log.log.size(), (size_t)total);
1940
1941 // Increase pg_num as if there would be a split
1942 int new_pg_num = pg_num * 16;
1943 OSDMap::Incremental inc(epoch + 1);
1944 inc.fsid = test_uuid;
1945 const pg_pool_t *pool = osdmap->get_pg_pool(pool_id);
1946 pg_pool_t newpool;
1947 newpool = *pool;
1948 newpool.set_pg_num(new_pg_num);
1949 newpool.set_pgp_num(new_pg_num);
1950 inc.new_pools[pool_id] = newpool;
1951 int ret = osdmap->apply_incremental(inc);
1952 ASSERT_EQ(ret, 0);
1953
1954 // We should have fewer entries after a filter
1955 {
1956 pg_log_t filtered, reject;
1957 pg_log_t::filter_log(
1958 pgid, *osdmap, hit_set_namespace, log, filtered, reject);
1959 log = IndexedLog(filtered);
1960 }
1961 EXPECT_LE(log.log.size(), (size_t)total);
1962
1963 // Make sure all internal entries are retained
1964 int count = 0;
1965 for (list<pg_log_entry_t>::iterator i = log.log.begin();
1966 i != log.log.end(); ++i) {
1967 if (i->soid.nspace == hit_set_namespace) count++;
1968 }
1969 EXPECT_EQ(count, num_internal);
1970 }
1971 }
1972
1973 TEST_F(PGLogTest, get_request) {
1974 clear();
1975
1976 // make sure writes, deletes, and errors are found
1977 vector<pg_log_entry_t> entries;
1978 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
1979 entries.push_back(
1980 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(6,2), eversion_t(3,4),
1981 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
1982 utime_t(0,1), -ENOENT));
1983 entries.push_back(
1984 pg_log_entry_t(pg_log_entry_t::MODIFY, oid, eversion_t(6,3), eversion_t(3,4),
1985 2, osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
1986 utime_t(1,2), 0));
1987 entries.push_back(
1988 pg_log_entry_t(pg_log_entry_t::DELETE, oid, eversion_t(7,4), eversion_t(7,4),
1989 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
1990 utime_t(10,2), 0));
1991 entries.push_back(
1992 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(7,5), eversion_t(7,4),
1993 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
1994 utime_t(20,1), -ENOENT));
1995
1996 for (auto &entry : entries) {
1997 log.add(entry);
1998 }
1999
2000 for (auto &entry : entries) {
2001 eversion_t replay_version;
2002 version_t user_version;
2003 int return_code = 0;
2004 bool got = log.get_request(
2005 entry.reqid, &replay_version, &user_version, &return_code);
2006 EXPECT_TRUE(got);
2007 EXPECT_EQ(entry.return_code, return_code);
2008 EXPECT_EQ(entry.version, replay_version);
2009 EXPECT_EQ(entry.user_version, user_version);
2010 }
2011 }
2012
2013 TEST_F(PGLogTest, ErrorNotIndexedByObject) {
2014 clear();
2015
2016 // make sure writes, deletes, and errors are found
2017 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
2018 log.add(
2019 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(6,2), eversion_t(3,4),
2020 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2021 utime_t(0,1), -ENOENT));
2022
2023 EXPECT_FALSE(log.logged_object(oid));
2024
2025 pg_log_entry_t modify(pg_log_entry_t::MODIFY, oid, eversion_t(6,3),
2026 eversion_t(3,4), 2,
2027 osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2028 utime_t(1,2), 0);
2029 log.add(modify);
2030
2031 EXPECT_TRUE(log.logged_object(oid));
2032 pg_log_entry_t *entry = log.objects[oid];
2033 EXPECT_EQ(modify.op, entry->op);
2034 EXPECT_EQ(modify.version, entry->version);
2035 EXPECT_EQ(modify.prior_version, entry->prior_version);
2036 EXPECT_EQ(modify.user_version, entry->user_version);
2037 EXPECT_EQ(modify.reqid, entry->reqid);
2038
2039 pg_log_entry_t del(pg_log_entry_t::DELETE, oid, eversion_t(7,4),
2040 eversion_t(7,4), 3,
2041 osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2042 utime_t(10,2), 0);
2043 log.add(del);
2044
2045 EXPECT_TRUE(log.logged_object(oid));
2046 entry = log.objects[oid];
2047 EXPECT_EQ(del.op, entry->op);
2048 EXPECT_EQ(del.version, entry->version);
2049 EXPECT_EQ(del.prior_version, entry->prior_version);
2050 EXPECT_EQ(del.user_version, entry->user_version);
2051 EXPECT_EQ(del.reqid, entry->reqid);
2052
2053 log.add(
2054 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(7,5), eversion_t(7,4),
2055 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2056 utime_t(20,1), -ENOENT));
2057
2058 EXPECT_TRUE(log.logged_object(oid));
2059 entry = log.objects[oid];
2060 EXPECT_EQ(del.op, entry->op);
2061 EXPECT_EQ(del.version, entry->version);
2062 EXPECT_EQ(del.prior_version, entry->prior_version);
2063 EXPECT_EQ(del.user_version, entry->user_version);
2064 EXPECT_EQ(del.reqid, entry->reqid);
2065 }
2066
2067 // Local Variables:
2068 // compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "
2069 // End: