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"
29 class PGLogTest
: public ::testing::Test
, protected PGLog
{
31 PGLogTest() : PGLog(g_ceph_context
) {}
32 void SetUp() override
{ }
34 void TearDown() override
{
38 static hobject_t
mk_obj(unsigned id
) {
46 static eversion_t
mk_evt(unsigned ep
, unsigned v
) {
47 return eversion_t(ep
, v
);
49 static pg_log_entry_t
mk_ple_mod(
50 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
52 e
.mark_unrollbackable();
53 e
.op
= pg_log_entry_t::MODIFY
;
59 static pg_log_entry_t
mk_ple_dt(
60 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
62 e
.mark_unrollbackable();
63 e
.op
= pg_log_entry_t::DELETE
;
69 static pg_log_entry_t
mk_ple_mod_rb(
70 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
72 e
.op
= pg_log_entry_t::MODIFY
;
78 static pg_log_entry_t
mk_ple_dt_rb(
79 const hobject_t
&hoid
, eversion_t v
, eversion_t pv
) {
81 e
.op
= pg_log_entry_t::DELETE
;
89 list
<pg_log_entry_t
> base
;
90 list
<pg_log_entry_t
> auth
;
91 list
<pg_log_entry_t
> div
;
96 set
<hobject_t
> toremove
;
97 list
<pg_log_entry_t
> torollback
;
106 fullauth
.log
.insert(fullauth
.log
.end(), base
.begin(), base
.end());
107 fullauth
.log
.insert(fullauth
.log
.end(), auth
.begin(), auth
.end());
108 fulldiv
.log
.insert(fulldiv
.log
.end(), base
.begin(), base
.end());
109 fulldiv
.log
.insert(fulldiv
.log
.end(), div
.begin(), div
.end());
111 fullauth
.head
= authinfo
.last_update
= fullauth
.log
.rbegin()->version
;
112 authinfo
.last_complete
= fullauth
.log
.rbegin()->version
;
113 authinfo
.log_tail
= fullauth
.log
.begin()->version
;
114 authinfo
.log_tail
.version
--;
115 fullauth
.tail
= authinfo
.log_tail
;
116 authinfo
.last_backfill
= hobject_t::get_max();
118 fulldiv
.head
= divinfo
.last_update
= fulldiv
.log
.rbegin()->version
;
119 divinfo
.last_complete
= eversion_t();
120 divinfo
.log_tail
= fulldiv
.log
.begin()->version
;
121 divinfo
.log_tail
.version
--;
122 fulldiv
.tail
= divinfo
.log_tail
;
123 divinfo
.last_backfill
= hobject_t::get_max();
125 if (init
.get_items().empty()) {
126 divinfo
.last_complete
= divinfo
.last_update
;
128 eversion_t fmissing
= init
.get_items().at(init
.get_rmissing().begin()->second
).need
;
129 for (list
<pg_log_entry_t
>::const_iterator i
= fulldiv
.log
.begin();
130 i
!= fulldiv
.log
.end();
132 if (i
->version
< fmissing
)
133 divinfo
.last_complete
= i
->version
;
142 void set_div_bounds(eversion_t head
, eversion_t tail
) {
143 fulldiv
.tail
= divinfo
.log_tail
= tail
;
144 fulldiv
.head
= divinfo
.last_update
= head
;
146 void set_auth_bounds(eversion_t head
, eversion_t tail
) {
147 fullauth
.tail
= authinfo
.log_tail
= tail
;
148 fullauth
.head
= authinfo
.last_update
= head
;
150 const IndexedLog
&get_fullauth() const { return fullauth
; }
151 const IndexedLog
&get_fulldiv() const { return fulldiv
; }
152 const pg_info_t
&get_authinfo() const { return authinfo
; }
153 const pg_info_t
&get_divinfo() const { return divinfo
; }
156 struct LogHandler
: public PGLog::LogEntryHandler
{
157 set
<hobject_t
> removed
;
158 list
<pg_log_entry_t
> rolledback
;
161 const pg_log_entry_t
&entry
) override
{
162 rolledback
.push_back(entry
);
165 const pg_log_entry_t
&entry
) override
{}
167 const hobject_t
&hoid
) override
{
168 removed
.insert(hoid
);
170 void try_stash(const hobject_t
&, version_t
) override
{
171 // lost/unfound cases are not tested yet
174 const pg_log_entry_t
&entry
) override
{}
177 template <typename missing_t
>
179 const TestCase
&tcase
,
180 const missing_t
&missing
) {
181 ASSERT_EQ(tcase
.final
.get_items().size(), missing
.get_items().size());
182 for (auto i
= missing
.get_items().begin();
183 i
!= missing
.get_items().end();
185 EXPECT_TRUE(tcase
.final
.get_items().count(i
->first
));
186 EXPECT_EQ(tcase
.final
.get_items().find(i
->first
)->second
.need
, i
->second
.need
);
187 EXPECT_EQ(tcase
.final
.get_items().find(i
->first
)->second
.have
, i
->second
.have
);
189 bool correct
= missing
.debug_verify_from_init(tcase
.init
, &(std::cout
));
190 ASSERT_TRUE(correct
);
193 void verify_sideeffects(
194 const TestCase
&tcase
,
195 const LogHandler
&handler
) {
196 ASSERT_EQ(tcase
.toremove
.size(), handler
.removed
.size());
197 ASSERT_EQ(tcase
.torollback
.size(), handler
.rolledback
.size());
200 list
<pg_log_entry_t
>::const_iterator titer
= tcase
.torollback
.begin();
201 list
<pg_log_entry_t
>::const_iterator hiter
= handler
.rolledback
.begin();
202 for (; titer
!= tcase
.torollback
.end(); ++titer
, ++hiter
) {
203 EXPECT_EQ(titer
->version
, hiter
->version
);
208 set
<hobject_t
>::const_iterator titer
= tcase
.toremove
.begin();
209 set
<hobject_t
>::const_iterator hiter
= handler
.removed
.begin();
210 for (; titer
!= tcase
.toremove
.end(); ++titer
, ++hiter
) {
211 EXPECT_EQ(*titer
, *hiter
);
216 void test_merge_log(const TestCase
&tcase
) {
218 log
= tcase
.get_fulldiv();
219 pg_info_t info
= tcase
.get_divinfo();
221 missing
= tcase
.init
;
225 olog
= tcase
.get_fullauth();
226 pg_info_t oinfo
= tcase
.get_authinfo();
229 bool dirty_info
= false;
230 bool dirty_big_info
= false;
232 oinfo
, olog
, pg_shard_t(1, shard_id_t(0)), info
,
233 &h
, dirty_info
, dirty_big_info
);
235 ASSERT_EQ(info
.last_update
, oinfo
.last_update
);
236 verify_missing(tcase
, missing
);
237 verify_sideeffects(tcase
, h
);
239 void test_proc_replica_log(const TestCase
&tcase
) {
241 log
= tcase
.get_fullauth();
242 pg_info_t info
= tcase
.get_authinfo();
244 pg_missing_t omissing
= tcase
.init
;
247 olog
= tcase
.get_fulldiv();
248 pg_info_t oinfo
= tcase
.get_divinfo();
251 oinfo
, olog
, omissing
, pg_shard_t(1, shard_id_t(0)));
253 assert(oinfo
.last_update
>= log
.tail
);
255 if (!tcase
.base
.empty()) {
256 ASSERT_EQ(tcase
.base
.rbegin()->version
, oinfo
.last_update
);
259 for (list
<pg_log_entry_t
>::const_iterator i
= tcase
.auth
.begin();
260 i
!= tcase
.auth
.end();
262 if (i
->version
> oinfo
.last_update
)
263 omissing
.add_next_event(*i
);
265 verify_missing(tcase
, omissing
);
267 void run_test_case(const TestCase
&tcase
) {
268 test_merge_log(tcase
);
269 test_proc_replica_log(tcase
);
273 struct TestHandler
: public PGLog::LogEntryHandler
{
274 list
<hobject_t
> &removed
;
275 explicit TestHandler(list
<hobject_t
> &removed
) : removed(removed
) {}
278 const pg_log_entry_t
&entry
) override
{}
280 const pg_log_entry_t
&entry
) override
{}
282 const hobject_t
&hoid
) override
{
283 removed
.push_back(hoid
);
285 void cant_rollback(const pg_log_entry_t
&entry
) {}
286 void try_stash(const hobject_t
&, version_t
) override
{
287 // lost/unfound cases are not tested yet
290 const pg_log_entry_t
&entry
) override
{}
293 TEST_F(PGLogTest
, rewind_divergent_log
) {
294 /* +----------------+
303 | (1,4) | x9 < newhead
316 list
<hobject_t
> remove_snap
;
317 bool dirty_info
= false;
318 bool dirty_big_info
= false;
320 hobject_t divergent_object
;
321 eversion_t divergent_version
;
325 divergent
.set_hash(0x9);
329 e
.mark_unrollbackable();
331 e
.version
= eversion_t(1, 1);
332 e
.soid
.set_hash(0x5);
333 log
.tail
= e
.version
;
334 log
.log
.push_back(e
);
335 e
.version
= newhead
= eversion_t(1, 4);
337 e
.op
= pg_log_entry_t::MODIFY
;
338 log
.log
.push_back(e
);
339 e
.version
= divergent_version
= eversion_t(1, 5);
340 e
.prior_version
= eversion_t(1, 4);
342 divergent_object
= e
.soid
;
343 e
.op
= pg_log_entry_t::DELETE
;
344 log
.log
.push_back(e
);
345 log
.head
= e
.version
;
348 info
.last_update
= log
.head
;
349 info
.last_complete
= log
.head
;
352 EXPECT_FALSE(missing
.have_missing());
353 EXPECT_EQ(3U, log
.log
.size());
354 EXPECT_TRUE(remove_snap
.empty());
355 EXPECT_EQ(log
.head
, info
.last_update
);
356 EXPECT_EQ(log
.head
, info
.last_complete
);
357 EXPECT_FALSE(is_dirty());
358 EXPECT_FALSE(dirty_info
);
359 EXPECT_FALSE(dirty_big_info
);
361 TestHandler
h(remove_snap
);
362 rewind_divergent_log(newhead
, info
, &h
,
363 dirty_info
, dirty_big_info
);
365 EXPECT_TRUE(log
.objects
.count(divergent
));
366 EXPECT_TRUE(missing
.is_missing(divergent_object
));
367 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
368 EXPECT_EQ(2U, log
.log
.size());
369 EXPECT_TRUE(remove_snap
.empty());
370 EXPECT_EQ(newhead
, info
.last_update
);
371 EXPECT_EQ(newhead
, info
.last_complete
);
372 EXPECT_TRUE(is_dirty());
373 EXPECT_TRUE(dirty_info
);
374 EXPECT_TRUE(dirty_big_info
);
377 /* +----------------+
383 tail > (1,1) | NULL |
385 | (1,4) | NULL < newhead
396 list
<hobject_t
> remove_snap
;
397 bool dirty_info
= false;
398 bool dirty_big_info
= false;
400 hobject_t divergent_object
;
401 eversion_t divergent_version
;
402 eversion_t prior_version
;
406 e
.mark_unrollbackable();
408 info
.log_tail
= log
.tail
= eversion_t(1, 1);
409 newhead
= eversion_t(1, 3);
410 e
.version
= divergent_version
= eversion_t(1, 5);
411 e
.soid
.set_hash(0x9);
412 divergent_object
= e
.soid
;
413 e
.op
= pg_log_entry_t::DELETE
;
414 e
.prior_version
= prior_version
= eversion_t(0, 2);
415 log
.log
.push_back(e
);
416 log
.head
= e
.version
;
419 EXPECT_FALSE(missing
.have_missing());
420 EXPECT_EQ(1U, log
.log
.size());
421 EXPECT_TRUE(remove_snap
.empty());
422 EXPECT_FALSE(is_dirty());
423 EXPECT_FALSE(dirty_info
);
424 EXPECT_FALSE(dirty_big_info
);
426 TestHandler
h(remove_snap
);
427 rewind_divergent_log(newhead
, info
, &h
,
428 dirty_info
, dirty_big_info
);
430 EXPECT_TRUE(missing
.is_missing(divergent_object
));
431 EXPECT_EQ(0U, log
.objects
.count(divergent_object
));
432 EXPECT_TRUE(log
.empty());
433 EXPECT_TRUE(remove_snap
.empty());
434 EXPECT_TRUE(is_dirty());
435 EXPECT_TRUE(dirty_info
);
436 EXPECT_TRUE(dirty_big_info
);
443 list
<hobject_t
> remove_snap
;
445 info
.log_tail
= log
.tail
= eversion_t(1, 5);
446 info
.last_update
= eversion_t(1, 6);
447 bool dirty_info
= false;
448 bool dirty_big_info
= false;
452 e
.mark_unrollbackable();
453 e
.version
= eversion_t(1, 5);
454 e
.soid
.set_hash(0x9);
459 e
.mark_unrollbackable();
460 e
.version
= eversion_t(1, 6);
461 e
.soid
.set_hash(0x10);
464 TestHandler
h(remove_snap
);
465 roll_forward_to(eversion_t(1, 6), &h
);
466 rewind_divergent_log(eversion_t(1, 5), info
, &h
,
467 dirty_info
, dirty_big_info
);
469 reset_backfill_claim_log(log
, &h
);
473 TEST_F(PGLogTest
, merge_old_entry
) {
474 // entries > last_backfill are silently ignored
478 ObjectStore::Transaction t
;
480 oe
.mark_unrollbackable();
482 list
<hobject_t
> remove_snap
;
484 info
.last_backfill
= hobject_t();
485 info
.last_backfill
.set_hash(100);
487 ASSERT_GT(oe
.soid
, info
.last_backfill
);
489 EXPECT_FALSE(is_dirty());
490 EXPECT_TRUE(remove_snap
.empty());
491 EXPECT_TRUE(t
.empty());
492 EXPECT_FALSE(missing
.have_missing());
493 EXPECT_TRUE(log
.empty());
495 TestHandler
h(remove_snap
);
496 merge_old_entry(t
, oe
, info
, &h
);
498 EXPECT_FALSE(is_dirty());
499 EXPECT_TRUE(remove_snap
.empty());
500 EXPECT_TRUE(t
.empty());
501 EXPECT_FALSE(missing
.have_missing());
502 EXPECT_TRUE(log
.empty());
505 // the new entry (from the logs) has a version that is higher than
506 // the old entry (from the log entry given in argument) : do
507 // nothing and return false
511 ObjectStore::Transaction t
;
513 list
<hobject_t
> remove_snap
;
516 ne
.mark_unrollbackable();
517 ne
.version
= eversion_t(2,1);
520 EXPECT_FALSE(is_dirty());
521 EXPECT_TRUE(remove_snap
.empty());
522 EXPECT_TRUE(t
.empty());
523 EXPECT_FALSE(missing
.have_missing());
524 EXPECT_EQ(1U, log
.log
.size());
525 EXPECT_EQ(ne
.version
, log
.log
.front().version
);
527 // the newer entry ( from the logs ) can be DELETE
529 log
.log
.front().op
= pg_log_entry_t::DELETE
;
531 oe
.mark_unrollbackable();
532 oe
.version
= eversion_t(1,1);
534 TestHandler
h(remove_snap
);
535 merge_old_entry(t
, oe
, info
, &h
);
538 // if the newer entry is not DELETE, the object must be in missing
540 pg_log_entry_t
&ne
= log
.log
.front();
541 ne
.op
= pg_log_entry_t::MODIFY
;
542 missing
.add_next_event(ne
);
544 oe
.mark_unrollbackable();
545 oe
.version
= eversion_t(1,1);
547 TestHandler
h(remove_snap
);
548 merge_old_entry(t
, oe
, info
, &h
);
550 missing
.rm(ne
.soid
, ne
.version
);
554 EXPECT_FALSE(is_dirty());
555 EXPECT_FALSE(remove_snap
.empty());
556 EXPECT_TRUE(t
.empty());
557 EXPECT_FALSE(missing
.have_missing());
558 EXPECT_EQ(1U, log
.log
.size());
559 EXPECT_EQ(ne
.version
, log
.log
.front().version
);
563 // the new entry (from the logs) has a version that is lower than
564 // the old entry (from the log entry given in argument) and
565 // old and new are delete : do nothing and return false
569 ObjectStore::Transaction t
;
571 oe
.mark_unrollbackable();
573 list
<hobject_t
> remove_snap
;
576 ne
.mark_unrollbackable();
577 ne
.version
= eversion_t(1,1);
578 ne
.op
= pg_log_entry_t::DELETE
;
581 oe
.version
= eversion_t(2,1);
582 oe
.op
= pg_log_entry_t::DELETE
;
584 EXPECT_FALSE(is_dirty());
585 EXPECT_TRUE(remove_snap
.empty());
586 EXPECT_TRUE(t
.empty());
587 EXPECT_FALSE(missing
.have_missing());
588 EXPECT_EQ(1U, log
.log
.size());
590 TestHandler
h(remove_snap
);
591 merge_old_entry(t
, oe
, info
, &h
);
593 EXPECT_FALSE(is_dirty());
594 EXPECT_TRUE(remove_snap
.empty());
595 EXPECT_TRUE(t
.empty());
596 EXPECT_FALSE(missing
.have_missing());
597 EXPECT_EQ(1U, log
.log
.size());
600 // the new entry (from the logs) has a version that is lower than
601 // the old entry (from the log entry given in argument) and
602 // old is update and new is DELETE :
603 // if the object is in missing, it is removed
607 ObjectStore::Transaction t
;
609 oe
.mark_unrollbackable();
611 list
<hobject_t
> remove_snap
;
614 ne
.mark_unrollbackable();
615 ne
.version
= eversion_t(1,1);
616 ne
.op
= pg_log_entry_t::DELETE
;
619 oe
.version
= eversion_t(2,1);
620 oe
.op
= pg_log_entry_t::MODIFY
;
621 missing
.add_next_event(oe
);
624 EXPECT_FALSE(is_dirty());
625 EXPECT_TRUE(remove_snap
.empty());
626 EXPECT_TRUE(t
.empty());
627 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
628 EXPECT_EQ(1U, log
.log
.size());
630 TestHandler
h(remove_snap
);
631 merge_old_entry(t
, oe
, info
, &h
);
634 EXPECT_FALSE(is_dirty());
635 EXPECT_TRUE(remove_snap
.size() > 0);
636 EXPECT_TRUE(t
.empty());
637 EXPECT_FALSE(missing
.have_missing());
638 EXPECT_EQ(1U, log
.log
.size());
641 // there is no new entry (from the logs) and
642 // the old entry (from the log entry given in argument) is not a CLONE and
643 // the old entry prior_version is greater than the tail of the log :
644 // do nothing and return false
648 ObjectStore::Transaction t
;
650 oe
.mark_unrollbackable();
652 list
<hobject_t
> remove_snap
;
654 info
.log_tail
= eversion_t(1,1);
655 oe
.op
= pg_log_entry_t::MODIFY
;
656 oe
.prior_version
= eversion_t(2,1);
657 missing_add(oe
.soid
, oe
.prior_version
, eversion_t());
660 EXPECT_FALSE(is_dirty());
661 EXPECT_TRUE(remove_snap
.empty());
662 EXPECT_TRUE(t
.empty());
663 EXPECT_TRUE(log
.empty());
665 TestHandler
h(remove_snap
);
666 merge_old_entry(t
, oe
, info
, &h
);
669 EXPECT_FALSE(is_dirty());
670 EXPECT_TRUE(remove_snap
.empty());
671 EXPECT_TRUE(t
.empty());
672 EXPECT_TRUE(log
.empty());
675 // there is no new entry (from the logs) and
676 // the old entry (from the log entry given in argument) is not a CLONE and
677 // the old entry (from the log entry given in argument) is not a DELETE and
678 // the old entry prior_version is lower than the tail of the log :
679 // add the old object to the remove_snap list and
680 // add the old object to divergent priors and
681 // add or update the prior_version of the object to missing and
686 ObjectStore::Transaction t
;
688 oe
.mark_unrollbackable();
690 list
<hobject_t
> remove_snap
;
692 info
.log_tail
= eversion_t(2,1);
694 oe
.op
= pg_log_entry_t::MODIFY
;
695 oe
.prior_version
= eversion_t(1,1);
697 EXPECT_FALSE(is_dirty());
698 EXPECT_TRUE(remove_snap
.empty());
699 EXPECT_TRUE(t
.empty());
700 EXPECT_FALSE(missing
.have_missing());
701 EXPECT_TRUE(log
.empty());
703 TestHandler
h(remove_snap
);
704 merge_old_entry(t
, oe
, info
, &h
);
706 EXPECT_TRUE(is_dirty());
707 EXPECT_EQ(oe
.soid
, remove_snap
.front());
708 EXPECT_TRUE(t
.empty());
709 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
710 EXPECT_TRUE(log
.empty());
713 // there is no new entry (from the logs) and
714 // the old entry (from the log entry given in argument) is not a CLONE and
715 // the old entry (from the log entry given in argument) is a DELETE and
716 // the old entry prior_version is lower than the tail of the log :
717 // add the old object to divergent priors and
718 // add or update the prior_version of the object to missing and
723 ObjectStore::Transaction t
;
725 oe
.mark_unrollbackable();
727 list
<hobject_t
> remove_snap
;
729 info
.log_tail
= eversion_t(2,1);
731 oe
.op
= pg_log_entry_t::DELETE
;
732 oe
.prior_version
= eversion_t(1,1);
734 EXPECT_FALSE(is_dirty());
735 EXPECT_TRUE(remove_snap
.empty());
736 EXPECT_TRUE(t
.empty());
737 EXPECT_FALSE(missing
.have_missing());
738 EXPECT_TRUE(log
.empty());
740 TestHandler
h(remove_snap
);
741 merge_old_entry(t
, oe
, info
, &h
);
743 EXPECT_TRUE(is_dirty());
744 EXPECT_TRUE(remove_snap
.empty());
745 EXPECT_TRUE(t
.empty());
746 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
747 EXPECT_TRUE(log
.empty());
751 // there is no new entry (from the logs) and
752 // the old entry (from the log entry given in argument) is not a CLONE and
753 // the old entry (from the log entry given in argument) is not a DELETE and
754 // the old entry prior_version is eversion_t() :
755 // add the old object to the remove_snap list and
756 // remove the prior_version of the object from missing, if any and
761 ObjectStore::Transaction t
;
763 oe
.mark_unrollbackable();
765 list
<hobject_t
> remove_snap
;
767 info
.log_tail
= eversion_t(10,1);
769 oe
.op
= pg_log_entry_t::MODIFY
;
770 oe
.prior_version
= eversion_t();
772 missing
.add(oe
.soid
, eversion_t(1,1), eversion_t());
775 EXPECT_FALSE(is_dirty());
776 EXPECT_TRUE(remove_snap
.empty());
777 EXPECT_TRUE(t
.empty());
778 EXPECT_TRUE(missing
.is_missing(oe
.soid
));
779 EXPECT_TRUE(log
.empty());
781 TestHandler
h(remove_snap
);
782 merge_old_entry(t
, oe
, info
, &h
);
785 EXPECT_FALSE(is_dirty());
786 EXPECT_EQ(oe
.soid
, remove_snap
.front());
787 EXPECT_TRUE(t
.empty());
788 EXPECT_FALSE(missing
.have_missing());
789 EXPECT_TRUE(log
.empty());
794 TEST_F(PGLogTest
, merge_log
) {
795 // head and tail match, last_backfill is set:
804 list
<hobject_t
> remove_snap
;
805 bool dirty_info
= false;
806 bool dirty_big_info
= false;
808 hobject_t
last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
809 info
.last_backfill
= last_backfill
;
810 eversion_t
stat_version(10, 1);
811 info
.stats
.version
= stat_version
;
812 log
.tail
= olog
.tail
= eversion_t(1, 1);
813 log
.head
= olog
.head
= eversion_t(2, 1);
815 EXPECT_FALSE(missing
.have_missing());
816 EXPECT_EQ(0U, log
.log
.size());
817 EXPECT_EQ(stat_version
, info
.stats
.version
);
818 EXPECT_TRUE(remove_snap
.empty());
819 EXPECT_EQ(last_backfill
, info
.last_backfill
);
820 EXPECT_TRUE(info
.purged_snaps
.empty());
821 EXPECT_FALSE(is_dirty());
822 EXPECT_FALSE(dirty_info
);
823 EXPECT_FALSE(dirty_big_info
);
825 TestHandler
h(remove_snap
);
826 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
827 dirty_info
, dirty_big_info
);
829 EXPECT_FALSE(missing
.have_missing());
830 EXPECT_EQ(0U, log
.log
.size());
831 EXPECT_EQ(stat_version
, info
.stats
.version
);
832 EXPECT_TRUE(remove_snap
.empty());
833 EXPECT_TRUE(info
.purged_snaps
.empty());
834 EXPECT_FALSE(is_dirty());
835 EXPECT_FALSE(dirty_info
);
836 EXPECT_FALSE(dirty_big_info
);
839 // head and tail match, last_backfill is not set: info.stats is
840 // copied from oinfo.stats but info.stats.reported_* is guaranteed to
841 // never be replaced by a lower version
849 list
<hobject_t
> remove_snap
;
850 bool dirty_info
= false;
851 bool dirty_big_info
= false;
853 eversion_t
stat_version(10, 1);
854 oinfo
.stats
.version
= stat_version
;
855 info
.stats
.reported_seq
= 1;
856 info
.stats
.reported_epoch
= 10;
857 oinfo
.stats
.reported_seq
= 1;
858 oinfo
.stats
.reported_epoch
= 1;
859 log
.tail
= olog
.tail
= eversion_t(1, 1);
860 log
.head
= olog
.head
= eversion_t(2, 1);
862 EXPECT_FALSE(missing
.have_missing());
863 EXPECT_EQ(0U, log
.log
.size());
864 EXPECT_EQ(eversion_t(), info
.stats
.version
);
865 EXPECT_EQ(1ull, info
.stats
.reported_seq
);
866 EXPECT_EQ(10u, info
.stats
.reported_epoch
);
867 EXPECT_TRUE(remove_snap
.empty());
868 EXPECT_TRUE(info
.last_backfill
.is_max());
869 EXPECT_TRUE(info
.purged_snaps
.empty());
870 EXPECT_FALSE(is_dirty());
871 EXPECT_FALSE(dirty_info
);
872 EXPECT_FALSE(dirty_big_info
);
874 TestHandler
h(remove_snap
);
875 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
876 dirty_info
, dirty_big_info
);
878 EXPECT_FALSE(missing
.have_missing());
879 EXPECT_EQ(0U, log
.log
.size());
880 EXPECT_EQ(stat_version
, info
.stats
.version
);
881 EXPECT_EQ(1ull, info
.stats
.reported_seq
);
882 EXPECT_EQ(10u, info
.stats
.reported_epoch
);
883 EXPECT_TRUE(remove_snap
.empty());
884 EXPECT_TRUE(info
.purged_snaps
.empty());
885 EXPECT_FALSE(is_dirty());
886 EXPECT_FALSE(dirty_info
);
887 EXPECT_FALSE(dirty_big_info
);
891 +--------------------------+
893 +--------+-------+---------+
895 |version | hash | version |
897 | | x5 | (1,1) < tail
900 tail > (1,4) | x7 | |
903 head > (1,5) | x9 | (1,5) < head
906 +--------+-------+---------+
933 list
<hobject_t
> remove_snap
;
934 bool dirty_info
= false;
935 bool dirty_big_info
= false;
939 e
.mark_unrollbackable();
941 e
.version
= eversion_t(1, 4);
942 e
.soid
.set_hash(0x5);
943 log
.tail
= e
.version
;
944 log
.log
.push_back(e
);
945 e
.version
= eversion_t(1, 5);
946 e
.soid
.set_hash(0x9);
947 log
.log
.push_back(e
);
948 log
.head
= e
.version
;
951 info
.last_update
= log
.head
;
953 e
.version
= eversion_t(1, 1);
954 e
.soid
.set_hash(0x5);
955 olog
.tail
= e
.version
;
956 olog
.log
.push_back(e
);
957 e
.version
= eversion_t(1, 5);
958 e
.soid
.set_hash(0x9);
959 olog
.log
.push_back(e
);
960 olog
.head
= e
.version
;
963 hobject_t
last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
964 info
.last_backfill
= last_backfill
;
965 eversion_t
stat_version(10, 1);
966 info
.stats
.version
= stat_version
;
968 EXPECT_FALSE(missing
.have_missing());
969 EXPECT_EQ(2U, log
.log
.size());
970 EXPECT_EQ(stat_version
, info
.stats
.version
);
971 EXPECT_TRUE(remove_snap
.empty());
972 EXPECT_EQ(last_backfill
, info
.last_backfill
);
973 EXPECT_TRUE(info
.purged_snaps
.empty());
974 EXPECT_FALSE(is_dirty());
975 EXPECT_FALSE(dirty_info
);
976 EXPECT_FALSE(dirty_big_info
);
978 TestHandler
h(remove_snap
);
979 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
980 dirty_info
, dirty_big_info
);
982 EXPECT_FALSE(missing
.have_missing());
983 EXPECT_EQ(3U, log
.log
.size());
984 EXPECT_EQ(stat_version
, info
.stats
.version
);
985 EXPECT_TRUE(remove_snap
.empty());
986 EXPECT_TRUE(info
.purged_snaps
.empty());
987 EXPECT_TRUE(is_dirty());
988 EXPECT_TRUE(dirty_info
);
989 EXPECT_TRUE(dirty_big_info
);
992 /* +--------------------------+
994 +--------+-------+---------+
996 |version | hash | version |
998 tail > (1,1) | x5 | (1,1) < tail
1001 | (1,2) | x3 | (1,2) < lower_bound
1004 head > (1,3) | x9 | |
1010 | | x7 | (2,4) < head
1012 +--------+-------+---------+
1014 The log entry (1,3) deletes the object x9 but the olog entry (2,3) modifies
1015 it and is authoritative : the log entry (1,3) is divergent.
1025 list
<hobject_t
> remove_snap
;
1026 bool dirty_info
= false;
1027 bool dirty_big_info
= false;
1029 hobject_t divergent_object
;
1033 e
.mark_unrollbackable();
1035 e
.version
= eversion_t(1, 1);
1036 e
.soid
.set_hash(0x5);
1037 log
.tail
= e
.version
;
1038 log
.log
.push_back(e
);
1039 e
.version
= eversion_t(1, 2);
1040 e
.soid
.set_hash(0x3);
1041 log
.log
.push_back(e
);
1042 e
.version
= eversion_t(1,3);
1043 e
.soid
.set_hash(0x9);
1044 divergent_object
= e
.soid
;
1045 e
.op
= pg_log_entry_t::DELETE
;
1046 log
.log
.push_back(e
);
1047 log
.head
= e
.version
;
1050 info
.last_update
= log
.head
;
1052 e
.version
= eversion_t(1, 1);
1053 e
.soid
.set_hash(0x5);
1054 olog
.tail
= e
.version
;
1055 olog
.log
.push_back(e
);
1056 e
.version
= eversion_t(1, 2);
1057 e
.soid
.set_hash(0x3);
1058 olog
.log
.push_back(e
);
1059 e
.version
= eversion_t(2, 3);
1060 e
.soid
.set_hash(0x9);
1061 e
.op
= pg_log_entry_t::MODIFY
;
1062 olog
.log
.push_back(e
);
1063 e
.version
= eversion_t(2, 4);
1064 e
.soid
.set_hash(0x7);
1065 e
.op
= pg_log_entry_t::DELETE
;
1066 olog
.log
.push_back(e
);
1067 olog
.head
= e
.version
;
1070 snapid_t
purged_snap(1);
1072 oinfo
.last_update
= olog
.head
;
1073 oinfo
.purged_snaps
.insert(purged_snap
);
1076 EXPECT_FALSE(missing
.have_missing());
1077 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1078 EXPECT_EQ(3U, log
.log
.size());
1079 EXPECT_TRUE(remove_snap
.empty());
1080 EXPECT_EQ(log
.head
, info
.last_update
);
1081 EXPECT_TRUE(info
.purged_snaps
.empty());
1082 EXPECT_FALSE(is_dirty());
1083 EXPECT_FALSE(dirty_info
);
1084 EXPECT_FALSE(dirty_big_info
);
1086 TestHandler
h(remove_snap
);
1087 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1088 dirty_info
, dirty_big_info
);
1090 /* When the divergent entry is a DELETE and the authoritative
1091 entry is a MODIFY, the object will be added to missing : it is
1092 a verifiable side effect proving the entry was identified
1095 EXPECT_TRUE(missing
.is_missing(divergent_object
));
1096 EXPECT_EQ(1U, log
.objects
.count(divergent_object
));
1097 EXPECT_EQ(4U, log
.log
.size());
1098 /* DELETE entries from olog that are appended to the hed of the
1099 log are also added to remove_snap.
1101 EXPECT_EQ(0x7U
, remove_snap
.front().get_hash());
1102 EXPECT_EQ(log
.head
, info
.last_update
);
1103 EXPECT_TRUE(info
.purged_snaps
.contains(purged_snap
));
1104 EXPECT_TRUE(is_dirty());
1105 EXPECT_TRUE(dirty_info
);
1106 EXPECT_TRUE(dirty_big_info
);
1109 /* +--------------------------+
1111 +--------+-------+---------+
1113 |version | hash | version |
1115 tail > (1,1) | x5 | (1,1) < tail
1118 | (1,4) | x7 | (1,4) < head
1121 head > (1,5) | x9 | |
1124 +--------+-------+---------+
1126 The head of the log entry (1,5) is divergent because it is greater than the
1137 list
<hobject_t
> remove_snap
;
1138 bool dirty_info
= false;
1139 bool dirty_big_info
= false;
1143 e
.mark_unrollbackable();
1145 e
.version
= eversion_t(1, 1);
1146 e
.soid
.set_hash(0x5);
1147 log
.tail
= e
.version
;
1148 log
.log
.push_back(e
);
1149 e
.version
= eversion_t(1, 4);
1150 e
.soid
.set_hash(0x7);
1151 log
.log
.push_back(e
);
1152 e
.version
= eversion_t(1, 5);
1153 e
.soid
.set_hash(0x9);
1154 log
.log
.push_back(e
);
1155 log
.head
= e
.version
;
1158 info
.last_update
= log
.head
;
1160 e
.version
= eversion_t(1, 1);
1161 e
.soid
.set_hash(0x5);
1162 olog
.tail
= e
.version
;
1163 olog
.log
.push_back(e
);
1164 e
.version
= eversion_t(1, 4);
1165 e
.soid
.set_hash(0x7);
1166 olog
.log
.push_back(e
);
1167 olog
.head
= e
.version
;
1170 hobject_t
last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
1171 info
.last_backfill
= last_backfill
;
1172 eversion_t
stat_version(10, 1);
1173 info
.stats
.version
= stat_version
;
1175 EXPECT_FALSE(missing
.have_missing());
1176 EXPECT_EQ(3U, log
.log
.size());
1177 EXPECT_EQ(stat_version
, info
.stats
.version
);
1178 EXPECT_TRUE(remove_snap
.empty());
1179 EXPECT_EQ(last_backfill
, info
.last_backfill
);
1180 EXPECT_TRUE(info
.purged_snaps
.empty());
1181 EXPECT_FALSE(is_dirty());
1182 EXPECT_FALSE(dirty_info
);
1183 EXPECT_FALSE(dirty_big_info
);
1185 TestHandler
h(remove_snap
);
1186 merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1187 dirty_info
, dirty_big_info
);
1189 EXPECT_FALSE(missing
.have_missing());
1190 EXPECT_EQ(2U, log
.log
.size());
1191 EXPECT_EQ(stat_version
, info
.stats
.version
);
1192 EXPECT_EQ(0x9U
, remove_snap
.front().get_hash());
1193 EXPECT_TRUE(info
.purged_snaps
.empty());
1194 EXPECT_TRUE(is_dirty());
1195 EXPECT_TRUE(dirty_info
);
1196 EXPECT_TRUE(dirty_big_info
);
1199 // If our log is empty, the incoming log needs to have not been trimmed.
1207 list
<hobject_t
> remove_snap
;
1208 bool dirty_info
= false;
1209 bool dirty_big_info
= false;
1211 // olog has been trimmed
1212 olog
.tail
= eversion_t(1, 1);
1214 TestHandler
h(remove_snap
);
1215 PrCtl unset_dumpable
;
1216 ASSERT_DEATH(merge_log(oinfo
, olog
, fromosd
, info
, &h
,
1217 dirty_info
, dirty_big_info
), "");
1222 TEST_F(PGLogTest
, proc_replica_log
) {
1223 // empty log : no side effect
1229 pg_missing_t omissing
;
1232 eversion_t
last_update(1, 1);
1233 log
.head
= olog
.head
= oinfo
.last_update
= last_update
;
1234 eversion_t
last_complete(1, 1);
1235 oinfo
.last_complete
= last_complete
;
1237 EXPECT_FALSE(omissing
.have_missing());
1238 EXPECT_EQ(last_update
, oinfo
.last_update
);
1239 EXPECT_EQ(last_complete
, oinfo
.last_complete
);
1241 proc_replica_log(oinfo
, olog
, omissing
, from
);
1243 EXPECT_FALSE(omissing
.have_missing());
1244 EXPECT_EQ(last_update
, oinfo
.last_update
);
1245 EXPECT_EQ(last_update
, oinfo
.last_complete
);
1248 /* +--------------------------+
1250 +--------+-------+---------+
1252 |version | hash | version |
1254 | | x3 | (1,1) < tail
1257 tail > (1,2) | x5 | |
1260 head > (1,3) | x9 | |
1263 | | x9 | (2,3) < head
1266 +--------+-------+---------+
1268 The log entry (1,3) deletes the object x9 and the olog entry
1269 (2,3) also deletes it : do nothing. The olog tail is ignored
1270 because it is before the log tail.
1278 pg_missing_t omissing
;
1283 e
.mark_unrollbackable();
1285 e
.version
= eversion_t(1, 2);
1286 e
.soid
.set_hash(0x5);
1287 log
.tail
= e
.version
;
1288 log
.log
.push_back(e
);
1289 e
.version
= eversion_t(1, 3);
1290 e
.soid
.set_hash(0x9);
1291 e
.op
= pg_log_entry_t::DELETE
;
1292 log
.log
.push_back(e
);
1293 log
.head
= e
.version
;
1296 e
.version
= eversion_t(1, 1);
1297 e
.soid
.set_hash(0x3);
1298 olog
.tail
= e
.version
;
1299 olog
.log
.push_back(e
);
1300 e
.version
= eversion_t(2, 3);
1301 e
.soid
.set_hash(0x9);
1302 e
.op
= pg_log_entry_t::DELETE
;
1303 olog
.log
.push_back(e
);
1304 olog
.head
= e
.version
;
1306 oinfo
.last_update
= olog
.head
;
1307 oinfo
.last_complete
= olog
.head
;
1310 EXPECT_FALSE(omissing
.have_missing());
1311 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1312 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1314 proc_replica_log(oinfo
, olog
, omissing
, from
);
1316 EXPECT_FALSE(omissing
.have_missing());
1324 pg_missing_t omissing
;
1327 hobject_t divergent_object
;
1331 e
.mark_unrollbackable();
1334 e
.soid
= divergent_object
;
1335 e
.soid
.set_hash(0x1);
1336 e
.version
= eversion_t(1, 1);
1337 log
.tail
= e
.version
;
1338 log
.log
.push_back(e
);
1340 e
.soid
= divergent_object
;
1341 e
.prior_version
= eversion_t(1, 1);
1342 e
.version
= eversion_t(1, 2);
1343 log
.tail
= e
.version
;
1344 log
.log
.push_back(e
);
1346 e
.soid
.set_hash(0x3);
1347 e
.version
= eversion_t(1, 4);
1348 log
.log
.push_back(e
);
1350 e
.soid
.set_hash(0x7);
1351 e
.version
= eversion_t(1, 5);
1352 log
.log
.push_back(e
);
1354 e
.soid
.set_hash(0x8);
1355 e
.version
= eversion_t(1, 6);
1356 log
.log
.push_back(e
);
1358 e
.soid
.set_hash(0x9);
1359 e
.op
= pg_log_entry_t::DELETE
;
1360 e
.version
= eversion_t(2, 7);
1361 log
.log
.push_back(e
);
1363 e
.soid
.set_hash(0xa);
1364 e
.version
= eversion_t(2, 8);
1365 log
.head
= e
.version
;
1366 log
.log
.push_back(e
);
1371 e
.soid
= divergent_object
;
1372 e
.soid
.set_hash(0x1);
1373 e
.version
= eversion_t(1, 1);
1374 olog
.tail
= e
.version
;
1375 olog
.log
.push_back(e
);
1377 e
.soid
= divergent_object
;
1378 e
.prior_version
= eversion_t(1, 1);
1379 e
.version
= eversion_t(1, 2);
1380 olog
.log
.push_back(e
);
1382 e
.prior_version
= eversion_t(0, 0);
1383 e
.soid
.set_hash(0x3);
1384 e
.version
= eversion_t(1, 4);
1385 olog
.log
.push_back(e
);
1387 e
.soid
.set_hash(0x7);
1388 e
.version
= eversion_t(1, 5);
1389 olog
.log
.push_back(e
);
1391 e
.soid
.set_hash(0x8);
1392 e
.version
= eversion_t(1, 6);
1393 olog
.log
.push_back(e
);
1395 e
.soid
.set_hash(0x9); // should not be added to missing, create
1396 e
.op
= pg_log_entry_t::MODIFY
;
1397 e
.version
= eversion_t(1, 7);
1398 olog
.log
.push_back(e
);
1400 e
.soid
= divergent_object
; // should be added to missing at 1,2
1401 e
.op
= pg_log_entry_t::MODIFY
;
1402 e
.version
= eversion_t(1, 8);
1403 e
.prior_version
= eversion_t(1, 2);
1404 olog
.log
.push_back(e
);
1405 olog
.head
= e
.version
;
1407 oinfo
.last_update
= olog
.head
;
1408 oinfo
.last_complete
= olog
.head
;
1411 EXPECT_FALSE(omissing
.have_missing());
1412 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1413 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1415 proc_replica_log(oinfo
, olog
, omissing
, from
);
1417 EXPECT_TRUE(omissing
.have_missing());
1418 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1419 EXPECT_EQ(eversion_t(1, 2), omissing
.get_items().at(divergent_object
).need
);
1420 EXPECT_EQ(eversion_t(1, 6), oinfo
.last_update
);
1421 EXPECT_EQ(eversion_t(1, 1), oinfo
.last_complete
);
1424 /* +--------------------------+
1426 +--------+-------+---------+
1428 |version | hash | version |
1430 tail > (1,1) | x9 | (1,1) < tail
1433 | (1,2) | x3 | (1,2) |
1436 head > (1,3) | x9 | |
1439 | | x9 | (2,3) < head
1442 +--------+-------+---------+
1444 The log entry (1,3) deletes the object x9 and the olog entry
1445 (2,3) also deletes it : do nothing.
1453 pg_missing_t omissing
;
1456 eversion_t
last_update(1, 2);
1457 hobject_t divergent_object
;
1458 divergent_object
.set_hash(0x9);
1462 e
.mark_unrollbackable();
1464 e
.version
= eversion_t(1, 1);
1465 e
.soid
= divergent_object
;
1466 log
.tail
= e
.version
;
1467 log
.log
.push_back(e
);
1468 e
.version
= last_update
;
1469 e
.soid
.set_hash(0x3);
1470 log
.log
.push_back(e
);
1471 e
.version
= eversion_t(2, 3);
1472 e
.prior_version
= eversion_t(1, 1);
1473 e
.soid
= divergent_object
;
1474 e
.op
= pg_log_entry_t::DELETE
;
1475 log
.log
.push_back(e
);
1476 log
.head
= e
.version
;
1479 e
.version
= eversion_t(1, 1);
1480 e
.soid
= divergent_object
;
1481 olog
.tail
= e
.version
;
1482 olog
.log
.push_back(e
);
1483 e
.version
= last_update
;
1484 e
.soid
.set_hash(0x3);
1485 olog
.log
.push_back(e
);
1486 e
.version
= eversion_t(1, 3);
1487 e
.prior_version
= eversion_t(1, 1);
1488 e
.soid
= divergent_object
;
1489 e
.op
= pg_log_entry_t::DELETE
;
1490 olog
.log
.push_back(e
);
1491 olog
.head
= e
.version
;
1493 oinfo
.last_update
= olog
.head
;
1494 oinfo
.last_complete
= olog
.head
;
1497 EXPECT_FALSE(omissing
.have_missing());
1498 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1499 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1501 proc_replica_log(oinfo
, olog
, omissing
, from
);
1503 EXPECT_TRUE(omissing
.have_missing());
1504 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1505 EXPECT_EQ(omissing
.get_items().at(divergent_object
).have
, eversion_t(0, 0));
1506 EXPECT_EQ(omissing
.get_items().at(divergent_object
).need
, eversion_t(1, 1));
1507 EXPECT_EQ(last_update
, oinfo
.last_update
);
1510 /* +--------------------------+
1512 +--------+-------+---------+
1514 |version | hash | version |
1516 tail > (1,1) | x9 | (1,1) < tail
1519 | (1,2) | x3 | (1,2) |
1522 head > (1,3) | x9 | |
1525 | | x9 | (2,3) < head
1528 +--------+-------+---------+
1530 The log entry (1,3) deletes the object x9 but the olog entry
1531 (2,3) modifies it : remove it from omissing.
1539 pg_missing_t omissing
;
1542 eversion_t
last_update(1, 2);
1543 hobject_t divergent_object
;
1547 e
.mark_unrollbackable();
1549 e
.version
= eversion_t(1, 1);
1550 e
.soid
= divergent_object
;
1551 log
.tail
= e
.version
;
1552 log
.log
.push_back(e
);
1553 e
.version
= last_update
;
1554 e
.soid
.set_hash(0x3);
1555 log
.log
.push_back(e
);
1556 e
.version
= eversion_t(2, 3);
1557 e
.prior_version
= eversion_t(1, 1);
1558 e
.soid
= divergent_object
;
1559 e
.op
= pg_log_entry_t::DELETE
;
1560 log
.log
.push_back(e
);
1561 log
.head
= e
.version
;
1564 e
.version
= eversion_t(1, 1);
1565 e
.soid
= divergent_object
;
1566 olog
.tail
= e
.version
;
1567 olog
.log
.push_back(e
);
1568 e
.version
= last_update
;
1569 e
.soid
.set_hash(0x3);
1570 olog
.log
.push_back(e
);
1571 e
.version
= eversion_t(1, 3);
1572 e
.prior_version
= eversion_t(1, 1);
1573 e
.soid
= divergent_object
;
1574 divergent_object
= e
.soid
;
1575 omissing
.add(divergent_object
, e
.version
, eversion_t());
1576 e
.op
= pg_log_entry_t::MODIFY
;
1577 olog
.log
.push_back(e
);
1578 olog
.head
= e
.version
;
1580 oinfo
.last_update
= olog
.head
;
1581 oinfo
.last_complete
= olog
.head
;
1584 EXPECT_TRUE(omissing
.have_missing());
1585 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1586 EXPECT_EQ(eversion_t(1, 3), omissing
.get_items().at(divergent_object
).need
);
1587 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1588 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1590 proc_replica_log(oinfo
, olog
, omissing
, from
);
1592 EXPECT_TRUE(omissing
.have_missing());
1593 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1594 EXPECT_EQ(omissing
.get_items().at(divergent_object
).have
, eversion_t(0, 0));
1595 EXPECT_EQ(omissing
.get_items().at(divergent_object
).need
, eversion_t(1, 1));
1596 EXPECT_EQ(last_update
, oinfo
.last_update
);
1599 /* +--------------------------+
1601 +--------+-------+---------+
1603 |version | hash | version |
1605 tail > (1,1) | x9 | (1,1) < tail
1608 | (1,2) | x3 | (1,2) |
1611 | | x9 | (1,3) < head
1614 head > (2,3) | x9 | |
1617 +--------+-------+---------+
1619 The log entry (2,3) deletes the object x9 but the olog entry
1620 (1,3) modifies it : proc_replica_log should adjust missing to
1621 1,1 for that object until add_next_event in PG::activate processes
1629 pg_missing_t omissing
;
1632 eversion_t
last_update(1, 2);
1633 hobject_t divergent_object
;
1634 eversion_t
new_version(2, 3);
1635 eversion_t
divergent_version(1, 3);
1639 e
.mark_unrollbackable();
1641 e
.version
= eversion_t(1, 1);
1642 e
.soid
.set_hash(0x9);
1643 log
.tail
= e
.version
;
1644 log
.log
.push_back(e
);
1645 e
.version
= last_update
;
1646 e
.soid
.set_hash(0x3);
1647 log
.log
.push_back(e
);
1648 e
.version
= new_version
;
1649 e
.prior_version
= eversion_t(1, 1);
1650 e
.soid
.set_hash(0x9);
1651 e
.op
= pg_log_entry_t::DELETE
;
1652 log
.log
.push_back(e
);
1653 log
.head
= e
.version
;
1656 e
.op
= pg_log_entry_t::MODIFY
;
1657 e
.version
= eversion_t(1, 1);
1658 e
.soid
.set_hash(0x9);
1659 olog
.tail
= e
.version
;
1660 olog
.log
.push_back(e
);
1661 e
.version
= last_update
;
1662 e
.soid
.set_hash(0x3);
1663 olog
.log
.push_back(e
);
1664 e
.version
= divergent_version
;
1665 e
.prior_version
= eversion_t(1, 1);
1666 e
.soid
.set_hash(0x9);
1667 divergent_object
= e
.soid
;
1668 omissing
.add(divergent_object
, e
.version
, eversion_t());
1669 e
.op
= pg_log_entry_t::MODIFY
;
1670 olog
.log
.push_back(e
);
1671 olog
.head
= e
.version
;
1673 oinfo
.last_update
= olog
.head
;
1674 oinfo
.last_complete
= olog
.head
;
1677 EXPECT_TRUE(omissing
.have_missing());
1678 EXPECT_TRUE(omissing
.is_missing(divergent_object
));
1679 EXPECT_EQ(divergent_version
, omissing
.get_items().at(divergent_object
).need
);
1680 EXPECT_EQ(olog
.head
, oinfo
.last_update
);
1681 EXPECT_EQ(olog
.head
, oinfo
.last_complete
);
1683 proc_replica_log(oinfo
, olog
, omissing
, from
);
1685 EXPECT_TRUE(omissing
.have_missing());
1686 EXPECT_TRUE(omissing
.get_items().begin()->second
.need
== eversion_t(1, 1));
1687 EXPECT_EQ(last_update
, oinfo
.last_update
);
1688 EXPECT_EQ(eversion_t(0, 0), oinfo
.last_complete
);
1693 TEST_F(PGLogTest
, merge_log_1
) {
1695 t
.base
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1697 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1699 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0));
1701 t
.toremove
.insert(mk_obj(1));
1707 TEST_F(PGLogTest
, merge_log_2
) {
1709 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1711 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1712 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1714 t
.torollback
.insert(
1715 t
.torollback
.begin(), t
.div
.rbegin(), t
.div
.rend());
1721 TEST_F(PGLogTest
, merge_log_3
) {
1723 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1725 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1726 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1728 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0));
1730 t
.toremove
.insert(mk_obj(1));
1736 TEST_F(PGLogTest
, merge_log_4
) {
1738 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1740 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1741 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1743 t
.init
.add(mk_obj(1), mk_evt(10, 102), mk_evt(0, 0));
1744 t
.final
.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0));
1750 TEST_F(PGLogTest
, merge_log_5
) {
1752 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1754 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1755 t
.div
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1757 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1759 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(0, 0));
1761 t
.toremove
.insert(mk_obj(1));
1767 TEST_F(PGLogTest
, merge_log_6
) {
1769 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1771 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1773 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100));
1779 TEST_F(PGLogTest
, merge_log_7
) {
1781 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1783 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1785 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80));
1786 t
.final
.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80));
1792 TEST_F(PGLogTest
, merge_log_8
) {
1794 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1796 t
.auth
.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1798 t
.init
.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80));
1800 t
.toremove
.insert(mk_obj(1));
1806 TEST_F(PGLogTest
, merge_log_prior_version_have
) {
1808 t
.base
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1810 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1812 t
.init
.add(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100));
1818 TEST_F(PGLogTest
, merge_log_split_missing_entries_at_head
) {
1820 t
.auth
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
1821 t
.auth
.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
1823 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(8, 70), mk_evt(8, 65)));
1826 t
.set_div_bounds(mk_evt(9, 79), mk_evt(8, 69));
1827 t
.set_auth_bounds(mk_evt(15, 160), mk_evt(9, 77));
1828 t
.final
.add(mk_obj(1), mk_evt(15, 150), mk_evt(8, 70));
1832 TEST_F(PGLogTest
, olog_tail_gt_log_tail_split
) {
1834 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
1835 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
1836 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150)));
1839 t
.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
1840 t
.set_auth_bounds(mk_evt(15, 156), mk_evt(10, 99));
1841 t
.final
.add(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150));
1845 TEST_F(PGLogTest
, olog_tail_gt_log_tail_split2
) {
1847 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
1848 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
1849 t
.auth
.push_back(mk_ple_mod(mk_obj(1), mk_evt(16, 155), mk_evt(15, 150)));
1850 t
.div
.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 153), mk_evt(15, 150)));
1853 t
.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
1854 t
.set_auth_bounds(mk_evt(16, 156), mk_evt(10, 99));
1855 t
.final
.add(mk_obj(1), mk_evt(16, 155), mk_evt(0, 0));
1856 t
.toremove
.insert(mk_obj(1));
1860 TEST_F(PGLogTest
, filter_log_1
) {
1866 int64_t pool_id
= 1;
1869 int pg_num
= max_osd
<< bits
;
1870 int num_objects
= 1000;
1871 int num_internal
= 10;
1873 // Set up splitting map
1874 OSDMap
*osdmap
= new OSDMap
;
1876 test_uuid
.generate_random();
1877 osdmap
->build_simple_with_pool(g_ceph_context
, epoch
, test_uuid
, max_osd
, bits
, bits
);
1878 osdmap
->set_state(osd_id
, CEPH_OSD_EXISTS
);
1880 const string
hit_set_namespace("internal");
1884 e
.mark_unrollbackable();
1885 e
.op
= pg_log_entry_t::MODIFY
;
1886 e
.soid
.pool
= pool_id
;
1890 for (i
= 1; i
<= num_objects
; ++i
) {
1891 e
.version
= eversion_t(epoch
, i
);
1892 // Use this to generate random file names
1893 uuid_name
.generate_random();
1896 e
.soid
.oid
.name
= name
.str();
1897 // First has no namespace
1899 // num_internal have the internal namspace
1900 if (i
<= num_internal
+ 1) {
1901 e
.soid
.nspace
= hit_set_namespace
;
1902 } else { // rest have different namespaces
1905 e
.soid
.nspace
= ns
.str();
1908 log
.log
.push_back(e
);
1910 log
.tail
= e
.version
;
1912 log
.head
= e
.version
;
1916 spg_t
pgid(pg_t(2, pool_id
), shard_id_t::NO_SHARD
);
1918 // See if we created the right number of entries
1919 int total
= log
.log
.size();
1920 ASSERT_EQ(total
, num_objects
);
1922 // Some should be removed
1924 pg_log_t filtered
, reject
;
1925 pg_log_t::filter_log(
1926 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
1927 log
= IndexedLog(filtered
);
1929 EXPECT_LE(log
.log
.size(), (size_t)total
);
1931 // If we filter a second time, there should be the same total
1932 total
= log
.log
.size();
1934 pg_log_t filtered
, reject
;
1935 pg_log_t::filter_log(
1936 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
1937 log
= IndexedLog(filtered
);
1939 EXPECT_EQ(log
.log
.size(), (size_t)total
);
1941 // Increase pg_num as if there would be a split
1942 int new_pg_num
= pg_num
* 16;
1943 OSDMap::Incremental
inc(epoch
+ 1);
1944 inc
.fsid
= test_uuid
;
1945 const pg_pool_t
*pool
= osdmap
->get_pg_pool(pool_id
);
1948 newpool
.set_pg_num(new_pg_num
);
1949 newpool
.set_pgp_num(new_pg_num
);
1950 inc
.new_pools
[pool_id
] = newpool
;
1951 int ret
= osdmap
->apply_incremental(inc
);
1954 // We should have fewer entries after a filter
1956 pg_log_t filtered
, reject
;
1957 pg_log_t::filter_log(
1958 pgid
, *osdmap
, hit_set_namespace
, log
, filtered
, reject
);
1959 log
= IndexedLog(filtered
);
1961 EXPECT_LE(log
.log
.size(), (size_t)total
);
1963 // Make sure all internal entries are retained
1965 for (list
<pg_log_entry_t
>::iterator i
= log
.log
.begin();
1966 i
!= log
.log
.end(); ++i
) {
1967 if (i
->soid
.nspace
== hit_set_namespace
) count
++;
1969 EXPECT_EQ(count
, num_internal
);
1973 TEST_F(PGLogTest
, get_request
) {
1976 // make sure writes, deletes, and errors are found
1977 vector
<pg_log_entry_t
> entries
;
1978 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
1980 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(6,2), eversion_t(3,4),
1981 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
1982 utime_t(0,1), -ENOENT
));
1984 pg_log_entry_t(pg_log_entry_t::MODIFY
, oid
, eversion_t(6,3), eversion_t(3,4),
1985 2, osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
1988 pg_log_entry_t(pg_log_entry_t::DELETE
, oid
, eversion_t(7,4), eversion_t(7,4),
1989 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
1992 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(7,5), eversion_t(7,4),
1993 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
1994 utime_t(20,1), -ENOENT
));
1996 for (auto &entry
: entries
) {
2000 for (auto &entry
: entries
) {
2001 eversion_t replay_version
;
2002 version_t user_version
;
2003 int return_code
= 0;
2004 bool got
= log
.get_request(
2005 entry
.reqid
, &replay_version
, &user_version
, &return_code
);
2007 EXPECT_EQ(entry
.return_code
, return_code
);
2008 EXPECT_EQ(entry
.version
, replay_version
);
2009 EXPECT_EQ(entry
.user_version
, user_version
);
2013 TEST_F(PGLogTest
, ErrorNotIndexedByObject
) {
2016 // make sure writes, deletes, and errors are found
2017 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
2019 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(6,2), eversion_t(3,4),
2020 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2021 utime_t(0,1), -ENOENT
));
2023 EXPECT_FALSE(log
.logged_object(oid
));
2025 pg_log_entry_t
modify(pg_log_entry_t::MODIFY
, oid
, eversion_t(6,3),
2027 osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2031 EXPECT_TRUE(log
.logged_object(oid
));
2032 pg_log_entry_t
*entry
= log
.objects
[oid
];
2033 EXPECT_EQ(modify
.op
, entry
->op
);
2034 EXPECT_EQ(modify
.version
, entry
->version
);
2035 EXPECT_EQ(modify
.prior_version
, entry
->prior_version
);
2036 EXPECT_EQ(modify
.user_version
, entry
->user_version
);
2037 EXPECT_EQ(modify
.reqid
, entry
->reqid
);
2039 pg_log_entry_t
del(pg_log_entry_t::DELETE
, oid
, eversion_t(7,4),
2041 osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2045 EXPECT_TRUE(log
.logged_object(oid
));
2046 entry
= log
.objects
[oid
];
2047 EXPECT_EQ(del
.op
, entry
->op
);
2048 EXPECT_EQ(del
.version
, entry
->version
);
2049 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2050 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2051 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2054 pg_log_entry_t(pg_log_entry_t::ERROR
, oid
, eversion_t(7,5), eversion_t(7,4),
2055 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2056 utime_t(20,1), -ENOENT
));
2058 EXPECT_TRUE(log
.logged_object(oid
));
2059 entry
= log
.objects
[oid
];
2060 EXPECT_EQ(del
.op
, entry
->op
);
2061 EXPECT_EQ(del
.version
, entry
->version
);
2062 EXPECT_EQ(del
.prior_version
, entry
->prior_version
);
2063 EXPECT_EQ(del
.user_version
, entry
->user_version
);
2064 EXPECT_EQ(del
.reqid
, entry
->reqid
);
2068 // compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "