1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
8 * Author: Loic Dachary <loic@dachary.org>
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)
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.
24 #include "gtest/gtest.h"
25 #include "osd/PGLog.h"
26 #include "osd/OSDMap.h"
27 #include "include/coredumpctl.h"
28 #include "../objectstore/store_test_fixture.h"
31 struct PGLogTestBase
{
32 static hobject_t
mk_obj(unsigned id
) {
41 static eversion_t
mk_evt(unsigned ep
, unsigned v
) {
42 return eversion_t(ep
, v
);
44 static pg_log_entry_t
mk_ple_mod(
45 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
, osd_reqid_t reqid
) {
47 e
.mark_unrollbackable();
48 e
.op
= pg_log_entry_t::MODIFY
;
55 static pg_log_entry_t
mk_ple_dt(
56 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
, osd_reqid_t reqid
) {
58 e
.mark_unrollbackable();
59 e
.op
= pg_log_entry_t::DELETE
;
66 static pg_log_entry_t
mk_ple_ldt(
67 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
69 e
.mark_unrollbackable();
70 e
.op
= pg_log_entry_t::LOST_DELETE
;
76 static pg_log_entry_t
mk_ple_mod_rb(
77 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
, osd_reqid_t reqid
) {
79 e
.op
= pg_log_entry_t::MODIFY
;
86 static pg_log_entry_t
mk_ple_dt_rb(
87 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
, osd_reqid_t reqid
) {
89 e
.op
= pg_log_entry_t::DELETE
;
96 static pg_log_entry_t
mk_ple_mod(
97 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
98 return mk_ple_mod(hoid
, v
, pv
, osd_reqid_t());
100 static pg_log_entry_t
mk_ple_dt(
101 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
102 return mk_ple_dt(hoid
, v
, pv
, osd_reqid_t());
104 static pg_log_entry_t
mk_ple_mod_rb(
105 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
106 return mk_ple_mod_rb(hoid
, v
, pv
, osd_reqid_t());
108 static pg_log_entry_t
mk_ple_dt_rb(
109 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
110 return mk_ple_dt_rb(hoid
, v
, pv
, osd_reqid_t());
115 class PGLogTest
: virtual public ::testing::Test
, protected PGLog
, public PGLogTestBase
{
117 PGLogTest() : PGLog(g_ceph_context
) {}
118 void SetUp() override
{
119 missing
.may_include_deletes
= true;
122 #include "common/ceph_context.h"
123 #include "common/config.h"
125 void TearDown() override
{
131 list
<pg_log_entry_t
> base
;
132 list
<pg_log_entry_t
> auth
;
133 list
<pg_log_entry_t
> div
;
138 set
<hobject_t
> toremove
;
139 list
<pg_log_entry_t
> torollback
;
140 bool deletes_during_peering
;
148 TestCase() : deletes_during_peering(false) {}
150 init
.may_include_deletes
= !deletes_during_peering
;
151 final
.may_include_deletes
= !deletes_during_peering
;
152 fullauth
.log
.insert(fullauth
.log
.end(), base
.begin(), base
.end());
153 fullauth
.log
.insert(fullauth
.log
.end(), auth
.begin(), auth
.end());
154 fulldiv
.log
.insert(fulldiv
.log
.end(), base
.begin(), base
.end());
155 fulldiv
.log
.insert(fulldiv
.log
.end(), div
.begin(), div
.end());
157 fullauth
.head
= authinfo
.last_update
= fullauth
.log
.rbegin()->version
;
158 authinfo
.last_complete
= fullauth
.log
.rbegin()->version
;
159 authinfo
.log_tail
= fullauth
.log
.begin()->version
;
160 authinfo
.log_tail
.version
--;
161 fullauth
.tail
= authinfo
.log_tail
;
162 authinfo
.last_backfill
= hobject_t::get_max();
164 fulldiv
.head
= divinfo
.last_update
= fulldiv
.log
.rbegin()->version
;
165 divinfo
.last_complete
= eversion_t();
166 divinfo
.log_tail
= fulldiv
.log
.begin()->version
;
167 divinfo
.log_tail
.version
--;
168 fulldiv
.tail
= divinfo
.log_tail
;
169 divinfo
.last_backfill
= hobject_t::get_max();
171 if (init
.get_items().empty()) {
172 divinfo
.last_complete
= divinfo
.last_update
;
174 eversion_t fmissing
= init
.get_items().at(init
.get_rmissing().begin()->second
).need
;
175 for (list
<pg_log_entry_t
>::const_iterator i
= fulldiv
.log
.begin();
176 i
!= fulldiv
.log
.end();
178 if (i
->version
< fmissing
)
179 divinfo
.last_complete
= i
->version
;
188 void set_div_bounds(eversion_t head
, eversion_t tail
) {
189 fulldiv
.tail
= divinfo
.log_tail
= tail
;
190 fulldiv
.head
= divinfo
.last_update
= head
;
192 void set_auth_bounds(eversion_t head
, eversion_t tail
) {
193 fullauth
.tail
= authinfo
.log_tail
= tail
;
194 fullauth
.head
= authinfo
.last_update
= head
;
196 const IndexedLog
&get_fullauth() const { return fullauth
; }
197 const IndexedLog
&get_fulldiv() const { return fulldiv
; }
198 const pg_info_t
&get_authinfo() const { return authinfo
; }
199 const pg_info_t
&get_divinfo() const { return divinfo
; }
200 }; // struct TestCase
202 struct LogHandler
: public PGLog::LogEntryHandler
{
203 set
<hobject_t
> removed
;
204 list
<pg_log_entry_t
> rolledback
;
207 const pg_log_entry_t
&entry
) override
{
208 rolledback
.push_back(entry
);
211 const pg_log_entry_t
&entry
) override
{}
213 const hobject_t
&hoid
) override
{
214 removed
.insert(hoid
);
216 void try_stash(const hobject_t
&, version_t
) override
{
217 // lost/unfound cases are not tested yet
220 const pg_log_entry_t
&entry
) override
{}
223 template <typename missing_t
>
225 const TestCase
&tcase
,
226 const missing_t
&missing
) {
227 ASSERT_EQ(tcase
.final
.get_items().size(), missing
.get_items().size());
228 for (auto i
= missing
.get_items().begin();
229 i
!= missing
.get_items().end();
231 EXPECT_TRUE(tcase
.final
.get_items().count(i
->first
));
232 EXPECT_EQ(tcase
.final
.get_items().find(i
->first
)->second
.need
, i
->second
.need
);
233 EXPECT_EQ(tcase
.final
.get_items().find(i
->first
)->second
.have
, i
->second
.have
);
235 bool correct
= missing
.debug_verify_from_init(tcase
.init
, &(std::cout
));
236 ASSERT_TRUE(correct
);
239 void verify_sideeffects(
240 const TestCase
&tcase
,
241 const LogHandler
&handler
) {
242 ASSERT_EQ(tcase
.toremove
.size(), handler
.removed
.size());
243 ASSERT_EQ(tcase
.torollback
.size(), handler
.rolledback
.size());
246 list
<pg_log_entry_t
>::const_iterator titer
= tcase
.torollback
.begin();
247 list
<pg_log_entry_t
>::const_iterator hiter
= handler
.rolledback
.begin();
248 for (; titer
!= tcase
.torollback
.end(); ++titer
, ++hiter
) {
249 EXPECT_EQ(titer
->version
, hiter
->version
);
254 set
<hobject_t
>::const_iterator titer
= tcase
.toremove
.begin();
255 set
<hobject_t
>::const_iterator hiter
= handler
.removed
.begin();
256 for (; titer
!= tcase
.toremove
.end(); ++titer
, ++hiter
) {
257 EXPECT_EQ(*titer
, *hiter
);
262 void test_merge_log(const TestCase
&tcase
) {
264 log
= tcase
.get_fulldiv();
265 pg_info_t info
= tcase
.get_divinfo();
267 missing
= tcase
.init
;
271 olog
= tcase
.get_fullauth();
272 pg_info_t oinfo
= tcase
.get_authinfo();
275 bool dirty_info
= false;
276 bool dirty_big_info
= false;
278 oinfo
, olog
, pg_shard_t(1, shard_id_t(0)), info
,
279 &h
, dirty_info
, dirty_big_info
);
281 ASSERT_EQ(info
.last_update
, oinfo
.last_update
);
282 verify_missing(tcase
, missing
);
283 verify_sideeffects(tcase
, h
);
286 void test_proc_replica_log(const TestCase
&tcase
) {
288 log
= tcase
.get_fullauth();
289 pg_info_t info
= tcase
.get_authinfo();
291 pg_missing_t omissing
= tcase
.init
;
294 olog
= tcase
.get_fulldiv();
295 pg_info_t oinfo
= tcase
.get_divinfo();
298 oinfo
, olog
, omissing
, pg_shard_t(1, shard_id_t(0)));
300 assert(oinfo
.last_update
>= log
.tail
);
302 if (!tcase
.base
.empty()) {
303 ASSERT_EQ(tcase
.base
.rbegin()->version
, oinfo
.last_update
);
306 for (list
<pg_log_entry_t
>::const_iterator i
= tcase
.auth
.begin();
307 i
!= tcase
.auth
.end();
309 if (i
->version
> oinfo
.last_update
) {
310 if (i
->is_delete() && tcase
.deletes_during_peering
) {
311 omissing
.rm(i
->soid
, i
->version
);
313 omissing
.add_next_event(*i
);
317 verify_missing(tcase
, omissing
);
318 } // test_proc_replica_log
320 void run_test_case(const TestCase
&tcase
) {
321 test_merge_log(tcase
);
322 test_proc_replica_log(tcase
);
324 }; // class PGLogTest
326 struct TestHandler
: public PGLog::LogEntryHandler
{
327 list
<hobject_t
> &removed
;
328 explicit TestHandler(list
<hobject_t
> &removed
) : removed(removed
) {}
331 const pg_log_entry_t
&entry
) override
{}
333 const pg_log_entry_t
&entry
) override
{}
335 const hobject_t
&hoid
) override
{
336 removed
.push_back(hoid
);
338 void cant_rollback(const pg_log_entry_t
&entry
) {}
339 void try_stash(const hobject_t
&, version_t
) override
{
340 // lost/unfound cases are not tested yet
343 const pg_log_entry_t
&entry
) override
{}
346 TEST_F(PGLogTest
, rewind_divergent_log
) {
347 /* +----------------+
356 | (1,4) | x9 < newhead
369 list
<hobject_t
> remove_snap
;
370 bool dirty_info
= false;
371 bool dirty_big_info
= false;
373 hobject_t divergent_object
;
374 eversion_t divergent_version
;
378 divergent
.set_hash(0x9);
382 e
.mark_unrollbackable();
384 e
.version
= eversion_t(1, 1);
385 e
.soid
.set_hash(0x5);
386 log
.tail
= e
.version
;
387 log
.log
.push_back(e
);
388 e
.version
= newhead
= eversion_t(1, 4);
390 e
.op
= pg_log_entry_t::MODIFY
;
391 log
.log
.push_back(e
);
392 e
.version
= divergent_version
= eversion_t(1, 5);
393 e
.prior_version
= eversion_t(1, 4);
395 divergent_object
= e
.soid
;
396 e
.op
= pg_log_entry_t::DELETE
;
397 log
.log
.push_back(e
);
398 log
.head
= e
.version
;
401 info
.last_update
= log
.head
;
402 info
.last_complete
= log
.head
;
405 EXPECT_FALSE(missing
.have_missing());
406 EXPECT_EQ(3U, log
.log
.size());
407 EXPECT_TRUE(remove_snap
.empty());
408 EXPECT_EQ(log
.head
, info
.last_update
);
409 EXPECT_EQ(log
.head
, info
.last_complete
);
410 EXPECT_FALSE(is_dirty());
411 EXPECT_FALSE(dirty_info
);
412 EXPECT_FALSE(dirty_big_info
);
414 TestHandler
h(remove_snap
);
415 rewind_divergent_log(newhead
, info
, &h
,
416 dirty_info
, dirty_big_info
);
418 EXPECT_TRUE(log
.objects
.count(divergent
));
419 EXPECT_TRUE(missing
.is_missing(divergent_object
));
420 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
421 EXPECT_EQ(2U, log
.log
.size());
422 EXPECT_TRUE(remove_snap
.empty());
423 EXPECT_EQ(newhead
, info
.last_update
);
424 EXPECT_EQ(newhead
, info
.last_complete
);
425 EXPECT_TRUE(is_dirty());
426 EXPECT_TRUE(dirty_info
);
427 EXPECT_TRUE(dirty_big_info
);
430 /* +----------------+
436 tail > (1,1) | NULL |
438 | (1,4) | NULL < newhead
449 list
<hobject_t
> remove_snap
;
450 bool dirty_info
= false;
451 bool dirty_big_info
= false;
453 hobject_t divergent_object
;
454 eversion_t divergent_version
;
455 eversion_t prior_version
;
459 e
.mark_unrollbackable();
461 info
.log_tail
= log
.tail
= eversion_t(1, 1);
462 newhead
= eversion_t(1, 3);
463 e
.version
= divergent_version
= eversion_t(1, 5);
464 e
.soid
.set_hash(0x9);
465 divergent_object
= e
.soid
;
466 e
.op
= pg_log_entry_t::DELETE
;
467 e
.prior_version
= prior_version
= eversion_t(0, 2);
468 log
.log
.push_back(e
);
469 log
.head
= e
.version
;
472 EXPECT_FALSE(missing
.have_missing());
473 EXPECT_EQ(1U, log
.log
.size());
474 EXPECT_TRUE(remove_snap
.empty());
475 EXPECT_FALSE(is_dirty());
476 EXPECT_FALSE(dirty_info
);
477 EXPECT_FALSE(dirty_big_info
);
479 TestHandler
h(remove_snap
);
480 rewind_divergent_log(newhead
, info
, &h
,
481 dirty_info
, dirty_big_info
);
483 EXPECT_TRUE(missing
.is_missing(divergent_object
));
484 EXPECT_EQ(0U, log
.objects
.count(divergent_object
));
485 EXPECT_TRUE(log
.empty());
486 EXPECT_TRUE(remove_snap
.empty());
487 EXPECT_TRUE(is_dirty());
488 EXPECT_TRUE(dirty_info
);
489 EXPECT_TRUE(dirty_big_info
);
496 list
<hobject_t
> remove_snap
;
498 info
.log_tail
= log
.tail
= eversion_t(1, 5);
499 info
.last_update
= eversion_t(1, 6);
500 bool dirty_info
= false;
501 bool dirty_big_info
= false;
505 e
.mark_unrollbackable();
506 e
.version
= eversion_t(1, 5);
507 e
.soid
.set_hash(0x9);
512 e
.mark_unrollbackable();
513 e
.version
= eversion_t(1, 6);
514 e
.soid
.set_hash(0x10);
517 TestHandler
h(remove_snap
);
518 roll_forward_to(eversion_t(1, 6), &h
);
519 rewind_divergent_log(eversion_t(1, 5), info
, &h
,
520 dirty_info
, dirty_big_info
);
522 reset_backfill_claim_log(log
, &h
);
526 TEST_F(PGLogTest
, merge_old_entry
) {
527 // entries > last_backfill are silently ignored
531 ObjectStore::Transaction t
;
533 oe
.mark_unrollbackable();
535 list
<hobject_t
> remove_snap
;
537 info
.last_backfill
= hobject_t();
538 info
.last_backfill
.set_hash(100);
540 ASSERT_GT(oe
.soid
, info
.last_backfill
);
542 EXPECT_FALSE(is_dirty());
543 EXPECT_TRUE(remove_snap
.empty());
544 EXPECT_TRUE(t
.empty());
545 EXPECT_FALSE(missing
.have_missing());
546 EXPECT_TRUE(log
.empty());
548 TestHandler
h(remove_snap
);
549 merge_old_entry(t
, oe
, info
, &h
);
551 EXPECT_FALSE(is_dirty());
552 EXPECT_TRUE(remove_snap
.empty());
553 EXPECT_TRUE(t
.empty());
554 EXPECT_FALSE(missing
.have_missing());
555 EXPECT_TRUE(log
.empty());
558 // the new entry (from the logs) has a version that is higher than
559 // the old entry (from the log entry given in argument) : do
560 // nothing and return false
564 ObjectStore::Transaction t
;
566 list
<hobject_t
> remove_snap
;
569 ne
.mark_unrollbackable();
570 ne
.version
= eversion_t(2,1);
573 EXPECT_FALSE(is_dirty());
574 EXPECT_TRUE(remove_snap
.empty());
575 EXPECT_TRUE(t
.empty());
576 EXPECT_FALSE(missing
.have_missing());
577 EXPECT_EQ(1U, log
.log
.size());
578 EXPECT_EQ(ne
.version
, log
.log
.front().version
);
580 // the newer entry ( from the logs ) can be DELETE
582 log
.log
.front().op
= pg_log_entry_t::DELETE
;
584 oe
.mark_unrollbackable();
585 oe
.version
= eversion_t(1,1);
587 TestHandler
h(remove_snap
);
588 merge_old_entry(t
, oe
, info
, &h
);
591 // if the newer entry is not DELETE, the object must be in missing
593 pg_log_entry_t
&ne
= log
.log
.front();
594 ne
.op
= pg_log_entry_t::MODIFY
;
595 missing
.add_next_event(ne
);
597 oe
.mark_unrollbackable();
598 oe
.version
= eversion_t(1,1);
600 TestHandler
h(remove_snap
);
601 merge_old_entry(t
, oe
, info
, &h
);
603 missing
.rm(ne
.soid
, ne
.version
);
607 EXPECT_FALSE(is_dirty());
608 EXPECT_FALSE(remove_snap
.empty());
609 EXPECT_TRUE(t
.empty());
610 EXPECT_FALSE(missing
.have_missing());
611 EXPECT_EQ(1U, log
.log
.size());
612 EXPECT_EQ(ne
.version
, log
.log
.front().version
);
616 // the new entry (from the logs) has a version that is lower than
617 // the old entry (from the log entry given in argument) and
618 // old and new are delete : do nothing and return false
622 ObjectStore::Transaction t
;
624 oe
.mark_unrollbackable();
626 list
<hobject_t
> remove_snap
;
629 ne
.mark_unrollbackable();
630 ne
.version
= eversion_t(1,1);
631 ne
.op
= pg_log_entry_t::DELETE
;
634 oe
.version
= eversion_t(2,1);
635 oe
.op
= pg_log_entry_t::DELETE
;
637 EXPECT_FALSE(is_dirty());
638 EXPECT_TRUE(remove_snap
.empty());
639 EXPECT_TRUE(t
.empty());
640 EXPECT_FALSE(missing
.have_missing());
641 EXPECT_EQ(1U, log
.log
.size());
643 TestHandler
h(remove_snap
);
644 merge_old_entry(t
, oe
, info
, &h
);
646 EXPECT_FALSE(is_dirty());
647 EXPECT_TRUE(remove_snap
.empty());
648 EXPECT_TRUE(t
.empty());
649 EXPECT_FALSE(missing
.have_missing());
650 EXPECT_EQ(1U, log
.log
.size());
653 // the new entry (from the logs) has a version that is lower than
654 // the old entry (from the log entry given in argument) and
655 // old is update and new is DELETE :
656 // if the object is in missing, it is removed
660 ObjectStore::Transaction t
;
662 oe
.mark_unrollbackable();
664 list
<hobject_t
> remove_snap
;
667 ne
.mark_unrollbackable();
668 ne
.version
= eversion_t(1,1);
669 ne
.op
= pg_log_entry_t::DELETE
;
672 oe
.version
= eversion_t(2,1);
673 oe
.op
= pg_log_entry_t::MODIFY
;
674 missing
.add_next_event(oe
);
677 EXPECT_FALSE(is_dirty());
678 EXPECT_TRUE(remove_snap
.empty());
679 EXPECT_TRUE(t
.empty());
680 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
681 EXPECT_EQ(1U, log
.log
.size());
683 TestHandler
h(remove_snap
);
684 merge_old_entry(t
, oe
, info
, &h
);
687 EXPECT_FALSE(is_dirty());
688 EXPECT_TRUE(remove_snap
.size() > 0);
689 EXPECT_TRUE(t
.empty());
690 EXPECT_FALSE(missing
.have_missing());
691 EXPECT_EQ(1U, log
.log
.size());
694 // there is no new entry (from the logs) and
695 // the old entry (from the log entry given in argument) is not a CLONE and
696 // the old entry prior_version is greater than the tail of the log :
697 // do nothing and return false
701 ObjectStore::Transaction t
;
703 oe
.mark_unrollbackable();
705 list
<hobject_t
> remove_snap
;
707 info
.log_tail
= eversion_t(1,1);
708 oe
.op
= pg_log_entry_t::MODIFY
;
709 oe
.prior_version
= eversion_t(2,1);
710 missing_add(oe
.soid
, oe
.prior_version
, eversion_t());
713 EXPECT_FALSE(is_dirty());
714 EXPECT_TRUE(remove_snap
.empty());
715 EXPECT_TRUE(t
.empty());
716 EXPECT_TRUE(log
.empty());
718 TestHandler
h(remove_snap
);
719 merge_old_entry(t
, oe
, info
, &h
);
722 EXPECT_FALSE(is_dirty());
723 EXPECT_TRUE(remove_snap
.empty());
724 EXPECT_TRUE(t
.empty());
725 EXPECT_TRUE(log
.empty());
728 // there is no new entry (from the logs) and
729 // the old entry (from the log entry given in argument) is not a CLONE and
730 // the old entry (from the log entry given in argument) is not a DELETE and
731 // the old entry prior_version is lower than the tail of the log :
732 // add the old object to the remove_snap list and
733 // add the old object to divergent priors and
734 // add or update the prior_version of the object to missing and
739 ObjectStore::Transaction t
;
741 oe
.mark_unrollbackable();
743 list
<hobject_t
> remove_snap
;
745 info
.log_tail
= eversion_t(2,1);
747 oe
.op
= pg_log_entry_t::MODIFY
;
748 oe
.prior_version
= eversion_t(1,1);
750 EXPECT_FALSE(is_dirty());
751 EXPECT_TRUE(remove_snap
.empty());
752 EXPECT_TRUE(t
.empty());
753 EXPECT_FALSE(missing
.have_missing());
754 EXPECT_TRUE(log
.empty());
756 TestHandler
h(remove_snap
);
757 merge_old_entry(t
, oe
, info
, &h
);
759 EXPECT_TRUE(is_dirty());
760 EXPECT_EQ(oe
.soid
, remove_snap
.front());
761 EXPECT_TRUE(t
.empty());
762 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
763 EXPECT_TRUE(log
.empty());
766 // there is no new entry (from the logs) and
767 // the old entry (from the log entry given in argument) is not a CLONE and
768 // the old entry (from the log entry given in argument) is a DELETE and
769 // the old entry prior_version is lower than the tail of the log :
770 // add the old object to divergent priors and
771 // add or update the prior_version of the object to missing and
776 ObjectStore::Transaction t
;
778 oe
.mark_unrollbackable();
780 list
<hobject_t
> remove_snap
;
782 info
.log_tail
= eversion_t(2,1);
784 oe
.op
= pg_log_entry_t::DELETE
;
785 oe
.prior_version
= eversion_t(1,1);
787 EXPECT_FALSE(is_dirty());
788 EXPECT_TRUE(remove_snap
.empty());
789 EXPECT_TRUE(t
.empty());
790 EXPECT_FALSE(missing
.have_missing());
791 EXPECT_TRUE(log
.empty());
793 TestHandler
h(remove_snap
);
794 merge_old_entry(t
, oe
, info
, &h
);
796 EXPECT_TRUE(is_dirty());
797 EXPECT_TRUE(remove_snap
.empty());
798 EXPECT_TRUE(t
.empty());
799 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
800 EXPECT_TRUE(log
.empty());
804 // there is no new entry (from the logs) and
805 // the old entry (from the log entry given in argument) is not a CLONE and
806 // the old entry (from the log entry given in argument) is not a DELETE and
807 // the old entry prior_version is eversion_t() :
808 // add the old object to the remove_snap list and
809 // remove the prior_version of the object from missing, if any and
814 ObjectStore::Transaction t
;
816 oe
.mark_unrollbackable();
818 list
<hobject_t
> remove_snap
;
820 info
.log_tail
= eversion_t(10,1);
822 oe
.op
= pg_log_entry_t::MODIFY
;
823 oe
.prior_version
= eversion_t();
825 missing
.add(oe
.soid
, eversion_t(1,1), eversion_t(), false);
828 EXPECT_FALSE(is_dirty());
829 EXPECT_TRUE(remove_snap
.empty());
830 EXPECT_TRUE(t
.empty());
831 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
832 EXPECT_TRUE(log
.empty());
834 TestHandler
h(remove_snap
);
835 merge_old_entry(t
, oe
, info
, &h
);
838 EXPECT_FALSE(is_dirty());
839 EXPECT_EQ(oe
.soid
, remove_snap
.front());
840 EXPECT_TRUE(t
.empty());
841 EXPECT_FALSE(missing
.have_missing());
842 EXPECT_TRUE(log
.empty());
847 TEST_F(PGLogTest
, merge_log
) {
848 // head and tail match, last_backfill is set:
857 list
<hobject_t
> remove_snap
;
858 bool dirty_info
= false;
859 bool dirty_big_info
= false;
861 hobject_t
last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
862 info
.last_backfill
= last_backfill
;
863 eversion_t
stat_version(10, 1);
864 info
.stats
.version
= stat_version
;
865 log
.tail
= olog
.tail
= eversion_t(1, 1);
866 log
.head
= olog
.head
= eversion_t(2, 1);
868 EXPECT_FALSE(missing
.have_missing());
869 EXPECT_EQ(0U, log
.log
.size());
870 EXPECT_EQ(stat_version
, info
.stats
.version
);
871 EXPECT_TRUE(remove_snap
.empty());
872 EXPECT_EQ(last_backfill
, info
.last_backfill
);
873 EXPECT_TRUE(info
.purged_snaps
.empty());
874 EXPECT_FALSE(is_dirty());
875 EXPECT_FALSE(dirty_info
);
876 EXPECT_FALSE(dirty_big_info
);
878 TestHandler
h(remove_snap
);
879 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
880 dirty_info
, dirty_big_info
);
882 EXPECT_FALSE(missing
.have_missing());
883 EXPECT_EQ(0U, log
.log
.size());
884 EXPECT_EQ(stat_version
, info
.stats
.version
);
885 EXPECT_TRUE(remove_snap
.empty());
886 EXPECT_TRUE(info
.purged_snaps
.empty());
887 EXPECT_FALSE(is_dirty());
888 EXPECT_FALSE(dirty_info
);
889 EXPECT_FALSE(dirty_big_info
);
892 // head and tail match, last_backfill is not set: info.stats is
893 // copied from oinfo.stats but info.stats.reported_* is guaranteed to
894 // never be replaced by a lower version
902 list
<hobject_t
> remove_snap
;
903 bool dirty_info
= false;
904 bool dirty_big_info
= false;
906 eversion_t
stat_version(10, 1);
907 oinfo
.stats
.version
= stat_version
;
908 info
.stats
.reported_seq
= 1;
909 info
.stats
.reported_epoch
= 10;
910 oinfo
.stats
.reported_seq
= 1;
911 oinfo
.stats
.reported_epoch
= 1;
912 log
.tail
= olog
.tail
= eversion_t(1, 1);
913 log
.head
= olog
.head
= eversion_t(2, 1);
914 missing
.may_include_deletes
= false;
916 EXPECT_FALSE(missing
.have_missing());
917 EXPECT_EQ(0U, log
.log
.size());
918 EXPECT_EQ(eversion_t(), info
.stats
.version
);
919 EXPECT_EQ(1ull, info
.stats
.reported_seq
);
920 EXPECT_EQ(10u, info
.stats
.reported_epoch
);
921 EXPECT_TRUE(remove_snap
.empty());
922 EXPECT_TRUE(info
.last_backfill
.is_max());
923 EXPECT_TRUE(info
.purged_snaps
.empty());
924 EXPECT_FALSE(is_dirty());
925 EXPECT_FALSE(dirty_info
);
926 EXPECT_FALSE(dirty_big_info
);
928 TestHandler
h(remove_snap
);
929 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
930 dirty_info
, dirty_big_info
);
932 EXPECT_FALSE(missing
.have_missing());
933 EXPECT_EQ(0U, log
.log
.size());
934 EXPECT_EQ(stat_version
, info
.stats
.version
);
935 EXPECT_EQ(1ull, info
.stats
.reported_seq
);
936 EXPECT_EQ(10u, info
.stats
.reported_epoch
);
937 EXPECT_TRUE(remove_snap
.empty());
938 EXPECT_TRUE(info
.purged_snaps
.empty());
939 EXPECT_FALSE(is_dirty());
940 EXPECT_FALSE(dirty_info
);
941 EXPECT_FALSE(dirty_big_info
);
945 +--------------------------+
947 +--------+-------+---------+
949 |version | hash | version |
951 | | x5 | (1,1) < tail
954 tail > (1,4) | x7 | |
957 head > (1,5) | x9 | (1,5) < head
960 +--------+-------+---------+
987 list
<hobject_t
> remove_snap
;
988 bool dirty_info
= false;
989 bool dirty_big_info
= false;
990 missing
.may_include_deletes
= false;
994 e
.mark_unrollbackable();
996 e
.version
= eversion_t(1, 4);
997 e
.soid
.set_hash(0x5);
998 log
.tail
= e
.version
;
999 log
.log
.push_back(e
);
1000 e
.version
= eversion_t(1, 5);
1001 e
.soid
.set_hash(0x9);
1002 log
.log
.push_back(e
);
1003 log
.head
= e
.version
;
1006 info
.last_update
= log
.head
;
1008 e
.version
= eversion_t(1, 1);
1009 e
.soid
.set_hash(0x5);
1010 olog
.tail
= e
.version
;
1011 olog
.log
.push_back(e
);
1012 e
.version
= eversion_t(1, 5);
1013 e
.soid
.set_hash(0x9);
1014 olog
.log
.push_back(e
);
1015 olog
.head
= e
.version
;
1018 hobject_t
last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
1019 info
.last_backfill
= last_backfill
;
1020 eversion_t
stat_version(10, 1);
1021 info
.stats
.version
= stat_version
;
1023 EXPECT_FALSE(missing
.have_missing());
1024 EXPECT_EQ(2U, log
.log
.size());
1025 EXPECT_EQ(stat_version
, info
.stats
.version
);
1026 EXPECT_TRUE(remove_snap
.empty());
1027 EXPECT_EQ(last_backfill
, info
.last_backfill
);
1028 EXPECT_TRUE(info
.purged_snaps
.empty());
1029 EXPECT_FALSE(is_dirty());
1030 EXPECT_FALSE(dirty_info
);
1031 EXPECT_FALSE(dirty_big_info
);
1033 TestHandler
h(remove_snap
);
1034 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1035 dirty_info
, dirty_big_info
);
1037 EXPECT_FALSE(missing
.have_missing());
1038 EXPECT_EQ(3U, log
.log
.size());
1039 EXPECT_EQ(stat_version
, info
.stats
.version
);
1040 EXPECT_TRUE(remove_snap
.empty());
1041 EXPECT_TRUE(info
.purged_snaps
.empty());
1042 EXPECT_TRUE(is_dirty());
1043 EXPECT_TRUE(dirty_info
);
1044 EXPECT_TRUE(dirty_big_info
);
1047 /* +--------------------------+
1049 +--------+-------+---------+
1051 |version | hash | version |
1053 tail > (1,1) | x5 | (1,1) < tail
1056 | (1,2) | x3 | (1,2) < lower_bound
1059 head > (1,3) | x9 | |
1065 | | x7 | (2,4) < head
1067 +--------+-------+---------+
1069 The log entry (1,3) deletes the object x9 but the olog entry (2,3) modifies
1070 it and is authoritative : the log entry (1,3) is divergent.
1080 list
<hobject_t
> remove_snap
;
1081 bool dirty_info
= false;
1082 bool dirty_big_info
= false;
1084 hobject_t divergent_object
;
1085 missing
.may_include_deletes
= true;
1089 e
.mark_unrollbackable();
1091 e
.version
= eversion_t(1, 1);
1092 e
.soid
.set_hash(0x5);
1093 log
.tail
= e
.version
;
1094 log
.log
.push_back(e
);
1095 e
.version
= eversion_t(1, 2);
1096 e
.soid
.set_hash(0x3);
1097 log
.log
.push_back(e
);
1098 e
.version
= eversion_t(1,3);
1099 e
.soid
.set_hash(0x9);
1100 divergent_object
= e
.soid
;
1101 e
.op
= pg_log_entry_t::DELETE
;
1102 log
.log
.push_back(e
);
1103 log
.head
= e
.version
;
1106 info
.last_update
= log
.head
;
1108 e
.version
= eversion_t(1, 1);
1109 e
.soid
.set_hash(0x5);
1110 olog
.tail
= e
.version
;
1111 olog
.log
.push_back(e
);
1112 e
.version
= eversion_t(1, 2);
1113 e
.soid
.set_hash(0x3);
1114 olog
.log
.push_back(e
);
1115 e
.version
= eversion_t(2, 3);
1116 e
.soid
.set_hash(0x9);
1117 e
.op
= pg_log_entry_t::MODIFY
;
1118 olog
.log
.push_back(e
);
1119 e
.version
= eversion_t(2, 4);
1120 e
.soid
.set_hash(0x7);
1121 e
.op
= pg_log_entry_t::DELETE
;
1122 olog
.log
.push_back(e
);
1123 olog
.head
= e
.version
;
1126 snapid_t
purged_snap(1);
1128 oinfo
.last_update
= olog
.head
;
1129 oinfo
.purged_snaps
.insert(purged_snap
);
1132 EXPECT_FALSE(missing
.have_missing());
1133 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1134 EXPECT_EQ(3U, log
.log
.size());
1135 EXPECT_TRUE(remove_snap
.empty());
1136 EXPECT_EQ(log
.head
, info
.last_update
);
1137 EXPECT_TRUE(info
.purged_snaps
.empty());
1138 EXPECT_FALSE(is_dirty());
1139 EXPECT_FALSE(dirty_info
);
1140 EXPECT_FALSE(dirty_big_info
);
1142 TestHandler
h(remove_snap
);
1143 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1144 dirty_info
, dirty_big_info
);
1146 /* When the divergent entry is a DELETE and the authoritative
1147 entry is a MODIFY, the object will be added to missing : it is
1148 a verifiable side effect proving the entry was identified
1151 EXPECT_TRUE(missing
.is_missing(divergent_object
));
1152 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1153 EXPECT_EQ(4U, log
.log
.size());
1154 /* DELETE entries from olog that are appended to the hed of the
1155 log, and the divergent version of the object is removed (added
1158 EXPECT_EQ(0x9U
, remove_snap
.front().get_hash());
1159 EXPECT_EQ(log
.head
, info
.last_update
);
1160 EXPECT_TRUE(info
.purged_snaps
.contains(purged_snap
));
1161 EXPECT_TRUE(is_dirty());
1162 EXPECT_TRUE(dirty_info
);
1163 EXPECT_TRUE(dirty_big_info
);
1166 /* +--------------------------+
1168 +--------+-------+---------+
1170 |version | hash | version |
1172 tail > (1,1) | x5 | (1,1) < tail
1175 | (1,2) | x3 | (1,2) < lower_bound
1178 head > (1,3) | x9 | |
1184 | | x7 | (2,4) < head
1186 +--------+-------+---------+
1188 The log entry (1,3) deletes the object x9 but the olog entry (2,3) modifies
1189 it and is authoritative : the log entry (1,3) is divergent.
1199 list
<hobject_t
> remove_snap
;
1200 bool dirty_info
= false;
1201 bool dirty_big_info
= false;
1203 hobject_t divergent_object
;
1207 e
.mark_unrollbackable();
1209 e
.version
= eversion_t(1, 1);
1210 e
.soid
.set_hash(0x5);
1211 log
.tail
= e
.version
;
1212 log
.log
.push_back(e
);
1213 e
.version
= eversion_t(1, 2);
1214 e
.soid
.set_hash(0x3);
1215 log
.log
.push_back(e
);
1216 e
.version
= eversion_t(1,3);
1217 e
.soid
.set_hash(0x9);
1218 divergent_object
= e
.soid
;
1219 e
.op
= pg_log_entry_t::DELETE
;
1220 log
.log
.push_back(e
);
1221 log
.head
= e
.version
;
1224 info
.last_update
= log
.head
;
1226 e
.version
= eversion_t(1, 1);
1227 e
.soid
.set_hash(0x5);
1228 olog
.tail
= e
.version
;
1229 olog
.log
.push_back(e
);
1230 e
.version
= eversion_t(1, 2);
1231 e
.soid
.set_hash(0x3);
1232 olog
.log
.push_back(e
);
1233 e
.version
= eversion_t(2, 3);
1234 e
.soid
.set_hash(0x9);
1235 e
.op
= pg_log_entry_t::MODIFY
;
1236 olog
.log
.push_back(e
);
1237 e
.version
= eversion_t(2, 4);
1238 e
.soid
.set_hash(0x7);
1239 e
.op
= pg_log_entry_t::DELETE
;
1240 olog
.log
.push_back(e
);
1241 olog
.head
= e
.version
;
1244 snapid_t
purged_snap(1);
1246 oinfo
.last_update
= olog
.head
;
1247 oinfo
.purged_snaps
.insert(purged_snap
);
1250 EXPECT_FALSE(missing
.have_missing());
1251 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1252 EXPECT_EQ(3U, log
.log
.size());
1253 EXPECT_TRUE(remove_snap
.empty());
1254 EXPECT_EQ(log
.head
, info
.last_update
);
1255 EXPECT_TRUE(info
.purged_snaps
.empty());
1256 EXPECT_FALSE(is_dirty());
1257 EXPECT_FALSE(dirty_info
);
1258 EXPECT_FALSE(dirty_big_info
);
1260 TestHandler
h(remove_snap
);
1261 missing
.may_include_deletes
= false;
1262 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1263 dirty_info
, dirty_big_info
);
1265 /* When the divergent entry is a DELETE and the authoritative
1266 entry is a MODIFY, the object will be added to missing : it is
1267 a verifiable side effect proving the entry was identified
1270 EXPECT_TRUE(missing
.is_missing(divergent_object
));
1271 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1272 EXPECT_EQ(4U, log
.log
.size());
1273 /* DELETE entries from olog that are appended to the hed of the
1274 log, and the divergent version of the object is removed (added
1275 to remove_snap). When peering handles deletes, it is the earlier
1276 version that is in the removed list.
1278 EXPECT_EQ(0x7U
, remove_snap
.front().get_hash());
1279 EXPECT_EQ(log
.head
, info
.last_update
);
1280 EXPECT_TRUE(info
.purged_snaps
.contains(purged_snap
));
1281 EXPECT_TRUE(is_dirty());
1282 EXPECT_TRUE(dirty_info
);
1283 EXPECT_TRUE(dirty_big_info
);
1286 /* +--------------------------+
1288 +--------+-------+---------+
1290 |version | hash | version |
1292 tail > (1,1) | x5 | (1,1) < tail
1295 | (1,4) | x7 | (1,4) < head
1298 head > (1,5) | x9 | |
1301 +--------+-------+---------+
1303 The head of the log entry (1,5) is divergent because it is greater than the
1314 list
<hobject_t
> remove_snap
;
1315 bool dirty_info
= false;
1316 bool dirty_big_info
= false;
1320 e
.mark_unrollbackable();
1322 e
.version
= eversion_t(1, 1);
1323 e
.soid
.set_hash(0x5);
1324 log
.tail
= e
.version
;
1325 log
.log
.push_back(e
);
1326 e
.version
= eversion_t(1, 4);
1327 e
.soid
.set_hash(0x7);
1328 log
.log
.push_back(e
);
1329 e
.version
= eversion_t(1, 5);
1330 e
.soid
.set_hash(0x9);
1331 log
.log
.push_back(e
);
1332 log
.head
= e
.version
;
1335 info
.last_update
= log
.head
;
1337 e
.version
= eversion_t(1, 1);
1338 e
.soid
.set_hash(0x5);
1339 olog
.tail
= e
.version
;
1340 olog
.log
.push_back(e
);
1341 e
.version
= eversion_t(1, 4);
1342 e
.soid
.set_hash(0x7);
1343 olog
.log
.push_back(e
);
1344 olog
.head
= e
.version
;
1347 hobject_t
last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
1348 info
.last_backfill
= last_backfill
;
1349 eversion_t
stat_version(10, 1);
1350 info
.stats
.version
= stat_version
;
1352 EXPECT_FALSE(missing
.have_missing());
1353 EXPECT_EQ(3U, log
.log
.size());
1354 EXPECT_EQ(stat_version
, info
.stats
.version
);
1355 EXPECT_TRUE(remove_snap
.empty());
1356 EXPECT_EQ(last_backfill
, info
.last_backfill
);
1357 EXPECT_TRUE(info
.purged_snaps
.empty());
1358 EXPECT_FALSE(is_dirty());
1359 EXPECT_FALSE(dirty_info
);
1360 EXPECT_FALSE(dirty_big_info
);
1362 TestHandler
h(remove_snap
);
1363 missing
.may_include_deletes
= false;
1364 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1365 dirty_info
, dirty_big_info
);
1367 EXPECT_FALSE(missing
.have_missing());
1368 EXPECT_EQ(2U, log
.log
.size());
1369 EXPECT_EQ(stat_version
, info
.stats
.version
);
1370 EXPECT_EQ(0x9U
, remove_snap
.front().get_hash());
1371 EXPECT_TRUE(info
.purged_snaps
.empty());
1372 EXPECT_TRUE(is_dirty());
1373 EXPECT_TRUE(dirty_info
);
1374 EXPECT_TRUE(dirty_big_info
);
1377 // If our log is empty, the incoming log needs to have not been trimmed.
1385 list
<hobject_t
> remove_snap
;
1386 bool dirty_info
= false;
1387 bool dirty_big_info
= false;
1389 // olog has been trimmed
1390 olog
.tail
= eversion_t(1, 1);
1392 TestHandler
h(remove_snap
);
1393 PrCtl unset_dumpable
;
1394 ASSERT_DEATH(merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1395 dirty_info
, dirty_big_info
), "");
1400 TEST_F(PGLogTest
, proc_replica_log
) {
1401 // empty log : no side effect
1407 pg_missing_t omissing
;
1410 eversion_t
last_update(1, 1);
1411 log
.head
= olog
.head
= oinfo
.last_update
= last_update
;
1412 eversion_t
last_complete(1, 1);
1413 oinfo
.last_complete
= last_complete
;
1415 EXPECT_FALSE(omissing
.have_missing());
1416 EXPECT_EQ(last_update
, oinfo
.last_update
);
1417 EXPECT_EQ(last_complete
, oinfo
.last_complete
);
1419 missing
.may_include_deletes
= false;
1420 proc_replica_log(oinfo
, olog
, omissing
, from
);
1422 EXPECT_FALSE(omissing
.have_missing());
1423 EXPECT_EQ(last_update
, oinfo
.last_update
);
1424 EXPECT_EQ(last_update
, oinfo
.last_complete
);
1427 /* +--------------------------+
1429 +--------+-------+---------+
1431 |version | hash | version |
1433 | | x3 | (1,1) < tail
1436 tail > (1,2) | x5 | |
1439 head > (1,3) | x9 | |
1442 | | x9 | (2,3) < head
1445 +--------+-------+---------+
1447 The log entry (1,3) deletes the object x9 and the olog entry
1448 (2,3) also deletes it : do nothing. The olog tail is ignored
1449 because it is before the log tail.
1457 pg_missing_t omissing
;
1462 e
.mark_unrollbackable();
1464 e
.version
= eversion_t(1, 2);
1465 e
.soid
.set_hash(0x5);
1466 log
.tail
= e
.version
;
1467 log
.log
.push_back(e
);
1468 e
.version
= eversion_t(1, 3);
1469 e
.soid
.set_hash(0x9);
1470 e
.op
= pg_log_entry_t::DELETE
;
1471 log
.log
.push_back(e
);
1472 log
.head
= e
.version
;
1475 e
.version
= eversion_t(1, 1);
1476 e
.soid
.set_hash(0x3);
1477 olog
.tail
= e
.version
;
1478 olog
.log
.push_back(e
);
1479 e
.version
= eversion_t(2, 3);
1480 e
.soid
.set_hash(0x9);
1481 e
.op
= pg_log_entry_t::DELETE
;
1482 olog
.log
.push_back(e
);
1483 olog
.head
= e
.version
;
1485 oinfo
.last_update
= olog
.head
;
1486 oinfo
.last_complete
= olog
.head
;
1489 EXPECT_FALSE(omissing
.have_missing());
1490 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1491 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1493 missing
.may_include_deletes
= false;
1494 proc_replica_log(oinfo
, olog
, omissing
, from
);
1496 EXPECT_FALSE(omissing
.have_missing());
1504 pg_missing_t omissing
;
1507 hobject_t divergent_object
;
1511 e
.mark_unrollbackable();
1514 e
.soid
= divergent_object
;
1515 e
.soid
.set_hash(0x1);
1516 e
.version
= eversion_t(1, 1);
1517 log
.tail
= e
.version
;
1518 log
.log
.push_back(e
);
1520 e
.soid
= divergent_object
;
1521 e
.prior_version
= eversion_t(1, 1);
1522 e
.version
= eversion_t(1, 2);
1523 log
.tail
= e
.version
;
1524 log
.log
.push_back(e
);
1526 e
.soid
.set_hash(0x3);
1527 e
.version
= eversion_t(1, 4);
1528 log
.log
.push_back(e
);
1530 e
.soid
.set_hash(0x7);
1531 e
.version
= eversion_t(1, 5);
1532 log
.log
.push_back(e
);
1534 e
.soid
.set_hash(0x8);
1535 e
.version
= eversion_t(1, 6);
1536 log
.log
.push_back(e
);
1538 e
.soid
.set_hash(0x9);
1539 e
.op
= pg_log_entry_t::DELETE
;
1540 e
.version
= eversion_t(2, 7);
1541 log
.log
.push_back(e
);
1543 e
.soid
.set_hash(0xa);
1544 e
.version
= eversion_t(2, 8);
1545 log
.head
= e
.version
;
1546 log
.log
.push_back(e
);
1551 e
.soid
= divergent_object
;
1552 e
.soid
.set_hash(0x1);
1553 e
.version
= eversion_t(1, 1);
1554 olog
.tail
= e
.version
;
1555 olog
.log
.push_back(e
);
1557 e
.soid
= divergent_object
;
1558 e
.prior_version
= eversion_t(1, 1);
1559 e
.version
= eversion_t(1, 2);
1560 olog
.log
.push_back(e
);
1562 e
.prior_version
= eversion_t(0, 0);
1563 e
.soid
.set_hash(0x3);
1564 e
.version
= eversion_t(1, 4);
1565 olog
.log
.push_back(e
);
1567 e
.soid
.set_hash(0x7);
1568 e
.version
= eversion_t(1, 5);
1569 olog
.log
.push_back(e
);
1571 e
.soid
.set_hash(0x8);
1572 e
.version
= eversion_t(1, 6);
1573 olog
.log
.push_back(e
);
1575 e
.soid
.set_hash(0x9); // should not be added to missing, create
1576 e
.op
= pg_log_entry_t::MODIFY
;
1577 e
.version
= eversion_t(1, 7);
1578 olog
.log
.push_back(e
);
1580 e
.soid
= divergent_object
; // should be added to missing at 1,2
1581 e
.op
= pg_log_entry_t::MODIFY
;
1582 e
.version
= eversion_t(1, 8);
1583 e
.prior_version
= eversion_t(1, 2);
1584 olog
.log
.push_back(e
);
1585 olog
.head
= e
.version
;
1587 oinfo
.last_update
= olog
.head
;
1588 oinfo
.last_complete
= olog
.head
;
1591 EXPECT_FALSE(omissing
.have_missing());
1592 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1593 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1595 missing
.may_include_deletes
= false;
1596 proc_replica_log(oinfo
, olog
, omissing
, from
);
1598 EXPECT_TRUE(omissing
.have_missing());
1599 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1600 EXPECT_EQ(eversion_t(1, 2), omissing
.get_items().at(divergent_object
).need
);
1601 EXPECT_EQ(eversion_t(1, 6), oinfo
.last_update
);
1602 EXPECT_EQ(eversion_t(1, 1), oinfo
.last_complete
);
1605 /* +--------------------------+
1607 +--------+-------+---------+
1609 |version | hash | version |
1611 tail > (1,1) | x9 | (1,1) < tail
1614 | (1,2) | x3 | (1,2) |
1617 head > (1,3) | x9 | |
1620 | | x9 | (2,3) < head
1623 +--------+-------+---------+
1625 The log entry (1,3) deletes the object x9 and the olog entry
1626 (2,3) also deletes it : do nothing.
1634 pg_missing_t omissing
;
1637 eversion_t
last_update(1, 2);
1638 hobject_t divergent_object
;
1639 divergent_object
.set_hash(0x9);
1643 e
.mark_unrollbackable();
1645 e
.version
= eversion_t(1, 1);
1646 e
.soid
= divergent_object
;
1647 log
.tail
= e
.version
;
1648 log
.log
.push_back(e
);
1649 e
.version
= last_update
;
1650 e
.soid
.set_hash(0x3);
1651 log
.log
.push_back(e
);
1652 e
.version
= eversion_t(2, 3);
1653 e
.prior_version
= eversion_t(1, 1);
1654 e
.soid
= divergent_object
;
1655 e
.op
= pg_log_entry_t::DELETE
;
1656 log
.log
.push_back(e
);
1657 log
.head
= e
.version
;
1660 e
.version
= eversion_t(1, 1);
1661 e
.soid
= divergent_object
;
1662 olog
.tail
= e
.version
;
1663 olog
.log
.push_back(e
);
1664 e
.version
= last_update
;
1665 e
.soid
.set_hash(0x3);
1666 olog
.log
.push_back(e
);
1667 e
.version
= eversion_t(1, 3);
1668 e
.prior_version
= eversion_t(1, 1);
1669 e
.soid
= divergent_object
;
1670 e
.op
= pg_log_entry_t::DELETE
;
1671 olog
.log
.push_back(e
);
1672 olog
.head
= e
.version
;
1674 oinfo
.last_update
= olog
.head
;
1675 oinfo
.last_complete
= olog
.head
;
1678 EXPECT_FALSE(omissing
.have_missing());
1679 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1680 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1682 missing
.may_include_deletes
= false;
1683 proc_replica_log(oinfo
, olog
, omissing
, from
);
1685 EXPECT_TRUE(omissing
.have_missing());
1686 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1687 EXPECT_EQ(omissing
.get_items().at(divergent_object
).have
, eversion_t(0, 0));
1688 EXPECT_EQ(omissing
.get_items().at(divergent_object
).need
, eversion_t(1, 1));
1689 EXPECT_EQ(last_update
, oinfo
.last_update
);
1692 /* +--------------------------+
1694 +--------+-------+---------+
1696 |version | hash | version |
1698 tail > (1,1) | x9 | (1,1) < tail
1701 | (1,2) | x3 | (1,2) |
1704 head > (1,3) | x9 | |
1707 | | x9 | (2,3) < head
1710 +--------+-------+---------+
1712 The log entry (1,3) deletes the object x9 but the olog entry
1713 (2,3) modifies it : remove it from omissing.
1721 pg_missing_t omissing
;
1724 eversion_t
last_update(1, 2);
1725 hobject_t divergent_object
;
1729 e
.mark_unrollbackable();
1731 e
.version
= eversion_t(1, 1);
1732 e
.soid
= divergent_object
;
1733 log
.tail
= e
.version
;
1734 log
.log
.push_back(e
);
1735 e
.version
= last_update
;
1736 e
.soid
.set_hash(0x3);
1737 log
.log
.push_back(e
);
1738 e
.version
= eversion_t(2, 3);
1739 e
.prior_version
= eversion_t(1, 1);
1740 e
.soid
= divergent_object
;
1741 e
.op
= pg_log_entry_t::DELETE
;
1742 log
.log
.push_back(e
);
1743 log
.head
= e
.version
;
1746 e
.version
= eversion_t(1, 1);
1747 e
.soid
= divergent_object
;
1748 olog
.tail
= e
.version
;
1749 olog
.log
.push_back(e
);
1750 e
.version
= last_update
;
1751 e
.soid
.set_hash(0x3);
1752 olog
.log
.push_back(e
);
1753 e
.version
= eversion_t(1, 3);
1754 e
.prior_version
= eversion_t(1, 1);
1755 e
.soid
= divergent_object
;
1756 divergent_object
= e
.soid
;
1757 omissing
.add(divergent_object
, e
.version
, eversion_t(), false);
1758 e
.op
= pg_log_entry_t::MODIFY
;
1759 olog
.log
.push_back(e
);
1760 olog
.head
= e
.version
;
1762 oinfo
.last_update
= olog
.head
;
1763 oinfo
.last_complete
= olog
.head
;
1766 EXPECT_TRUE(omissing
.have_missing());
1767 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1768 EXPECT_EQ(eversion_t(1, 3), omissing
.get_items().at(divergent_object
).need
);
1769 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1770 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1772 missing
.may_include_deletes
= false;
1773 proc_replica_log(oinfo
, olog
, omissing
, from
);
1775 EXPECT_TRUE(omissing
.have_missing());
1776 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1777 EXPECT_EQ(omissing
.get_items().at(divergent_object
).have
, eversion_t(0, 0));
1778 EXPECT_EQ(omissing
.get_items().at(divergent_object
).need
, eversion_t(1, 1));
1779 EXPECT_EQ(last_update
, oinfo
.last_update
);
1782 /* +--------------------------+
1784 +--------+-------+---------+
1786 |version | hash | version |
1788 tail > (1,1) | x9 | (1,1) < tail
1791 | (1,2) | x3 | (1,2) |
1794 | | x9 | (1,3) < head
1797 head > (2,3) | x9 | |
1800 +--------+-------+---------+
1802 The log entry (2,3) deletes the object x9 but the olog entry
1803 (1,3) modifies it : proc_replica_log should adjust missing to
1804 1,1 for that object until add_next_event in PG::activate processes
1812 pg_missing_t omissing
;
1815 eversion_t
last_update(1, 2);
1816 hobject_t divergent_object
;
1817 eversion_t
new_version(2, 3);
1818 eversion_t
divergent_version(1, 3);
1822 e
.mark_unrollbackable();
1824 e
.version
= eversion_t(1, 1);
1825 e
.soid
.set_hash(0x9);
1826 log
.tail
= e
.version
;
1827 log
.log
.push_back(e
);
1828 e
.version
= last_update
;
1829 e
.soid
.set_hash(0x3);
1830 log
.log
.push_back(e
);
1831 e
.version
= new_version
;
1832 e
.prior_version
= eversion_t(1, 1);
1833 e
.soid
.set_hash(0x9);
1834 e
.op
= pg_log_entry_t::DELETE
;
1835 log
.log
.push_back(e
);
1836 log
.head
= e
.version
;
1839 e
.op
= pg_log_entry_t::MODIFY
;
1840 e
.version
= eversion_t(1, 1);
1841 e
.soid
.set_hash(0x9);
1842 olog
.tail
= e
.version
;
1843 olog
.log
.push_back(e
);
1844 e
.version
= last_update
;
1845 e
.soid
.set_hash(0x3);
1846 olog
.log
.push_back(e
);
1847 e
.version
= divergent_version
;
1848 e
.prior_version
= eversion_t(1, 1);
1849 e
.soid
.set_hash(0x9);
1850 divergent_object
= e
.soid
;
1851 omissing
.add(divergent_object
, e
.version
, eversion_t(), false);
1852 e
.op
= pg_log_entry_t::MODIFY
;
1853 olog
.log
.push_back(e
);
1854 olog
.head
= e
.version
;
1856 oinfo
.last_update
= olog
.head
;
1857 oinfo
.last_complete
= olog
.head
;
1860 EXPECT_TRUE(omissing
.have_missing());
1861 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1862 EXPECT_EQ(divergent_version
, omissing
.get_items().at(divergent_object
).need
);
1863 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1864 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1866 missing
.may_include_deletes
= false;
1867 proc_replica_log(oinfo
, olog
, omissing
, from
);
1869 EXPECT_TRUE(omissing
.have_missing());
1870 EXPECT_TRUE(omissing
.get_items().begin()->second
.need
== eversion_t(1, 1));
1871 EXPECT_EQ(last_update
, oinfo
.last_update
);
1872 EXPECT_EQ(eversion_t(0, 0), oinfo
.last_complete
);
1877 TEST_F(PGLogTest
, merge_log_1
) {
1879 t
.base
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1881 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1883 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1885 t
.toremove
.insert(mk_obj(1));
1891 TEST_F(PGLogTest
, merge_log_2
) {
1893 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1895 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1896 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1898 t
.torollback
.insert(
1899 t
.torollback
.begin(), t
.div
.rbegin(), t
.div
.rend());
1905 TEST_F(PGLogTest
, merge_log_3
) {
1907 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1909 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1910 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1912 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1914 t
.toremove
.insert(mk_obj(1));
1920 TEST_F(PGLogTest
, merge_log_4
) {
1922 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1924 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1925 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1927 t
.init
.add(mk_obj(1), mk_evt(10, 102), mk_evt(0, 0), false);
1928 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1934 TEST_F(PGLogTest
, merge_log_5
) {
1936 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1938 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1939 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1941 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1943 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(0, 0), false);
1945 t
.toremove
.insert(mk_obj(1));
1951 TEST_F(PGLogTest
, merge_log_6
) {
1953 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1955 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1957 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100), false);
1963 TEST_F(PGLogTest
, merge_log_7
) {
1965 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1967 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1969 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1970 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), false);
1976 TEST_F(PGLogTest
, merge_log_8
) {
1978 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1980 t
.auth
.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1982 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1983 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), true);
1989 TEST_F(PGLogTest
, merge_log_9
) {
1991 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1993 t
.auth
.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1995 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1996 t
.toremove
.insert(mk_obj(1));
1997 t
.deletes_during_peering
= true;
2003 TEST_F(PGLogTest
, merge_log_10
) {
2005 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2007 t
.auth
.push_back(mk_ple_ldt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
2009 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
2010 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), true);
2016 TEST_F(PGLogTest
, merge_log_prior_version_have
) {
2018 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2020 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
2022 t
.init
.add(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100), false);
2028 TEST_F(PGLogTest
, merge_log_split_missing_entries_at_head
) {
2030 t
.auth
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2031 t
.auth
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2033 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(8, 70), mk_evt(8, 65)));
2036 t
.set_div_bounds(mk_evt(9, 79), mk_evt(8, 69));
2037 t
.set_auth_bounds(mk_evt(15, 160), mk_evt(9, 77));
2038 t
.final
.add(mk_obj(1), mk_evt(15, 150), mk_evt(8, 70), false);
2042 TEST_F(PGLogTest
, olog_tail_gt_log_tail_split
) {
2044 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2045 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2046 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150)));
2049 t
.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
2050 t
.set_auth_bounds(mk_evt(15, 156), mk_evt(10, 99));
2051 t
.final
.add(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150), false);
2055 TEST_F(PGLogTest
, olog_tail_gt_log_tail_split2
) {
2057 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2058 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2059 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(16, 155), mk_evt(15, 150)));
2060 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 153), mk_evt(15, 150)));
2063 t
.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
2064 t
.set_auth_bounds(mk_evt(16, 156), mk_evt(10, 99));
2065 t
.final
.add(mk_obj(1), mk_evt(16, 155), mk_evt(0, 0), false);
2066 t
.toremove
.insert(mk_obj(1));
2070 TEST_F(PGLogTest
, filter_log_1
) {
2076 int64_t pool_id
= 1;
2079 int pg_num
= max_osd
<< bits
;
2080 int num_objects
= 1000;
2081 int num_internal
= 10;
2083 // Set up splitting map
2084 OSDMap
*osdmap
= new OSDMap
;
2086 test_uuid
.generate_random();
2087 osdmap
->build_simple_with_pool(g_ceph_context
, epoch
, test_uuid
, max_osd
, bits
, bits
);
2088 osdmap
->set_state(osd_id
, CEPH_OSD_EXISTS
);
2090 const string
hit_set_namespace("internal");
2094 e
.mark_unrollbackable();
2095 e
.op
= pg_log_entry_t::MODIFY
;
2096 e
.soid
.pool
= pool_id
;
2100 for (i
= 1; i
<= num_objects
; ++i
) {
2101 e
.version
= eversion_t(epoch
, i
);
2102 // Use this to generate random file names
2103 uuid_name
.generate_random();
2106 e
.soid
.oid
.name
= name
.str();
2107 // First has no namespace
2109 // num_internal have the internal namspace
2110 if (i
<= num_internal
+ 1) {
2111 e
.soid
.nspace
= hit_set_namespace
;
2112 } else { // rest have different namespaces
2115 e
.soid
.nspace
= ns
.str();
2118 log
.log
.push_back(e
);
2120 log
.tail
= e
.version
;
2122 log
.head
= e
.version
;
2126 spg_t
pgid(pg_t(2, pool_id
), shard_id_t::NO_SHARD
);
2128 // See if we created the right number of entries
2129 int total
= log
.log
.size();
2130 ASSERT_EQ(total
, num_objects
);
2132 // Some should be removed
2134 pg_log_t filtered
, reject
;
2135 pg_log_t::filter_log(
2136 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
2137 log
= IndexedLog(filtered
);
2139 EXPECT_LE(log
.log
.size(), (size_t)total
);
2141 // If we filter a second time, there should be the same total
2142 total
= log
.log
.size();
2144 pg_log_t filtered
, reject
;
2145 pg_log_t::filter_log(
2146 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
2147 log
= IndexedLog(filtered
);
2149 EXPECT_EQ(log
.log
.size(), (size_t)total
);
2151 // Increase pg_num as if there would be a split
2152 int new_pg_num
= pg_num
* 16;
2153 OSDMap::Incremental
inc(epoch
+ 1);
2154 inc
.fsid
= test_uuid
;
2155 const pg_pool_t
*pool
= osdmap
->get_pg_pool(pool_id
);
2158 newpool
.set_pg_num(new_pg_num
);
2159 newpool
.set_pgp_num(new_pg_num
);
2160 inc
.new_pools
[pool_id
] = newpool
;
2161 int ret
= osdmap
->apply_incremental(inc
);
2164 // We should have fewer entries after a filter
2166 pg_log_t filtered
, reject
;
2167 pg_log_t::filter_log(
2168 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
2169 log
= IndexedLog(filtered
);
2171 EXPECT_LE(log
.log
.size(), (size_t)total
);
2173 // Make sure all internal entries are retained
2175 for (list
<pg_log_entry_t
>::iterator i
= log
.log
.begin();
2176 i
!= log
.log
.end(); ++i
) {
2177 if (i
->soid
.nspace
== hit_set_namespace
) count
++;
2179 EXPECT_EQ(count
, num_internal
);
2183 TEST_F(PGLogTest
, get_request
) {
2186 // make sure writes, deletes, and errors are found
2187 vector
<pg_log_entry_t
> entries
;
2188 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
2190 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(6,2), eversion_t(3,4),
2191 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2192 utime_t(0,1), -ENOENT
));
2194 pg_log_entry_t(pg_log_entry_t::MODIFY
, oid
, eversion_t(6,3), eversion_t(3,4),
2195 2, osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2198 pg_log_entry_t(pg_log_entry_t::DELETE
, oid
, eversion_t(7,4), eversion_t(7,4),
2199 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2202 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(7,5), eversion_t(7,4),
2203 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2204 utime_t(20,1), -ENOENT
));
2206 for (auto &entry
: entries
) {
2210 for (auto &entry
: entries
) {
2211 eversion_t replay_version
;
2212 version_t user_version
;
2213 int return_code
= 0;
2214 bool got
= log
.get_request(
2215 entry
.reqid
, &replay_version
, &user_version
, &return_code
);
2217 EXPECT_EQ(entry
.return_code
, return_code
);
2218 EXPECT_EQ(entry
.version
, replay_version
);
2219 EXPECT_EQ(entry
.user_version
, user_version
);
2223 TEST_F(PGLogTest
, ErrorNotIndexedByObject
) {
2226 // make sure writes, deletes, and errors are found
2227 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
2229 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(6,2), eversion_t(3,4),
2230 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2231 utime_t(0,1), -ENOENT
));
2233 EXPECT_FALSE(log
.logged_object(oid
));
2235 pg_log_entry_t
modify(pg_log_entry_t::MODIFY
, oid
, eversion_t(6,3),
2237 osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2241 EXPECT_TRUE(log
.logged_object(oid
));
2242 pg_log_entry_t
*entry
= log
.objects
[oid
];
2243 EXPECT_EQ(modify
.op
, entry
->op
);
2244 EXPECT_EQ(modify
.version
, entry
->version
);
2245 EXPECT_EQ(modify
.prior_version
, entry
->prior_version
);
2246 EXPECT_EQ(modify
.user_version
, entry
->user_version
);
2247 EXPECT_EQ(modify
.reqid
, entry
->reqid
);
2249 pg_log_entry_t
del(pg_log_entry_t::DELETE
, oid
, eversion_t(7,4),
2251 osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2255 EXPECT_TRUE(log
.logged_object(oid
));
2256 entry
= log
.objects
[oid
];
2257 EXPECT_EQ(del
.op
, entry
->op
);
2258 EXPECT_EQ(del
.version
, entry
->version
);
2259 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2260 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2261 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2264 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(7,5), eversion_t(7,4),
2265 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2266 utime_t(20,1), -ENOENT
));
2268 EXPECT_TRUE(log
.logged_object(oid
));
2269 entry
= log
.objects
[oid
];
2270 EXPECT_EQ(del
.op
, entry
->op
);
2271 EXPECT_EQ(del
.version
, entry
->version
);
2272 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2273 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2274 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2277 TEST_F(PGLogTest
, split_into_preserves_may_include_deletes
) {
2281 rebuilt_missing_with_deletes
= false;
2282 missing
.may_include_deletes
= true;
2283 PGLog
child_log(cct
, prefix_provider
);
2285 split_into(child_pg
, 6, &child_log
);
2286 ASSERT_TRUE(child_log
.get_missing().may_include_deletes
);
2287 ASSERT_TRUE(child_log
.get_rebuilt_missing_with_deletes());
2291 rebuilt_missing_with_deletes
= false;
2292 missing
.may_include_deletes
= false;
2293 PGLog
child_log(cct
, prefix_provider
);
2295 split_into(child_pg
, 6, &child_log
);
2296 ASSERT_FALSE(child_log
.get_missing().may_include_deletes
);
2297 ASSERT_FALSE(child_log
.get_rebuilt_missing_with_deletes());
2301 class PGLogTestRebuildMissing
: public PGLogTest
, public StoreTestFixture
{
2303 PGLogTestRebuildMissing() : PGLogTest(), StoreTestFixture("memstore") {}
2304 void SetUp() override
{
2305 StoreTestFixture::SetUp();
2306 ObjectStore::Sequencer
osr(__func__
);
2307 ObjectStore::Transaction t
;
2308 test_coll
= coll_t(spg_t(pg_t(1, 1)));
2309 t
.create_collection(test_coll
, 0);
2310 store
->apply_transaction(&osr
, std::move(t
));
2311 existing_oid
= mk_obj(0);
2312 nonexistent_oid
= mk_obj(1);
2313 ghobject_t
existing_ghobj(existing_oid
);
2314 object_info_t existing_info
;
2315 existing_info
.version
= eversion_t(6, 2);
2317 ::encode(existing_info
, enc_oi
, 0);
2318 ObjectStore::Transaction t2
;
2319 t2
.touch(test_coll
, ghobject_t(existing_oid
));
2320 t2
.setattr(test_coll
, ghobject_t(existing_oid
), OI_ATTR
, enc_oi
);
2321 ASSERT_EQ(0u, store
->apply_transaction(&osr
, std::move(t2
)));
2322 info
.last_backfill
= hobject_t::get_max();
2323 info
.last_complete
= eversion_t();
2326 void TearDown() override
{
2328 missing
.may_include_deletes
= false;
2329 StoreTestFixture::TearDown();
2334 hobject_t existing_oid
, nonexistent_oid
;
2336 void run_rebuild_missing_test(const map
<hobject_t
, pg_missing_item
> &expected_missing_items
) {
2337 rebuild_missing_set_with_deletes(store
.get(), test_coll
, info
);
2338 ASSERT_EQ(expected_missing_items
, missing
.get_items());
2342 TEST_F(PGLogTestRebuildMissing
, EmptyLog
) {
2343 missing
.add(existing_oid
, mk_evt(6, 2), mk_evt(6, 3), false);
2344 missing
.add(nonexistent_oid
, mk_evt(7, 4), mk_evt(0, 0), false);
2345 map
<hobject_t
, pg_missing_item
> orig_missing
= missing
.get_items();
2346 run_rebuild_missing_test(orig_missing
);
2349 TEST_F(PGLogTestRebuildMissing
, SameVersionMod
) {
2350 missing
.add(existing_oid
, mk_evt(6, 2), mk_evt(6, 1), false);
2351 log
.add(mk_ple_mod(existing_oid
, mk_evt(6, 2), mk_evt(6, 1)));
2352 map
<hobject_t
, pg_missing_item
> empty_missing
;
2353 run_rebuild_missing_test(empty_missing
);
2356 TEST_F(PGLogTestRebuildMissing
, DelExisting
) {
2357 missing
.add(existing_oid
, mk_evt(6, 3), mk_evt(6, 2), false);
2358 log
.add(mk_ple_dt(existing_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2359 map
<hobject_t
, pg_missing_item
> expected
;
2360 expected
[existing_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(6, 2), true);
2361 run_rebuild_missing_test(expected
);
2364 TEST_F(PGLogTestRebuildMissing
, DelNonexistent
) {
2365 log
.add(mk_ple_dt(nonexistent_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2366 map
<hobject_t
, pg_missing_item
> expected
;
2367 expected
[nonexistent_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2368 run_rebuild_missing_test(expected
);
2371 TEST_F(PGLogTestRebuildMissing
, MissingNotInLog
) {
2372 missing
.add(mk_obj(10), mk_evt(8, 12), mk_evt(8, 10), false);
2373 log
.add(mk_ple_dt(nonexistent_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2374 map
<hobject_t
, pg_missing_item
> expected
;
2375 expected
[nonexistent_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2376 expected
[mk_obj(10)] = pg_missing_item(mk_evt(8, 12), mk_evt(8, 10), false);
2377 run_rebuild_missing_test(expected
);
2381 class PGLogMergeDupsTest
: public ::testing::Test
, protected PGLog
{
2385 PGLogMergeDupsTest() : PGLog(g_ceph_context
) { }
2387 void SetUp() override
{ }
2389 void TearDown() override
{
2393 static pg_log_dup_t
create_dup_entry(uint a
, uint b
) {
2394 // make each dup_entry unique by using different client id's
2395 static uint client_id
= 777;
2396 return pg_log_dup_t(eversion_t(a
, b
),
2398 osd_reqid_t(entity_name_t::CLIENT(client_id
++), 8, 1),
2402 static std::vector
<pg_log_dup_t
> example_dups_1() {
2403 std::vector
<pg_log_dup_t
> result
= {
2404 create_dup_entry(10, 11),
2405 create_dup_entry(10, 12),
2406 create_dup_entry(11, 1),
2407 create_dup_entry(12, 3),
2408 create_dup_entry(13, 99)
2413 static std::vector
<pg_log_dup_t
> example_dups_2() {
2414 std::vector
<pg_log_dup_t
> result
= {
2415 create_dup_entry(12, 3),
2416 create_dup_entry(13, 99),
2417 create_dup_entry(15, 11),
2418 create_dup_entry(16, 14),
2419 create_dup_entry(16, 32)
2424 void add_dups(uint a
, uint b
) {
2425 log
.dups
.push_back(create_dup_entry(a
, b
));
2428 void add_dups(const std::vector
<pg_log_dup_t
>& l
) {
2430 log
.dups
.push_back(i
);
2434 static void add_dups(IndexedLog
& log
, const std::vector
<pg_log_dup_t
>& dups
) {
2435 for (auto& i
: dups
) {
2436 log
.dups
.push_back(i
);
2440 void check_order() {
2441 eversion_t
prev(0, 0);
2443 for (auto& i
: log
.dups
) {
2444 EXPECT_LT(prev
, i
.version
) << "verify versions monotonically increase";
2449 void check_index() {
2450 EXPECT_EQ(log
.dups
.size(), log
.dup_index
.size());
2451 for (auto& i
: log
.dups
) {
2452 EXPECT_EQ(1u, log
.dup_index
.count(i
.reqid
));
2457 TEST_F(PGLogMergeDupsTest
, OtherEmpty
) {
2458 log
.tail
= eversion_t(14, 5);
2462 add_dups(example_dups_1());
2465 bool changed
= merge_log_dups(olog
);
2467 EXPECT_FALSE(changed
);
2468 EXPECT_EQ(5u, log
.dups
.size());
2470 if (5 == log
.dups
.size()) {
2471 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2472 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2473 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2474 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2481 TEST_F(PGLogMergeDupsTest
, AmEmpty
) {
2482 log
.tail
= eversion_t(14, 5);
2487 add_dups(olog
, example_dups_1());
2489 bool changed
= merge_log_dups(olog
);
2491 EXPECT_TRUE(changed
);
2492 EXPECT_EQ(5u, log
.dups
.size());
2494 if (5 == log
.dups
.size()) {
2495 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2496 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2498 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2499 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2506 TEST_F(PGLogMergeDupsTest
, AmEmptyOverlap
) {
2507 log
.tail
= eversion_t(12, 3);
2512 add_dups(olog
, example_dups_1());
2514 bool changed
= merge_log_dups(olog
);
2516 EXPECT_TRUE(changed
);
2517 EXPECT_EQ(3u, log
.dups
.size());
2519 if (3 == log
.dups
.size()) {
2520 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2521 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2523 EXPECT_EQ(11u, log
.dups
.back().version
.epoch
);
2524 EXPECT_EQ(1u, log
.dups
.back().version
.version
);
2531 TEST_F(PGLogMergeDupsTest
, Same
) {
2532 log
.tail
= eversion_t(14, 1);
2536 add_dups(example_dups_1());
2538 add_dups(olog
, example_dups_1());
2540 bool changed
= merge_log_dups(olog
);
2542 EXPECT_FALSE(changed
);
2543 EXPECT_EQ(5u, log
.dups
.size());
2545 if (5 == log
.dups
.size()) {
2546 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2547 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2549 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2550 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2558 TEST_F(PGLogMergeDupsTest
, Later
) {
2559 log
.tail
= eversion_t(16, 14);
2563 add_dups(example_dups_1());
2565 add_dups(olog
, example_dups_2());
2567 bool changed
= merge_log_dups(olog
);
2569 EXPECT_TRUE(changed
);
2570 EXPECT_EQ(6u, log
.dups
.size());
2572 if (6 == log
.dups
.size()) {
2573 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2574 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2576 EXPECT_EQ(15u, log
.dups
.back().version
.epoch
);
2577 EXPECT_EQ(11u, log
.dups
.back().version
.version
);
2585 TEST_F(PGLogMergeDupsTest
, Earlier
) {
2586 log
.tail
= eversion_t(17, 2);
2590 add_dups(example_dups_2());
2592 add_dups(olog
, example_dups_1());
2594 bool changed
= merge_log_dups(olog
);
2596 EXPECT_TRUE(changed
);
2597 EXPECT_EQ(8u, log
.dups
.size());
2599 if (6 == log
.dups
.size()) {
2600 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2601 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2603 EXPECT_EQ(16u, log
.dups
.back().version
.epoch
);
2604 EXPECT_EQ(32u, log
.dups
.back().version
.version
);
2612 TEST_F(PGLogMergeDupsTest
, Superset
) {
2613 log
.tail
= eversion_t(17, 2);
2617 add_dups(example_dups_1());
2620 olog
.dups
.push_back(create_dup_entry(9, 5));
2621 olog
.dups
.push_back(create_dup_entry(15, 11));
2623 bool changed
= merge_log_dups(olog
);
2625 EXPECT_TRUE(changed
);
2626 EXPECT_EQ(7u, log
.dups
.size());
2628 if (7 == log
.dups
.size()) {
2629 EXPECT_EQ(9u, log
.dups
.front().version
.epoch
);
2630 EXPECT_EQ(5u, log
.dups
.front().version
.version
);
2632 EXPECT_EQ(15u, log
.dups
.back().version
.epoch
);
2633 EXPECT_EQ(11u, log
.dups
.back().version
.version
);
2641 struct PGLogTrimTest
:
2642 public ::testing::Test
,
2643 public PGLogTestBase
,
2644 public PGLog::IndexedLog
2646 std::list
<hobject_t
*> test_hobjects
;
2649 void SetUp() override
{
2650 cct
= (new CephContext(CEPH_ENTITY_TYPE_OSD
))->get();
2652 hobject_t::generate_test_instances(test_hobjects
);
2655 void SetUp(unsigned min_entries
, unsigned max_entries
, unsigned dup_track
) {
2656 constexpr size_t size
= 10;
2658 char min_entries_s
[size
];
2659 char max_entries_s
[size
];
2660 char dup_track_s
[size
];
2662 snprintf(min_entries_s
, size
, "%u", min_entries
);
2663 snprintf(max_entries_s
, size
, "%u", max_entries
);
2664 snprintf(dup_track_s
, size
, "%u", dup_track
);
2666 cct
->_conf
->set_val_or_die("osd_min_pg_log_entries", min_entries_s
);
2667 cct
->_conf
->set_val_or_die("osd_max_pg_log_entries", max_entries_s
);
2668 cct
->_conf
->set_val_or_die("osd_pg_log_dups_tracked", dup_track_s
);
2671 void TearDown() override
{
2672 while (!test_hobjects
.empty()) {
2673 delete test_hobjects
.front();
2674 test_hobjects
.pop_front();
2679 }; // struct PGLogTrimTest
2683 TEST_F(PGLogTest
, Trim1
) {
2686 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2687 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2688 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150)));
2689 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2690 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(21, 165), mk_evt(26, 160)));
2691 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(21, 165), mk_evt(31, 171)));
2698 TEST_F(PGLogTrimTest
, TestMakingCephContext
)
2702 EXPECT_EQ(1u, cct
->_conf
->osd_min_pg_log_entries
);
2703 EXPECT_EQ(2u, cct
->_conf
->osd_max_pg_log_entries
);
2704 EXPECT_EQ(5u, cct
->_conf
->osd_pg_log_dups_tracked
);
2708 TEST_F(PGLogTrimTest
, TestPartialTrim
)
2711 PGLog::IndexedLog log
;
2712 log
.head
= mk_evt(24, 0);
2713 log
.skip_can_rollback_to_to_head();
2714 log
.head
= mk_evt(9, 0);
2716 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2717 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2718 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2719 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2720 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2721 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2723 std::set
<eversion_t
> trimmed
;
2724 std::set
<std::string
> trimmed_dups
;
2725 bool dirty_dups
= false;
2727 log
.trim(cct
, mk_evt(19, 157), &trimmed
, &trimmed_dups
, &dirty_dups
);
2729 EXPECT_EQ(true, dirty_dups
);
2730 EXPECT_EQ(3u, log
.log
.size());
2731 EXPECT_EQ(3u, trimmed
.size());
2732 EXPECT_EQ(2u, log
.dups
.size());
2733 EXPECT_EQ(0u, trimmed_dups
.size());
2737 std::set
<eversion_t
> trimmed2
;
2738 std::set
<std::string
> trimmed_dups2
;
2739 bool dirty_dups2
= false;
2741 log
.trim(cct
, mk_evt(20, 164), &trimmed2
, &trimmed_dups2
, &dirty_dups2
);
2743 EXPECT_EQ(true, dirty_dups2
);
2744 EXPECT_EQ(2u, log
.log
.size());
2745 EXPECT_EQ(1u, trimmed2
.size());
2746 EXPECT_EQ(2u, log
.dups
.size());
2747 EXPECT_EQ(1u, trimmed_dups2
.size());
2751 TEST_F(PGLogTrimTest
, TestTrimNoTrimmed
) {
2753 PGLog::IndexedLog log
;
2754 log
.head
= mk_evt(20, 0);
2755 log
.skip_can_rollback_to_to_head();
2756 log
.head
= mk_evt(9, 0);
2758 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2759 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2760 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2761 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2762 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2763 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2765 bool dirty_dups
= false;
2767 log
.trim(cct
, mk_evt(19, 157), nullptr, nullptr, &dirty_dups
);
2769 EXPECT_EQ(true, dirty_dups
);
2770 EXPECT_EQ(3u, log
.log
.size());
2771 EXPECT_EQ(2u, log
.dups
.size());
2775 TEST_F(PGLogTrimTest
, TestTrimNoDups
)
2778 PGLog::IndexedLog log
;
2779 log
.head
= mk_evt(20, 0);
2780 log
.skip_can_rollback_to_to_head();
2781 log
.head
= mk_evt(9, 0);
2783 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2784 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2785 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2786 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2787 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2788 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2790 std::set
<eversion_t
> trimmed
;
2791 std::set
<std::string
> trimmed_dups
;
2792 bool dirty_dups
= false;
2794 log
.trim(cct
, mk_evt(19, 157), &trimmed
, &trimmed_dups
, &dirty_dups
);
2796 EXPECT_FALSE(dirty_dups
);
2797 EXPECT_EQ(3u, log
.log
.size());
2798 EXPECT_EQ(3u, trimmed
.size());
2799 EXPECT_EQ(0u, log
.dups
.size());
2800 EXPECT_EQ(0u, trimmed_dups
.size());
2803 TEST_F(PGLogTrimTest
, TestNoTrim
)
2806 PGLog::IndexedLog log
;
2807 log
.head
= mk_evt(24, 0);
2808 log
.skip_can_rollback_to_to_head();
2809 log
.head
= mk_evt(9, 0);
2811 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2812 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2813 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2814 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2815 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2816 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2818 std::set
<eversion_t
> trimmed
;
2819 std::set
<std::string
> trimmed_dups
;
2820 bool dirty_dups
= false;
2822 log
.trim(cct
, mk_evt(9, 99), &trimmed
, &trimmed_dups
, &dirty_dups
);
2824 EXPECT_FALSE(dirty_dups
);
2825 EXPECT_EQ(6u, log
.log
.size());
2826 EXPECT_EQ(0u, trimmed
.size());
2827 EXPECT_EQ(0u, log
.dups
.size());
2828 EXPECT_EQ(0u, trimmed_dups
.size());
2831 TEST_F(PGLogTrimTest
, TestTrimAll
)
2834 PGLog::IndexedLog log
;
2835 log
.head
= mk_evt(24, 0);
2836 log
.skip_can_rollback_to_to_head();
2837 log
.head
= mk_evt(9, 0);
2839 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2840 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2841 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2842 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2843 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2844 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2846 std::set
<eversion_t
> trimmed
;
2847 std::set
<std::string
> trimmed_dups
;
2848 bool dirty_dups
= false;
2850 log
.trim(cct
, mk_evt(22, 180), &trimmed
, &trimmed_dups
, &dirty_dups
);
2852 EXPECT_EQ(true, dirty_dups
);
2853 EXPECT_EQ(0u, log
.log
.size());
2854 EXPECT_EQ(6u, trimmed
.size());
2855 EXPECT_EQ(5u, log
.dups
.size());
2856 EXPECT_EQ(0u, trimmed_dups
.size());
2860 TEST_F(PGLogTrimTest
, TestGetRequest
) {
2862 PGLog::IndexedLog log
;
2863 log
.head
= mk_evt(20, 0);
2864 log
.skip_can_rollback_to_to_head();
2865 log
.head
= mk_evt(9, 0);
2867 entity_name_t client
= entity_name_t::CLIENT(777);
2869 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70),
2870 osd_reqid_t(client
, 8, 1)));
2871 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100),
2872 osd_reqid_t(client
, 8, 2)));
2873 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150),
2874 osd_reqid_t(client
, 8, 3)));
2875 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152),
2876 osd_reqid_t(client
, 8, 4)));
2877 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160),
2878 osd_reqid_t(client
, 8, 5)));
2879 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166),
2880 osd_reqid_t(client
, 8, 6)));
2882 bool dirty_dups
= false;
2884 log
.trim(cct
, mk_evt(19, 157), nullptr, nullptr, &dirty_dups
);
2886 EXPECT_EQ(true, dirty_dups
);
2887 EXPECT_EQ(3u, log
.log
.size());
2888 EXPECT_EQ(2u, log
.dups
.size());
2891 version_t user_version
;
2894 osd_reqid_t log_reqid
= osd_reqid_t(client
, 8, 5);
2895 osd_reqid_t dup_reqid
= osd_reqid_t(client
, 8, 3);
2896 osd_reqid_t bad_reqid
= osd_reqid_t(client
, 8, 1);
2900 result
= log
.get_request(log_reqid
, &version
, &user_version
, &return_code
);
2901 EXPECT_EQ(true, result
);
2902 EXPECT_EQ(mk_evt(21, 165), version
);
2904 result
= log
.get_request(dup_reqid
, &version
, &user_version
, &return_code
);
2905 EXPECT_EQ(true, result
);
2906 EXPECT_EQ(mk_evt(15, 155), version
);
2908 result
= log
.get_request(bad_reqid
, &version
, &user_version
, &return_code
);
2909 EXPECT_FALSE(result
);
2914 // compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "