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
, std::move(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
, std::move(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
, std::move(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
, std::move(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
, std::move(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
, std::move(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
, std::move(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 vector
<pg_log_op_return_item_t
> op_returns
;
2208 bool got
= log
.get_request(
2209 entry
.reqid
, &replay_version
, &user_version
, &return_code
, &op_returns
);
2211 EXPECT_EQ(entry
.return_code
, return_code
);
2212 EXPECT_EQ(entry
.version
, replay_version
);
2213 EXPECT_EQ(entry
.user_version
, user_version
);
2217 TEST_F(PGLogTest
, ErrorNotIndexedByObject
) {
2220 // make sure writes, deletes, and errors are found
2221 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
2223 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(6,2), eversion_t(3,4),
2224 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2225 utime_t(0,1), -ENOENT
));
2227 EXPECT_FALSE(log
.logged_object(oid
));
2229 pg_log_entry_t
modify(pg_log_entry_t::MODIFY
, oid
, eversion_t(6,3),
2231 osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2235 EXPECT_TRUE(log
.logged_object(oid
));
2236 pg_log_entry_t
*entry
= log
.objects
[oid
];
2237 EXPECT_EQ(modify
.op
, entry
->op
);
2238 EXPECT_EQ(modify
.version
, entry
->version
);
2239 EXPECT_EQ(modify
.prior_version
, entry
->prior_version
);
2240 EXPECT_EQ(modify
.user_version
, entry
->user_version
);
2241 EXPECT_EQ(modify
.reqid
, entry
->reqid
);
2243 pg_log_entry_t
del(pg_log_entry_t::DELETE
, oid
, eversion_t(7,4),
2245 osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2249 EXPECT_TRUE(log
.logged_object(oid
));
2250 entry
= log
.objects
[oid
];
2251 EXPECT_EQ(del
.op
, entry
->op
);
2252 EXPECT_EQ(del
.version
, entry
->version
);
2253 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2254 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2255 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2258 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(7,5), eversion_t(7,4),
2259 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2260 utime_t(20,1), -ENOENT
));
2262 EXPECT_TRUE(log
.logged_object(oid
));
2263 entry
= log
.objects
[oid
];
2264 EXPECT_EQ(del
.op
, entry
->op
);
2265 EXPECT_EQ(del
.version
, entry
->version
);
2266 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2267 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2268 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2271 TEST_F(PGLogTest
, split_into_preserves_may_include_deletes
) {
2275 may_include_deletes_in_missing_dirty
= false;
2276 missing
.may_include_deletes
= true;
2277 PGLog
child_log(cct
);
2279 split_into(child_pg
, 6, &child_log
);
2280 ASSERT_TRUE(child_log
.get_missing().may_include_deletes
);
2281 ASSERT_TRUE(child_log
.get_may_include_deletes_in_missing_dirty());
2285 may_include_deletes_in_missing_dirty
= false;
2286 missing
.may_include_deletes
= false;
2287 PGLog
child_log(cct
);
2289 split_into(child_pg
, 6, &child_log
);
2290 ASSERT_FALSE(child_log
.get_missing().may_include_deletes
);
2291 ASSERT_FALSE(child_log
.get_may_include_deletes_in_missing_dirty());
2295 class PGLogTestRebuildMissing
: public PGLogTest
, public StoreTestFixture
{
2297 PGLogTestRebuildMissing() : PGLogTest(), StoreTestFixture("memstore") {}
2298 void SetUp() override
{
2299 StoreTestFixture::SetUp();
2300 ObjectStore::Transaction t
;
2301 test_coll
= coll_t(spg_t(pg_t(1, 1)));
2302 ch
= store
->create_new_collection(test_coll
);
2303 t
.create_collection(test_coll
, 0);
2304 store
->queue_transaction(ch
, std::move(t
));
2305 existing_oid
= mk_obj(0);
2306 nonexistent_oid
= mk_obj(1);
2307 ghobject_t
existing_ghobj(existing_oid
);
2308 object_info_t existing_info
;
2309 existing_info
.version
= eversion_t(6, 2);
2311 encode(existing_info
, enc_oi
, 0);
2312 ObjectStore::Transaction t2
;
2313 t2
.touch(test_coll
, ghobject_t(existing_oid
));
2314 t2
.setattr(test_coll
, ghobject_t(existing_oid
), OI_ATTR
, enc_oi
);
2315 ASSERT_EQ(0, store
->queue_transaction(ch
, std::move(t2
)));
2316 info
.last_backfill
= hobject_t::get_max();
2317 info
.last_complete
= eversion_t();
2320 void TearDown() override
{
2322 missing
.may_include_deletes
= false;
2323 StoreTestFixture::TearDown();
2328 hobject_t existing_oid
, nonexistent_oid
;
2330 void run_rebuild_missing_test(const map
<hobject_t
, pg_missing_item
> &expected_missing_items
) {
2331 rebuild_missing_set_with_deletes(store
.get(), ch
, info
);
2332 ASSERT_EQ(expected_missing_items
, missing
.get_items());
2336 TEST_F(PGLogTestRebuildMissing
, EmptyLog
) {
2337 missing
.add(existing_oid
, mk_evt(6, 2), mk_evt(6, 3), false);
2338 missing
.add(nonexistent_oid
, mk_evt(7, 4), mk_evt(0, 0), false);
2339 map
<hobject_t
, pg_missing_item
> orig_missing
= missing
.get_items();
2340 run_rebuild_missing_test(orig_missing
);
2343 TEST_F(PGLogTestRebuildMissing
, SameVersionMod
) {
2344 missing
.add(existing_oid
, mk_evt(6, 2), mk_evt(6, 1), false);
2345 log
.add(mk_ple_mod(existing_oid
, mk_evt(6, 2), mk_evt(6, 1)));
2346 map
<hobject_t
, pg_missing_item
> empty_missing
;
2347 run_rebuild_missing_test(empty_missing
);
2350 TEST_F(PGLogTestRebuildMissing
, DelExisting
) {
2351 missing
.add(existing_oid
, mk_evt(6, 3), mk_evt(6, 2), false);
2352 log
.add(mk_ple_dt(existing_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2353 map
<hobject_t
, pg_missing_item
> expected
;
2354 expected
[existing_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(6, 2), true);
2355 run_rebuild_missing_test(expected
);
2358 TEST_F(PGLogTestRebuildMissing
, DelNonexistent
) {
2359 log
.add(mk_ple_dt(nonexistent_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2360 map
<hobject_t
, pg_missing_item
> expected
;
2361 expected
[nonexistent_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2362 run_rebuild_missing_test(expected
);
2365 TEST_F(PGLogTestRebuildMissing
, MissingNotInLog
) {
2366 missing
.add(mk_obj(10), mk_evt(8, 12), mk_evt(8, 10), false);
2367 log
.add(mk_ple_dt(nonexistent_oid
, mk_evt(7, 5), mk_evt(7, 4)));
2368 map
<hobject_t
, pg_missing_item
> expected
;
2369 expected
[nonexistent_oid
] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2370 expected
[mk_obj(10)] = pg_missing_item(mk_evt(8, 12), mk_evt(8, 10), false);
2371 run_rebuild_missing_test(expected
);
2375 class PGLogMergeDupsTest
: protected PGLog
, public StoreTestFixture
{
2379 PGLogMergeDupsTest() : PGLog(g_ceph_context
), StoreTestFixture("memstore") { }
2381 void SetUp() override
{
2382 StoreTestFixture::SetUp();
2383 ObjectStore::Transaction t
;
2384 test_coll
= coll_t(spg_t(pg_t(1, 1)));
2385 auto ch
= store
->create_new_collection(test_coll
);
2386 t
.create_collection(test_coll
, 0);
2387 store
->queue_transaction(ch
, std::move(t
));
2390 void TearDown() override
{
2391 test_disk_roundtrip();
2393 StoreTestFixture::TearDown();
2396 static pg_log_dup_t
create_dup_entry(uint a
, uint b
) {
2397 // make each dup_entry unique by using different client id's
2398 static uint client_id
= 777;
2399 return pg_log_dup_t(eversion_t(a
, b
),
2401 osd_reqid_t(entity_name_t::CLIENT(client_id
++), 8, 1),
2405 static std::vector
<pg_log_dup_t
> example_dups_1() {
2406 std::vector
<pg_log_dup_t
> result
= {
2407 create_dup_entry(10, 11),
2408 create_dup_entry(10, 12),
2409 create_dup_entry(11, 1),
2410 create_dup_entry(12, 3),
2411 create_dup_entry(13, 99)
2416 static std::vector
<pg_log_dup_t
> example_dups_2() {
2417 std::vector
<pg_log_dup_t
> result
= {
2418 create_dup_entry(12, 3),
2419 create_dup_entry(13, 99),
2420 create_dup_entry(15, 11),
2421 create_dup_entry(16, 14),
2422 create_dup_entry(16, 32)
2427 void add_dups(uint a
, uint b
) {
2428 log
.dups
.push_back(create_dup_entry(a
, b
));
2429 write_from_dups
= std::min(write_from_dups
, log
.dups
.back().version
);
2432 void add_dups(const std::vector
<pg_log_dup_t
>& l
) {
2434 log
.dups
.push_back(i
);
2435 write_from_dups
= std::min(write_from_dups
, log
.dups
.back().version
);
2439 static void add_dups(IndexedLog
& log
, const std::vector
<pg_log_dup_t
>& dups
) {
2440 for (auto& i
: dups
) {
2441 log
.dups
.push_back(i
);
2445 void check_order() {
2446 eversion_t
prev(0, 0);
2448 for (auto& i
: log
.dups
) {
2449 EXPECT_LT(prev
, i
.version
) << "verify versions monotonically increase";
2454 void check_index() {
2455 EXPECT_EQ(log
.dups
.size(), log
.dup_index
.size());
2456 for (auto& i
: log
.dups
) {
2457 EXPECT_EQ(1u, log
.dup_index
.count(i
.reqid
));
2461 void test_disk_roundtrip() {
2462 ObjectStore::Transaction t
;
2466 ghobject_t
log_oid(hoid
);
2467 map
<string
, bufferlist
> km
;
2468 write_log_and_missing(t
, &km
, test_coll
, log_oid
, false);
2470 t
.omap_setkeys(test_coll
, log_oid
, km
);
2472 auto ch
= store
->open_collection(test_coll
);
2473 ASSERT_EQ(0, store
->queue_transaction(ch
, std::move(t
)));
2475 auto orig_dups
= log
.dups
;
2478 read_log_and_missing(store
.get(), ch
, log_oid
,
2479 pg_info_t(), err
, false);
2480 ASSERT_EQ(orig_dups
.size(), log
.dups
.size());
2481 ASSERT_EQ(orig_dups
, log
.dups
);
2482 auto dups_it
= log
.dups
.begin();
2483 for (auto orig_dup
: orig_dups
) {
2484 ASSERT_EQ(orig_dup
, *dups_it
);
2492 TEST_F(PGLogMergeDupsTest
, OtherEmpty
) {
2493 log
.tail
= eversion_t(14, 5);
2497 add_dups(example_dups_1());
2500 bool changed
= merge_log_dups(olog
);
2502 EXPECT_FALSE(changed
);
2503 EXPECT_EQ(5u, log
.dups
.size());
2505 if (5 == log
.dups
.size()) {
2506 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2507 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2508 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2509 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2516 TEST_F(PGLogMergeDupsTest
, AmEmpty
) {
2517 log
.tail
= eversion_t(14, 5);
2522 add_dups(olog
, example_dups_1());
2524 bool changed
= merge_log_dups(olog
);
2526 EXPECT_TRUE(changed
);
2527 EXPECT_EQ(5u, log
.dups
.size());
2529 if (5 == log
.dups
.size()) {
2530 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2531 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2533 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2534 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2541 TEST_F(PGLogMergeDupsTest
, AmEmptyOverlap
) {
2542 log
.tail
= eversion_t(12, 3);
2547 add_dups(olog
, example_dups_1());
2549 bool changed
= merge_log_dups(olog
);
2551 EXPECT_TRUE(changed
);
2552 EXPECT_EQ(4u, log
.dups
.size());
2554 if (4 == log
.dups
.size()) {
2555 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2556 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2558 EXPECT_EQ(12u, log
.dups
.back().version
.epoch
);
2559 EXPECT_EQ(3u, log
.dups
.back().version
.version
);
2566 TEST_F(PGLogMergeDupsTest
, Same
) {
2567 log
.tail
= eversion_t(14, 1);
2571 add_dups(example_dups_1());
2573 add_dups(olog
, example_dups_1());
2575 bool changed
= merge_log_dups(olog
);
2577 EXPECT_FALSE(changed
);
2578 EXPECT_EQ(5u, log
.dups
.size());
2580 if (5 == log
.dups
.size()) {
2581 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2582 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2584 EXPECT_EQ(13u, log
.dups
.back().version
.epoch
);
2585 EXPECT_EQ(99u, log
.dups
.back().version
.version
);
2593 TEST_F(PGLogMergeDupsTest
, Later
) {
2594 log
.tail
= eversion_t(16, 14);
2598 add_dups(example_dups_1());
2600 add_dups(olog
, example_dups_2());
2602 bool changed
= merge_log_dups(olog
);
2604 EXPECT_TRUE(changed
);
2605 EXPECT_EQ(7u, log
.dups
.size());
2607 if (7 == log
.dups
.size()) {
2608 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2609 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2611 EXPECT_EQ(16u, log
.dups
.back().version
.epoch
);
2612 EXPECT_EQ(14u, log
.dups
.back().version
.version
);
2620 TEST_F(PGLogMergeDupsTest
, Earlier
) {
2621 log
.tail
= eversion_t(17, 2);
2625 add_dups(example_dups_2());
2627 add_dups(olog
, example_dups_1());
2629 bool changed
= merge_log_dups(olog
);
2631 EXPECT_TRUE(changed
);
2632 EXPECT_EQ(8u, log
.dups
.size());
2634 if (6 == log
.dups
.size()) {
2635 EXPECT_EQ(10u, log
.dups
.front().version
.epoch
);
2636 EXPECT_EQ(11u, log
.dups
.front().version
.version
);
2638 EXPECT_EQ(16u, log
.dups
.back().version
.epoch
);
2639 EXPECT_EQ(32u, log
.dups
.back().version
.version
);
2647 TEST_F(PGLogMergeDupsTest
, Superset
) {
2648 log
.tail
= eversion_t(17, 2);
2652 add_dups(example_dups_1());
2655 olog
.dups
.push_back(create_dup_entry(9, 5));
2656 olog
.dups
.push_back(create_dup_entry(15, 11));
2658 bool changed
= merge_log_dups(olog
);
2660 EXPECT_TRUE(changed
);
2661 EXPECT_EQ(7u, log
.dups
.size());
2663 if (7 == log
.dups
.size()) {
2664 EXPECT_EQ(9u, log
.dups
.front().version
.epoch
);
2665 EXPECT_EQ(5u, log
.dups
.front().version
.version
);
2667 EXPECT_EQ(15u, log
.dups
.back().version
.epoch
);
2668 EXPECT_EQ(11u, log
.dups
.back().version
.version
);
2676 struct PGLogTrimTest
:
2677 public ::testing::Test
,
2678 public PGLogTestBase
,
2679 public PGLog::IndexedLog
2681 CephContext
*cct
= g_ceph_context
;
2683 using ::testing::Test::SetUp
;
2684 void SetUp(unsigned dup_track
) {
2685 constexpr size_t size
= 10;
2687 char dup_track_s
[size
];
2689 snprintf(dup_track_s
, size
, "%u", dup_track
);
2691 cct
->_conf
.set_val_or_die("osd_pg_log_dups_tracked", dup_track_s
);
2693 }; // struct PGLogTrimTest
2696 TEST_F(PGLogTrimTest
, TestMakingCephContext
)
2700 EXPECT_EQ(5u, cct
->_conf
->osd_pg_log_dups_tracked
);
2704 TEST_F(PGLogTrimTest
, TestPartialTrim
)
2707 PGLog::IndexedLog log
;
2708 log
.head
= mk_evt(24, 0);
2709 log
.skip_can_rollback_to_to_head();
2710 log
.head
= mk_evt(9, 0);
2712 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2713 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2714 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2715 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2716 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2717 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2719 std::set
<eversion_t
> trimmed
;
2720 std::set
<std::string
> trimmed_dups
;
2721 eversion_t write_from_dups
= eversion_t::max();
2723 log
.trim(cct
, mk_evt(19, 157), &trimmed
, &trimmed_dups
, &write_from_dups
);
2725 EXPECT_EQ(eversion_t(15, 150), write_from_dups
);
2726 EXPECT_EQ(3u, log
.log
.size());
2727 EXPECT_EQ(3u, trimmed
.size());
2728 EXPECT_EQ(2u, log
.dups
.size());
2729 EXPECT_EQ(0u, trimmed_dups
.size());
2733 std::set
<eversion_t
> trimmed2
;
2734 std::set
<std::string
> trimmed_dups2
;
2735 eversion_t write_from_dups2
= eversion_t::max();
2737 log
.trim(cct
, mk_evt(20, 164), &trimmed2
, &trimmed_dups2
, &write_from_dups2
);
2739 EXPECT_EQ(eversion_t(19, 160), write_from_dups2
);
2740 EXPECT_EQ(2u, log
.log
.size());
2741 EXPECT_EQ(1u, trimmed2
.size());
2742 EXPECT_EQ(2u, log
.dups
.size());
2743 EXPECT_EQ(1u, trimmed_dups2
.size());
2747 TEST_F(PGLogTrimTest
, TestTrimNoTrimmed
) {
2749 PGLog::IndexedLog log
;
2750 log
.head
= mk_evt(20, 0);
2751 log
.skip_can_rollback_to_to_head();
2752 log
.head
= mk_evt(9, 0);
2754 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2755 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2756 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2757 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2758 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2759 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2761 eversion_t write_from_dups
= eversion_t::max();
2763 log
.trim(cct
, mk_evt(19, 157), nullptr, nullptr, &write_from_dups
);
2765 EXPECT_EQ(eversion_t(15, 150), write_from_dups
);
2766 EXPECT_EQ(3u, log
.log
.size());
2767 EXPECT_EQ(2u, log
.dups
.size());
2771 TEST_F(PGLogTrimTest
, TestTrimNoDups
)
2774 PGLog::IndexedLog log
;
2775 log
.head
= mk_evt(20, 0);
2776 log
.skip_can_rollback_to_to_head();
2777 log
.head
= mk_evt(9, 0);
2779 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2780 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2781 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2782 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2783 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2784 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2786 std::set
<eversion_t
> trimmed
;
2787 std::set
<std::string
> trimmed_dups
;
2788 eversion_t write_from_dups
= eversion_t::max();
2790 log
.trim(cct
, mk_evt(19, 157), &trimmed
, &trimmed_dups
, &write_from_dups
);
2792 EXPECT_EQ(eversion_t::max(), write_from_dups
);
2793 EXPECT_EQ(3u, log
.log
.size());
2794 EXPECT_EQ(3u, trimmed
.size());
2795 EXPECT_EQ(0u, log
.dups
.size());
2796 EXPECT_EQ(0u, trimmed_dups
.size());
2799 TEST_F(PGLogTrimTest
, TestNoTrim
)
2802 PGLog::IndexedLog log
;
2803 log
.head
= mk_evt(24, 0);
2804 log
.skip_can_rollback_to_to_head();
2805 log
.head
= mk_evt(9, 0);
2807 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2808 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2809 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2810 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2811 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2812 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2814 std::set
<eversion_t
> trimmed
;
2815 std::set
<std::string
> trimmed_dups
;
2816 eversion_t write_from_dups
= eversion_t::max();
2818 log
.trim(cct
, mk_evt(9, 99), &trimmed
, &trimmed_dups
, &write_from_dups
);
2820 EXPECT_EQ(eversion_t::max(), write_from_dups
);
2821 EXPECT_EQ(6u, log
.log
.size());
2822 EXPECT_EQ(0u, trimmed
.size());
2823 EXPECT_EQ(0u, log
.dups
.size());
2824 EXPECT_EQ(0u, trimmed_dups
.size());
2827 TEST_F(PGLogTrimTest
, TestTrimAll
)
2830 PGLog::IndexedLog log
;
2831 EXPECT_EQ(0u, log
.dup_index
.size()); // Sanity check
2832 log
.head
= mk_evt(24, 0);
2833 log
.skip_can_rollback_to_to_head();
2834 log
.head
= mk_evt(9, 0);
2836 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2837 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2838 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2839 log
.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2840 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2841 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2843 std::set
<eversion_t
> trimmed
;
2844 std::set
<std::string
> trimmed_dups
;
2845 eversion_t write_from_dups
= eversion_t::max();
2847 log
.trim(cct
, mk_evt(22, 180), &trimmed
, &trimmed_dups
, &write_from_dups
);
2849 EXPECT_EQ(eversion_t(15, 150), write_from_dups
);
2850 EXPECT_EQ(0u, log
.log
.size());
2851 EXPECT_EQ(6u, trimmed
.size());
2852 EXPECT_EQ(5u, log
.dups
.size());
2853 EXPECT_EQ(0u, trimmed_dups
.size());
2854 EXPECT_EQ(0u, log
.dup_index
.size()); // dup_index entry should be trimmed
2858 TEST_F(PGLogTrimTest
, TestGetRequest
) {
2860 PGLog::IndexedLog log
;
2861 log
.head
= mk_evt(20, 0);
2862 log
.skip_can_rollback_to_to_head();
2863 log
.head
= mk_evt(9, 0);
2865 entity_name_t client
= entity_name_t::CLIENT(777);
2867 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70),
2868 osd_reqid_t(client
, 8, 1)));
2869 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100),
2870 osd_reqid_t(client
, 8, 2)));
2871 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150),
2872 osd_reqid_t(client
, 8, 3)));
2873 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152),
2874 osd_reqid_t(client
, 8, 4)));
2875 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160),
2876 osd_reqid_t(client
, 8, 5)));
2877 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166),
2878 osd_reqid_t(client
, 8, 6)));
2880 eversion_t write_from_dups
= eversion_t::max();
2882 log
.trim(cct
, mk_evt(19, 157), nullptr, nullptr, &write_from_dups
);
2884 EXPECT_EQ(eversion_t(15, 150), write_from_dups
);
2885 EXPECT_EQ(3u, log
.log
.size());
2886 EXPECT_EQ(2u, log
.dups
.size());
2889 version_t user_version
;
2891 vector
<pg_log_op_return_item_t
> op_returns
;
2893 osd_reqid_t log_reqid
= osd_reqid_t(client
, 8, 5);
2894 osd_reqid_t dup_reqid
= osd_reqid_t(client
, 8, 3);
2895 osd_reqid_t bad_reqid
= osd_reqid_t(client
, 8, 1);
2899 result
= log
.get_request(log_reqid
, &version
, &user_version
, &return_code
,
2901 EXPECT_EQ(true, result
);
2902 EXPECT_EQ(mk_evt(21, 165), version
);
2904 result
= log
.get_request(dup_reqid
, &version
, &user_version
, &return_code
,
2906 EXPECT_EQ(true, result
);
2907 EXPECT_EQ(mk_evt(15, 155), version
);
2909 result
= log
.get_request(bad_reqid
, &version
, &user_version
, &return_code
,
2911 EXPECT_FALSE(result
);
2914 TEST_F(PGLogTest
, _merge_object_divergent_entries
) {
2916 // Test for issue 20843
2918 hobject_t
hoid(object_t(/*name*/"notify.7"),
2923 /*nspace*/string(""));
2924 mempool::osd_pglog::list
<pg_log_entry_t
> orig_entries
;
2925 orig_entries
.push_back(mk_ple_mod(hoid
, eversion_t(8336, 957), eversion_t(8336, 952)));
2926 orig_entries
.push_back(mk_ple_err(hoid
, eversion_t(8336, 958)));
2927 orig_entries
.push_back(mk_ple_err(hoid
, eversion_t(8336, 959)));
2928 orig_entries
.push_back(mk_ple_mod(hoid
, eversion_t(8336, 960), eversion_t(8336, 957)));
2929 log
.add(mk_ple_mod(hoid
, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2931 /*need*/eversion_t(8971, 1070),
2932 /*have*/eversion_t(8336, 952),
2935 LogHandler rollbacker
;
2936 _merge_object_divergent_entries(log
, hoid
,
2937 orig_entries
, oinfo
,
2938 log
.get_can_rollback_to(),
2939 missing
, &rollbacker
,
2944 // skip leading error entries
2946 hobject_t
hoid(object_t(/*name*/"notify.7"),
2951 /*nspace*/string(""));
2952 mempool::osd_pglog::list
<pg_log_entry_t
> orig_entries
;
2953 orig_entries
.push_back(mk_ple_err(hoid
, eversion_t(8336, 956)));
2954 orig_entries
.push_back(mk_ple_mod(hoid
, eversion_t(8336, 957), eversion_t(8336, 952)));
2955 log
.add(mk_ple_mod(hoid
, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2957 /*need*/eversion_t(8971, 1070),
2958 /*have*/eversion_t(8336, 952),
2961 LogHandler rollbacker
;
2962 _merge_object_divergent_entries(log
, hoid
,
2963 orig_entries
, oinfo
,
2964 log
.get_can_rollback_to(),
2965 missing
, &rollbacker
,
2971 TEST(eversion_t
, get_key_name
) {
2972 eversion_t
a(1234, 5678);
2973 std::string a_key_name
= a
.get_key_name();
2974 EXPECT_EQ("0000001234.00000000000000005678", a_key_name
);
2977 TEST(pg_log_dup_t
, get_key_name
) {
2978 pg_log_dup_t
a(eversion_t(1234, 5678),
2980 osd_reqid_t(entity_name_t::CLIENT(777), 8, 999),
2982 std::string a_key_name
= a
.get_key_name();
2983 EXPECT_EQ("dup_0000001234.00000000000000005678", a_key_name
);
2987 // This tests trim() to make copies of
2988 // 2 log entries (107, 106) and 3 additional for a total
2989 // of 5 dups. Nothing from the original dups is copied.
2990 TEST_F(PGLogTrimTest
, TestTrimDups
) {
2992 PGLog::IndexedLog log
;
2993 log
.head
= mk_evt(21, 107);
2994 log
.skip_can_rollback_to_to_head();
2995 log
.tail
= mk_evt(9, 99);
2996 log
.head
= mk_evt(9, 99);
2998 entity_name_t client
= entity_name_t::CLIENT(777);
3000 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3001 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client
, 8, 1))));
3003 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3004 osd_reqid_t(client
, 8, 1)));
3005 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3006 osd_reqid_t(client
, 8, 2)));
3007 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3008 osd_reqid_t(client
, 8, 3)));
3009 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3010 osd_reqid_t(client
, 8, 4)));
3011 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3012 osd_reqid_t(client
, 8, 5)));
3013 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3014 osd_reqid_t(client
, 8, 6)));
3015 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3016 osd_reqid_t(client
, 8, 6)));
3017 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3018 osd_reqid_t(client
, 8, 6)));
3020 eversion_t write_from_dups
= eversion_t::max();
3022 log
.trim(cct
, mk_evt(21, 105), nullptr, nullptr, &write_from_dups
);
3024 EXPECT_EQ(eversion_t(20, 103), write_from_dups
) << log
;
3025 EXPECT_EQ(2u, log
.log
.size()) << log
;
3026 EXPECT_EQ(3u, log
.dups
.size()) << log
;
3029 // This tests trim() to make copies of
3030 // 4 log entries (107, 106, 105, 104) and 5 additional for a total
3031 // of 9 dups. Only 1 of 2 existing dups are copied.
3032 TEST_F(PGLogTrimTest
, TestTrimDups2
) {
3034 PGLog::IndexedLog log
;
3035 log
.head
= mk_evt(21, 107);
3036 log
.skip_can_rollback_to_to_head();
3037 log
.tail
= mk_evt(9, 99);
3038 log
.head
= mk_evt(9, 99);
3040 entity_name_t client
= entity_name_t::CLIENT(777);
3042 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3043 mk_evt(9, 98), mk_evt(8, 97), osd_reqid_t(client
, 8, 1))));
3044 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3045 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client
, 8, 1))));
3047 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3048 osd_reqid_t(client
, 8, 1)));
3049 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3050 osd_reqid_t(client
, 8, 2)));
3051 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3052 osd_reqid_t(client
, 8, 3)));
3053 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3054 osd_reqid_t(client
, 8, 4)));
3055 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3056 osd_reqid_t(client
, 8, 5)));
3057 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3058 osd_reqid_t(client
, 8, 6)));
3059 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3060 osd_reqid_t(client
, 8, 6)));
3061 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3062 osd_reqid_t(client
, 8, 6)));
3064 eversion_t write_from_dups
= eversion_t::max();
3066 log
.trim(cct
, mk_evt(20, 103), nullptr, nullptr, &write_from_dups
);
3068 EXPECT_EQ(eversion_t(10, 100), write_from_dups
) << log
;
3069 EXPECT_EQ(4u, log
.log
.size()) << log
;
3070 EXPECT_EQ(5u, log
.dups
.size()) << log
;
3073 // This tests copy_up_to() to make copies of
3074 // 2 log entries (107, 106) and 3 additional for a total
3075 // of 5 dups. Nothing from the original dups is copied.
3076 TEST_F(PGLogTrimTest
, TestCopyUpTo
) {
3078 PGLog::IndexedLog log
, copy
;
3079 log
.tail
= mk_evt(9, 99);
3080 log
.head
= mk_evt(9, 99);
3082 entity_name_t client
= entity_name_t::CLIENT(777);
3084 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3085 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client
, 8, 1))));
3087 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3088 osd_reqid_t(client
, 8, 1)));
3089 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3090 osd_reqid_t(client
, 8, 2)));
3091 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3092 osd_reqid_t(client
, 8, 3)));
3093 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3094 osd_reqid_t(client
, 8, 4)));
3095 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3096 osd_reqid_t(client
, 8, 5)));
3097 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3098 osd_reqid_t(client
, 8, 6)));
3099 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3100 osd_reqid_t(client
, 8, 6)));
3101 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3102 osd_reqid_t(client
, 8, 6)));
3104 copy
.copy_up_to(cct
, log
, 2);
3106 EXPECT_EQ(2u, copy
.log
.size()) << copy
;
3107 EXPECT_EQ(copy
.head
, mk_evt(21, 107)) << copy
;
3108 EXPECT_EQ(copy
.tail
, mk_evt(21, 105)) << copy
;
3109 // Tracking 5 means 3 additional as dups
3110 EXPECT_EQ(3u, copy
.dups
.size()) << copy
;
3113 // This tests copy_up_to() to make copies of
3114 // 4 log entries (107, 106, 105, 104) and 5 additional for a total
3115 // of 5 dups. Only 1 of 2 existing dups are copied.
3116 TEST_F(PGLogTrimTest
, TestCopyUpTo2
) {
3118 PGLog::IndexedLog log
, copy
;
3119 log
.tail
= mk_evt(9, 99);
3120 log
.head
= mk_evt(9, 99);
3122 entity_name_t client
= entity_name_t::CLIENT(777);
3124 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3125 mk_evt(8, 98), mk_evt(8, 97), osd_reqid_t(client
, 8, 1))));
3126 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3127 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client
, 8, 1))));
3129 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3130 osd_reqid_t(client
, 8, 1)));
3131 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3132 osd_reqid_t(client
, 8, 2)));
3133 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3134 osd_reqid_t(client
, 8, 3)));
3135 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3136 osd_reqid_t(client
, 8, 4)));
3137 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3138 osd_reqid_t(client
, 8, 5)));
3139 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3140 osd_reqid_t(client
, 8, 6)));
3141 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3142 osd_reqid_t(client
, 8, 6)));
3143 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3144 osd_reqid_t(client
, 8, 6)));
3146 copy
.copy_up_to(cct
, log
, 4);
3148 EXPECT_EQ(4u, copy
.log
.size()) << copy
;
3149 EXPECT_EQ(copy
.head
, mk_evt(21, 107)) << copy
;
3150 EXPECT_EQ(copy
.tail
, mk_evt(20, 103)) << copy
;
3151 // Tracking 5 means 3 additional as dups
3152 EXPECT_EQ(5u, copy
.dups
.size()) << copy
;
3155 // This tests copy_after() by specifying a version that copies
3156 // 2 log entries (107, 106) and 3 additional for a total
3157 // of 5 dups. Nothing of the original dups is copied.
3158 TEST_F(PGLogTrimTest
, TestCopyAfter
) {
3160 PGLog::IndexedLog log
, copy
;
3161 log
.tail
= mk_evt(9, 99);
3162 log
.head
= mk_evt(9, 99);
3164 entity_name_t client
= entity_name_t::CLIENT(777);
3166 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3167 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client
, 8, 1))));
3169 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3170 osd_reqid_t(client
, 8, 1)));
3171 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3172 osd_reqid_t(client
, 8, 2)));
3173 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3174 osd_reqid_t(client
, 8, 3)));
3175 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3176 osd_reqid_t(client
, 8, 4)));
3177 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3178 osd_reqid_t(client
, 8, 5)));
3179 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3180 osd_reqid_t(client
, 8, 6)));
3181 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3182 osd_reqid_t(client
, 8, 6)));
3183 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3184 osd_reqid_t(client
, 8, 6)));
3186 copy
.copy_after(cct
, log
, mk_evt(21, 105));
3188 EXPECT_EQ(2u, copy
.log
.size()) << copy
;
3189 EXPECT_EQ(copy
.head
, mk_evt(21, 107)) << copy
;
3190 EXPECT_EQ(copy
.tail
, mk_evt(21, 105)) << copy
;
3191 // Tracking 5 means 3 additional as dups
3192 EXPECT_EQ(3u, copy
.dups
.size()) << copy
;
3195 // This copies everything dups and log because of the large max dups
3196 // and value passed to copy_after().
3197 TEST_F(PGLogTrimTest
, TestCopyAfter2
) {
3199 PGLog::IndexedLog log
, copy
;
3200 log
.tail
= mk_evt(9, 99);
3201 log
.head
= mk_evt(9, 99);
3203 entity_name_t client
= entity_name_t::CLIENT(777);
3205 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3206 mk_evt(8, 93), mk_evt(8, 92), osd_reqid_t(client
, 8, 1))));
3207 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3208 mk_evt(8, 94), mk_evt(8, 93), osd_reqid_t(client
, 8, 1))));
3209 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3210 mk_evt(8, 95), mk_evt(8, 94), osd_reqid_t(client
, 8, 1))));
3211 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3212 mk_evt(8, 96), mk_evt(8, 95), osd_reqid_t(client
, 8, 1))));
3213 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3214 mk_evt(8, 97), mk_evt(8, 96), osd_reqid_t(client
, 8, 1))));
3215 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3216 mk_evt(8, 98), mk_evt(8, 97), osd_reqid_t(client
, 8, 1))));
3217 log
.dups
.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3218 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client
, 8, 1))));
3220 log
.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3221 osd_reqid_t(client
, 8, 1)));
3222 log
.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3223 osd_reqid_t(client
, 8, 2)));
3224 log
.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3225 osd_reqid_t(client
, 8, 3)));
3226 log
.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3227 osd_reqid_t(client
, 8, 4)));
3228 log
.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3229 osd_reqid_t(client
, 8, 5)));
3230 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3231 osd_reqid_t(client
, 8, 6)));
3232 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3233 osd_reqid_t(client
, 8, 6)));
3234 log
.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3235 osd_reqid_t(client
, 8, 6)));
3237 copy
.copy_after(cct
, log
, mk_evt(9, 99));
3239 EXPECT_EQ(8u, copy
.log
.size()) << copy
;
3240 EXPECT_EQ(copy
.head
, mk_evt(21, 107)) << copy
;
3241 EXPECT_EQ(copy
.tail
, mk_evt(9, 99)) << copy
;
3242 // Tracking 3000 is larger than all entries, so all dups copied
3243 EXPECT_EQ(7u, copy
.dups
.size()) << copy
;
3247 // compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "