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 ceph_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
);
1393 TEST_F(PGLogTest
, proc_replica_log
) {
1394 // empty log : no side effect
1400 pg_missing_t omissing
;
1403 eversion_t
last_update(1, 1);
1404 log
.head
= olog
.head
= oinfo
.last_update
= last_update
;
1405 eversion_t
last_complete(1, 1);
1406 oinfo
.last_complete
= last_complete
;
1408 EXPECT_FALSE(omissing
.have_missing());
1409 EXPECT_EQ(last_update
, oinfo
.last_update
);
1410 EXPECT_EQ(last_complete
, oinfo
.last_complete
);
1412 missing
.may_include_deletes
= false;
1413 proc_replica_log(oinfo
, olog
, omissing
, from
);
1415 EXPECT_FALSE(omissing
.have_missing());
1416 EXPECT_EQ(last_update
, oinfo
.last_update
);
1417 EXPECT_EQ(last_update
, oinfo
.last_complete
);
1420 /* +--------------------------+
1422 +--------+-------+---------+
1424 |version | hash | version |
1426 | | x3 | (1,1) < tail
1429 tail > (1,2) | x5 | |
1432 head > (1,3) | x9 | |
1435 | | x9 | (2,3) < head
1438 +--------+-------+---------+
1440 The log entry (1,3) deletes the object x9 and the olog entry
1441 (2,3) also deletes it : do nothing. The olog tail is ignored
1442 because it is before the log tail.
1450 pg_missing_t omissing
;
1455 e
.mark_unrollbackable();
1457 e
.version
= eversion_t(1, 2);
1458 e
.soid
.set_hash(0x5);
1459 log
.tail
= e
.version
;
1460 log
.log
.push_back(e
);
1461 e
.version
= eversion_t(1, 3);
1462 e
.soid
.set_hash(0x9);
1463 e
.op
= pg_log_entry_t::DELETE
;
1464 log
.log
.push_back(e
);
1465 log
.head
= e
.version
;
1468 e
.version
= eversion_t(1, 1);
1469 e
.soid
.set_hash(0x3);
1470 olog
.tail
= e
.version
;
1471 olog
.log
.push_back(e
);
1472 e
.version
= eversion_t(2, 3);
1473 e
.soid
.set_hash(0x9);
1474 e
.op
= pg_log_entry_t::DELETE
;
1475 olog
.log
.push_back(e
);
1476 olog
.head
= e
.version
;
1478 oinfo
.last_update
= olog
.head
;
1479 oinfo
.last_complete
= olog
.head
;
1482 EXPECT_FALSE(omissing
.have_missing());
1483 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1484 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1486 missing
.may_include_deletes
= false;
1487 proc_replica_log(oinfo
, olog
, omissing
, from
);
1489 EXPECT_FALSE(omissing
.have_missing());
1497 pg_missing_t omissing
;
1500 hobject_t divergent_object
;
1504 e
.mark_unrollbackable();
1507 e
.soid
= divergent_object
;
1508 e
.soid
.set_hash(0x1);
1509 e
.version
= eversion_t(1, 1);
1510 log
.tail
= e
.version
;
1511 log
.log
.push_back(e
);
1513 e
.soid
= divergent_object
;
1514 e
.prior_version
= eversion_t(1, 1);
1515 e
.version
= eversion_t(1, 2);
1516 log
.tail
= e
.version
;
1517 log
.log
.push_back(e
);
1519 e
.soid
.set_hash(0x3);
1520 e
.version
= eversion_t(1, 4);
1521 log
.log
.push_back(e
);
1523 e
.soid
.set_hash(0x7);
1524 e
.version
= eversion_t(1, 5);
1525 log
.log
.push_back(e
);
1527 e
.soid
.set_hash(0x8);
1528 e
.version
= eversion_t(1, 6);
1529 log
.log
.push_back(e
);
1531 e
.soid
.set_hash(0x9);
1532 e
.op
= pg_log_entry_t::DELETE
;
1533 e
.version
= eversion_t(2, 7);
1534 log
.log
.push_back(e
);
1536 e
.soid
.set_hash(0xa);
1537 e
.version
= eversion_t(2, 8);
1538 log
.head
= e
.version
;
1539 log
.log
.push_back(e
);
1544 e
.soid
= divergent_object
;
1545 e
.soid
.set_hash(0x1);
1546 e
.version
= eversion_t(1, 1);
1547 olog
.tail
= e
.version
;
1548 olog
.log
.push_back(e
);
1550 e
.soid
= divergent_object
;
1551 e
.prior_version
= eversion_t(1, 1);
1552 e
.version
= eversion_t(1, 2);
1553 olog
.log
.push_back(e
);
1555 e
.prior_version
= eversion_t(0, 0);
1556 e
.soid
.set_hash(0x3);
1557 e
.version
= eversion_t(1, 4);
1558 olog
.log
.push_back(e
);
1560 e
.soid
.set_hash(0x7);
1561 e
.version
= eversion_t(1, 5);
1562 olog
.log
.push_back(e
);
1564 e
.soid
.set_hash(0x8);
1565 e
.version
= eversion_t(1, 6);
1566 olog
.log
.push_back(e
);
1568 e
.soid
.set_hash(0x9); // should not be added to missing, create
1569 e
.op
= pg_log_entry_t::MODIFY
;
1570 e
.version
= eversion_t(1, 7);
1571 olog
.log
.push_back(e
);
1573 e
.soid
= divergent_object
; // should be added to missing at 1,2
1574 e
.op
= pg_log_entry_t::MODIFY
;
1575 e
.version
= eversion_t(1, 8);
1576 e
.prior_version
= eversion_t(1, 2);
1577 olog
.log
.push_back(e
);
1578 olog
.head
= e
.version
;
1580 oinfo
.last_update
= olog
.head
;
1581 oinfo
.last_complete
= olog
.head
;
1584 EXPECT_FALSE(omissing
.have_missing());
1585 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1586 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1588 missing
.may_include_deletes
= false;
1589 proc_replica_log(oinfo
, olog
, omissing
, from
);
1591 EXPECT_TRUE(omissing
.have_missing());
1592 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1593 EXPECT_EQ(eversion_t(1, 2), omissing
.get_items().at(divergent_object
).need
);
1594 EXPECT_EQ(eversion_t(1, 6), oinfo
.last_update
);
1595 EXPECT_EQ(eversion_t(1, 1), oinfo
.last_complete
);
1598 /* +--------------------------+
1600 +--------+-------+---------+
1602 |version | hash | version |
1604 tail > (1,1) | x9 | (1,1) < tail
1607 | (1,2) | x3 | (1,2) |
1610 head > (1,3) | x9 | |
1613 | | x9 | (2,3) < head
1616 +--------+-------+---------+
1618 The log entry (1,3) deletes the object x9 and the olog entry
1619 (2,3) also deletes it : do nothing.
1627 pg_missing_t omissing
;
1630 eversion_t
last_update(1, 2);
1631 hobject_t divergent_object
;
1632 divergent_object
.set_hash(0x9);
1636 e
.mark_unrollbackable();
1638 e
.version
= eversion_t(1, 1);
1639 e
.soid
= divergent_object
;
1640 log
.tail
= e
.version
;
1641 log
.log
.push_back(e
);
1642 e
.version
= last_update
;
1643 e
.soid
.set_hash(0x3);
1644 log
.log
.push_back(e
);
1645 e
.version
= eversion_t(2, 3);
1646 e
.prior_version
= eversion_t(1, 1);
1647 e
.soid
= divergent_object
;
1648 e
.op
= pg_log_entry_t::DELETE
;
1649 log
.log
.push_back(e
);
1650 log
.head
= e
.version
;
1653 e
.version
= eversion_t(1, 1);
1654 e
.soid
= divergent_object
;
1655 olog
.tail
= e
.version
;
1656 olog
.log
.push_back(e
);
1657 e
.version
= last_update
;
1658 e
.soid
.set_hash(0x3);
1659 olog
.log
.push_back(e
);
1660 e
.version
= eversion_t(1, 3);
1661 e
.prior_version
= eversion_t(1, 1);
1662 e
.soid
= divergent_object
;
1663 e
.op
= pg_log_entry_t::DELETE
;
1664 olog
.log
.push_back(e
);
1665 olog
.head
= e
.version
;
1667 oinfo
.last_update
= olog
.head
;
1668 oinfo
.last_complete
= olog
.head
;
1671 EXPECT_FALSE(omissing
.have_missing());
1672 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1673 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1675 missing
.may_include_deletes
= false;
1676 proc_replica_log(oinfo
, olog
, omissing
, from
);
1678 EXPECT_TRUE(omissing
.have_missing());
1679 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1680 EXPECT_EQ(omissing
.get_items().at(divergent_object
).have
, eversion_t(0, 0));
1681 EXPECT_EQ(omissing
.get_items().at(divergent_object
).need
, eversion_t(1, 1));
1682 EXPECT_EQ(last_update
, oinfo
.last_update
);
1685 /* +--------------------------+
1687 +--------+-------+---------+
1689 |version | hash | version |
1691 tail > (1,1) | x9 | (1,1) < tail
1694 | (1,2) | x3 | (1,2) |
1697 head > (1,3) | x9 | |
1700 | | x9 | (2,3) < head
1703 +--------+-------+---------+
1705 The log entry (1,3) deletes the object x9 but the olog entry
1706 (2,3) modifies it : remove it from omissing.
1714 pg_missing_t omissing
;
1717 eversion_t
last_update(1, 2);
1718 hobject_t divergent_object
;
1722 e
.mark_unrollbackable();
1724 e
.version
= eversion_t(1, 1);
1725 e
.soid
= divergent_object
;
1726 log
.tail
= e
.version
;
1727 log
.log
.push_back(e
);
1728 e
.version
= last_update
;
1729 e
.soid
.set_hash(0x3);
1730 log
.log
.push_back(e
);
1731 e
.version
= eversion_t(2, 3);
1732 e
.prior_version
= eversion_t(1, 1);
1733 e
.soid
= divergent_object
;
1734 e
.op
= pg_log_entry_t::DELETE
;
1735 log
.log
.push_back(e
);
1736 log
.head
= e
.version
;
1739 e
.version
= eversion_t(1, 1);
1740 e
.soid
= divergent_object
;
1741 olog
.tail
= e
.version
;
1742 olog
.log
.push_back(e
);
1743 e
.version
= last_update
;
1744 e
.soid
.set_hash(0x3);
1745 olog
.log
.push_back(e
);
1746 e
.version
= eversion_t(1, 3);
1747 e
.prior_version
= eversion_t(1, 1);
1748 e
.soid
= divergent_object
;
1749 divergent_object
= e
.soid
;
1750 omissing
.add(divergent_object
, e
.version
, eversion_t(), false);
1751 e
.op
= pg_log_entry_t::MODIFY
;
1752 olog
.log
.push_back(e
);
1753 olog
.head
= e
.version
;
1755 oinfo
.last_update
= olog
.head
;
1756 oinfo
.last_complete
= olog
.head
;
1759 EXPECT_TRUE(omissing
.have_missing());
1760 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1761 EXPECT_EQ(eversion_t(1, 3), omissing
.get_items().at(divergent_object
).need
);
1762 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1763 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1765 missing
.may_include_deletes
= false;
1766 proc_replica_log(oinfo
, olog
, omissing
, from
);
1768 EXPECT_TRUE(omissing
.have_missing());
1769 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1770 EXPECT_EQ(omissing
.get_items().at(divergent_object
).have
, eversion_t(0, 0));
1771 EXPECT_EQ(omissing
.get_items().at(divergent_object
).need
, eversion_t(1, 1));
1772 EXPECT_EQ(last_update
, oinfo
.last_update
);
1775 /* +--------------------------+
1777 +--------+-------+---------+
1779 |version | hash | version |
1781 tail > (1,1) | x9 | (1,1) < tail
1784 | (1,2) | x3 | (1,2) |
1787 | | x9 | (1,3) < head
1790 head > (2,3) | x9 | |
1793 +--------+-------+---------+
1795 The log entry (2,3) deletes the object x9 but the olog entry
1796 (1,3) modifies it : proc_replica_log should adjust missing to
1797 1,1 for that object until add_next_event in PG::activate processes
1805 pg_missing_t omissing
;
1808 eversion_t
last_update(1, 2);
1809 hobject_t divergent_object
;
1810 eversion_t
new_version(2, 3);
1811 eversion_t
divergent_version(1, 3);
1815 e
.mark_unrollbackable();
1817 e
.version
= eversion_t(1, 1);
1818 e
.soid
.set_hash(0x9);
1819 log
.tail
= e
.version
;
1820 log
.log
.push_back(e
);
1821 e
.version
= last_update
;
1822 e
.soid
.set_hash(0x3);
1823 log
.log
.push_back(e
);
1824 e
.version
= new_version
;
1825 e
.prior_version
= eversion_t(1, 1);
1826 e
.soid
.set_hash(0x9);
1827 e
.op
= pg_log_entry_t::DELETE
;
1828 log
.log
.push_back(e
);
1829 log
.head
= e
.version
;
1832 e
.op
= pg_log_entry_t::MODIFY
;
1833 e
.version
= eversion_t(1, 1);
1834 e
.soid
.set_hash(0x9);
1835 olog
.tail
= e
.version
;
1836 olog
.log
.push_back(e
);
1837 e
.version
= last_update
;
1838 e
.soid
.set_hash(0x3);
1839 olog
.log
.push_back(e
);
1840 e
.version
= divergent_version
;
1841 e
.prior_version
= eversion_t(1, 1);
1842 e
.soid
.set_hash(0x9);
1843 divergent_object
= e
.soid
;
1844 omissing
.add(divergent_object
, e
.version
, eversion_t(), false);
1845 e
.op
= pg_log_entry_t::MODIFY
;
1846 olog
.log
.push_back(e
);
1847 olog
.head
= e
.version
;
1849 oinfo
.last_update
= olog
.head
;
1850 oinfo
.last_complete
= olog
.head
;
1853 EXPECT_TRUE(omissing
.have_missing());
1854 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1855 EXPECT_EQ(divergent_version
, omissing
.get_items().at(divergent_object
).need
);
1856 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1857 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1859 missing
.may_include_deletes
= false;
1860 proc_replica_log(oinfo
, olog
, omissing
, from
);
1862 EXPECT_TRUE(omissing
.have_missing());
1863 EXPECT_TRUE(omissing
.get_items().begin()->second
.need
== eversion_t(1, 1));
1864 EXPECT_EQ(last_update
, oinfo
.last_update
);
1865 EXPECT_EQ(eversion_t(0, 0), oinfo
.last_complete
);
1870 TEST_F(PGLogTest
, merge_log_1
) {
1872 t
.base
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1874 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1876 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1878 t
.toremove
.insert(mk_obj(1));
1884 TEST_F(PGLogTest
, merge_log_2
) {
1886 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1888 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1889 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1891 t
.torollback
.insert(
1892 t
.torollback
.begin(), t
.div
.rbegin(), t
.div
.rend());
1898 TEST_F(PGLogTest
, merge_log_3
) {
1900 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1902 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1903 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1905 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1907 t
.toremove
.insert(mk_obj(1));
1913 TEST_F(PGLogTest
, merge_log_4
) {
1915 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1917 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1918 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1920 t
.init
.add(mk_obj(1), mk_evt(10, 102), mk_evt(0, 0), false);
1921 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1927 TEST_F(PGLogTest
, merge_log_5
) {
1929 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1931 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1932 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1934 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1936 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(0, 0), false);
1938 t
.toremove
.insert(mk_obj(1));
1944 TEST_F(PGLogTest
, merge_log_6
) {
1946 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1948 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1950 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100), false);
1956 TEST_F(PGLogTest
, merge_log_7
) {
1958 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1960 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1962 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1963 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), false);
1969 TEST_F(PGLogTest
, merge_log_8
) {
1971 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1973 t
.auth
.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1975 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1976 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), true);
1982 TEST_F(PGLogTest
, merge_log_9
) {
1984 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1986 t
.auth
.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1988 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1989 t
.toremove
.insert(mk_obj(1));
1990 t
.deletes_during_peering
= true;
1996 TEST_F(PGLogTest
, merge_log_10
) {
1998 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2000 t
.auth
.push_back(mk_ple_ldt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
2002 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
2003 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), true);
2009 TEST_F(PGLogTest
, merge_log_prior_version_have
) {
2011 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2013 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
2015 t
.init
.add(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100), false);
2021 TEST_F(PGLogTest
, merge_log_split_missing_entries_at_head
) {
2023 t
.auth
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2024 t
.auth
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2026 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(8, 70), mk_evt(8, 65)));
2029 t
.set_div_bounds(mk_evt(9, 79), mk_evt(8, 69));
2030 t
.set_auth_bounds(mk_evt(15, 160), mk_evt(9, 77));
2031 t
.final
.add(mk_obj(1), mk_evt(15, 150), mk_evt(8, 70), false);
2035 TEST_F(PGLogTest
, olog_tail_gt_log_tail_split
) {
2037 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2038 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2039 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150)));
2042 t
.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
2043 t
.set_auth_bounds(mk_evt(15, 156), mk_evt(10, 99));
2044 t
.final
.add(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150), false);
2048 TEST_F(PGLogTest
, olog_tail_gt_log_tail_split2
) {
2050 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2051 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2052 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(16, 155), mk_evt(15, 150)));
2053 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 153), mk_evt(15, 150)));
2056 t
.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
2057 t
.set_auth_bounds(mk_evt(16, 156), mk_evt(10, 99));
2058 t
.final
.add(mk_obj(1), mk_evt(16, 155), mk_evt(0, 0), false);
2059 t
.toremove
.insert(mk_obj(1));
2063 TEST_F(PGLogTest
, filter_log_1
) {
2069 int64_t pool_id
= 1;
2072 int pg_num
= max_osd
<< bits
;
2073 int num_objects
= 1000;
2074 int num_internal
= 10;
2076 // Set up splitting map
2077 OSDMap
*osdmap
= new OSDMap
;
2079 test_uuid
.generate_random();
2080 osdmap
->build_simple_with_pool(g_ceph_context
, epoch
, test_uuid
, max_osd
, bits
, bits
);
2081 osdmap
->set_state(osd_id
, CEPH_OSD_EXISTS
);
2083 const string
hit_set_namespace("internal");
2087 e
.mark_unrollbackable();
2088 e
.op
= pg_log_entry_t::MODIFY
;
2089 e
.soid
.pool
= pool_id
;
2093 for (i
= 1; i
<= num_objects
; ++i
) {
2094 e
.version
= eversion_t(epoch
, i
);
2095 // Use this to generate random file names
2096 uuid_name
.generate_random();
2099 e
.soid
.oid
.name
= name
.str();
2100 // First has no namespace
2102 // num_internal have the internal namspace
2103 if (i
<= num_internal
+ 1) {
2104 e
.soid
.nspace
= hit_set_namespace
;
2105 } else { // rest have different namespaces
2108 e
.soid
.nspace
= ns
.str();
2111 log
.log
.push_back(e
);
2113 log
.tail
= e
.version
;
2115 log
.head
= e
.version
;
2119 spg_t
pgid(pg_t(2, pool_id
), shard_id_t::NO_SHARD
);
2121 // See if we created the right number of entries
2122 int total
= log
.log
.size();
2123 ASSERT_EQ(total
, num_objects
);
2125 // Some should be removed
2127 pg_log_t filtered
, reject
;
2128 pg_log_t::filter_log(
2129 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
2130 log
= IndexedLog(filtered
);
2132 EXPECT_LE(log
.log
.size(), (size_t)total
);
2134 // If we filter a second time, there should be the same total
2135 total
= log
.log
.size();
2137 pg_log_t filtered
, reject
;
2138 pg_log_t::filter_log(
2139 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
2140 log
= IndexedLog(filtered
);
2142 EXPECT_EQ(log
.log
.size(), (size_t)total
);
2144 // Increase pg_num as if there would be a split
2145 int new_pg_num
= pg_num
* 16;
2146 OSDMap::Incremental
inc(epoch
+ 1);
2147 inc
.fsid
= test_uuid
;
2148 const pg_pool_t
*pool
= osdmap
->get_pg_pool(pool_id
);
2151 newpool
.set_pg_num(new_pg_num
);
2152 newpool
.set_pgp_num(new_pg_num
);
2153 inc
.new_pools
[pool_id
] = newpool
;
2154 int ret
= osdmap
->apply_incremental(inc
);
2157 // We should have fewer entries after a filter
2159 pg_log_t filtered
, reject
;
2160 pg_log_t::filter_log(
2161 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
2162 log
= IndexedLog(filtered
);
2164 EXPECT_LE(log
.log
.size(), (size_t)total
);
2166 // Make sure all internal entries are retained
2168 for (list
<pg_log_entry_t
>::iterator i
= log
.log
.begin();
2169 i
!= log
.log
.end(); ++i
) {
2170 if (i
->soid
.nspace
== hit_set_namespace
) count
++;
2172 EXPECT_EQ(count
, num_internal
);
2176 TEST_F(PGLogTest
, get_request
) {
2179 // make sure writes, deletes, and errors are found
2180 vector
<pg_log_entry_t
> entries
;
2181 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
2183 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(6,2), eversion_t(3,4),
2184 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2185 utime_t(0,1), -ENOENT
));
2187 pg_log_entry_t(pg_log_entry_t::MODIFY
, oid
, eversion_t(6,3), eversion_t(3,4),
2188 2, osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2191 pg_log_entry_t(pg_log_entry_t::DELETE
, oid
, eversion_t(7,4), eversion_t(7,4),
2192 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2195 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(7,5), eversion_t(7,4),
2196 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2197 utime_t(20,1), -ENOENT
));
2199 for (auto &entry
: entries
) {
2203 for (auto &entry
: entries
) {
2204 eversion_t replay_version
;
2205 version_t user_version
;
2206 int return_code
= 0;
2207 bool got
= log
.get_request(
2208 entry
.reqid
, &replay_version
, &user_version
, &return_code
);
2210 EXPECT_EQ(entry
.return_code
, return_code
);
2211 EXPECT_EQ(entry
.version
, replay_version
);
2212 EXPECT_EQ(entry
.user_version
, user_version
);
2216 TEST_F(PGLogTest
, ErrorNotIndexedByObject
) {
2219 // make sure writes, deletes, and errors are found
2220 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
2222 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(6,2), eversion_t(3,4),
2223 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2224 utime_t(0,1), -ENOENT
));
2226 EXPECT_FALSE(log
.logged_object(oid
));
2228 pg_log_entry_t
modify(pg_log_entry_t::MODIFY
, oid
, eversion_t(6,3),
2230 osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2234 EXPECT_TRUE(log
.logged_object(oid
));
2235 pg_log_entry_t
*entry
= log
.objects
[oid
];
2236 EXPECT_EQ(modify
.op
, entry
->op
);
2237 EXPECT_EQ(modify
.version
, entry
->version
);
2238 EXPECT_EQ(modify
.prior_version
, entry
->prior_version
);
2239 EXPECT_EQ(modify
.user_version
, entry
->user_version
);
2240 EXPECT_EQ(modify
.reqid
, entry
->reqid
);
2242 pg_log_entry_t
del(pg_log_entry_t::DELETE
, oid
, eversion_t(7,4),
2244 osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2248 EXPECT_TRUE(log
.logged_object(oid
));
2249 entry
= log
.objects
[oid
];
2250 EXPECT_EQ(del
.op
, entry
->op
);
2251 EXPECT_EQ(del
.version
, entry
->version
);
2252 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2253 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2254 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2257 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(7,5), eversion_t(7,4),
2258 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2259 utime_t(20,1), -ENOENT
));
2261 EXPECT_TRUE(log
.logged_object(oid
));
2262 entry
= log
.objects
[oid
];
2263 EXPECT_EQ(del
.op
, entry
->op
);
2264 EXPECT_EQ(del
.version
, entry
->version
);
2265 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2266 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2267 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2270 TEST_F(PGLogTest
, split_into_preserves_may_include_deletes
) {
2274 rebuilt_missing_with_deletes
= false;
2275 missing
.may_include_deletes
= true;
2276 PGLog
child_log(cct
);
2278 split_into(child_pg
, 6, &child_log
);
2279 ASSERT_TRUE(child_log
.get_missing().may_include_deletes
);
2280 ASSERT_TRUE(child_log
.get_rebuilt_missing_with_deletes());
2284 rebuilt_missing_with_deletes
= false;
2285 missing
.may_include_deletes
= false;
2286 PGLog
child_log(cct
);
2288 split_into(child_pg
, 6, &child_log
);
2289 ASSERT_FALSE(child_log
.get_missing().may_include_deletes
);
2290 ASSERT_FALSE(child_log
.get_rebuilt_missing_with_deletes());
2294 class PGLogTestRebuildMissing
: public PGLogTest
, public StoreTestFixture
{
2296 PGLogTestRebuildMissing() : PGLogTest(), StoreTestFixture("memstore") {}
2297 void SetUp() override
{
2298 StoreTestFixture::SetUp();
2299 ObjectStore::Transaction t
;
2300 test_coll
= coll_t(spg_t(pg_t(1, 1)));
2301 ch
= store
->create_new_collection(test_coll
);
2302 t
.create_collection(test_coll
, 0);
2303 store
->queue_transaction(ch
, std::move(t
));
2304 existing_oid
= mk_obj(0);
2305 nonexistent_oid
= mk_obj(1);
2306 ghobject_t
existing_ghobj(existing_oid
);
2307 object_info_t existing_info
;
2308 existing_info
.version
= eversion_t(6, 2);
2310 encode(existing_info
, enc_oi
, 0);
2311 ObjectStore::Transaction t2
;
2312 t2
.touch(test_coll
, ghobject_t(existing_oid
));
2313 t2
.setattr(test_coll
, ghobject_t(existing_oid
), OI_ATTR
, enc_oi
);
2314 ASSERT_EQ(0, store
->queue_transaction(ch
, std::move(t2
)));
2315 info
.last_backfill
= hobject_t::get_max();
2316 info
.last_complete
= eversion_t();
2319 void TearDown() override
{
2321 missing
.may_include_deletes
= false;
2322 StoreTestFixture::TearDown();
2327 hobject_t existing_oid
, nonexistent_oid
;
2329 void run_rebuild_missing_test(const map
<hobject_t
, pg_missing_item
> &expected_missing_items
) {
2330 rebuild_missing_set_with_deletes(store
.get(), ch
, info
);
2331 ASSERT_EQ(expected_missing_items
, missing
.get_items());
2335 TEST_F(PGLogTestRebuildMissing
, EmptyLog
) {
2336 missing
.add(existing_oid
, mk_evt(6, 2), mk_evt(6, 3), false);
2337 missing
.add(nonexistent_oid
, mk_evt(7, 4), mk_evt(0, 0), false);
2338 map
<hobject_t
, pg_missing_item
> orig_missing
= missing
.get_items();
2339 run_rebuild_missing_test(orig_missing
);
2342 TEST_F(PGLogTestRebuildMissing
, SameVersionMod
) {
2343 missing
.add(existing_oid
, mk_evt(6, 2), mk_evt(6, 1), false);
2344 log
.add(mk_ple_mod(existing_oid
, mk_evt(6, 2), mk_evt(6, 1)));
2345 map
<hobject_t
, pg_missing_item
> empty_missing
;
2346 run_rebuild_missing_test(empty_missing
);
2349 TEST_F(PGLogTestRebuildMissing
, DelExisting
) {
2350 missing
.add(existing_oid
, mk_evt(6, 3), mk_evt(6, 2), false);
2351 log
.add(mk_ple_dt(existing_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2352 map
<hobject_t
, pg_missing_item
> expected
;
2353 expected
[existing_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(6, 2), true);
2354 run_rebuild_missing_test(expected
);
2357 TEST_F(PGLogTestRebuildMissing
, DelNonexistent
) {
2358 log
.add(mk_ple_dt(nonexistent_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2359 map
<hobject_t
, pg_missing_item
> expected
;
2360 expected
[nonexistent_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2361 run_rebuild_missing_test(expected
);
2364 TEST_F(PGLogTestRebuildMissing
, MissingNotInLog
) {
2365 missing
.add(mk_obj(10), mk_evt(8, 12), mk_evt(8, 10), false);
2366 log
.add(mk_ple_dt(nonexistent_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2367 map
<hobject_t
, pg_missing_item
> expected
;
2368 expected
[nonexistent_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2369 expected
[mk_obj(10)] = pg_missing_item(mk_evt(8, 12), mk_evt(8, 10), false);
2370 run_rebuild_missing_test(expected
);
2374 class PGLogMergeDupsTest
: protected PGLog
, public StoreTestFixture
{
2378 PGLogMergeDupsTest() : PGLog(g_ceph_context
), StoreTestFixture("memstore") { }
2380 void SetUp() override
{
2381 StoreTestFixture::SetUp();
2382 ObjectStore::Transaction t
;
2383 test_coll
= coll_t(spg_t(pg_t(1, 1)));
2384 auto ch
= store
->create_new_collection(test_coll
);
2385 t
.create_collection(test_coll
, 0);
2386 store
->queue_transaction(ch
, std::move(t
));
2389 void TearDown() override
{
2390 test_disk_roundtrip();
2392 StoreTestFixture::TearDown();
2395 static pg_log_dup_t
create_dup_entry(uint a
, uint b
) {
2396 // make each dup_entry unique by using different client id's
2397 static uint client_id
= 777;
2398 return pg_log_dup_t(eversion_t(a
, b
),
2400 osd_reqid_t(entity_name_t::CLIENT(client_id
++), 8, 1),
2404 static std::vector
<pg_log_dup_t
> example_dups_1() {
2405 std::vector
<pg_log_dup_t
> result
= {
2406 create_dup_entry(10, 11),
2407 create_dup_entry(10, 12),
2408 create_dup_entry(11, 1),
2409 create_dup_entry(12, 3),
2410 create_dup_entry(13, 99)
2415 static std::vector
<pg_log_dup_t
> example_dups_2() {
2416 std::vector
<pg_log_dup_t
> result
= {
2417 create_dup_entry(12, 3),
2418 create_dup_entry(13, 99),
2419 create_dup_entry(15, 11),
2420 create_dup_entry(16, 14),
2421 create_dup_entry(16, 32)
2426 void add_dups(uint a
, uint b
) {
2427 log
.dups
.push_back(create_dup_entry(a
, b
));
2428 write_from_dups
= std::min(write_from_dups
, log
.dups
.back().version
);
2431 void add_dups(const std::vector
<pg_log_dup_t
>& l
) {
2433 log
.dups
.push_back(i
);
2434 write_from_dups
= std::min(write_from_dups
, log
.dups
.back().version
);
2438 static void add_dups(IndexedLog
& log
, const std::vector
<pg_log_dup_t
>& dups
) {
2439 for (auto& i
: dups
) {
2440 log
.dups
.push_back(i
);
2444 void check_order() {
2445 eversion_t
prev(0, 0);
2447 for (auto& i
: log
.dups
) {
2448 EXPECT_LT(prev
, i
.version
) << "verify versions monotonically increase";
2453 void check_index() {
2454 EXPECT_EQ(log
.dups
.size(), log
.dup_index
.size());
2455 for (auto& i
: log
.dups
) {
2456 EXPECT_EQ(1u, log
.dup_index
.count(i
.reqid
));
2460 void test_disk_roundtrip() {
2461 ObjectStore::Transaction t
;
2465 ghobject_t
log_oid(hoid
);
2466 map
<string
, bufferlist
> km
;
2467 write_log_and_missing(t
, &km
, test_coll
, log_oid
, false);
2469 t
.omap_setkeys(test_coll
, log_oid
, km
);
2471 auto ch
= store
->open_collection(test_coll
);
2472 ASSERT_EQ(0, store
->queue_transaction(ch
, std::move(t
)));
2474 auto orig_dups
= log
.dups
;
2477 read_log_and_missing(store
.get(), ch
, log_oid
,
2478 pg_info_t(), err
, false);
2479 ASSERT_EQ(orig_dups
.size(), log
.dups
.size());
2480 ASSERT_EQ(orig_dups
, log
.dups
);
2481 auto dups_it
= log
.dups
.begin();
2482 for (auto orig_dup
: orig_dups
) {
2483 ASSERT_EQ(orig_dup
, *dups_it
);
2491 TEST_F(PGLogMergeDupsTest
, OtherEmpty
) {
2492 log
.tail
= eversion_t(14, 5);
2496 add_dups(example_dups_1());
2499 bool changed
= merge_log_dups(olog
);
2501 EXPECT_FALSE(changed
);
2502 EXPECT_EQ(5u, log
.dups
.size());
2504 if (5 == log
.dups
.size()) {
2505 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2506 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2507 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2508 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2515 TEST_F(PGLogMergeDupsTest
, AmEmpty
) {
2516 log
.tail
= eversion_t(14, 5);
2521 add_dups(olog
, example_dups_1());
2523 bool changed
= merge_log_dups(olog
);
2525 EXPECT_TRUE(changed
);
2526 EXPECT_EQ(5u, log
.dups
.size());
2528 if (5 == log
.dups
.size()) {
2529 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2530 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2532 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2533 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2540 TEST_F(PGLogMergeDupsTest
, AmEmptyOverlap
) {
2541 log
.tail
= eversion_t(12, 3);
2546 add_dups(olog
, example_dups_1());
2548 bool changed
= merge_log_dups(olog
);
2550 EXPECT_TRUE(changed
);
2551 EXPECT_EQ(3u, log
.dups
.size());
2553 if (3 == log
.dups
.size()) {
2554 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2555 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2557 EXPECT_EQ(11u, log
.dups
.back().version
.epoch
);
2558 EXPECT_EQ(1u, log
.dups
.back().version
.version
);
2565 TEST_F(PGLogMergeDupsTest
, Same
) {
2566 log
.tail
= eversion_t(14, 1);
2570 add_dups(example_dups_1());
2572 add_dups(olog
, example_dups_1());
2574 bool changed
= merge_log_dups(olog
);
2576 EXPECT_FALSE(changed
);
2577 EXPECT_EQ(5u, log
.dups
.size());
2579 if (5 == log
.dups
.size()) {
2580 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2581 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2583 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2584 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2592 TEST_F(PGLogMergeDupsTest
, Later
) {
2593 log
.tail
= eversion_t(16, 14);
2597 add_dups(example_dups_1());
2599 add_dups(olog
, example_dups_2());
2601 bool changed
= merge_log_dups(olog
);
2603 EXPECT_TRUE(changed
);
2604 EXPECT_EQ(6u, log
.dups
.size());
2606 if (6 == log
.dups
.size()) {
2607 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2608 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2610 EXPECT_EQ(15u, log
.dups
.back().version
.epoch
);
2611 EXPECT_EQ(11u, log
.dups
.back().version
.version
);
2619 TEST_F(PGLogMergeDupsTest
, Earlier
) {
2620 log
.tail
= eversion_t(17, 2);
2624 add_dups(example_dups_2());
2626 add_dups(olog
, example_dups_1());
2628 bool changed
= merge_log_dups(olog
);
2630 EXPECT_TRUE(changed
);
2631 EXPECT_EQ(8u, log
.dups
.size());
2633 if (6 == log
.dups
.size()) {
2634 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2635 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2637 EXPECT_EQ(16u, log
.dups
.back().version
.epoch
);
2638 EXPECT_EQ(32u, log
.dups
.back().version
.version
);
2646 TEST_F(PGLogMergeDupsTest
, Superset
) {
2647 log
.tail
= eversion_t(17, 2);
2651 add_dups(example_dups_1());
2654 olog
.dups
.push_back(create_dup_entry(9, 5));
2655 olog
.dups
.push_back(create_dup_entry(15, 11));
2657 bool changed
= merge_log_dups(olog
);
2659 EXPECT_TRUE(changed
);
2660 EXPECT_EQ(7u, log
.dups
.size());
2662 if (7 == log
.dups
.size()) {
2663 EXPECT_EQ(9u, log
.dups
.front().version
.epoch
);
2664 EXPECT_EQ(5u, log
.dups
.front().version
.version
);
2666 EXPECT_EQ(15u, log
.dups
.back().version
.epoch
);
2667 EXPECT_EQ(11u, log
.dups
.back().version
.version
);
2675 struct PGLogTrimTest
:
2676 public ::testing::Test
,
2677 public PGLogTestBase
,
2678 public PGLog::IndexedLog
2680 CephContext
*cct
= g_ceph_context
;
2682 using ::testing::Test::SetUp
;
2683 void SetUp(unsigned min_entries
, unsigned max_entries
, unsigned dup_track
) {
2684 constexpr size_t size
= 10;
2686 char min_entries_s
[size
];
2687 char max_entries_s
[size
];
2688 char dup_track_s
[size
];
2690 snprintf(min_entries_s
, size
, "%u", min_entries
);
2691 snprintf(max_entries_s
, size
, "%u", max_entries
);
2692 snprintf(dup_track_s
, size
, "%u", dup_track
);
2694 cct
->_conf
.set_val_or_die("osd_min_pg_log_entries", min_entries_s
);
2695 cct
->_conf
.set_val_or_die("osd_max_pg_log_entries", max_entries_s
);
2696 cct
->_conf
.set_val_or_die("osd_pg_log_dups_tracked", dup_track_s
);
2698 }; // struct PGLogTrimTest
2701 TEST_F(PGLogTrimTest
, TestMakingCephContext
)
2705 EXPECT_EQ(1u, cct
->_conf
->osd_min_pg_log_entries
);
2706 EXPECT_EQ(2u, cct
->_conf
->osd_max_pg_log_entries
);
2707 EXPECT_EQ(5u, cct
->_conf
->osd_pg_log_dups_tracked
);
2711 TEST_F(PGLogTrimTest
, TestPartialTrim
)
2714 PGLog::IndexedLog log
;
2715 log
.head
= mk_evt(24, 0);
2716 log
.skip_can_rollback_to_to_head();
2717 log
.head
= mk_evt(9, 0);
2719 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2720 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2721 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2722 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2723 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2724 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2726 std::set
<eversion_t
> trimmed
;
2727 std::set
<std::string
> trimmed_dups
;
2728 eversion_t write_from_dups
= eversion_t::max();
2730 log
.trim(cct
, mk_evt(19, 157), &trimmed
, &trimmed_dups
, &write_from_dups
);
2732 EXPECT_EQ(eversion_t(15, 150), write_from_dups
);
2733 EXPECT_EQ(3u, log
.log
.size());
2734 EXPECT_EQ(3u, trimmed
.size());
2735 EXPECT_EQ(2u, log
.dups
.size());
2736 EXPECT_EQ(0u, trimmed_dups
.size());
2740 std::set
<eversion_t
> trimmed2
;
2741 std::set
<std::string
> trimmed_dups2
;
2742 eversion_t write_from_dups2
= eversion_t::max();
2744 log
.trim(cct
, mk_evt(20, 164), &trimmed2
, &trimmed_dups2
, &write_from_dups2
);
2746 EXPECT_EQ(eversion_t(19, 160), write_from_dups2
);
2747 EXPECT_EQ(2u, log
.log
.size());
2748 EXPECT_EQ(1u, trimmed2
.size());
2749 EXPECT_EQ(2u, log
.dups
.size());
2750 EXPECT_EQ(1u, trimmed_dups2
.size());
2754 TEST_F(PGLogTrimTest
, TestTrimNoTrimmed
) {
2756 PGLog::IndexedLog log
;
2757 log
.head
= mk_evt(20, 0);
2758 log
.skip_can_rollback_to_to_head();
2759 log
.head
= mk_evt(9, 0);
2761 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2762 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2763 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2764 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2765 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2766 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2768 eversion_t write_from_dups
= eversion_t::max();
2770 log
.trim(cct
, mk_evt(19, 157), nullptr, nullptr, &write_from_dups
);
2772 EXPECT_EQ(eversion_t(15, 150), write_from_dups
);
2773 EXPECT_EQ(3u, log
.log
.size());
2774 EXPECT_EQ(2u, log
.dups
.size());
2778 TEST_F(PGLogTrimTest
, TestTrimNoDups
)
2781 PGLog::IndexedLog log
;
2782 log
.head
= mk_evt(20, 0);
2783 log
.skip_can_rollback_to_to_head();
2784 log
.head
= mk_evt(9, 0);
2786 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2787 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2788 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2789 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2790 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2791 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2793 std::set
<eversion_t
> trimmed
;
2794 std::set
<std::string
> trimmed_dups
;
2795 eversion_t write_from_dups
= eversion_t::max();
2797 log
.trim(cct
, mk_evt(19, 157), &trimmed
, &trimmed_dups
, &write_from_dups
);
2799 EXPECT_EQ(eversion_t::max(), write_from_dups
);
2800 EXPECT_EQ(3u, log
.log
.size());
2801 EXPECT_EQ(3u, trimmed
.size());
2802 EXPECT_EQ(0u, log
.dups
.size());
2803 EXPECT_EQ(0u, trimmed_dups
.size());
2806 TEST_F(PGLogTrimTest
, TestNoTrim
)
2809 PGLog::IndexedLog log
;
2810 log
.head
= mk_evt(24, 0);
2811 log
.skip_can_rollback_to_to_head();
2812 log
.head
= mk_evt(9, 0);
2814 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2815 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2816 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2817 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2818 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2819 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2821 std::set
<eversion_t
> trimmed
;
2822 std::set
<std::string
> trimmed_dups
;
2823 eversion_t write_from_dups
= eversion_t::max();
2825 log
.trim(cct
, mk_evt(9, 99), &trimmed
, &trimmed_dups
, &write_from_dups
);
2827 EXPECT_EQ(eversion_t::max(), write_from_dups
);
2828 EXPECT_EQ(6u, log
.log
.size());
2829 EXPECT_EQ(0u, trimmed
.size());
2830 EXPECT_EQ(0u, log
.dups
.size());
2831 EXPECT_EQ(0u, trimmed_dups
.size());
2834 TEST_F(PGLogTrimTest
, TestTrimAll
)
2837 PGLog::IndexedLog log
;
2838 EXPECT_EQ(0u, log
.dup_index
.size()); // Sanity check
2839 log
.head
= mk_evt(24, 0);
2840 log
.skip_can_rollback_to_to_head();
2841 log
.head
= mk_evt(9, 0);
2843 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2844 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2845 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2846 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2847 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2848 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2850 std::set
<eversion_t
> trimmed
;
2851 std::set
<std::string
> trimmed_dups
;
2852 eversion_t write_from_dups
= eversion_t::max();
2854 log
.trim(cct
, mk_evt(22, 180), &trimmed
, &trimmed_dups
, &write_from_dups
);
2856 EXPECT_EQ(eversion_t(15, 150), write_from_dups
);
2857 EXPECT_EQ(0u, log
.log
.size());
2858 EXPECT_EQ(6u, trimmed
.size());
2859 EXPECT_EQ(5u, log
.dups
.size());
2860 EXPECT_EQ(0u, trimmed_dups
.size());
2861 EXPECT_EQ(0u, log
.dup_index
.size()); // dup_index entry should be trimmed
2865 TEST_F(PGLogTrimTest
, TestGetRequest
) {
2867 PGLog::IndexedLog log
;
2868 log
.head
= mk_evt(20, 0);
2869 log
.skip_can_rollback_to_to_head();
2870 log
.head
= mk_evt(9, 0);
2872 entity_name_t client
= entity_name_t::CLIENT(777);
2874 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70),
2875 osd_reqid_t(client
, 8, 1)));
2876 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100),
2877 osd_reqid_t(client
, 8, 2)));
2878 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150),
2879 osd_reqid_t(client
, 8, 3)));
2880 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152),
2881 osd_reqid_t(client
, 8, 4)));
2882 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160),
2883 osd_reqid_t(client
, 8, 5)));
2884 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166),
2885 osd_reqid_t(client
, 8, 6)));
2887 eversion_t write_from_dups
= eversion_t::max();
2889 log
.trim(cct
, mk_evt(19, 157), nullptr, nullptr, &write_from_dups
);
2891 EXPECT_EQ(eversion_t(15, 150), write_from_dups
);
2892 EXPECT_EQ(3u, log
.log
.size());
2893 EXPECT_EQ(2u, log
.dups
.size());
2896 version_t user_version
;
2899 osd_reqid_t log_reqid
= osd_reqid_t(client
, 8, 5);
2900 osd_reqid_t dup_reqid
= osd_reqid_t(client
, 8, 3);
2901 osd_reqid_t bad_reqid
= osd_reqid_t(client
, 8, 1);
2905 result
= log
.get_request(log_reqid
, &version
, &user_version
, &return_code
);
2906 EXPECT_EQ(true, result
);
2907 EXPECT_EQ(mk_evt(21, 165), version
);
2909 result
= log
.get_request(dup_reqid
, &version
, &user_version
, &return_code
);
2910 EXPECT_EQ(true, result
);
2911 EXPECT_EQ(mk_evt(15, 155), version
);
2913 result
= log
.get_request(bad_reqid
, &version
, &user_version
, &return_code
);
2914 EXPECT_FALSE(result
);
2917 TEST_F(PGLogTest
, _merge_object_divergent_entries
) {
2919 // Test for issue 20843
2921 hobject_t
hoid(object_t(/*name*/"notify.7"),
2926 /*nspace*/string(""));
2927 mempool::osd_pglog::list
<pg_log_entry_t
> orig_entries
;
2928 orig_entries
.push_back(mk_ple_mod(hoid
, eversion_t(8336, 957), eversion_t(8336, 952)));
2929 orig_entries
.push_back(mk_ple_err(hoid
, eversion_t(8336, 958)));
2930 orig_entries
.push_back(mk_ple_err(hoid
, eversion_t(8336, 959)));
2931 orig_entries
.push_back(mk_ple_mod(hoid
, eversion_t(8336, 960), eversion_t(8336, 957)));
2932 log
.add(mk_ple_mod(hoid
, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2934 /*need*/eversion_t(8971, 1070),
2935 /*have*/eversion_t(8336, 952),
2938 LogHandler rollbacker
;
2939 _merge_object_divergent_entries(log
, hoid
,
2940 orig_entries
, oinfo
,
2941 log
.get_can_rollback_to(),
2942 missing
, &rollbacker
,
2947 // skip leading error entries
2949 hobject_t
hoid(object_t(/*name*/"notify.7"),
2954 /*nspace*/string(""));
2955 mempool::osd_pglog::list
<pg_log_entry_t
> orig_entries
;
2956 orig_entries
.push_back(mk_ple_err(hoid
, eversion_t(8336, 956)));
2957 orig_entries
.push_back(mk_ple_mod(hoid
, eversion_t(8336, 957), eversion_t(8336, 952)));
2958 log
.add(mk_ple_mod(hoid
, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2960 /*need*/eversion_t(8971, 1070),
2961 /*have*/eversion_t(8336, 952),
2964 LogHandler rollbacker
;
2965 _merge_object_divergent_entries(log
, hoid
,
2966 orig_entries
, oinfo
,
2967 log
.get_can_rollback_to(),
2968 missing
, &rollbacker
,
2974 TEST(eversion_t
, get_key_name
) {
2975 eversion_t
a(1234, 5678);
2976 std::string a_key_name
= a
.get_key_name();
2977 EXPECT_EQ("0000001234.00000000000000005678", a_key_name
);
2980 TEST(pg_log_dup_t
, get_key_name
) {
2981 pg_log_dup_t
a(eversion_t(1234, 5678),
2983 osd_reqid_t(entity_name_t::CLIENT(777), 8, 999),
2985 std::string a_key_name
= a
.get_key_name();
2986 EXPECT_EQ("dup_0000001234.00000000000000005678", a_key_name
);
2990 // compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "