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_err(
97 const hobject_t
&hoid
, eversion_t v
, osd_reqid_t reqid
) {
99 e
.op
= pg_log_entry_t::ERROR
;
102 e
.prior_version
= eversion_t(0, 0);
106 static pg_log_entry_t
mk_ple_mod(
107 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
108 return mk_ple_mod(hoid
, v
, pv
, osd_reqid_t());
110 static pg_log_entry_t
mk_ple_dt(
111 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
112 return mk_ple_dt(hoid
, v
, pv
, osd_reqid_t());
114 static pg_log_entry_t
mk_ple_mod_rb(
115 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
116 return mk_ple_mod_rb(hoid
, v
, pv
, osd_reqid_t());
118 static pg_log_entry_t
mk_ple_dt_rb(
119 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
120 return mk_ple_dt_rb(hoid
, v
, pv
, osd_reqid_t());
122 static pg_log_entry_t
mk_ple_err(
123 const hobject_t
&hoid
, eversion_t v
) {
124 return mk_ple_err(hoid
, v
, osd_reqid_t());
129 class PGLogTest
: virtual public ::testing::Test
, protected PGLog
, public PGLogTestBase
{
131 PGLogTest() : PGLog(g_ceph_context
) {}
132 void SetUp() override
{
133 missing
.may_include_deletes
= true;
136 #include "common/ceph_context.h"
137 #include "common/config.h"
139 void TearDown() override
{
145 list
<pg_log_entry_t
> base
;
146 list
<pg_log_entry_t
> auth
;
147 list
<pg_log_entry_t
> div
;
152 set
<hobject_t
> toremove
;
153 list
<pg_log_entry_t
> torollback
;
154 bool deletes_during_peering
;
162 TestCase() : deletes_during_peering(false) {}
164 init
.may_include_deletes
= !deletes_during_peering
;
165 final
.may_include_deletes
= !deletes_during_peering
;
166 fullauth
.log
.insert(fullauth
.log
.end(), base
.begin(), base
.end());
167 fullauth
.log
.insert(fullauth
.log
.end(), auth
.begin(), auth
.end());
168 fulldiv
.log
.insert(fulldiv
.log
.end(), base
.begin(), base
.end());
169 fulldiv
.log
.insert(fulldiv
.log
.end(), div
.begin(), div
.end());
171 fullauth
.head
= authinfo
.last_update
= fullauth
.log
.rbegin()->version
;
172 authinfo
.last_complete
= fullauth
.log
.rbegin()->version
;
173 authinfo
.log_tail
= fullauth
.log
.begin()->version
;
174 authinfo
.log_tail
.version
--;
175 fullauth
.tail
= authinfo
.log_tail
;
176 authinfo
.last_backfill
= hobject_t::get_max();
178 fulldiv
.head
= divinfo
.last_update
= fulldiv
.log
.rbegin()->version
;
179 divinfo
.last_complete
= eversion_t();
180 divinfo
.log_tail
= fulldiv
.log
.begin()->version
;
181 divinfo
.log_tail
.version
--;
182 fulldiv
.tail
= divinfo
.log_tail
;
183 divinfo
.last_backfill
= hobject_t::get_max();
185 if (init
.get_items().empty()) {
186 divinfo
.last_complete
= divinfo
.last_update
;
188 eversion_t fmissing
= init
.get_items().at(init
.get_rmissing().begin()->second
).need
;
189 for (list
<pg_log_entry_t
>::const_iterator i
= fulldiv
.log
.begin();
190 i
!= fulldiv
.log
.end();
192 if (i
->version
< fmissing
)
193 divinfo
.last_complete
= i
->version
;
202 void set_div_bounds(eversion_t head
, eversion_t tail
) {
203 fulldiv
.tail
= divinfo
.log_tail
= tail
;
204 fulldiv
.head
= divinfo
.last_update
= head
;
206 void set_auth_bounds(eversion_t head
, eversion_t tail
) {
207 fullauth
.tail
= authinfo
.log_tail
= tail
;
208 fullauth
.head
= authinfo
.last_update
= head
;
210 const IndexedLog
&get_fullauth() const { return fullauth
; }
211 const IndexedLog
&get_fulldiv() const { return fulldiv
; }
212 const pg_info_t
&get_authinfo() const { return authinfo
; }
213 const pg_info_t
&get_divinfo() const { return divinfo
; }
214 }; // struct TestCase
216 struct LogHandler
: public PGLog::LogEntryHandler
{
217 set
<hobject_t
> removed
;
218 list
<pg_log_entry_t
> rolledback
;
221 const pg_log_entry_t
&entry
) override
{
222 rolledback
.push_back(entry
);
225 const pg_log_entry_t
&entry
) override
{}
227 const hobject_t
&hoid
) override
{
228 removed
.insert(hoid
);
230 void try_stash(const hobject_t
&, version_t
) override
{
231 // lost/unfound cases are not tested yet
234 const pg_log_entry_t
&entry
) override
{}
237 template <typename missing_t
>
239 const TestCase
&tcase
,
240 const missing_t
&missing
) {
241 ASSERT_EQ(tcase
.final
.get_items().size(), missing
.get_items().size());
242 for (auto i
= missing
.get_items().begin();
243 i
!= missing
.get_items().end();
245 EXPECT_TRUE(tcase
.final
.get_items().count(i
->first
));
246 EXPECT_EQ(tcase
.final
.get_items().find(i
->first
)->second
.need
, i
->second
.need
);
247 EXPECT_EQ(tcase
.final
.get_items().find(i
->first
)->second
.have
, i
->second
.have
);
249 bool correct
= missing
.debug_verify_from_init(tcase
.init
, &(std::cout
));
250 ASSERT_TRUE(correct
);
253 void verify_sideeffects(
254 const TestCase
&tcase
,
255 const LogHandler
&handler
) {
256 ASSERT_EQ(tcase
.toremove
.size(), handler
.removed
.size());
257 ASSERT_EQ(tcase
.torollback
.size(), handler
.rolledback
.size());
260 list
<pg_log_entry_t
>::const_iterator titer
= tcase
.torollback
.begin();
261 list
<pg_log_entry_t
>::const_iterator hiter
= handler
.rolledback
.begin();
262 for (; titer
!= tcase
.torollback
.end(); ++titer
, ++hiter
) {
263 EXPECT_EQ(titer
->version
, hiter
->version
);
268 set
<hobject_t
>::const_iterator titer
= tcase
.toremove
.begin();
269 set
<hobject_t
>::const_iterator hiter
= handler
.removed
.begin();
270 for (; titer
!= tcase
.toremove
.end(); ++titer
, ++hiter
) {
271 EXPECT_EQ(*titer
, *hiter
);
276 void test_merge_log(const TestCase
&tcase
) {
278 log
= tcase
.get_fulldiv();
279 pg_info_t info
= tcase
.get_divinfo();
281 missing
= tcase
.init
;
285 olog
= tcase
.get_fullauth();
286 pg_info_t oinfo
= tcase
.get_authinfo();
289 bool dirty_info
= false;
290 bool dirty_big_info
= false;
292 oinfo
, olog
, pg_shard_t(1, shard_id_t(0)), info
,
293 &h
, dirty_info
, dirty_big_info
);
295 ASSERT_EQ(info
.last_update
, oinfo
.last_update
);
296 verify_missing(tcase
, missing
);
297 verify_sideeffects(tcase
, h
);
300 void test_proc_replica_log(const TestCase
&tcase
) {
302 log
= tcase
.get_fullauth();
303 pg_info_t info
= tcase
.get_authinfo();
305 pg_missing_t omissing
= tcase
.init
;
308 olog
= tcase
.get_fulldiv();
309 pg_info_t oinfo
= tcase
.get_divinfo();
312 oinfo
, olog
, omissing
, pg_shard_t(1, shard_id_t(0)));
314 assert(oinfo
.last_update
>= log
.tail
);
316 if (!tcase
.base
.empty()) {
317 ASSERT_EQ(tcase
.base
.rbegin()->version
, oinfo
.last_update
);
320 for (list
<pg_log_entry_t
>::const_iterator i
= tcase
.auth
.begin();
321 i
!= tcase
.auth
.end();
323 if (i
->version
> oinfo
.last_update
) {
324 if (i
->is_delete() && tcase
.deletes_during_peering
) {
325 omissing
.rm(i
->soid
, i
->version
);
327 omissing
.add_next_event(*i
);
331 verify_missing(tcase
, omissing
);
332 } // test_proc_replica_log
334 void run_test_case(const TestCase
&tcase
) {
335 test_merge_log(tcase
);
336 test_proc_replica_log(tcase
);
338 }; // class PGLogTest
340 struct TestHandler
: public PGLog::LogEntryHandler
{
341 list
<hobject_t
> &removed
;
342 explicit TestHandler(list
<hobject_t
> &removed
) : removed(removed
) {}
345 const pg_log_entry_t
&entry
) override
{}
347 const pg_log_entry_t
&entry
) override
{}
349 const hobject_t
&hoid
) override
{
350 removed
.push_back(hoid
);
352 void cant_rollback(const pg_log_entry_t
&entry
) {}
353 void try_stash(const hobject_t
&, version_t
) override
{
354 // lost/unfound cases are not tested yet
357 const pg_log_entry_t
&entry
) override
{}
360 TEST_F(PGLogTest
, rewind_divergent_log
) {
361 /* +----------------+
370 | (1,4) | x9 < newhead
383 list
<hobject_t
> remove_snap
;
384 bool dirty_info
= false;
385 bool dirty_big_info
= false;
387 hobject_t divergent_object
;
388 eversion_t divergent_version
;
392 divergent
.set_hash(0x9);
396 e
.mark_unrollbackable();
398 e
.version
= eversion_t(1, 1);
399 e
.soid
.set_hash(0x5);
400 log
.tail
= e
.version
;
401 log
.log
.push_back(e
);
402 e
.version
= newhead
= eversion_t(1, 4);
404 e
.op
= pg_log_entry_t::MODIFY
;
405 log
.log
.push_back(e
);
406 e
.version
= divergent_version
= eversion_t(1, 5);
407 e
.prior_version
= eversion_t(1, 4);
409 divergent_object
= e
.soid
;
410 e
.op
= pg_log_entry_t::DELETE
;
411 log
.log
.push_back(e
);
412 log
.head
= e
.version
;
415 info
.last_update
= log
.head
;
416 info
.last_complete
= log
.head
;
419 EXPECT_FALSE(missing
.have_missing());
420 EXPECT_EQ(3U, log
.log
.size());
421 EXPECT_TRUE(remove_snap
.empty());
422 EXPECT_EQ(log
.head
, info
.last_update
);
423 EXPECT_EQ(log
.head
, info
.last_complete
);
424 EXPECT_FALSE(is_dirty());
425 EXPECT_FALSE(dirty_info
);
426 EXPECT_FALSE(dirty_big_info
);
428 TestHandler
h(remove_snap
);
429 rewind_divergent_log(newhead
, info
, &h
,
430 dirty_info
, dirty_big_info
);
432 EXPECT_TRUE(log
.objects
.count(divergent
));
433 EXPECT_TRUE(missing
.is_missing(divergent_object
));
434 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
435 EXPECT_EQ(2U, log
.log
.size());
436 EXPECT_TRUE(remove_snap
.empty());
437 EXPECT_EQ(newhead
, info
.last_update
);
438 EXPECT_EQ(newhead
, info
.last_complete
);
439 EXPECT_TRUE(is_dirty());
440 EXPECT_TRUE(dirty_info
);
441 EXPECT_TRUE(dirty_big_info
);
444 /* +----------------+
450 tail > (1,1) | NULL |
452 | (1,4) | NULL < newhead
463 list
<hobject_t
> remove_snap
;
464 bool dirty_info
= false;
465 bool dirty_big_info
= false;
467 hobject_t divergent_object
;
468 eversion_t divergent_version
;
469 eversion_t prior_version
;
473 e
.mark_unrollbackable();
475 info
.log_tail
= log
.tail
= eversion_t(1, 1);
476 newhead
= eversion_t(1, 3);
477 e
.version
= divergent_version
= eversion_t(1, 5);
478 e
.soid
.set_hash(0x9);
479 divergent_object
= e
.soid
;
480 e
.op
= pg_log_entry_t::DELETE
;
481 e
.prior_version
= prior_version
= eversion_t(0, 2);
482 log
.log
.push_back(e
);
483 log
.head
= e
.version
;
486 EXPECT_FALSE(missing
.have_missing());
487 EXPECT_EQ(1U, log
.log
.size());
488 EXPECT_TRUE(remove_snap
.empty());
489 EXPECT_FALSE(is_dirty());
490 EXPECT_FALSE(dirty_info
);
491 EXPECT_FALSE(dirty_big_info
);
493 TestHandler
h(remove_snap
);
494 rewind_divergent_log(newhead
, info
, &h
,
495 dirty_info
, dirty_big_info
);
497 EXPECT_TRUE(missing
.is_missing(divergent_object
));
498 EXPECT_EQ(0U, log
.objects
.count(divergent_object
));
499 EXPECT_TRUE(log
.empty());
500 EXPECT_TRUE(remove_snap
.empty());
501 EXPECT_TRUE(is_dirty());
502 EXPECT_TRUE(dirty_info
);
503 EXPECT_TRUE(dirty_big_info
);
510 list
<hobject_t
> remove_snap
;
512 info
.log_tail
= log
.tail
= eversion_t(1, 5);
513 info
.last_update
= eversion_t(1, 6);
514 bool dirty_info
= false;
515 bool dirty_big_info
= false;
519 e
.mark_unrollbackable();
520 e
.version
= eversion_t(1, 5);
521 e
.soid
.set_hash(0x9);
526 e
.mark_unrollbackable();
527 e
.version
= eversion_t(1, 6);
528 e
.soid
.set_hash(0x10);
531 TestHandler
h(remove_snap
);
532 roll_forward_to(eversion_t(1, 6), &h
);
533 rewind_divergent_log(eversion_t(1, 5), info
, &h
,
534 dirty_info
, dirty_big_info
);
536 reset_backfill_claim_log(log
, &h
);
540 TEST_F(PGLogTest
, merge_old_entry
) {
541 // entries > last_backfill are silently ignored
545 ObjectStore::Transaction t
;
547 oe
.mark_unrollbackable();
549 list
<hobject_t
> remove_snap
;
551 info
.last_backfill
= hobject_t();
552 info
.last_backfill
.set_hash(100);
554 ASSERT_GT(oe
.soid
, info
.last_backfill
);
556 EXPECT_FALSE(is_dirty());
557 EXPECT_TRUE(remove_snap
.empty());
558 EXPECT_TRUE(t
.empty());
559 EXPECT_FALSE(missing
.have_missing());
560 EXPECT_TRUE(log
.empty());
562 TestHandler
h(remove_snap
);
563 merge_old_entry(t
, oe
, info
, &h
);
565 EXPECT_FALSE(is_dirty());
566 EXPECT_TRUE(remove_snap
.empty());
567 EXPECT_TRUE(t
.empty());
568 EXPECT_FALSE(missing
.have_missing());
569 EXPECT_TRUE(log
.empty());
572 // the new entry (from the logs) has a version that is higher than
573 // the old entry (from the log entry given in argument) : do
574 // nothing and return false
578 ObjectStore::Transaction t
;
580 list
<hobject_t
> remove_snap
;
583 ne
.mark_unrollbackable();
584 ne
.version
= eversion_t(2,1);
587 EXPECT_FALSE(is_dirty());
588 EXPECT_TRUE(remove_snap
.empty());
589 EXPECT_TRUE(t
.empty());
590 EXPECT_FALSE(missing
.have_missing());
591 EXPECT_EQ(1U, log
.log
.size());
592 EXPECT_EQ(ne
.version
, log
.log
.front().version
);
594 // the newer entry ( from the logs ) can be DELETE
596 log
.log
.front().op
= pg_log_entry_t::DELETE
;
598 oe
.mark_unrollbackable();
599 oe
.version
= eversion_t(1,1);
601 TestHandler
h(remove_snap
);
602 merge_old_entry(t
, oe
, info
, &h
);
605 // if the newer entry is not DELETE, the object must be in missing
607 pg_log_entry_t
&ne
= log
.log
.front();
608 ne
.op
= pg_log_entry_t::MODIFY
;
609 missing
.add_next_event(ne
);
611 oe
.mark_unrollbackable();
612 oe
.version
= eversion_t(1,1);
614 TestHandler
h(remove_snap
);
615 merge_old_entry(t
, oe
, info
, &h
);
617 missing
.rm(ne
.soid
, ne
.version
);
621 EXPECT_FALSE(is_dirty());
622 EXPECT_FALSE(remove_snap
.empty());
623 EXPECT_TRUE(t
.empty());
624 EXPECT_FALSE(missing
.have_missing());
625 EXPECT_EQ(1U, log
.log
.size());
626 EXPECT_EQ(ne
.version
, log
.log
.front().version
);
630 // the new entry (from the logs) has a version that is lower than
631 // the old entry (from the log entry given in argument) and
632 // old and new are delete : do nothing and return false
636 ObjectStore::Transaction t
;
638 oe
.mark_unrollbackable();
640 list
<hobject_t
> remove_snap
;
643 ne
.mark_unrollbackable();
644 ne
.version
= eversion_t(1,1);
645 ne
.op
= pg_log_entry_t::DELETE
;
648 oe
.version
= eversion_t(2,1);
649 oe
.op
= pg_log_entry_t::DELETE
;
651 EXPECT_FALSE(is_dirty());
652 EXPECT_TRUE(remove_snap
.empty());
653 EXPECT_TRUE(t
.empty());
654 EXPECT_FALSE(missing
.have_missing());
655 EXPECT_EQ(1U, log
.log
.size());
657 TestHandler
h(remove_snap
);
658 merge_old_entry(t
, oe
, info
, &h
);
660 EXPECT_FALSE(is_dirty());
661 EXPECT_TRUE(remove_snap
.empty());
662 EXPECT_TRUE(t
.empty());
663 EXPECT_FALSE(missing
.have_missing());
664 EXPECT_EQ(1U, log
.log
.size());
667 // the new entry (from the logs) has a version that is lower than
668 // the old entry (from the log entry given in argument) and
669 // old is update and new is DELETE :
670 // if the object is in missing, it is removed
674 ObjectStore::Transaction t
;
676 oe
.mark_unrollbackable();
678 list
<hobject_t
> remove_snap
;
681 ne
.mark_unrollbackable();
682 ne
.version
= eversion_t(1,1);
683 ne
.op
= pg_log_entry_t::DELETE
;
686 oe
.version
= eversion_t(2,1);
687 oe
.op
= pg_log_entry_t::MODIFY
;
688 missing
.add_next_event(oe
);
691 EXPECT_FALSE(is_dirty());
692 EXPECT_TRUE(remove_snap
.empty());
693 EXPECT_TRUE(t
.empty());
694 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
695 EXPECT_EQ(1U, log
.log
.size());
697 TestHandler
h(remove_snap
);
698 merge_old_entry(t
, oe
, info
, &h
);
701 EXPECT_FALSE(is_dirty());
702 EXPECT_TRUE(remove_snap
.size() > 0);
703 EXPECT_TRUE(t
.empty());
704 EXPECT_FALSE(missing
.have_missing());
705 EXPECT_EQ(1U, log
.log
.size());
708 // there is no new entry (from the logs) and
709 // the old entry (from the log entry given in argument) is not a CLONE and
710 // the old entry prior_version is greater than the tail of the log :
711 // do nothing and return false
715 ObjectStore::Transaction t
;
717 oe
.mark_unrollbackable();
719 list
<hobject_t
> remove_snap
;
721 info
.log_tail
= eversion_t(1,1);
722 oe
.op
= pg_log_entry_t::MODIFY
;
723 oe
.prior_version
= eversion_t(2,1);
724 missing_add(oe
.soid
, oe
.prior_version
, eversion_t());
727 EXPECT_FALSE(is_dirty());
728 EXPECT_TRUE(remove_snap
.empty());
729 EXPECT_TRUE(t
.empty());
730 EXPECT_TRUE(log
.empty());
732 TestHandler
h(remove_snap
);
733 merge_old_entry(t
, oe
, info
, &h
);
736 EXPECT_FALSE(is_dirty());
737 EXPECT_TRUE(remove_snap
.empty());
738 EXPECT_TRUE(t
.empty());
739 EXPECT_TRUE(log
.empty());
742 // there is no new entry (from the logs) and
743 // the old entry (from the log entry given in argument) is not a CLONE and
744 // the old entry (from the log entry given in argument) is not a DELETE and
745 // the old entry prior_version is lower than the tail of the log :
746 // add the old object to the remove_snap list and
747 // add the old object to divergent priors and
748 // add or update the prior_version of the object to missing and
753 ObjectStore::Transaction t
;
755 oe
.mark_unrollbackable();
757 list
<hobject_t
> remove_snap
;
759 info
.log_tail
= eversion_t(2,1);
761 oe
.op
= pg_log_entry_t::MODIFY
;
762 oe
.prior_version
= eversion_t(1,1);
764 EXPECT_FALSE(is_dirty());
765 EXPECT_TRUE(remove_snap
.empty());
766 EXPECT_TRUE(t
.empty());
767 EXPECT_FALSE(missing
.have_missing());
768 EXPECT_TRUE(log
.empty());
770 TestHandler
h(remove_snap
);
771 merge_old_entry(t
, oe
, info
, &h
);
773 EXPECT_TRUE(is_dirty());
774 EXPECT_EQ(oe
.soid
, remove_snap
.front());
775 EXPECT_TRUE(t
.empty());
776 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
777 EXPECT_TRUE(log
.empty());
780 // there is no new entry (from the logs) and
781 // the old entry (from the log entry given in argument) is not a CLONE and
782 // the old entry (from the log entry given in argument) is a DELETE and
783 // the old entry prior_version is lower than the tail of the log :
784 // add the old object to divergent priors and
785 // add or update the prior_version of the object to missing and
790 ObjectStore::Transaction t
;
792 oe
.mark_unrollbackable();
794 list
<hobject_t
> remove_snap
;
796 info
.log_tail
= eversion_t(2,1);
798 oe
.op
= pg_log_entry_t::DELETE
;
799 oe
.prior_version
= eversion_t(1,1);
801 EXPECT_FALSE(is_dirty());
802 EXPECT_TRUE(remove_snap
.empty());
803 EXPECT_TRUE(t
.empty());
804 EXPECT_FALSE(missing
.have_missing());
805 EXPECT_TRUE(log
.empty());
807 TestHandler
h(remove_snap
);
808 merge_old_entry(t
, oe
, info
, &h
);
810 EXPECT_TRUE(is_dirty());
811 EXPECT_TRUE(remove_snap
.empty());
812 EXPECT_TRUE(t
.empty());
813 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
814 EXPECT_TRUE(log
.empty());
818 // there is no new entry (from the logs) and
819 // the old entry (from the log entry given in argument) is not a CLONE and
820 // the old entry (from the log entry given in argument) is not a DELETE and
821 // the old entry prior_version is eversion_t() :
822 // add the old object to the remove_snap list and
823 // remove the prior_version of the object from missing, if any and
828 ObjectStore::Transaction t
;
830 oe
.mark_unrollbackable();
832 list
<hobject_t
> remove_snap
;
834 info
.log_tail
= eversion_t(10,1);
836 oe
.op
= pg_log_entry_t::MODIFY
;
837 oe
.prior_version
= eversion_t();
839 missing
.add(oe
.soid
, eversion_t(1,1), eversion_t(), false);
842 EXPECT_FALSE(is_dirty());
843 EXPECT_TRUE(remove_snap
.empty());
844 EXPECT_TRUE(t
.empty());
845 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
846 EXPECT_TRUE(log
.empty());
848 TestHandler
h(remove_snap
);
849 merge_old_entry(t
, oe
, info
, &h
);
852 EXPECT_FALSE(is_dirty());
853 EXPECT_EQ(oe
.soid
, remove_snap
.front());
854 EXPECT_TRUE(t
.empty());
855 EXPECT_FALSE(missing
.have_missing());
856 EXPECT_TRUE(log
.empty());
861 TEST_F(PGLogTest
, merge_log
) {
862 // head and tail match, last_backfill is set:
871 list
<hobject_t
> remove_snap
;
872 bool dirty_info
= false;
873 bool dirty_big_info
= false;
875 hobject_t
last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
876 info
.last_backfill
= last_backfill
;
877 eversion_t
stat_version(10, 1);
878 info
.stats
.version
= stat_version
;
879 log
.tail
= olog
.tail
= eversion_t(1, 1);
880 log
.head
= olog
.head
= eversion_t(2, 1);
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_EQ(last_backfill
, info
.last_backfill
);
887 EXPECT_TRUE(info
.purged_snaps
.empty());
888 EXPECT_FALSE(is_dirty());
889 EXPECT_FALSE(dirty_info
);
890 EXPECT_FALSE(dirty_big_info
);
892 TestHandler
h(remove_snap
);
893 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
894 dirty_info
, dirty_big_info
);
896 EXPECT_FALSE(missing
.have_missing());
897 EXPECT_EQ(0U, log
.log
.size());
898 EXPECT_EQ(stat_version
, info
.stats
.version
);
899 EXPECT_TRUE(remove_snap
.empty());
900 EXPECT_TRUE(info
.purged_snaps
.empty());
901 EXPECT_FALSE(is_dirty());
902 EXPECT_FALSE(dirty_info
);
903 EXPECT_FALSE(dirty_big_info
);
906 // head and tail match, last_backfill is not set: info.stats is
907 // copied from oinfo.stats but info.stats.reported_* is guaranteed to
908 // never be replaced by a lower version
916 list
<hobject_t
> remove_snap
;
917 bool dirty_info
= false;
918 bool dirty_big_info
= false;
920 eversion_t
stat_version(10, 1);
921 oinfo
.stats
.version
= stat_version
;
922 info
.stats
.reported_seq
= 1;
923 info
.stats
.reported_epoch
= 10;
924 oinfo
.stats
.reported_seq
= 1;
925 oinfo
.stats
.reported_epoch
= 1;
926 log
.tail
= olog
.tail
= eversion_t(1, 1);
927 log
.head
= olog
.head
= eversion_t(2, 1);
928 missing
.may_include_deletes
= false;
930 EXPECT_FALSE(missing
.have_missing());
931 EXPECT_EQ(0U, log
.log
.size());
932 EXPECT_EQ(eversion_t(), info
.stats
.version
);
933 EXPECT_EQ(1ull, info
.stats
.reported_seq
);
934 EXPECT_EQ(10u, info
.stats
.reported_epoch
);
935 EXPECT_TRUE(remove_snap
.empty());
936 EXPECT_TRUE(info
.last_backfill
.is_max());
937 EXPECT_TRUE(info
.purged_snaps
.empty());
938 EXPECT_FALSE(is_dirty());
939 EXPECT_FALSE(dirty_info
);
940 EXPECT_FALSE(dirty_big_info
);
942 TestHandler
h(remove_snap
);
943 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
944 dirty_info
, dirty_big_info
);
946 EXPECT_FALSE(missing
.have_missing());
947 EXPECT_EQ(0U, log
.log
.size());
948 EXPECT_EQ(stat_version
, info
.stats
.version
);
949 EXPECT_EQ(1ull, info
.stats
.reported_seq
);
950 EXPECT_EQ(10u, info
.stats
.reported_epoch
);
951 EXPECT_TRUE(remove_snap
.empty());
952 EXPECT_TRUE(info
.purged_snaps
.empty());
953 EXPECT_FALSE(is_dirty());
954 EXPECT_FALSE(dirty_info
);
955 EXPECT_FALSE(dirty_big_info
);
959 +--------------------------+
961 +--------+-------+---------+
963 |version | hash | version |
965 | | x5 | (1,1) < tail
968 tail > (1,4) | x7 | |
971 head > (1,5) | x9 | (1,5) < head
974 +--------+-------+---------+
1001 list
<hobject_t
> remove_snap
;
1002 bool dirty_info
= false;
1003 bool dirty_big_info
= false;
1004 missing
.may_include_deletes
= false;
1008 e
.mark_unrollbackable();
1010 e
.version
= eversion_t(1, 4);
1011 e
.soid
.set_hash(0x5);
1012 log
.tail
= e
.version
;
1013 log
.log
.push_back(e
);
1014 e
.version
= eversion_t(1, 5);
1015 e
.soid
.set_hash(0x9);
1016 log
.log
.push_back(e
);
1017 log
.head
= e
.version
;
1020 info
.last_update
= log
.head
;
1022 e
.version
= eversion_t(1, 1);
1023 e
.soid
.set_hash(0x5);
1024 olog
.tail
= e
.version
;
1025 olog
.log
.push_back(e
);
1026 e
.version
= eversion_t(1, 5);
1027 e
.soid
.set_hash(0x9);
1028 olog
.log
.push_back(e
);
1029 olog
.head
= e
.version
;
1032 hobject_t
last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
1033 info
.last_backfill
= last_backfill
;
1034 eversion_t
stat_version(10, 1);
1035 info
.stats
.version
= stat_version
;
1037 EXPECT_FALSE(missing
.have_missing());
1038 EXPECT_EQ(2U, log
.log
.size());
1039 EXPECT_EQ(stat_version
, info
.stats
.version
);
1040 EXPECT_TRUE(remove_snap
.empty());
1041 EXPECT_EQ(last_backfill
, info
.last_backfill
);
1042 EXPECT_TRUE(info
.purged_snaps
.empty());
1043 EXPECT_FALSE(is_dirty());
1044 EXPECT_FALSE(dirty_info
);
1045 EXPECT_FALSE(dirty_big_info
);
1047 TestHandler
h(remove_snap
);
1048 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1049 dirty_info
, dirty_big_info
);
1051 EXPECT_FALSE(missing
.have_missing());
1052 EXPECT_EQ(3U, log
.log
.size());
1053 EXPECT_EQ(stat_version
, info
.stats
.version
);
1054 EXPECT_TRUE(remove_snap
.empty());
1055 EXPECT_TRUE(info
.purged_snaps
.empty());
1056 EXPECT_TRUE(is_dirty());
1057 EXPECT_TRUE(dirty_info
);
1058 EXPECT_TRUE(dirty_big_info
);
1061 /* +--------------------------+
1063 +--------+-------+---------+
1065 |version | hash | version |
1067 tail > (1,1) | x5 | (1,1) < tail
1070 | (1,2) | x3 | (1,2) < lower_bound
1073 head > (1,3) | x9 | |
1079 | | x7 | (2,4) < head
1081 +--------+-------+---------+
1083 The log entry (1,3) deletes the object x9 but the olog entry (2,3) modifies
1084 it and is authoritative : the log entry (1,3) is divergent.
1094 list
<hobject_t
> remove_snap
;
1095 bool dirty_info
= false;
1096 bool dirty_big_info
= false;
1098 hobject_t divergent_object
;
1099 missing
.may_include_deletes
= true;
1103 e
.mark_unrollbackable();
1105 e
.version
= eversion_t(1, 1);
1106 e
.soid
.set_hash(0x5);
1107 log
.tail
= e
.version
;
1108 log
.log
.push_back(e
);
1109 e
.version
= eversion_t(1, 2);
1110 e
.soid
.set_hash(0x3);
1111 log
.log
.push_back(e
);
1112 e
.version
= eversion_t(1,3);
1113 e
.soid
.set_hash(0x9);
1114 divergent_object
= e
.soid
;
1115 e
.op
= pg_log_entry_t::DELETE
;
1116 log
.log
.push_back(e
);
1117 log
.head
= e
.version
;
1120 info
.last_update
= log
.head
;
1122 e
.version
= eversion_t(1, 1);
1123 e
.soid
.set_hash(0x5);
1124 olog
.tail
= e
.version
;
1125 olog
.log
.push_back(e
);
1126 e
.version
= eversion_t(1, 2);
1127 e
.soid
.set_hash(0x3);
1128 olog
.log
.push_back(e
);
1129 e
.version
= eversion_t(2, 3);
1130 e
.soid
.set_hash(0x9);
1131 e
.op
= pg_log_entry_t::MODIFY
;
1132 olog
.log
.push_back(e
);
1133 e
.version
= eversion_t(2, 4);
1134 e
.soid
.set_hash(0x7);
1135 e
.op
= pg_log_entry_t::DELETE
;
1136 olog
.log
.push_back(e
);
1137 olog
.head
= e
.version
;
1140 snapid_t
purged_snap(1);
1142 oinfo
.last_update
= olog
.head
;
1143 oinfo
.purged_snaps
.insert(purged_snap
);
1146 EXPECT_FALSE(missing
.have_missing());
1147 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1148 EXPECT_EQ(3U, log
.log
.size());
1149 EXPECT_TRUE(remove_snap
.empty());
1150 EXPECT_EQ(log
.head
, info
.last_update
);
1151 EXPECT_TRUE(info
.purged_snaps
.empty());
1152 EXPECT_FALSE(is_dirty());
1153 EXPECT_FALSE(dirty_info
);
1154 EXPECT_FALSE(dirty_big_info
);
1156 TestHandler
h(remove_snap
);
1157 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1158 dirty_info
, dirty_big_info
);
1160 /* When the divergent entry is a DELETE and the authoritative
1161 entry is a MODIFY, the object will be added to missing : it is
1162 a verifiable side effect proving the entry was identified
1165 EXPECT_TRUE(missing
.is_missing(divergent_object
));
1166 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1167 EXPECT_EQ(4U, log
.log
.size());
1168 /* DELETE entries from olog that are appended to the hed of the
1169 log, and the divergent version of the object is removed (added
1172 EXPECT_EQ(0x9U
, remove_snap
.front().get_hash());
1173 EXPECT_EQ(log
.head
, info
.last_update
);
1174 EXPECT_TRUE(info
.purged_snaps
.contains(purged_snap
));
1175 EXPECT_TRUE(is_dirty());
1176 EXPECT_TRUE(dirty_info
);
1177 EXPECT_TRUE(dirty_big_info
);
1180 /* +--------------------------+
1182 +--------+-------+---------+
1184 |version | hash | version |
1186 tail > (1,1) | x5 | (1,1) < tail
1189 | (1,2) | x3 | (1,2) < lower_bound
1192 head > (1,3) | x9 | |
1198 | | x7 | (2,4) < head
1200 +--------+-------+---------+
1202 The log entry (1,3) deletes the object x9 but the olog entry (2,3) modifies
1203 it and is authoritative : the log entry (1,3) is divergent.
1213 list
<hobject_t
> remove_snap
;
1214 bool dirty_info
= false;
1215 bool dirty_big_info
= false;
1217 hobject_t divergent_object
;
1221 e
.mark_unrollbackable();
1223 e
.version
= eversion_t(1, 1);
1224 e
.soid
.set_hash(0x5);
1225 log
.tail
= e
.version
;
1226 log
.log
.push_back(e
);
1227 e
.version
= eversion_t(1, 2);
1228 e
.soid
.set_hash(0x3);
1229 log
.log
.push_back(e
);
1230 e
.version
= eversion_t(1,3);
1231 e
.soid
.set_hash(0x9);
1232 divergent_object
= e
.soid
;
1233 e
.op
= pg_log_entry_t::DELETE
;
1234 log
.log
.push_back(e
);
1235 log
.head
= e
.version
;
1238 info
.last_update
= log
.head
;
1240 e
.version
= eversion_t(1, 1);
1241 e
.soid
.set_hash(0x5);
1242 olog
.tail
= e
.version
;
1243 olog
.log
.push_back(e
);
1244 e
.version
= eversion_t(1, 2);
1245 e
.soid
.set_hash(0x3);
1246 olog
.log
.push_back(e
);
1247 e
.version
= eversion_t(2, 3);
1248 e
.soid
.set_hash(0x9);
1249 e
.op
= pg_log_entry_t::MODIFY
;
1250 olog
.log
.push_back(e
);
1251 e
.version
= eversion_t(2, 4);
1252 e
.soid
.set_hash(0x7);
1253 e
.op
= pg_log_entry_t::DELETE
;
1254 olog
.log
.push_back(e
);
1255 olog
.head
= e
.version
;
1258 snapid_t
purged_snap(1);
1260 oinfo
.last_update
= olog
.head
;
1261 oinfo
.purged_snaps
.insert(purged_snap
);
1264 EXPECT_FALSE(missing
.have_missing());
1265 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1266 EXPECT_EQ(3U, log
.log
.size());
1267 EXPECT_TRUE(remove_snap
.empty());
1268 EXPECT_EQ(log
.head
, info
.last_update
);
1269 EXPECT_TRUE(info
.purged_snaps
.empty());
1270 EXPECT_FALSE(is_dirty());
1271 EXPECT_FALSE(dirty_info
);
1272 EXPECT_FALSE(dirty_big_info
);
1274 TestHandler
h(remove_snap
);
1275 missing
.may_include_deletes
= false;
1276 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1277 dirty_info
, dirty_big_info
);
1279 /* When the divergent entry is a DELETE and the authoritative
1280 entry is a MODIFY, the object will be added to missing : it is
1281 a verifiable side effect proving the entry was identified
1284 EXPECT_TRUE(missing
.is_missing(divergent_object
));
1285 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1286 EXPECT_EQ(4U, log
.log
.size());
1287 /* DELETE entries from olog that are appended to the hed of the
1288 log, and the divergent version of the object is removed (added
1289 to remove_snap). When peering handles deletes, it is the earlier
1290 version that is in the removed list.
1292 EXPECT_EQ(0x7U
, remove_snap
.front().get_hash());
1293 EXPECT_EQ(log
.head
, info
.last_update
);
1294 EXPECT_TRUE(info
.purged_snaps
.contains(purged_snap
));
1295 EXPECT_TRUE(is_dirty());
1296 EXPECT_TRUE(dirty_info
);
1297 EXPECT_TRUE(dirty_big_info
);
1300 /* +--------------------------+
1302 +--------+-------+---------+
1304 |version | hash | version |
1306 tail > (1,1) | x5 | (1,1) < tail
1309 | (1,4) | x7 | (1,4) < head
1312 head > (1,5) | x9 | |
1315 +--------+-------+---------+
1317 The head of the log entry (1,5) is divergent because it is greater than the
1328 list
<hobject_t
> remove_snap
;
1329 bool dirty_info
= false;
1330 bool dirty_big_info
= false;
1334 e
.mark_unrollbackable();
1336 e
.version
= eversion_t(1, 1);
1337 e
.soid
.set_hash(0x5);
1338 log
.tail
= e
.version
;
1339 log
.log
.push_back(e
);
1340 e
.version
= eversion_t(1, 4);
1341 e
.soid
.set_hash(0x7);
1342 log
.log
.push_back(e
);
1343 e
.version
= eversion_t(1, 5);
1344 e
.soid
.set_hash(0x9);
1345 log
.log
.push_back(e
);
1346 log
.head
= e
.version
;
1349 info
.last_update
= log
.head
;
1351 e
.version
= eversion_t(1, 1);
1352 e
.soid
.set_hash(0x5);
1353 olog
.tail
= e
.version
;
1354 olog
.log
.push_back(e
);
1355 e
.version
= eversion_t(1, 4);
1356 e
.soid
.set_hash(0x7);
1357 olog
.log
.push_back(e
);
1358 olog
.head
= e
.version
;
1361 hobject_t
last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
1362 info
.last_backfill
= last_backfill
;
1363 eversion_t
stat_version(10, 1);
1364 info
.stats
.version
= stat_version
;
1366 EXPECT_FALSE(missing
.have_missing());
1367 EXPECT_EQ(3U, log
.log
.size());
1368 EXPECT_EQ(stat_version
, info
.stats
.version
);
1369 EXPECT_TRUE(remove_snap
.empty());
1370 EXPECT_EQ(last_backfill
, info
.last_backfill
);
1371 EXPECT_TRUE(info
.purged_snaps
.empty());
1372 EXPECT_FALSE(is_dirty());
1373 EXPECT_FALSE(dirty_info
);
1374 EXPECT_FALSE(dirty_big_info
);
1376 TestHandler
h(remove_snap
);
1377 missing
.may_include_deletes
= false;
1378 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1379 dirty_info
, dirty_big_info
);
1381 EXPECT_FALSE(missing
.have_missing());
1382 EXPECT_EQ(2U, log
.log
.size());
1383 EXPECT_EQ(stat_version
, info
.stats
.version
);
1384 EXPECT_EQ(0x9U
, remove_snap
.front().get_hash());
1385 EXPECT_TRUE(info
.purged_snaps
.empty());
1386 EXPECT_TRUE(is_dirty());
1387 EXPECT_TRUE(dirty_info
);
1388 EXPECT_TRUE(dirty_big_info
);
1391 // If our log is empty, the incoming log needs to have not been trimmed.
1399 list
<hobject_t
> remove_snap
;
1400 bool dirty_info
= false;
1401 bool dirty_big_info
= false;
1403 // olog has been trimmed
1404 olog
.tail
= eversion_t(1, 1);
1406 TestHandler
h(remove_snap
);
1407 PrCtl unset_dumpable
;
1408 ASSERT_DEATH(merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1409 dirty_info
, dirty_big_info
), "");
1414 TEST_F(PGLogTest
, proc_replica_log
) {
1415 // empty log : no side effect
1421 pg_missing_t omissing
;
1424 eversion_t
last_update(1, 1);
1425 log
.head
= olog
.head
= oinfo
.last_update
= last_update
;
1426 eversion_t
last_complete(1, 1);
1427 oinfo
.last_complete
= last_complete
;
1429 EXPECT_FALSE(omissing
.have_missing());
1430 EXPECT_EQ(last_update
, oinfo
.last_update
);
1431 EXPECT_EQ(last_complete
, oinfo
.last_complete
);
1433 missing
.may_include_deletes
= false;
1434 proc_replica_log(oinfo
, olog
, omissing
, from
);
1436 EXPECT_FALSE(omissing
.have_missing());
1437 EXPECT_EQ(last_update
, oinfo
.last_update
);
1438 EXPECT_EQ(last_update
, oinfo
.last_complete
);
1441 /* +--------------------------+
1443 +--------+-------+---------+
1445 |version | hash | version |
1447 | | x3 | (1,1) < tail
1450 tail > (1,2) | x5 | |
1453 head > (1,3) | x9 | |
1456 | | x9 | (2,3) < head
1459 +--------+-------+---------+
1461 The log entry (1,3) deletes the object x9 and the olog entry
1462 (2,3) also deletes it : do nothing. The olog tail is ignored
1463 because it is before the log tail.
1471 pg_missing_t omissing
;
1476 e
.mark_unrollbackable();
1478 e
.version
= eversion_t(1, 2);
1479 e
.soid
.set_hash(0x5);
1480 log
.tail
= e
.version
;
1481 log
.log
.push_back(e
);
1482 e
.version
= eversion_t(1, 3);
1483 e
.soid
.set_hash(0x9);
1484 e
.op
= pg_log_entry_t::DELETE
;
1485 log
.log
.push_back(e
);
1486 log
.head
= e
.version
;
1489 e
.version
= eversion_t(1, 1);
1490 e
.soid
.set_hash(0x3);
1491 olog
.tail
= e
.version
;
1492 olog
.log
.push_back(e
);
1493 e
.version
= eversion_t(2, 3);
1494 e
.soid
.set_hash(0x9);
1495 e
.op
= pg_log_entry_t::DELETE
;
1496 olog
.log
.push_back(e
);
1497 olog
.head
= e
.version
;
1499 oinfo
.last_update
= olog
.head
;
1500 oinfo
.last_complete
= olog
.head
;
1503 EXPECT_FALSE(omissing
.have_missing());
1504 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1505 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1507 missing
.may_include_deletes
= false;
1508 proc_replica_log(oinfo
, olog
, omissing
, from
);
1510 EXPECT_FALSE(omissing
.have_missing());
1518 pg_missing_t omissing
;
1521 hobject_t divergent_object
;
1525 e
.mark_unrollbackable();
1528 e
.soid
= divergent_object
;
1529 e
.soid
.set_hash(0x1);
1530 e
.version
= eversion_t(1, 1);
1531 log
.tail
= e
.version
;
1532 log
.log
.push_back(e
);
1534 e
.soid
= divergent_object
;
1535 e
.prior_version
= eversion_t(1, 1);
1536 e
.version
= eversion_t(1, 2);
1537 log
.tail
= e
.version
;
1538 log
.log
.push_back(e
);
1540 e
.soid
.set_hash(0x3);
1541 e
.version
= eversion_t(1, 4);
1542 log
.log
.push_back(e
);
1544 e
.soid
.set_hash(0x7);
1545 e
.version
= eversion_t(1, 5);
1546 log
.log
.push_back(e
);
1548 e
.soid
.set_hash(0x8);
1549 e
.version
= eversion_t(1, 6);
1550 log
.log
.push_back(e
);
1552 e
.soid
.set_hash(0x9);
1553 e
.op
= pg_log_entry_t::DELETE
;
1554 e
.version
= eversion_t(2, 7);
1555 log
.log
.push_back(e
);
1557 e
.soid
.set_hash(0xa);
1558 e
.version
= eversion_t(2, 8);
1559 log
.head
= e
.version
;
1560 log
.log
.push_back(e
);
1565 e
.soid
= divergent_object
;
1566 e
.soid
.set_hash(0x1);
1567 e
.version
= eversion_t(1, 1);
1568 olog
.tail
= e
.version
;
1569 olog
.log
.push_back(e
);
1571 e
.soid
= divergent_object
;
1572 e
.prior_version
= eversion_t(1, 1);
1573 e
.version
= eversion_t(1, 2);
1574 olog
.log
.push_back(e
);
1576 e
.prior_version
= eversion_t(0, 0);
1577 e
.soid
.set_hash(0x3);
1578 e
.version
= eversion_t(1, 4);
1579 olog
.log
.push_back(e
);
1581 e
.soid
.set_hash(0x7);
1582 e
.version
= eversion_t(1, 5);
1583 olog
.log
.push_back(e
);
1585 e
.soid
.set_hash(0x8);
1586 e
.version
= eversion_t(1, 6);
1587 olog
.log
.push_back(e
);
1589 e
.soid
.set_hash(0x9); // should not be added to missing, create
1590 e
.op
= pg_log_entry_t::MODIFY
;
1591 e
.version
= eversion_t(1, 7);
1592 olog
.log
.push_back(e
);
1594 e
.soid
= divergent_object
; // should be added to missing at 1,2
1595 e
.op
= pg_log_entry_t::MODIFY
;
1596 e
.version
= eversion_t(1, 8);
1597 e
.prior_version
= eversion_t(1, 2);
1598 olog
.log
.push_back(e
);
1599 olog
.head
= e
.version
;
1601 oinfo
.last_update
= olog
.head
;
1602 oinfo
.last_complete
= olog
.head
;
1605 EXPECT_FALSE(omissing
.have_missing());
1606 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1607 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1609 missing
.may_include_deletes
= false;
1610 proc_replica_log(oinfo
, olog
, omissing
, from
);
1612 EXPECT_TRUE(omissing
.have_missing());
1613 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1614 EXPECT_EQ(eversion_t(1, 2), omissing
.get_items().at(divergent_object
).need
);
1615 EXPECT_EQ(eversion_t(1, 6), oinfo
.last_update
);
1616 EXPECT_EQ(eversion_t(1, 1), oinfo
.last_complete
);
1619 /* +--------------------------+
1621 +--------+-------+---------+
1623 |version | hash | version |
1625 tail > (1,1) | x9 | (1,1) < tail
1628 | (1,2) | x3 | (1,2) |
1631 head > (1,3) | x9 | |
1634 | | x9 | (2,3) < head
1637 +--------+-------+---------+
1639 The log entry (1,3) deletes the object x9 and the olog entry
1640 (2,3) also deletes it : do nothing.
1648 pg_missing_t omissing
;
1651 eversion_t
last_update(1, 2);
1652 hobject_t divergent_object
;
1653 divergent_object
.set_hash(0x9);
1657 e
.mark_unrollbackable();
1659 e
.version
= eversion_t(1, 1);
1660 e
.soid
= divergent_object
;
1661 log
.tail
= e
.version
;
1662 log
.log
.push_back(e
);
1663 e
.version
= last_update
;
1664 e
.soid
.set_hash(0x3);
1665 log
.log
.push_back(e
);
1666 e
.version
= eversion_t(2, 3);
1667 e
.prior_version
= eversion_t(1, 1);
1668 e
.soid
= divergent_object
;
1669 e
.op
= pg_log_entry_t::DELETE
;
1670 log
.log
.push_back(e
);
1671 log
.head
= e
.version
;
1674 e
.version
= eversion_t(1, 1);
1675 e
.soid
= divergent_object
;
1676 olog
.tail
= e
.version
;
1677 olog
.log
.push_back(e
);
1678 e
.version
= last_update
;
1679 e
.soid
.set_hash(0x3);
1680 olog
.log
.push_back(e
);
1681 e
.version
= eversion_t(1, 3);
1682 e
.prior_version
= eversion_t(1, 1);
1683 e
.soid
= divergent_object
;
1684 e
.op
= pg_log_entry_t::DELETE
;
1685 olog
.log
.push_back(e
);
1686 olog
.head
= e
.version
;
1688 oinfo
.last_update
= olog
.head
;
1689 oinfo
.last_complete
= olog
.head
;
1692 EXPECT_FALSE(omissing
.have_missing());
1693 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1694 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1696 missing
.may_include_deletes
= false;
1697 proc_replica_log(oinfo
, olog
, omissing
, from
);
1699 EXPECT_TRUE(omissing
.have_missing());
1700 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1701 EXPECT_EQ(omissing
.get_items().at(divergent_object
).have
, eversion_t(0, 0));
1702 EXPECT_EQ(omissing
.get_items().at(divergent_object
).need
, eversion_t(1, 1));
1703 EXPECT_EQ(last_update
, oinfo
.last_update
);
1706 /* +--------------------------+
1708 +--------+-------+---------+
1710 |version | hash | version |
1712 tail > (1,1) | x9 | (1,1) < tail
1715 | (1,2) | x3 | (1,2) |
1718 head > (1,3) | x9 | |
1721 | | x9 | (2,3) < head
1724 +--------+-------+---------+
1726 The log entry (1,3) deletes the object x9 but the olog entry
1727 (2,3) modifies it : remove it from omissing.
1735 pg_missing_t omissing
;
1738 eversion_t
last_update(1, 2);
1739 hobject_t divergent_object
;
1743 e
.mark_unrollbackable();
1745 e
.version
= eversion_t(1, 1);
1746 e
.soid
= divergent_object
;
1747 log
.tail
= e
.version
;
1748 log
.log
.push_back(e
);
1749 e
.version
= last_update
;
1750 e
.soid
.set_hash(0x3);
1751 log
.log
.push_back(e
);
1752 e
.version
= eversion_t(2, 3);
1753 e
.prior_version
= eversion_t(1, 1);
1754 e
.soid
= divergent_object
;
1755 e
.op
= pg_log_entry_t::DELETE
;
1756 log
.log
.push_back(e
);
1757 log
.head
= e
.version
;
1760 e
.version
= eversion_t(1, 1);
1761 e
.soid
= divergent_object
;
1762 olog
.tail
= e
.version
;
1763 olog
.log
.push_back(e
);
1764 e
.version
= last_update
;
1765 e
.soid
.set_hash(0x3);
1766 olog
.log
.push_back(e
);
1767 e
.version
= eversion_t(1, 3);
1768 e
.prior_version
= eversion_t(1, 1);
1769 e
.soid
= divergent_object
;
1770 divergent_object
= e
.soid
;
1771 omissing
.add(divergent_object
, e
.version
, eversion_t(), false);
1772 e
.op
= pg_log_entry_t::MODIFY
;
1773 olog
.log
.push_back(e
);
1774 olog
.head
= e
.version
;
1776 oinfo
.last_update
= olog
.head
;
1777 oinfo
.last_complete
= olog
.head
;
1780 EXPECT_TRUE(omissing
.have_missing());
1781 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1782 EXPECT_EQ(eversion_t(1, 3), omissing
.get_items().at(divergent_object
).need
);
1783 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1784 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1786 missing
.may_include_deletes
= false;
1787 proc_replica_log(oinfo
, olog
, omissing
, from
);
1789 EXPECT_TRUE(omissing
.have_missing());
1790 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1791 EXPECT_EQ(omissing
.get_items().at(divergent_object
).have
, eversion_t(0, 0));
1792 EXPECT_EQ(omissing
.get_items().at(divergent_object
).need
, eversion_t(1, 1));
1793 EXPECT_EQ(last_update
, oinfo
.last_update
);
1796 /* +--------------------------+
1798 +--------+-------+---------+
1800 |version | hash | version |
1802 tail > (1,1) | x9 | (1,1) < tail
1805 | (1,2) | x3 | (1,2) |
1808 | | x9 | (1,3) < head
1811 head > (2,3) | x9 | |
1814 +--------+-------+---------+
1816 The log entry (2,3) deletes the object x9 but the olog entry
1817 (1,3) modifies it : proc_replica_log should adjust missing to
1818 1,1 for that object until add_next_event in PG::activate processes
1826 pg_missing_t omissing
;
1829 eversion_t
last_update(1, 2);
1830 hobject_t divergent_object
;
1831 eversion_t
new_version(2, 3);
1832 eversion_t
divergent_version(1, 3);
1836 e
.mark_unrollbackable();
1838 e
.version
= eversion_t(1, 1);
1839 e
.soid
.set_hash(0x9);
1840 log
.tail
= e
.version
;
1841 log
.log
.push_back(e
);
1842 e
.version
= last_update
;
1843 e
.soid
.set_hash(0x3);
1844 log
.log
.push_back(e
);
1845 e
.version
= new_version
;
1846 e
.prior_version
= eversion_t(1, 1);
1847 e
.soid
.set_hash(0x9);
1848 e
.op
= pg_log_entry_t::DELETE
;
1849 log
.log
.push_back(e
);
1850 log
.head
= e
.version
;
1853 e
.op
= pg_log_entry_t::MODIFY
;
1854 e
.version
= eversion_t(1, 1);
1855 e
.soid
.set_hash(0x9);
1856 olog
.tail
= e
.version
;
1857 olog
.log
.push_back(e
);
1858 e
.version
= last_update
;
1859 e
.soid
.set_hash(0x3);
1860 olog
.log
.push_back(e
);
1861 e
.version
= divergent_version
;
1862 e
.prior_version
= eversion_t(1, 1);
1863 e
.soid
.set_hash(0x9);
1864 divergent_object
= e
.soid
;
1865 omissing
.add(divergent_object
, e
.version
, eversion_t(), false);
1866 e
.op
= pg_log_entry_t::MODIFY
;
1867 olog
.log
.push_back(e
);
1868 olog
.head
= e
.version
;
1870 oinfo
.last_update
= olog
.head
;
1871 oinfo
.last_complete
= olog
.head
;
1874 EXPECT_TRUE(omissing
.have_missing());
1875 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1876 EXPECT_EQ(divergent_version
, omissing
.get_items().at(divergent_object
).need
);
1877 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1878 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1880 missing
.may_include_deletes
= false;
1881 proc_replica_log(oinfo
, olog
, omissing
, from
);
1883 EXPECT_TRUE(omissing
.have_missing());
1884 EXPECT_TRUE(omissing
.get_items().begin()->second
.need
== eversion_t(1, 1));
1885 EXPECT_EQ(last_update
, oinfo
.last_update
);
1886 EXPECT_EQ(eversion_t(0, 0), oinfo
.last_complete
);
1891 TEST_F(PGLogTest
, merge_log_1
) {
1893 t
.base
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1895 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1897 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1899 t
.toremove
.insert(mk_obj(1));
1905 TEST_F(PGLogTest
, merge_log_2
) {
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_rb(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
.torollback
.insert(
1913 t
.torollback
.begin(), t
.div
.rbegin(), t
.div
.rend());
1919 TEST_F(PGLogTest
, merge_log_3
) {
1921 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1923 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1924 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1926 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1928 t
.toremove
.insert(mk_obj(1));
1934 TEST_F(PGLogTest
, merge_log_4
) {
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_rb(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
.init
.add(mk_obj(1), mk_evt(10, 102), mk_evt(0, 0), false);
1942 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1948 TEST_F(PGLogTest
, merge_log_5
) {
1950 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1952 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1953 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
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(0, 0), false);
1959 t
.toremove
.insert(mk_obj(1));
1965 TEST_F(PGLogTest
, merge_log_6
) {
1967 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1969 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1971 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100), false);
1977 TEST_F(PGLogTest
, merge_log_7
) {
1979 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1981 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1983 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1984 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), false);
1990 TEST_F(PGLogTest
, merge_log_8
) {
1992 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1994 t
.auth
.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1996 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1997 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), true);
2003 TEST_F(PGLogTest
, merge_log_9
) {
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_dt(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
.toremove
.insert(mk_obj(1));
2011 t
.deletes_during_peering
= true;
2017 TEST_F(PGLogTest
, merge_log_10
) {
2019 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2021 t
.auth
.push_back(mk_ple_ldt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
2023 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
2024 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), true);
2030 TEST_F(PGLogTest
, merge_log_prior_version_have
) {
2032 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2034 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
2036 t
.init
.add(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100), false);
2042 TEST_F(PGLogTest
, merge_log_split_missing_entries_at_head
) {
2044 t
.auth
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2045 t
.auth
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2047 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(8, 70), mk_evt(8, 65)));
2050 t
.set_div_bounds(mk_evt(9, 79), mk_evt(8, 69));
2051 t
.set_auth_bounds(mk_evt(15, 160), mk_evt(9, 77));
2052 t
.final
.add(mk_obj(1), mk_evt(15, 150), mk_evt(8, 70), false);
2056 TEST_F(PGLogTest
, olog_tail_gt_log_tail_split
) {
2058 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2059 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2060 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150)));
2063 t
.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
2064 t
.set_auth_bounds(mk_evt(15, 156), mk_evt(10, 99));
2065 t
.final
.add(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150), false);
2069 TEST_F(PGLogTest
, olog_tail_gt_log_tail_split2
) {
2071 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2072 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2073 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(16, 155), mk_evt(15, 150)));
2074 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 153), mk_evt(15, 150)));
2077 t
.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
2078 t
.set_auth_bounds(mk_evt(16, 156), mk_evt(10, 99));
2079 t
.final
.add(mk_obj(1), mk_evt(16, 155), mk_evt(0, 0), false);
2080 t
.toremove
.insert(mk_obj(1));
2084 TEST_F(PGLogTest
, filter_log_1
) {
2090 int64_t pool_id
= 1;
2093 int pg_num
= max_osd
<< bits
;
2094 int num_objects
= 1000;
2095 int num_internal
= 10;
2097 // Set up splitting map
2098 OSDMap
*osdmap
= new OSDMap
;
2100 test_uuid
.generate_random();
2101 osdmap
->build_simple_with_pool(g_ceph_context
, epoch
, test_uuid
, max_osd
, bits
, bits
);
2102 osdmap
->set_state(osd_id
, CEPH_OSD_EXISTS
);
2104 const string
hit_set_namespace("internal");
2108 e
.mark_unrollbackable();
2109 e
.op
= pg_log_entry_t::MODIFY
;
2110 e
.soid
.pool
= pool_id
;
2114 for (i
= 1; i
<= num_objects
; ++i
) {
2115 e
.version
= eversion_t(epoch
, i
);
2116 // Use this to generate random file names
2117 uuid_name
.generate_random();
2120 e
.soid
.oid
.name
= name
.str();
2121 // First has no namespace
2123 // num_internal have the internal namspace
2124 if (i
<= num_internal
+ 1) {
2125 e
.soid
.nspace
= hit_set_namespace
;
2126 } else { // rest have different namespaces
2129 e
.soid
.nspace
= ns
.str();
2132 log
.log
.push_back(e
);
2134 log
.tail
= e
.version
;
2136 log
.head
= e
.version
;
2140 spg_t
pgid(pg_t(2, pool_id
), shard_id_t::NO_SHARD
);
2142 // See if we created the right number of entries
2143 int total
= log
.log
.size();
2144 ASSERT_EQ(total
, num_objects
);
2146 // Some should be removed
2148 pg_log_t filtered
, reject
;
2149 pg_log_t::filter_log(
2150 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
2151 log
= IndexedLog(filtered
);
2153 EXPECT_LE(log
.log
.size(), (size_t)total
);
2155 // If we filter a second time, there should be the same total
2156 total
= log
.log
.size();
2158 pg_log_t filtered
, reject
;
2159 pg_log_t::filter_log(
2160 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
2161 log
= IndexedLog(filtered
);
2163 EXPECT_EQ(log
.log
.size(), (size_t)total
);
2165 // Increase pg_num as if there would be a split
2166 int new_pg_num
= pg_num
* 16;
2167 OSDMap::Incremental
inc(epoch
+ 1);
2168 inc
.fsid
= test_uuid
;
2169 const pg_pool_t
*pool
= osdmap
->get_pg_pool(pool_id
);
2172 newpool
.set_pg_num(new_pg_num
);
2173 newpool
.set_pgp_num(new_pg_num
);
2174 inc
.new_pools
[pool_id
] = newpool
;
2175 int ret
= osdmap
->apply_incremental(inc
);
2178 // We should have fewer entries after a filter
2180 pg_log_t filtered
, reject
;
2181 pg_log_t::filter_log(
2182 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
2183 log
= IndexedLog(filtered
);
2185 EXPECT_LE(log
.log
.size(), (size_t)total
);
2187 // Make sure all internal entries are retained
2189 for (list
<pg_log_entry_t
>::iterator i
= log
.log
.begin();
2190 i
!= log
.log
.end(); ++i
) {
2191 if (i
->soid
.nspace
== hit_set_namespace
) count
++;
2193 EXPECT_EQ(count
, num_internal
);
2197 TEST_F(PGLogTest
, get_request
) {
2200 // make sure writes, deletes, and errors are found
2201 vector
<pg_log_entry_t
> entries
;
2202 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
2204 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(6,2), eversion_t(3,4),
2205 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2206 utime_t(0,1), -ENOENT
));
2208 pg_log_entry_t(pg_log_entry_t::MODIFY
, oid
, eversion_t(6,3), eversion_t(3,4),
2209 2, osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2212 pg_log_entry_t(pg_log_entry_t::DELETE
, oid
, eversion_t(7,4), eversion_t(7,4),
2213 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2216 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(7,5), eversion_t(7,4),
2217 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2218 utime_t(20,1), -ENOENT
));
2220 for (auto &entry
: entries
) {
2224 for (auto &entry
: entries
) {
2225 eversion_t replay_version
;
2226 version_t user_version
;
2227 int return_code
= 0;
2228 bool got
= log
.get_request(
2229 entry
.reqid
, &replay_version
, &user_version
, &return_code
);
2231 EXPECT_EQ(entry
.return_code
, return_code
);
2232 EXPECT_EQ(entry
.version
, replay_version
);
2233 EXPECT_EQ(entry
.user_version
, user_version
);
2237 TEST_F(PGLogTest
, ErrorNotIndexedByObject
) {
2240 // make sure writes, deletes, and errors are found
2241 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
2243 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(6,2), eversion_t(3,4),
2244 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2245 utime_t(0,1), -ENOENT
));
2247 EXPECT_FALSE(log
.logged_object(oid
));
2249 pg_log_entry_t
modify(pg_log_entry_t::MODIFY
, oid
, eversion_t(6,3),
2251 osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2255 EXPECT_TRUE(log
.logged_object(oid
));
2256 pg_log_entry_t
*entry
= log
.objects
[oid
];
2257 EXPECT_EQ(modify
.op
, entry
->op
);
2258 EXPECT_EQ(modify
.version
, entry
->version
);
2259 EXPECT_EQ(modify
.prior_version
, entry
->prior_version
);
2260 EXPECT_EQ(modify
.user_version
, entry
->user_version
);
2261 EXPECT_EQ(modify
.reqid
, entry
->reqid
);
2263 pg_log_entry_t
del(pg_log_entry_t::DELETE
, oid
, eversion_t(7,4),
2265 osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2269 EXPECT_TRUE(log
.logged_object(oid
));
2270 entry
= log
.objects
[oid
];
2271 EXPECT_EQ(del
.op
, entry
->op
);
2272 EXPECT_EQ(del
.version
, entry
->version
);
2273 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2274 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2275 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2278 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(7,5), eversion_t(7,4),
2279 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2280 utime_t(20,1), -ENOENT
));
2282 EXPECT_TRUE(log
.logged_object(oid
));
2283 entry
= log
.objects
[oid
];
2284 EXPECT_EQ(del
.op
, entry
->op
);
2285 EXPECT_EQ(del
.version
, entry
->version
);
2286 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2287 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2288 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2291 TEST_F(PGLogTest
, split_into_preserves_may_include_deletes
) {
2295 rebuilt_missing_with_deletes
= false;
2296 missing
.may_include_deletes
= true;
2297 PGLog
child_log(cct
, prefix_provider
);
2299 split_into(child_pg
, 6, &child_log
);
2300 ASSERT_TRUE(child_log
.get_missing().may_include_deletes
);
2301 ASSERT_TRUE(child_log
.get_rebuilt_missing_with_deletes());
2305 rebuilt_missing_with_deletes
= false;
2306 missing
.may_include_deletes
= false;
2307 PGLog
child_log(cct
, prefix_provider
);
2309 split_into(child_pg
, 6, &child_log
);
2310 ASSERT_FALSE(child_log
.get_missing().may_include_deletes
);
2311 ASSERT_FALSE(child_log
.get_rebuilt_missing_with_deletes());
2315 class PGLogTestRebuildMissing
: public PGLogTest
, public StoreTestFixture
{
2317 PGLogTestRebuildMissing() : PGLogTest(), StoreTestFixture("memstore") {}
2318 void SetUp() override
{
2319 StoreTestFixture::SetUp();
2320 ObjectStore::Sequencer
osr(__func__
);
2321 ObjectStore::Transaction t
;
2322 test_coll
= coll_t(spg_t(pg_t(1, 1)));
2323 t
.create_collection(test_coll
, 0);
2324 store
->apply_transaction(&osr
, std::move(t
));
2325 existing_oid
= mk_obj(0);
2326 nonexistent_oid
= mk_obj(1);
2327 ghobject_t
existing_ghobj(existing_oid
);
2328 object_info_t existing_info
;
2329 existing_info
.version
= eversion_t(6, 2);
2331 ::encode(existing_info
, enc_oi
, 0);
2332 ObjectStore::Transaction t2
;
2333 t2
.touch(test_coll
, ghobject_t(existing_oid
));
2334 t2
.setattr(test_coll
, ghobject_t(existing_oid
), OI_ATTR
, enc_oi
);
2335 ASSERT_EQ(0u, store
->apply_transaction(&osr
, std::move(t2
)));
2336 info
.last_backfill
= hobject_t::get_max();
2337 info
.last_complete
= eversion_t();
2340 void TearDown() override
{
2342 missing
.may_include_deletes
= false;
2343 StoreTestFixture::TearDown();
2348 hobject_t existing_oid
, nonexistent_oid
;
2350 void run_rebuild_missing_test(const map
<hobject_t
, pg_missing_item
> &expected_missing_items
) {
2351 rebuild_missing_set_with_deletes(store
.get(), test_coll
, info
);
2352 ASSERT_EQ(expected_missing_items
, missing
.get_items());
2356 TEST_F(PGLogTestRebuildMissing
, EmptyLog
) {
2357 missing
.add(existing_oid
, mk_evt(6, 2), mk_evt(6, 3), false);
2358 missing
.add(nonexistent_oid
, mk_evt(7, 4), mk_evt(0, 0), false);
2359 map
<hobject_t
, pg_missing_item
> orig_missing
= missing
.get_items();
2360 run_rebuild_missing_test(orig_missing
);
2363 TEST_F(PGLogTestRebuildMissing
, SameVersionMod
) {
2364 missing
.add(existing_oid
, mk_evt(6, 2), mk_evt(6, 1), false);
2365 log
.add(mk_ple_mod(existing_oid
, mk_evt(6, 2), mk_evt(6, 1)));
2366 map
<hobject_t
, pg_missing_item
> empty_missing
;
2367 run_rebuild_missing_test(empty_missing
);
2370 TEST_F(PGLogTestRebuildMissing
, DelExisting
) {
2371 missing
.add(existing_oid
, mk_evt(6, 3), mk_evt(6, 2), false);
2372 log
.add(mk_ple_dt(existing_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2373 map
<hobject_t
, pg_missing_item
> expected
;
2374 expected
[existing_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(6, 2), true);
2375 run_rebuild_missing_test(expected
);
2378 TEST_F(PGLogTestRebuildMissing
, DelNonexistent
) {
2379 log
.add(mk_ple_dt(nonexistent_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2380 map
<hobject_t
, pg_missing_item
> expected
;
2381 expected
[nonexistent_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2382 run_rebuild_missing_test(expected
);
2385 TEST_F(PGLogTestRebuildMissing
, MissingNotInLog
) {
2386 missing
.add(mk_obj(10), mk_evt(8, 12), mk_evt(8, 10), false);
2387 log
.add(mk_ple_dt(nonexistent_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2388 map
<hobject_t
, pg_missing_item
> expected
;
2389 expected
[nonexistent_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2390 expected
[mk_obj(10)] = pg_missing_item(mk_evt(8, 12), mk_evt(8, 10), false);
2391 run_rebuild_missing_test(expected
);
2395 class PGLogMergeDupsTest
: public ::testing::Test
, protected PGLog
{
2399 PGLogMergeDupsTest() : PGLog(g_ceph_context
) { }
2401 void SetUp() override
{ }
2403 void TearDown() override
{
2407 static pg_log_dup_t
create_dup_entry(uint a
, uint b
) {
2408 // make each dup_entry unique by using different client id's
2409 static uint client_id
= 777;
2410 return pg_log_dup_t(eversion_t(a
, b
),
2412 osd_reqid_t(entity_name_t::CLIENT(client_id
++), 8, 1),
2416 static std::vector
<pg_log_dup_t
> example_dups_1() {
2417 std::vector
<pg_log_dup_t
> result
= {
2418 create_dup_entry(10, 11),
2419 create_dup_entry(10, 12),
2420 create_dup_entry(11, 1),
2421 create_dup_entry(12, 3),
2422 create_dup_entry(13, 99)
2427 static std::vector
<pg_log_dup_t
> example_dups_2() {
2428 std::vector
<pg_log_dup_t
> result
= {
2429 create_dup_entry(12, 3),
2430 create_dup_entry(13, 99),
2431 create_dup_entry(15, 11),
2432 create_dup_entry(16, 14),
2433 create_dup_entry(16, 32)
2438 void add_dups(uint a
, uint b
) {
2439 log
.dups
.push_back(create_dup_entry(a
, b
));
2442 void add_dups(const std::vector
<pg_log_dup_t
>& l
) {
2444 log
.dups
.push_back(i
);
2448 static void add_dups(IndexedLog
& log
, const std::vector
<pg_log_dup_t
>& dups
) {
2449 for (auto& i
: dups
) {
2450 log
.dups
.push_back(i
);
2454 void check_order() {
2455 eversion_t
prev(0, 0);
2457 for (auto& i
: log
.dups
) {
2458 EXPECT_LT(prev
, i
.version
) << "verify versions monotonically increase";
2463 void check_index() {
2464 EXPECT_EQ(log
.dups
.size(), log
.dup_index
.size());
2465 for (auto& i
: log
.dups
) {
2466 EXPECT_EQ(1u, log
.dup_index
.count(i
.reqid
));
2471 TEST_F(PGLogMergeDupsTest
, OtherEmpty
) {
2472 log
.tail
= eversion_t(14, 5);
2476 add_dups(example_dups_1());
2479 bool changed
= merge_log_dups(olog
);
2481 EXPECT_FALSE(changed
);
2482 EXPECT_EQ(5u, log
.dups
.size());
2484 if (5 == log
.dups
.size()) {
2485 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2486 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2487 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2488 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2495 TEST_F(PGLogMergeDupsTest
, AmEmpty
) {
2496 log
.tail
= eversion_t(14, 5);
2501 add_dups(olog
, example_dups_1());
2503 bool changed
= merge_log_dups(olog
);
2505 EXPECT_TRUE(changed
);
2506 EXPECT_EQ(5u, log
.dups
.size());
2508 if (5 == log
.dups
.size()) {
2509 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2510 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2512 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2513 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2520 TEST_F(PGLogMergeDupsTest
, AmEmptyOverlap
) {
2521 log
.tail
= eversion_t(12, 3);
2526 add_dups(olog
, example_dups_1());
2528 bool changed
= merge_log_dups(olog
);
2530 EXPECT_TRUE(changed
);
2531 EXPECT_EQ(3u, log
.dups
.size());
2533 if (3 == log
.dups
.size()) {
2534 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2535 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2537 EXPECT_EQ(11u, log
.dups
.back().version
.epoch
);
2538 EXPECT_EQ(1u, log
.dups
.back().version
.version
);
2545 TEST_F(PGLogMergeDupsTest
, Same
) {
2546 log
.tail
= eversion_t(14, 1);
2550 add_dups(example_dups_1());
2552 add_dups(olog
, example_dups_1());
2554 bool changed
= merge_log_dups(olog
);
2556 EXPECT_FALSE(changed
);
2557 EXPECT_EQ(5u, log
.dups
.size());
2559 if (5 == log
.dups
.size()) {
2560 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2561 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2563 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2564 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2572 TEST_F(PGLogMergeDupsTest
, Later
) {
2573 log
.tail
= eversion_t(16, 14);
2577 add_dups(example_dups_1());
2579 add_dups(olog
, example_dups_2());
2581 bool changed
= merge_log_dups(olog
);
2583 EXPECT_TRUE(changed
);
2584 EXPECT_EQ(6u, log
.dups
.size());
2586 if (6 == log
.dups
.size()) {
2587 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2588 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2590 EXPECT_EQ(15u, log
.dups
.back().version
.epoch
);
2591 EXPECT_EQ(11u, log
.dups
.back().version
.version
);
2599 TEST_F(PGLogMergeDupsTest
, Earlier
) {
2600 log
.tail
= eversion_t(17, 2);
2604 add_dups(example_dups_2());
2606 add_dups(olog
, example_dups_1());
2608 bool changed
= merge_log_dups(olog
);
2610 EXPECT_TRUE(changed
);
2611 EXPECT_EQ(8u, log
.dups
.size());
2613 if (6 == log
.dups
.size()) {
2614 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2615 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2617 EXPECT_EQ(16u, log
.dups
.back().version
.epoch
);
2618 EXPECT_EQ(32u, log
.dups
.back().version
.version
);
2626 TEST_F(PGLogMergeDupsTest
, Superset
) {
2627 log
.tail
= eversion_t(17, 2);
2631 add_dups(example_dups_1());
2634 olog
.dups
.push_back(create_dup_entry(9, 5));
2635 olog
.dups
.push_back(create_dup_entry(15, 11));
2637 bool changed
= merge_log_dups(olog
);
2639 EXPECT_TRUE(changed
);
2640 EXPECT_EQ(7u, log
.dups
.size());
2642 if (7 == log
.dups
.size()) {
2643 EXPECT_EQ(9u, log
.dups
.front().version
.epoch
);
2644 EXPECT_EQ(5u, log
.dups
.front().version
.version
);
2646 EXPECT_EQ(15u, log
.dups
.back().version
.epoch
);
2647 EXPECT_EQ(11u, log
.dups
.back().version
.version
);
2655 struct PGLogTrimTest
:
2656 public ::testing::Test
,
2657 public PGLogTestBase
,
2658 public PGLog::IndexedLog
2660 std::list
<hobject_t
*> test_hobjects
;
2663 void SetUp() override
{
2664 cct
= (new CephContext(CEPH_ENTITY_TYPE_OSD
))->get();
2666 hobject_t::generate_test_instances(test_hobjects
);
2669 void SetUp(unsigned min_entries
, unsigned max_entries
, unsigned dup_track
) {
2670 constexpr size_t size
= 10;
2672 char min_entries_s
[size
];
2673 char max_entries_s
[size
];
2674 char dup_track_s
[size
];
2676 snprintf(min_entries_s
, size
, "%u", min_entries
);
2677 snprintf(max_entries_s
, size
, "%u", max_entries
);
2678 snprintf(dup_track_s
, size
, "%u", dup_track
);
2680 cct
->_conf
->set_val_or_die("osd_min_pg_log_entries", min_entries_s
);
2681 cct
->_conf
->set_val_or_die("osd_max_pg_log_entries", max_entries_s
);
2682 cct
->_conf
->set_val_or_die("osd_pg_log_dups_tracked", dup_track_s
);
2685 void TearDown() override
{
2686 while (!test_hobjects
.empty()) {
2687 delete test_hobjects
.front();
2688 test_hobjects
.pop_front();
2693 }; // struct PGLogTrimTest
2697 TEST_F(PGLogTest
, Trim1
) {
2700 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2701 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2702 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150)));
2703 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2704 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(21, 165), mk_evt(26, 160)));
2705 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(21, 165), mk_evt(31, 171)));
2712 TEST_F(PGLogTrimTest
, TestMakingCephContext
)
2716 EXPECT_EQ(1u, cct
->_conf
->osd_min_pg_log_entries
);
2717 EXPECT_EQ(2u, cct
->_conf
->osd_max_pg_log_entries
);
2718 EXPECT_EQ(5u, cct
->_conf
->osd_pg_log_dups_tracked
);
2722 TEST_F(PGLogTrimTest
, TestPartialTrim
)
2725 PGLog::IndexedLog log
;
2726 log
.head
= mk_evt(24, 0);
2727 log
.skip_can_rollback_to_to_head();
2728 log
.head
= mk_evt(9, 0);
2730 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2731 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2732 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2733 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2734 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2735 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2737 std::set
<eversion_t
> trimmed
;
2738 std::set
<std::string
> trimmed_dups
;
2739 bool dirty_dups
= false;
2741 log
.trim(cct
, mk_evt(19, 157), &trimmed
, &trimmed_dups
, &dirty_dups
);
2743 EXPECT_EQ(true, dirty_dups
);
2744 EXPECT_EQ(3u, log
.log
.size());
2745 EXPECT_EQ(3u, trimmed
.size());
2746 EXPECT_EQ(2u, log
.dups
.size());
2747 EXPECT_EQ(0u, trimmed_dups
.size());
2751 std::set
<eversion_t
> trimmed2
;
2752 std::set
<std::string
> trimmed_dups2
;
2753 bool dirty_dups2
= false;
2755 log
.trim(cct
, mk_evt(20, 164), &trimmed2
, &trimmed_dups2
, &dirty_dups2
);
2757 EXPECT_EQ(true, dirty_dups2
);
2758 EXPECT_EQ(2u, log
.log
.size());
2759 EXPECT_EQ(1u, trimmed2
.size());
2760 EXPECT_EQ(2u, log
.dups
.size());
2761 EXPECT_EQ(1u, trimmed_dups2
.size());
2765 TEST_F(PGLogTrimTest
, TestTrimNoTrimmed
) {
2767 PGLog::IndexedLog log
;
2768 log
.head
= mk_evt(20, 0);
2769 log
.skip_can_rollback_to_to_head();
2770 log
.head
= mk_evt(9, 0);
2772 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2773 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2774 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2775 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2776 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2777 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2779 bool dirty_dups
= false;
2781 log
.trim(cct
, mk_evt(19, 157), nullptr, nullptr, &dirty_dups
);
2783 EXPECT_EQ(true, dirty_dups
);
2784 EXPECT_EQ(3u, log
.log
.size());
2785 EXPECT_EQ(2u, log
.dups
.size());
2789 TEST_F(PGLogTrimTest
, TestTrimNoDups
)
2792 PGLog::IndexedLog log
;
2793 log
.head
= mk_evt(20, 0);
2794 log
.skip_can_rollback_to_to_head();
2795 log
.head
= mk_evt(9, 0);
2797 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2798 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2799 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2800 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2801 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2802 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2804 std::set
<eversion_t
> trimmed
;
2805 std::set
<std::string
> trimmed_dups
;
2806 bool dirty_dups
= false;
2808 log
.trim(cct
, mk_evt(19, 157), &trimmed
, &trimmed_dups
, &dirty_dups
);
2810 EXPECT_FALSE(dirty_dups
);
2811 EXPECT_EQ(3u, log
.log
.size());
2812 EXPECT_EQ(3u, trimmed
.size());
2813 EXPECT_EQ(0u, log
.dups
.size());
2814 EXPECT_EQ(0u, trimmed_dups
.size());
2817 TEST_F(PGLogTrimTest
, TestNoTrim
)
2820 PGLog::IndexedLog log
;
2821 log
.head
= mk_evt(24, 0);
2822 log
.skip_can_rollback_to_to_head();
2823 log
.head
= mk_evt(9, 0);
2825 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2826 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2827 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2828 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2829 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2830 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2832 std::set
<eversion_t
> trimmed
;
2833 std::set
<std::string
> trimmed_dups
;
2834 bool dirty_dups
= false;
2836 log
.trim(cct
, mk_evt(9, 99), &trimmed
, &trimmed_dups
, &dirty_dups
);
2838 EXPECT_FALSE(dirty_dups
);
2839 EXPECT_EQ(6u, log
.log
.size());
2840 EXPECT_EQ(0u, trimmed
.size());
2841 EXPECT_EQ(0u, log
.dups
.size());
2842 EXPECT_EQ(0u, trimmed_dups
.size());
2845 TEST_F(PGLogTrimTest
, TestTrimAll
)
2848 PGLog::IndexedLog log
;
2849 log
.head
= mk_evt(24, 0);
2850 log
.skip_can_rollback_to_to_head();
2851 log
.head
= mk_evt(9, 0);
2853 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2854 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2855 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2856 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2857 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2858 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2860 std::set
<eversion_t
> trimmed
;
2861 std::set
<std::string
> trimmed_dups
;
2862 bool dirty_dups
= false;
2864 log
.trim(cct
, mk_evt(22, 180), &trimmed
, &trimmed_dups
, &dirty_dups
);
2866 EXPECT_EQ(true, dirty_dups
);
2867 EXPECT_EQ(0u, log
.log
.size());
2868 EXPECT_EQ(6u, trimmed
.size());
2869 EXPECT_EQ(5u, log
.dups
.size());
2870 EXPECT_EQ(0u, trimmed_dups
.size());
2874 TEST_F(PGLogTrimTest
, TestGetRequest
) {
2876 PGLog::IndexedLog log
;
2877 log
.head
= mk_evt(20, 0);
2878 log
.skip_can_rollback_to_to_head();
2879 log
.head
= mk_evt(9, 0);
2881 entity_name_t client
= entity_name_t::CLIENT(777);
2883 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70),
2884 osd_reqid_t(client
, 8, 1)));
2885 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100),
2886 osd_reqid_t(client
, 8, 2)));
2887 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150),
2888 osd_reqid_t(client
, 8, 3)));
2889 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152),
2890 osd_reqid_t(client
, 8, 4)));
2891 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160),
2892 osd_reqid_t(client
, 8, 5)));
2893 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166),
2894 osd_reqid_t(client
, 8, 6)));
2896 bool dirty_dups
= false;
2898 log
.trim(cct
, mk_evt(19, 157), nullptr, nullptr, &dirty_dups
);
2900 EXPECT_EQ(true, dirty_dups
);
2901 EXPECT_EQ(3u, log
.log
.size());
2902 EXPECT_EQ(2u, log
.dups
.size());
2905 version_t user_version
;
2908 osd_reqid_t log_reqid
= osd_reqid_t(client
, 8, 5);
2909 osd_reqid_t dup_reqid
= osd_reqid_t(client
, 8, 3);
2910 osd_reqid_t bad_reqid
= osd_reqid_t(client
, 8, 1);
2914 result
= log
.get_request(log_reqid
, &version
, &user_version
, &return_code
);
2915 EXPECT_EQ(true, result
);
2916 EXPECT_EQ(mk_evt(21, 165), version
);
2918 result
= log
.get_request(dup_reqid
, &version
, &user_version
, &return_code
);
2919 EXPECT_EQ(true, result
);
2920 EXPECT_EQ(mk_evt(15, 155), version
);
2922 result
= log
.get_request(bad_reqid
, &version
, &user_version
, &return_code
);
2923 EXPECT_FALSE(result
);
2926 TEST_F(PGLogTest
, _merge_object_divergent_entries
) {
2928 // Test for issue 20843
2930 hobject_t
hoid(object_t(/*name*/"notify.7"),
2935 /*nspace*/string(""));
2936 mempool::osd_pglog::list
<pg_log_entry_t
> orig_entries
;
2937 orig_entries
.push_back(mk_ple_mod(hoid
, eversion_t(8336, 957), eversion_t(8336, 952)));
2938 orig_entries
.push_back(mk_ple_err(hoid
, eversion_t(8336, 958)));
2939 orig_entries
.push_back(mk_ple_err(hoid
, eversion_t(8336, 959)));
2940 orig_entries
.push_back(mk_ple_mod(hoid
, eversion_t(8336, 960), eversion_t(8336, 957)));
2941 log
.add(mk_ple_mod(hoid
, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2943 /*need*/eversion_t(8971, 1070),
2944 /*have*/eversion_t(8336, 952),
2947 LogHandler rollbacker
;
2948 _merge_object_divergent_entries(log
, hoid
,
2949 orig_entries
, oinfo
,
2950 log
.get_can_rollback_to(),
2951 missing
, &rollbacker
,
2956 // skip leading error entries
2958 hobject_t
hoid(object_t(/*name*/"notify.7"),
2963 /*nspace*/string(""));
2964 mempool::osd_pglog::list
<pg_log_entry_t
> orig_entries
;
2965 orig_entries
.push_back(mk_ple_err(hoid
, eversion_t(8336, 956)));
2966 orig_entries
.push_back(mk_ple_mod(hoid
, eversion_t(8336, 957), eversion_t(8336, 952)));
2967 log
.add(mk_ple_mod(hoid
, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2969 /*need*/eversion_t(8971, 1070),
2970 /*have*/eversion_t(8336, 952),
2973 LogHandler rollbacker
;
2974 _merge_object_divergent_entries(log
, hoid
,
2975 orig_entries
, oinfo
,
2976 log
.get_can_rollback_to(),
2977 missing
, &rollbacker
,
2984 // compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "