]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/osd/TestPGLog.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / osd / TestPGLog.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
7 *
8 * Author: Loic Dachary <loic@dachary.org>
9 *
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)
13 * any later version.
14 *
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.
19 *
20 */
21
22 #include <stdio.h>
23 #include <signal.h>
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"
29
30
31 struct PGLogTestBase {
32 static hobject_t mk_obj(unsigned id) {
33 hobject_t hoid;
34 stringstream ss;
35 ss << "obj_" << id;
36 hoid.oid = ss.str();
37 hoid.set_hash(id);
38 hoid.pool = 1;
39 return hoid;
40 }
41 static eversion_t mk_evt(unsigned ep, unsigned v) {
42 return eversion_t(ep, v);
43 }
44 static pg_log_entry_t mk_ple_mod(
45 const hobject_t &hoid, eversion_t v, eversion_t pv, osd_reqid_t reqid) {
46 pg_log_entry_t e;
47 e.mark_unrollbackable();
48 e.op = pg_log_entry_t::MODIFY;
49 e.soid = hoid;
50 e.version = v;
51 e.prior_version = pv;
52 e.reqid = reqid;
53 return e;
54 }
55 static pg_log_entry_t mk_ple_dt(
56 const hobject_t &hoid, eversion_t v, eversion_t pv, osd_reqid_t reqid) {
57 pg_log_entry_t e;
58 e.mark_unrollbackable();
59 e.op = pg_log_entry_t::DELETE;
60 e.soid = hoid;
61 e.version = v;
62 e.prior_version = pv;
63 e.reqid = reqid;
64 return e;
65 }
66 static pg_log_entry_t mk_ple_ldt(
67 const hobject_t &hoid, eversion_t v, eversion_t pv) {
68 pg_log_entry_t e;
69 e.mark_unrollbackable();
70 e.op = pg_log_entry_t::LOST_DELETE;
71 e.soid = hoid;
72 e.version = v;
73 e.prior_version = pv;
74 return e;
75 }
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) {
78 pg_log_entry_t e;
79 e.op = pg_log_entry_t::MODIFY;
80 e.soid = hoid;
81 e.version = v;
82 e.prior_version = pv;
83 e.reqid = reqid;
84 return e;
85 }
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) {
88 pg_log_entry_t e;
89 e.op = pg_log_entry_t::DELETE;
90 e.soid = hoid;
91 e.version = v;
92 e.prior_version = pv;
93 e.reqid = reqid;
94 return e;
95 }
96 static pg_log_entry_t mk_ple_err(
97 const hobject_t &hoid, eversion_t v, osd_reqid_t reqid) {
98 pg_log_entry_t e;
99 e.op = pg_log_entry_t::ERROR;
100 e.soid = hoid;
101 e.version = v;
102 e.prior_version = eversion_t(0, 0);
103 e.reqid = reqid;
104 return e;
105 }
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());
109 }
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());
113 }
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());
117 }
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());
121 }
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());
125 }
126 }; // PGLogTestBase
127
128
129 class PGLogTest : virtual public ::testing::Test, protected PGLog, public PGLogTestBase {
130 public:
131 PGLogTest() : PGLog(g_ceph_context) {}
132 void SetUp() override {
133 missing.may_include_deletes = true;
134 }
135
136 #include "common/ceph_context.h"
137 #include "common/config.h"
138
139 void TearDown() override {
140 clear();
141 }
142
143
144 struct TestCase {
145 list<pg_log_entry_t> base;
146 list<pg_log_entry_t> auth;
147 list<pg_log_entry_t> div;
148
149 pg_missing_t init;
150 pg_missing_t final;
151
152 set<hobject_t> toremove;
153 list<pg_log_entry_t> torollback;
154 bool deletes_during_peering;
155
156 private:
157 IndexedLog fullauth;
158 IndexedLog fulldiv;
159 pg_info_t authinfo;
160 pg_info_t divinfo;
161 public:
162 TestCase() : deletes_during_peering(false) {}
163 void setup() {
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());
170
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();
177
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();
184
185 if (init.get_items().empty()) {
186 divinfo.last_complete = divinfo.last_update;
187 } else {
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();
191 ++i) {
192 if (i->version < fmissing)
193 divinfo.last_complete = i->version;
194 else
195 break;
196 }
197 }
198
199 fullauth.index();
200 fulldiv.index();
201 }
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;
205 }
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;
209 }
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
215
216 struct LogHandler : public PGLog::LogEntryHandler {
217 set<hobject_t> removed;
218 list<pg_log_entry_t> rolledback;
219
220 void rollback(
221 const pg_log_entry_t &entry) override {
222 rolledback.push_back(entry);
223 }
224 void rollforward(
225 const pg_log_entry_t &entry) override {}
226 void remove(
227 const hobject_t &hoid) override {
228 removed.insert(hoid);
229 }
230 void try_stash(const hobject_t &, version_t) override {
231 // lost/unfound cases are not tested yet
232 }
233 void trim(
234 const pg_log_entry_t &entry) override {}
235 };
236
237 template <typename missing_t>
238 void verify_missing(
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();
244 ++i) {
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);
248 }
249 bool correct = missing.debug_verify_from_init(tcase.init, &(std::cout));
250 ASSERT_TRUE(correct);
251 }
252
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());
258
259 {
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);
264 }
265 }
266
267 {
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);
272 }
273 }
274 }
275
276 void test_merge_log(const TestCase &tcase) {
277 clear();
278 log = tcase.get_fulldiv();
279 pg_info_t info = tcase.get_divinfo();
280
281 missing = tcase.init;
282 missing.flush();
283
284 IndexedLog olog;
285 olog = tcase.get_fullauth();
286 pg_info_t oinfo = tcase.get_authinfo();
287
288 LogHandler h;
289 bool dirty_info = false;
290 bool dirty_big_info = false;
291 merge_log(
292 oinfo, olog, pg_shard_t(1, shard_id_t(0)), info,
293 &h, dirty_info, dirty_big_info);
294
295 ASSERT_EQ(info.last_update, oinfo.last_update);
296 verify_missing(tcase, missing);
297 verify_sideeffects(tcase, h);
298 }
299
300 void test_proc_replica_log(const TestCase &tcase) {
301 clear();
302 log = tcase.get_fullauth();
303 pg_info_t info = tcase.get_authinfo();
304
305 pg_missing_t omissing = tcase.init;
306
307 IndexedLog olog;
308 olog = tcase.get_fulldiv();
309 pg_info_t oinfo = tcase.get_divinfo();
310
311 proc_replica_log(
312 oinfo, olog, omissing, pg_shard_t(1, shard_id_t(0)));
313
314 ceph_assert(oinfo.last_update >= log.tail);
315
316 if (!tcase.base.empty()) {
317 ASSERT_EQ(tcase.base.rbegin()->version, oinfo.last_update);
318 }
319
320 for (list<pg_log_entry_t>::const_iterator i = tcase.auth.begin();
321 i != tcase.auth.end();
322 ++i) {
323 if (i->version > oinfo.last_update) {
324 if (i->is_delete() && tcase.deletes_during_peering) {
325 omissing.rm(i->soid, i->version);
326 } else {
327 omissing.add_next_event(*i);
328 }
329 }
330 }
331 verify_missing(tcase, omissing);
332 } // test_proc_replica_log
333
334 void run_test_case(const TestCase &tcase) {
335 test_merge_log(tcase);
336 test_proc_replica_log(tcase);
337 }
338 }; // class PGLogTest
339
340 struct TestHandler : public PGLog::LogEntryHandler {
341 list<hobject_t> &removed;
342 explicit TestHandler(list<hobject_t> &removed) : removed(removed) {}
343
344 void rollback(
345 const pg_log_entry_t &entry) override {}
346 void rollforward(
347 const pg_log_entry_t &entry) override {}
348 void remove(
349 const hobject_t &hoid) override {
350 removed.push_back(hoid);
351 }
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
355 }
356 void trim(
357 const pg_log_entry_t &entry) override {}
358 };
359
360 TEST_F(PGLogTest, rewind_divergent_log) {
361 /* +----------------+
362 | log |
363 +--------+-------+
364 | |object |
365 |version | hash |
366 | | |
367 tail > (1,1) | x5 |
368 | | |
369 | | |
370 | (1,4) | x9 < newhead
371 | MODIFY | |
372 | | |
373 head > (1,5) | x9 |
374 | DELETE | |
375 | | |
376 +--------+-------+
377
378 */
379 {
380 clear();
381
382 pg_info_t info;
383 list<hobject_t> remove_snap;
384 bool dirty_info = false;
385 bool dirty_big_info = false;
386
387 hobject_t divergent_object;
388 eversion_t divergent_version;
389 eversion_t newhead;
390
391 hobject_t divergent;
392 divergent.set_hash(0x9);
393
394 {
395 pg_log_entry_t e;
396 e.mark_unrollbackable();
397
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);
403 e.soid = divergent;
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);
408 e.soid = divergent;
409 divergent_object = e.soid;
410 e.op = pg_log_entry_t::DELETE;
411 log.log.push_back(e);
412 log.head = e.version;
413 log.index();
414
415 info.last_update = log.head;
416 info.last_complete = log.head;
417 }
418
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);
427
428 TestHandler h(remove_snap);
429 rewind_divergent_log(newhead, info, &h,
430 dirty_info, dirty_big_info);
431
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);
442 }
443
444 /* +----------------+
445 | log |
446 +--------+-------+
447 | |object |
448 |version | hash |
449 | | |
450 tail > (1,1) | NULL |
451 | | |
452 | (1,4) | NULL < newhead
453 | | |
454 head > (1,5) | x9 |
455 | | |
456 +--------+-------+
457
458 */
459 {
460 clear();
461
462 pg_info_t info;
463 list<hobject_t> remove_snap;
464 bool dirty_info = false;
465 bool dirty_big_info = false;
466
467 hobject_t divergent_object;
468 eversion_t divergent_version;
469 eversion_t prior_version;
470 eversion_t newhead;
471 {
472 pg_log_entry_t e;
473 e.mark_unrollbackable();
474
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;
484 }
485
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);
492
493 TestHandler h(remove_snap);
494 rewind_divergent_log(newhead, info, &h,
495 dirty_info, dirty_big_info);
496
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);
504 }
505
506 // Test for 13965
507 {
508 clear();
509
510 list<hobject_t> remove_snap;
511 pg_info_t info;
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;
516
517 {
518 pg_log_entry_t e;
519 e.mark_unrollbackable();
520 e.version = eversion_t(1, 5);
521 e.soid.set_hash(0x9);
522 add(e);
523 }
524 {
525 pg_log_entry_t e;
526 e.mark_unrollbackable();
527 e.version = eversion_t(1, 6);
528 e.soid.set_hash(0x10);
529 add(e);
530 }
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);
535 pg_log_t log;
536 reset_backfill_claim_log(log, &h);
537 }
538 }
539
540 TEST_F(PGLogTest, merge_old_entry) {
541 // entries > last_backfill are silently ignored
542 {
543 clear();
544
545 ObjectStore::Transaction t;
546 pg_log_entry_t oe;
547 oe.mark_unrollbackable();
548 pg_info_t info;
549 list<hobject_t> remove_snap;
550
551 info.last_backfill = hobject_t();
552 info.last_backfill.set_hash(100);
553 oe.soid.set_hash(2);
554 ASSERT_GT(oe.soid, info.last_backfill);
555
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());
561
562 TestHandler h(remove_snap);
563 merge_old_entry(t, oe, info, &h);
564
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());
570 }
571
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
575 {
576 clear();
577
578 ObjectStore::Transaction t;
579 pg_info_t info;
580 list<hobject_t> remove_snap;
581
582 pg_log_entry_t ne;
583 ne.mark_unrollbackable();
584 ne.version = eversion_t(2,1);
585 log.add(ne);
586
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);
593
594 // the newer entry ( from the logs ) can be DELETE
595 {
596 log.log.front().op = pg_log_entry_t::DELETE;
597 pg_log_entry_t oe;
598 oe.mark_unrollbackable();
599 oe.version = eversion_t(1,1);
600
601 TestHandler h(remove_snap);
602 merge_old_entry(t, oe, info, &h);
603 }
604
605 // if the newer entry is not DELETE, the object must be in missing
606 {
607 pg_log_entry_t &ne = log.log.front();
608 ne.op = pg_log_entry_t::MODIFY;
609 missing.add_next_event(ne);
610 pg_log_entry_t oe;
611 oe.mark_unrollbackable();
612 oe.version = eversion_t(1,1);
613
614 TestHandler h(remove_snap);
615 merge_old_entry(t, oe, info, &h);
616
617 missing.rm(ne.soid, ne.version);
618 }
619
620 missing.flush();
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);
627
628 }
629
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
633 {
634 clear();
635
636 ObjectStore::Transaction t;
637 pg_log_entry_t oe;
638 oe.mark_unrollbackable();
639 pg_info_t info;
640 list<hobject_t> remove_snap;
641
642 pg_log_entry_t ne;
643 ne.mark_unrollbackable();
644 ne.version = eversion_t(1,1);
645 ne.op = pg_log_entry_t::DELETE;
646 log.add(ne);
647
648 oe.version = eversion_t(2,1);
649 oe.op = pg_log_entry_t::DELETE;
650
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());
656
657 TestHandler h(remove_snap);
658 merge_old_entry(t, oe, info, &h);
659
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());
665 }
666
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
671 {
672 clear();
673
674 ObjectStore::Transaction t;
675 pg_log_entry_t oe;
676 oe.mark_unrollbackable();
677 pg_info_t info;
678 list<hobject_t> remove_snap;
679
680 pg_log_entry_t ne;
681 ne.mark_unrollbackable();
682 ne.version = eversion_t(1,1);
683 ne.op = pg_log_entry_t::DELETE;
684 log.add(ne);
685
686 oe.version = eversion_t(2,1);
687 oe.op = pg_log_entry_t::MODIFY;
688 missing.add_next_event(oe);
689
690 missing.flush();
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());
696
697 TestHandler h(remove_snap);
698 merge_old_entry(t, oe, info, &h);
699
700 missing.flush();
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());
706 }
707
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
712 {
713 clear();
714
715 ObjectStore::Transaction t;
716 pg_log_entry_t oe;
717 oe.mark_unrollbackable();
718 pg_info_t info;
719 list<hobject_t> remove_snap;
720
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());
725
726 missing.flush();
727 EXPECT_FALSE(is_dirty());
728 EXPECT_TRUE(remove_snap.empty());
729 EXPECT_TRUE(t.empty());
730 EXPECT_TRUE(log.empty());
731
732 TestHandler h(remove_snap);
733 merge_old_entry(t, oe, info, &h);
734
735 missing.flush();
736 EXPECT_FALSE(is_dirty());
737 EXPECT_TRUE(remove_snap.empty());
738 EXPECT_TRUE(t.empty());
739 EXPECT_TRUE(log.empty());
740 }
741
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
749 // return false
750 {
751 clear();
752
753 ObjectStore::Transaction t;
754 pg_log_entry_t oe;
755 oe.mark_unrollbackable();
756 pg_info_t info;
757 list<hobject_t> remove_snap;
758
759 info.log_tail = eversion_t(2,1);
760 oe.soid.set_hash(1);
761 oe.op = pg_log_entry_t::MODIFY;
762 oe.prior_version = eversion_t(1,1);
763
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());
769
770 TestHandler h(remove_snap);
771 merge_old_entry(t, oe, info, &h);
772
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());
778 }
779
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
786 // return false
787 {
788 clear();
789
790 ObjectStore::Transaction t;
791 pg_log_entry_t oe;
792 oe.mark_unrollbackable();
793 pg_info_t info;
794 list<hobject_t> remove_snap;
795
796 info.log_tail = eversion_t(2,1);
797 oe.soid.set_hash(1);
798 oe.op = pg_log_entry_t::DELETE;
799 oe.prior_version = eversion_t(1,1);
800
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());
806
807 TestHandler h(remove_snap);
808 merge_old_entry(t, oe, info, &h);
809
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());
815 }
816
817
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
824 // return false
825 {
826 clear();
827
828 ObjectStore::Transaction t;
829 pg_log_entry_t oe;
830 oe.mark_unrollbackable();
831 pg_info_t info;
832 list<hobject_t> remove_snap;
833
834 info.log_tail = eversion_t(10,1);
835 oe.soid.set_hash(1);
836 oe.op = pg_log_entry_t::MODIFY;
837 oe.prior_version = eversion_t();
838
839 missing.add(oe.soid, eversion_t(1,1), eversion_t(), false);
840
841 missing.flush();
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());
847
848 TestHandler h(remove_snap);
849 merge_old_entry(t, oe, info, &h);
850
851 missing.flush();
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());
857 }
858
859 }
860
861 TEST_F(PGLogTest, merge_log) {
862 // head and tail match, last_backfill is set:
863 // noop
864 {
865 clear();
866
867 pg_log_t olog;
868 pg_info_t oinfo;
869 pg_shard_t fromosd;
870 pg_info_t info;
871 list<hobject_t> remove_snap;
872 bool dirty_info = false;
873 bool dirty_big_info = false;
874
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);
881
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);
891
892 TestHandler h(remove_snap);
893 merge_log(oinfo, olog, fromosd, info, &h,
894 dirty_info, dirty_big_info);
895
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);
904 }
905
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
909 {
910 clear();
911
912 pg_log_t olog;
913 pg_info_t oinfo;
914 pg_shard_t fromosd;
915 pg_info_t info;
916 list<hobject_t> remove_snap;
917 bool dirty_info = false;
918 bool dirty_big_info = false;
919
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;
929
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);
941
942 TestHandler h(remove_snap);
943 merge_log(oinfo, olog, fromosd, info, &h,
944 dirty_info, dirty_big_info);
945
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);
956 }
957
958 /* Before
959 +--------------------------+
960 | log olog |
961 +--------+-------+---------+
962 | |object | |
963 |version | hash | version |
964 | | | |
965 | | x5 | (1,1) < tail
966 | | | |
967 | | | |
968 tail > (1,4) | x7 | |
969 | | | |
970 | | | |
971 head > (1,5) | x9 | (1,5) < head
972 | | | |
973 | | | |
974 +--------+-------+---------+
975
976 After
977 +-----------------
978 | log |
979 +--------+-------+
980 | |object |
981 |version | hash |
982 | | |
983 tail > (1,1) | x5 |
984 | | |
985 | | |
986 | (1,4) | x7 |
987 | | |
988 | | |
989 head > (1,5) | x9 |
990 | | |
991 | | |
992 +--------+-------+
993 */
994 {
995 clear();
996
997 pg_log_t olog;
998 pg_info_t oinfo;
999 pg_shard_t fromosd;
1000 pg_info_t info;
1001 list<hobject_t> remove_snap;
1002 bool dirty_info = false;
1003 bool dirty_big_info = false;
1004 missing.may_include_deletes = false;
1005
1006 {
1007 pg_log_entry_t e;
1008 e.mark_unrollbackable();
1009
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;
1018 log.index();
1019
1020 info.last_update = log.head;
1021
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;
1030 }
1031
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;
1036
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);
1046
1047 TestHandler h(remove_snap);
1048 merge_log(oinfo, olog, fromosd, info, &h,
1049 dirty_info, dirty_big_info);
1050
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);
1059 }
1060
1061 /* +--------------------------+
1062 | log olog |
1063 +--------+-------+---------+
1064 | |object | |
1065 |version | hash | version |
1066 | | | |
1067 tail > (1,1) | x5 | (1,1) < tail
1068 | | | |
1069 | | | |
1070 | (1,2) | x3 | (1,2) < lower_bound
1071 | | | |
1072 | | | |
1073 head > (1,3) | x9 | |
1074 | DELETE | | |
1075 | | | |
1076 | | x9 | (2,3) |
1077 | | | MODIFY |
1078 | | | |
1079 | | x7 | (2,4) < head
1080 | | | DELETE |
1081 +--------+-------+---------+
1082
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.
1085
1086 */
1087 {
1088 clear();
1089
1090 pg_log_t olog;
1091 pg_info_t oinfo;
1092 pg_shard_t fromosd;
1093 pg_info_t info;
1094 list<hobject_t> remove_snap;
1095 bool dirty_info = false;
1096 bool dirty_big_info = false;
1097
1098 hobject_t divergent_object;
1099 missing.may_include_deletes = true;
1100
1101 {
1102 pg_log_entry_t e;
1103 e.mark_unrollbackable();
1104
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;
1118 log.index();
1119
1120 info.last_update = log.head;
1121
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;
1138 }
1139
1140 snapid_t purged_snap(1);
1141 {
1142 oinfo.last_update = olog.head;
1143 oinfo.purged_snaps.insert(purged_snap);
1144 }
1145
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);
1155
1156 TestHandler h(remove_snap);
1157 merge_log(oinfo, olog, fromosd, info, &h,
1158 dirty_info, dirty_big_info);
1159
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
1163 to be divergent.
1164 */
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
1170 to remove_snap)
1171 */
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);
1178 }
1179
1180 /* +--------------------------+
1181 | log olog |
1182 +--------+-------+---------+
1183 | |object | |
1184 |version | hash | version |
1185 | | | |
1186 tail > (1,1) | x5 | (1,1) < tail
1187 | | | |
1188 | | | |
1189 | (1,2) | x3 | (1,2) < lower_bound
1190 | | | |
1191 | | | |
1192 head > (1,3) | x9 | |
1193 | DELETE | | |
1194 | | | |
1195 | | x9 | (2,3) |
1196 | | | MODIFY |
1197 | | | |
1198 | | x7 | (2,4) < head
1199 | | | DELETE |
1200 +--------+-------+---------+
1201
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.
1204
1205 */
1206 {
1207 clear();
1208
1209 pg_log_t olog;
1210 pg_info_t oinfo;
1211 pg_shard_t fromosd;
1212 pg_info_t info;
1213 list<hobject_t> remove_snap;
1214 bool dirty_info = false;
1215 bool dirty_big_info = false;
1216
1217 hobject_t divergent_object;
1218
1219 {
1220 pg_log_entry_t e;
1221 e.mark_unrollbackable();
1222
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;
1236 log.index();
1237
1238 info.last_update = log.head;
1239
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;
1256 }
1257
1258 snapid_t purged_snap(1);
1259 {
1260 oinfo.last_update = olog.head;
1261 oinfo.purged_snaps.insert(purged_snap);
1262 }
1263
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);
1273
1274 TestHandler h(remove_snap);
1275 missing.may_include_deletes = false;
1276 merge_log(oinfo, olog, fromosd, info, &h,
1277 dirty_info, dirty_big_info);
1278
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
1282 to be divergent.
1283 */
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.
1291 */
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);
1298 }
1299
1300 /* +--------------------------+
1301 | log olog |
1302 +--------+-------+---------+
1303 | |object | |
1304 |version | hash | version |
1305 | | | |
1306 tail > (1,1) | x5 | (1,1) < tail
1307 | | | |
1308 | | | |
1309 | (1,4) | x7 | (1,4) < head
1310 | | | |
1311 | | | |
1312 head > (1,5) | x9 | |
1313 | | | |
1314 | | | |
1315 +--------+-------+---------+
1316
1317 The head of the log entry (1,5) is divergent because it is greater than the
1318 head of olog.
1319
1320 */
1321 {
1322 clear();
1323
1324 pg_log_t olog;
1325 pg_info_t oinfo;
1326 pg_shard_t fromosd;
1327 pg_info_t info;
1328 list<hobject_t> remove_snap;
1329 bool dirty_info = false;
1330 bool dirty_big_info = false;
1331
1332 {
1333 pg_log_entry_t e;
1334 e.mark_unrollbackable();
1335
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;
1347 log.index();
1348
1349 info.last_update = log.head;
1350
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;
1359 }
1360
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;
1365
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);
1375
1376 TestHandler h(remove_snap);
1377 missing.may_include_deletes = false;
1378 merge_log(oinfo, olog, fromosd, info, &h,
1379 dirty_info, dirty_big_info);
1380
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);
1389 }
1390
1391 }
1392
1393 TEST_F(PGLogTest, proc_replica_log) {
1394 // empty log : no side effect
1395 {
1396 clear();
1397
1398 pg_log_t olog;
1399 pg_info_t oinfo;
1400 pg_missing_t omissing;
1401 pg_shard_t from;
1402
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;
1407
1408 EXPECT_FALSE(omissing.have_missing());
1409 EXPECT_EQ(last_update, oinfo.last_update);
1410 EXPECT_EQ(last_complete, oinfo.last_complete);
1411
1412 missing.may_include_deletes = false;
1413 proc_replica_log(oinfo, olog, omissing, from);
1414
1415 EXPECT_FALSE(omissing.have_missing());
1416 EXPECT_EQ(last_update, oinfo.last_update);
1417 EXPECT_EQ(last_update, oinfo.last_complete);
1418 }
1419
1420 /* +--------------------------+
1421 | log olog |
1422 +--------+-------+---------+
1423 | |object | |
1424 |version | hash | version |
1425 | | | |
1426 | | x3 | (1,1) < tail
1427 | | | |
1428 | | | |
1429 tail > (1,2) | x5 | |
1430 | | | |
1431 | | | |
1432 head > (1,3) | x9 | |
1433 | DELETE | | |
1434 | | | |
1435 | | x9 | (2,3) < head
1436 | | | DELETE |
1437 | | | |
1438 +--------+-------+---------+
1439
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.
1443
1444 */
1445 {
1446 clear();
1447
1448 pg_log_t olog;
1449 pg_info_t oinfo;
1450 pg_missing_t omissing;
1451 pg_shard_t from;
1452
1453 {
1454 pg_log_entry_t e;
1455 e.mark_unrollbackable();
1456
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;
1466 log.index();
1467
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;
1477
1478 oinfo.last_update = olog.head;
1479 oinfo.last_complete = olog.head;
1480 }
1481
1482 EXPECT_FALSE(omissing.have_missing());
1483 EXPECT_EQ(olog.head, oinfo.last_update);
1484 EXPECT_EQ(olog.head, oinfo.last_complete);
1485
1486 missing.may_include_deletes = false;
1487 proc_replica_log(oinfo, olog, omissing, from);
1488
1489 EXPECT_FALSE(omissing.have_missing());
1490 }
1491
1492 {
1493 clear();
1494
1495 pg_log_t olog;
1496 pg_info_t oinfo;
1497 pg_missing_t omissing;
1498 pg_shard_t from;
1499
1500 hobject_t divergent_object;
1501
1502 {
1503 pg_log_entry_t e;
1504 e.mark_unrollbackable();
1505
1506 {
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);
1512
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);
1518
1519 e.soid.set_hash(0x3);
1520 e.version = eversion_t(1, 4);
1521 log.log.push_back(e);
1522
1523 e.soid.set_hash(0x7);
1524 e.version = eversion_t(1, 5);
1525 log.log.push_back(e);
1526
1527 e.soid.set_hash(0x8);
1528 e.version = eversion_t(1, 6);
1529 log.log.push_back(e);
1530
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);
1535
1536 e.soid.set_hash(0xa);
1537 e.version = eversion_t(2, 8);
1538 log.head = e.version;
1539 log.log.push_back(e);
1540 }
1541 log.index();
1542
1543 {
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);
1549
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);
1554
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);
1559
1560 e.soid.set_hash(0x7);
1561 e.version = eversion_t(1, 5);
1562 olog.log.push_back(e);
1563
1564 e.soid.set_hash(0x8);
1565 e.version = eversion_t(1, 6);
1566 olog.log.push_back(e);
1567
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);
1572
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;
1579 }
1580 oinfo.last_update = olog.head;
1581 oinfo.last_complete = olog.head;
1582 }
1583
1584 EXPECT_FALSE(omissing.have_missing());
1585 EXPECT_EQ(olog.head, oinfo.last_update);
1586 EXPECT_EQ(olog.head, oinfo.last_complete);
1587
1588 missing.may_include_deletes = false;
1589 proc_replica_log(oinfo, olog, omissing, from);
1590
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);
1596 }
1597
1598 /* +--------------------------+
1599 | olog log |
1600 +--------+-------+---------+
1601 | |object | |
1602 |version | hash | version |
1603 | | | |
1604 tail > (1,1) | x9 | (1,1) < tail
1605 | | | |
1606 | | | |
1607 | (1,2) | x3 | (1,2) |
1608 | | | |
1609 | | | |
1610 head > (1,3) | x9 | |
1611 | DELETE | | |
1612 | | | |
1613 | | x9 | (2,3) < head
1614 | | | DELETE |
1615 | | | |
1616 +--------+-------+---------+
1617
1618 The log entry (1,3) deletes the object x9 and the olog entry
1619 (2,3) also deletes it : do nothing.
1620
1621 */
1622 {
1623 clear();
1624
1625 pg_log_t olog;
1626 pg_info_t oinfo;
1627 pg_missing_t omissing;
1628 pg_shard_t from;
1629
1630 eversion_t last_update(1, 2);
1631 hobject_t divergent_object;
1632 divergent_object.set_hash(0x9);
1633
1634 {
1635 pg_log_entry_t e;
1636 e.mark_unrollbackable();
1637
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;
1651 log.index();
1652
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;
1666
1667 oinfo.last_update = olog.head;
1668 oinfo.last_complete = olog.head;
1669 }
1670
1671 EXPECT_FALSE(omissing.have_missing());
1672 EXPECT_EQ(olog.head, oinfo.last_update);
1673 EXPECT_EQ(olog.head, oinfo.last_complete);
1674
1675 missing.may_include_deletes = false;
1676 proc_replica_log(oinfo, olog, omissing, from);
1677
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);
1683 }
1684
1685 /* +--------------------------+
1686 | olog log |
1687 +--------+-------+---------+
1688 | |object | |
1689 |version | hash | version |
1690 | | | |
1691 tail > (1,1) | x9 | (1,1) < tail
1692 | | | |
1693 | | | |
1694 | (1,2) | x3 | (1,2) |
1695 | | | |
1696 | | | |
1697 head > (1,3) | x9 | |
1698 | MODIFY | | |
1699 | | | |
1700 | | x9 | (2,3) < head
1701 | | | DELETE |
1702 | | | |
1703 +--------+-------+---------+
1704
1705 The log entry (1,3) deletes the object x9 but the olog entry
1706 (2,3) modifies it : remove it from omissing.
1707
1708 */
1709 {
1710 clear();
1711
1712 pg_log_t olog;
1713 pg_info_t oinfo;
1714 pg_missing_t omissing;
1715 pg_shard_t from;
1716
1717 eversion_t last_update(1, 2);
1718 hobject_t divergent_object;
1719
1720 {
1721 pg_log_entry_t e;
1722 e.mark_unrollbackable();
1723
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;
1737 log.index();
1738
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;
1754
1755 oinfo.last_update = olog.head;
1756 oinfo.last_complete = olog.head;
1757 }
1758
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);
1764
1765 missing.may_include_deletes = false;
1766 proc_replica_log(oinfo, olog, omissing, from);
1767
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);
1773 }
1774
1775 /* +--------------------------+
1776 | log olog |
1777 +--------+-------+---------+
1778 | |object | |
1779 |version | hash | version |
1780 | | | |
1781 tail > (1,1) | x9 | (1,1) < tail
1782 | | | |
1783 | | | |
1784 | (1,2) | x3 | (1,2) |
1785 | | | |
1786 | | | |
1787 | | x9 | (1,3) < head
1788 | | | MODIFY |
1789 | | | |
1790 head > (2,3) | x9 | |
1791 | DELETE | | |
1792 | | | |
1793 +--------+-------+---------+
1794
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
1798 the delete.
1799 */
1800 {
1801 clear();
1802
1803 pg_log_t olog;
1804 pg_info_t oinfo;
1805 pg_missing_t omissing;
1806 pg_shard_t from;
1807
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);
1812
1813 {
1814 pg_log_entry_t e;
1815 e.mark_unrollbackable();
1816
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;
1830 log.index();
1831
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;
1848
1849 oinfo.last_update = olog.head;
1850 oinfo.last_complete = olog.head;
1851 }
1852
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);
1858
1859 missing.may_include_deletes = false;
1860 proc_replica_log(oinfo, olog, omissing, from);
1861
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);
1866 }
1867
1868 }
1869
1870 TEST_F(PGLogTest, merge_log_1) {
1871 TestCase t;
1872 t.base.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1873
1874 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1875
1876 t.final.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1877
1878 t.toremove.insert(mk_obj(1));
1879
1880 t.setup();
1881 run_test_case(t);
1882 }
1883
1884 TEST_F(PGLogTest, merge_log_2) {
1885 TestCase t;
1886 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1887
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)));
1890
1891 t.torollback.insert(
1892 t.torollback.begin(), t.div.rbegin(), t.div.rend());
1893
1894 t.setup();
1895 run_test_case(t);
1896 }
1897
1898 TEST_F(PGLogTest, merge_log_3) {
1899 TestCase t;
1900 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1901
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)));
1904
1905 t.final.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1906
1907 t.toremove.insert(mk_obj(1));
1908
1909 t.setup();
1910 run_test_case(t);
1911 }
1912
1913 TEST_F(PGLogTest, merge_log_4) {
1914 TestCase t;
1915 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1916
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)));
1919
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);
1922
1923 t.setup();
1924 run_test_case(t);
1925 }
1926
1927 TEST_F(PGLogTest, merge_log_5) {
1928 TestCase t;
1929 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1930
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)));
1933
1934 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1935
1936 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(0, 0), false);
1937
1938 t.toremove.insert(mk_obj(1));
1939
1940 t.setup();
1941 run_test_case(t);
1942 }
1943
1944 TEST_F(PGLogTest, merge_log_6) {
1945 TestCase t;
1946 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1947
1948 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1949
1950 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100), false);
1951
1952 t.setup();
1953 run_test_case(t);
1954 }
1955
1956 TEST_F(PGLogTest, merge_log_7) {
1957 TestCase t;
1958 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1959
1960 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1961
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);
1964
1965 t.setup();
1966 run_test_case(t);
1967 }
1968
1969 TEST_F(PGLogTest, merge_log_8) {
1970 TestCase t;
1971 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1972
1973 t.auth.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1974
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);
1977
1978 t.setup();
1979 run_test_case(t);
1980 }
1981
1982 TEST_F(PGLogTest, merge_log_9) {
1983 TestCase t;
1984 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1985
1986 t.auth.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1987
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;
1991
1992 t.setup();
1993 run_test_case(t);
1994 }
1995
1996 TEST_F(PGLogTest, merge_log_10) {
1997 TestCase t;
1998 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1999
2000 t.auth.push_back(mk_ple_ldt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
2001
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);
2004
2005 t.setup();
2006 run_test_case(t);
2007 }
2008
2009 TEST_F(PGLogTest, merge_log_prior_version_have) {
2010 TestCase t;
2011 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2012
2013 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
2014
2015 t.init.add(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100), false);
2016
2017 t.setup();
2018 run_test_case(t);
2019 }
2020
2021 TEST_F(PGLogTest, merge_log_split_missing_entries_at_head) {
2022 TestCase t;
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)));
2025
2026 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(8, 70), mk_evt(8, 65)));
2027
2028 t.setup();
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);
2032 run_test_case(t);
2033 }
2034
2035 TEST_F(PGLogTest, olog_tail_gt_log_tail_split) {
2036 TestCase t;
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)));
2040
2041 t.setup();
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);
2045 run_test_case(t);
2046 }
2047
2048 TEST_F(PGLogTest, olog_tail_gt_log_tail_split2) {
2049 TestCase t;
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)));
2054
2055 t.setup();
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));
2060 run_test_case(t);
2061 }
2062
2063 TEST_F(PGLogTest, filter_log_1) {
2064 {
2065 clear();
2066
2067 int osd_id = 1;
2068 epoch_t epoch = 40;
2069 int64_t pool_id = 1;
2070 int bits = 2;
2071 int max_osd = 4;
2072 int pg_num = max_osd << bits;
2073 int num_objects = 1000;
2074 int num_internal = 10;
2075
2076 // Set up splitting map
2077 OSDMap *osdmap = new OSDMap;
2078 uuid_d test_uuid;
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);
2082
2083 const string hit_set_namespace("internal");
2084
2085 {
2086 pg_log_entry_t e;
2087 e.mark_unrollbackable();
2088 e.op = pg_log_entry_t::MODIFY;
2089 e.soid.pool = pool_id;
2090
2091 uuid_d uuid_name;
2092 int i;
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();
2097 ostringstream name;
2098 name << uuid_name;
2099 e.soid.oid.name = name.str();
2100 // First has no namespace
2101 if (i != 1) {
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
2106 ostringstream ns;
2107 ns << "ns" << i;
2108 e.soid.nspace = ns.str();
2109 }
2110 }
2111 log.log.push_back(e);
2112 if (i == 1)
2113 log.tail = e.version;
2114 }
2115 log.head = e.version;
2116 log.index();
2117 }
2118
2119 spg_t pgid(pg_t(2, pool_id), shard_id_t::NO_SHARD);
2120
2121 // See if we created the right number of entries
2122 int total = log.log.size();
2123 ASSERT_EQ(total, num_objects);
2124
2125 // Some should be removed
2126 {
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);
2131 }
2132 EXPECT_LE(log.log.size(), (size_t)total);
2133
2134 // If we filter a second time, there should be the same total
2135 total = log.log.size();
2136 {
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);
2141 }
2142 EXPECT_EQ(log.log.size(), (size_t)total);
2143
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);
2149 pg_pool_t newpool;
2150 newpool = *pool;
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);
2155 ASSERT_EQ(ret, 0);
2156
2157 // We should have fewer entries after a filter
2158 {
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);
2163 }
2164 EXPECT_LE(log.log.size(), (size_t)total);
2165
2166 // Make sure all internal entries are retained
2167 int count = 0;
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++;
2171 }
2172 EXPECT_EQ(count, num_internal);
2173 }
2174 }
2175
2176 TEST_F(PGLogTest, get_request) {
2177 clear();
2178
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, "");
2182 entries.push_back(
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));
2186 entries.push_back(
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),
2189 utime_t(1,2), 0));
2190 entries.push_back(
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),
2193 utime_t(10,2), 0));
2194 entries.push_back(
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));
2198
2199 for (auto &entry : entries) {
2200 log.add(entry);
2201 }
2202
2203 for (auto &entry : entries) {
2204 eversion_t replay_version;
2205 version_t user_version;
2206 int return_code = 0;
2207 bool got = log.get_request(
2208 entry.reqid, &replay_version, &user_version, &return_code);
2209 EXPECT_TRUE(got);
2210 EXPECT_EQ(entry.return_code, return_code);
2211 EXPECT_EQ(entry.version, replay_version);
2212 EXPECT_EQ(entry.user_version, user_version);
2213 }
2214 }
2215
2216 TEST_F(PGLogTest, ErrorNotIndexedByObject) {
2217 clear();
2218
2219 // make sure writes, deletes, and errors are found
2220 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
2221 log.add(
2222 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(6,2), eversion_t(3,4),
2223 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2224 utime_t(0,1), -ENOENT));
2225
2226 EXPECT_FALSE(log.logged_object(oid));
2227
2228 pg_log_entry_t modify(pg_log_entry_t::MODIFY, oid, eversion_t(6,3),
2229 eversion_t(3,4), 2,
2230 osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2231 utime_t(1,2), 0);
2232 log.add(modify);
2233
2234 EXPECT_TRUE(log.logged_object(oid));
2235 pg_log_entry_t *entry = log.objects[oid];
2236 EXPECT_EQ(modify.op, entry->op);
2237 EXPECT_EQ(modify.version, entry->version);
2238 EXPECT_EQ(modify.prior_version, entry->prior_version);
2239 EXPECT_EQ(modify.user_version, entry->user_version);
2240 EXPECT_EQ(modify.reqid, entry->reqid);
2241
2242 pg_log_entry_t del(pg_log_entry_t::DELETE, oid, eversion_t(7,4),
2243 eversion_t(7,4), 3,
2244 osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2245 utime_t(10,2), 0);
2246 log.add(del);
2247
2248 EXPECT_TRUE(log.logged_object(oid));
2249 entry = log.objects[oid];
2250 EXPECT_EQ(del.op, entry->op);
2251 EXPECT_EQ(del.version, entry->version);
2252 EXPECT_EQ(del.prior_version, entry->prior_version);
2253 EXPECT_EQ(del.user_version, entry->user_version);
2254 EXPECT_EQ(del.reqid, entry->reqid);
2255
2256 log.add(
2257 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(7,5), eversion_t(7,4),
2258 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2259 utime_t(20,1), -ENOENT));
2260
2261 EXPECT_TRUE(log.logged_object(oid));
2262 entry = log.objects[oid];
2263 EXPECT_EQ(del.op, entry->op);
2264 EXPECT_EQ(del.version, entry->version);
2265 EXPECT_EQ(del.prior_version, entry->prior_version);
2266 EXPECT_EQ(del.user_version, entry->user_version);
2267 EXPECT_EQ(del.reqid, entry->reqid);
2268 }
2269
2270 TEST_F(PGLogTest, split_into_preserves_may_include_deletes) {
2271 clear();
2272
2273 {
2274 rebuilt_missing_with_deletes = false;
2275 missing.may_include_deletes = true;
2276 PGLog child_log(cct);
2277 pg_t child_pg;
2278 split_into(child_pg, 6, &child_log);
2279 ASSERT_TRUE(child_log.get_missing().may_include_deletes);
2280 ASSERT_TRUE(child_log.get_rebuilt_missing_with_deletes());
2281 }
2282
2283 {
2284 rebuilt_missing_with_deletes = false;
2285 missing.may_include_deletes = false;
2286 PGLog child_log(cct);
2287 pg_t child_pg;
2288 split_into(child_pg, 6, &child_log);
2289 ASSERT_FALSE(child_log.get_missing().may_include_deletes);
2290 ASSERT_FALSE(child_log.get_rebuilt_missing_with_deletes());
2291 }
2292 }
2293
2294 class PGLogTestRebuildMissing : public PGLogTest, public StoreTestFixture {
2295 public:
2296 PGLogTestRebuildMissing() : PGLogTest(), StoreTestFixture("memstore") {}
2297 void SetUp() override {
2298 StoreTestFixture::SetUp();
2299 ObjectStore::Transaction t;
2300 test_coll = coll_t(spg_t(pg_t(1, 1)));
2301 ch = store->create_new_collection(test_coll);
2302 t.create_collection(test_coll, 0);
2303 store->queue_transaction(ch, std::move(t));
2304 existing_oid = mk_obj(0);
2305 nonexistent_oid = mk_obj(1);
2306 ghobject_t existing_ghobj(existing_oid);
2307 object_info_t existing_info;
2308 existing_info.version = eversion_t(6, 2);
2309 bufferlist enc_oi;
2310 encode(existing_info, enc_oi, 0);
2311 ObjectStore::Transaction t2;
2312 t2.touch(test_coll, ghobject_t(existing_oid));
2313 t2.setattr(test_coll, ghobject_t(existing_oid), OI_ATTR, enc_oi);
2314 ASSERT_EQ(0, store->queue_transaction(ch, std::move(t2)));
2315 info.last_backfill = hobject_t::get_max();
2316 info.last_complete = eversion_t();
2317 }
2318
2319 void TearDown() override {
2320 clear();
2321 missing.may_include_deletes = false;
2322 StoreTestFixture::TearDown();
2323 }
2324
2325 pg_info_t info;
2326 coll_t test_coll;
2327 hobject_t existing_oid, nonexistent_oid;
2328
2329 void run_rebuild_missing_test(const map<hobject_t, pg_missing_item> &expected_missing_items) {
2330 rebuild_missing_set_with_deletes(store.get(), ch, info);
2331 ASSERT_EQ(expected_missing_items, missing.get_items());
2332 }
2333 };
2334
2335 TEST_F(PGLogTestRebuildMissing, EmptyLog) {
2336 missing.add(existing_oid, mk_evt(6, 2), mk_evt(6, 3), false);
2337 missing.add(nonexistent_oid, mk_evt(7, 4), mk_evt(0, 0), false);
2338 map<hobject_t, pg_missing_item> orig_missing = missing.get_items();
2339 run_rebuild_missing_test(orig_missing);
2340 }
2341
2342 TEST_F(PGLogTestRebuildMissing, SameVersionMod) {
2343 missing.add(existing_oid, mk_evt(6, 2), mk_evt(6, 1), false);
2344 log.add(mk_ple_mod(existing_oid, mk_evt(6, 2), mk_evt(6, 1)));
2345 map<hobject_t, pg_missing_item> empty_missing;
2346 run_rebuild_missing_test(empty_missing);
2347 }
2348
2349 TEST_F(PGLogTestRebuildMissing, DelExisting) {
2350 missing.add(existing_oid, mk_evt(6, 3), mk_evt(6, 2), false);
2351 log.add(mk_ple_dt(existing_oid, mk_evt(7, 5), mk_evt(7, 4)));
2352 map<hobject_t, pg_missing_item> expected;
2353 expected[existing_oid] = pg_missing_item(mk_evt(7, 5), mk_evt(6, 2), true);
2354 run_rebuild_missing_test(expected);
2355 }
2356
2357 TEST_F(PGLogTestRebuildMissing, DelNonexistent) {
2358 log.add(mk_ple_dt(nonexistent_oid, mk_evt(7, 5), mk_evt(7, 4)));
2359 map<hobject_t, pg_missing_item> expected;
2360 expected[nonexistent_oid] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2361 run_rebuild_missing_test(expected);
2362 }
2363
2364 TEST_F(PGLogTestRebuildMissing, MissingNotInLog) {
2365 missing.add(mk_obj(10), mk_evt(8, 12), mk_evt(8, 10), false);
2366 log.add(mk_ple_dt(nonexistent_oid, mk_evt(7, 5), mk_evt(7, 4)));
2367 map<hobject_t, pg_missing_item> expected;
2368 expected[nonexistent_oid] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2369 expected[mk_obj(10)] = pg_missing_item(mk_evt(8, 12), mk_evt(8, 10), false);
2370 run_rebuild_missing_test(expected);
2371 }
2372
2373
2374 class PGLogMergeDupsTest : protected PGLog, public StoreTestFixture {
2375
2376 public:
2377
2378 PGLogMergeDupsTest() : PGLog(g_ceph_context), StoreTestFixture("memstore") { }
2379
2380 void SetUp() override {
2381 StoreTestFixture::SetUp();
2382 ObjectStore::Transaction t;
2383 test_coll = coll_t(spg_t(pg_t(1, 1)));
2384 auto ch = store->create_new_collection(test_coll);
2385 t.create_collection(test_coll, 0);
2386 store->queue_transaction(ch, std::move(t));
2387 }
2388
2389 void TearDown() override {
2390 test_disk_roundtrip();
2391 clear();
2392 StoreTestFixture::TearDown();
2393 }
2394
2395 static pg_log_dup_t create_dup_entry(uint a, uint b) {
2396 // make each dup_entry unique by using different client id's
2397 static uint client_id = 777;
2398 return pg_log_dup_t(eversion_t(a, b),
2399 a,
2400 osd_reqid_t(entity_name_t::CLIENT(client_id++), 8, 1),
2401 0);
2402 }
2403
2404 static std::vector<pg_log_dup_t> example_dups_1() {
2405 std::vector<pg_log_dup_t> result = {
2406 create_dup_entry(10, 11),
2407 create_dup_entry(10, 12),
2408 create_dup_entry(11, 1),
2409 create_dup_entry(12, 3),
2410 create_dup_entry(13, 99)
2411 };
2412 return result;
2413 }
2414
2415 static std::vector<pg_log_dup_t> example_dups_2() {
2416 std::vector<pg_log_dup_t> result = {
2417 create_dup_entry(12, 3),
2418 create_dup_entry(13, 99),
2419 create_dup_entry(15, 11),
2420 create_dup_entry(16, 14),
2421 create_dup_entry(16, 32)
2422 };
2423 return result;
2424 }
2425
2426 void add_dups(uint a, uint b) {
2427 log.dups.push_back(create_dup_entry(a, b));
2428 write_from_dups = std::min(write_from_dups, log.dups.back().version);
2429 }
2430
2431 void add_dups(const std::vector<pg_log_dup_t>& l) {
2432 for (auto& i : l) {
2433 log.dups.push_back(i);
2434 write_from_dups = std::min(write_from_dups, log.dups.back().version);
2435 }
2436 }
2437
2438 static void add_dups(IndexedLog& log, const std::vector<pg_log_dup_t>& dups) {
2439 for (auto& i : dups) {
2440 log.dups.push_back(i);
2441 }
2442 }
2443
2444 void check_order() {
2445 eversion_t prev(0, 0);
2446
2447 for (auto& i : log.dups) {
2448 EXPECT_LT(prev, i.version) << "verify versions monotonically increase";
2449 prev = i.version;
2450 }
2451 }
2452
2453 void check_index() {
2454 EXPECT_EQ(log.dups.size(), log.dup_index.size());
2455 for (auto& i : log.dups) {
2456 EXPECT_EQ(1u, log.dup_index.count(i.reqid));
2457 }
2458 }
2459
2460 void test_disk_roundtrip() {
2461 ObjectStore::Transaction t;
2462 hobject_t hoid;
2463 hoid.pool = 1;
2464 hoid.oid = "log";
2465 ghobject_t log_oid(hoid);
2466 map<string, bufferlist> km;
2467 write_log_and_missing(t, &km, test_coll, log_oid, false);
2468 if (!km.empty()) {
2469 t.omap_setkeys(test_coll, log_oid, km);
2470 }
2471 auto ch = store->open_collection(test_coll);
2472 ASSERT_EQ(0, store->queue_transaction(ch, std::move(t)));
2473
2474 auto orig_dups = log.dups;
2475 clear();
2476 ostringstream err;
2477 read_log_and_missing(store.get(), ch, log_oid,
2478 pg_info_t(), err, false);
2479 ASSERT_EQ(orig_dups.size(), log.dups.size());
2480 ASSERT_EQ(orig_dups, log.dups);
2481 auto dups_it = log.dups.begin();
2482 for (auto orig_dup : orig_dups) {
2483 ASSERT_EQ(orig_dup, *dups_it);
2484 ++dups_it;
2485 }
2486 }
2487
2488 coll_t test_coll;
2489 };
2490
2491 TEST_F(PGLogMergeDupsTest, OtherEmpty) {
2492 log.tail = eversion_t(14, 5);
2493
2494 IndexedLog olog;
2495
2496 add_dups(example_dups_1());
2497 index();
2498
2499 bool changed = merge_log_dups(olog);
2500
2501 EXPECT_FALSE(changed);
2502 EXPECT_EQ(5u, log.dups.size());
2503
2504 if (5 == log.dups.size()) {
2505 EXPECT_EQ(10u, log.dups.front().version.epoch);
2506 EXPECT_EQ(11u, log.dups.front().version.version);
2507 EXPECT_EQ(13u, log.dups.back().version.epoch);
2508 EXPECT_EQ(99u, log.dups.back().version.version);
2509 }
2510
2511 check_order();
2512 check_index();
2513 }
2514
2515 TEST_F(PGLogMergeDupsTest, AmEmpty) {
2516 log.tail = eversion_t(14, 5);
2517 index();
2518
2519 IndexedLog olog;
2520
2521 add_dups(olog, example_dups_1());
2522
2523 bool changed = merge_log_dups(olog);
2524
2525 EXPECT_TRUE(changed);
2526 EXPECT_EQ(5u, log.dups.size());
2527
2528 if (5 == log.dups.size()) {
2529 EXPECT_EQ(10u, log.dups.front().version.epoch);
2530 EXPECT_EQ(11u, log.dups.front().version.version);
2531
2532 EXPECT_EQ(13u, log.dups.back().version.epoch);
2533 EXPECT_EQ(99u, log.dups.back().version.version);
2534 }
2535
2536 check_order();
2537 check_index();
2538 }
2539
2540 TEST_F(PGLogMergeDupsTest, AmEmptyOverlap) {
2541 log.tail = eversion_t(12, 3);
2542 index();
2543
2544 IndexedLog olog;
2545
2546 add_dups(olog, example_dups_1());
2547
2548 bool changed = merge_log_dups(olog);
2549
2550 EXPECT_TRUE(changed);
2551 EXPECT_EQ(3u, log.dups.size());
2552
2553 if (3 == log.dups.size()) {
2554 EXPECT_EQ(10u, log.dups.front().version.epoch);
2555 EXPECT_EQ(11u, log.dups.front().version.version);
2556
2557 EXPECT_EQ(11u, log.dups.back().version.epoch);
2558 EXPECT_EQ(1u, log.dups.back().version.version);
2559 }
2560
2561 check_order();
2562 check_index();
2563 }
2564
2565 TEST_F(PGLogMergeDupsTest, Same) {
2566 log.tail = eversion_t(14, 1);
2567
2568 IndexedLog olog;
2569
2570 add_dups(example_dups_1());
2571 index();
2572 add_dups(olog, example_dups_1());
2573
2574 bool changed = merge_log_dups(olog);
2575
2576 EXPECT_FALSE(changed);
2577 EXPECT_EQ(5u, log.dups.size());
2578
2579 if (5 == log.dups.size()) {
2580 EXPECT_EQ(10u, log.dups.front().version.epoch);
2581 EXPECT_EQ(11u, log.dups.front().version.version);
2582
2583 EXPECT_EQ(13u, log.dups.back().version.epoch);
2584 EXPECT_EQ(99u, log.dups.back().version.version);
2585 }
2586
2587 check_order();
2588 check_index();
2589 }
2590
2591
2592 TEST_F(PGLogMergeDupsTest, Later) {
2593 log.tail = eversion_t(16, 14);
2594
2595 IndexedLog olog;
2596
2597 add_dups(example_dups_1());
2598 index();
2599 add_dups(olog, example_dups_2());
2600
2601 bool changed = merge_log_dups(olog);
2602
2603 EXPECT_TRUE(changed);
2604 EXPECT_EQ(6u, log.dups.size());
2605
2606 if (6 == log.dups.size()) {
2607 EXPECT_EQ(10u, log.dups.front().version.epoch);
2608 EXPECT_EQ(11u, log.dups.front().version.version);
2609
2610 EXPECT_EQ(15u, log.dups.back().version.epoch);
2611 EXPECT_EQ(11u, log.dups.back().version.version);
2612 }
2613
2614 check_order();
2615 check_index();
2616 }
2617
2618
2619 TEST_F(PGLogMergeDupsTest, Earlier) {
2620 log.tail = eversion_t(17, 2);
2621
2622 IndexedLog olog;
2623
2624 add_dups(example_dups_2());
2625 index();
2626 add_dups(olog, example_dups_1());
2627
2628 bool changed = merge_log_dups(olog);
2629
2630 EXPECT_TRUE(changed);
2631 EXPECT_EQ(8u, log.dups.size());
2632
2633 if (6 == log.dups.size()) {
2634 EXPECT_EQ(10u, log.dups.front().version.epoch);
2635 EXPECT_EQ(11u, log.dups.front().version.version);
2636
2637 EXPECT_EQ(16u, log.dups.back().version.epoch);
2638 EXPECT_EQ(32u, log.dups.back().version.version);
2639 }
2640
2641 check_order();
2642 check_index();
2643 }
2644
2645
2646 TEST_F(PGLogMergeDupsTest, Superset) {
2647 log.tail = eversion_t(17, 2);
2648
2649 IndexedLog olog;
2650
2651 add_dups(example_dups_1());
2652 index();
2653
2654 olog.dups.push_back(create_dup_entry(9, 5));
2655 olog.dups.push_back(create_dup_entry(15, 11));
2656
2657 bool changed = merge_log_dups(olog);
2658
2659 EXPECT_TRUE(changed);
2660 EXPECT_EQ(7u, log.dups.size());
2661
2662 if (7 == log.dups.size()) {
2663 EXPECT_EQ(9u, log.dups.front().version.epoch);
2664 EXPECT_EQ(5u, log.dups.front().version.version);
2665
2666 EXPECT_EQ(15u, log.dups.back().version.epoch);
2667 EXPECT_EQ(11u, log.dups.back().version.version);
2668 }
2669
2670 check_order();
2671 check_index();
2672 }
2673
2674
2675 struct PGLogTrimTest :
2676 public ::testing::Test,
2677 public PGLogTestBase,
2678 public PGLog::IndexedLog
2679 {
2680 CephContext *cct = g_ceph_context;
2681
2682 using ::testing::Test::SetUp;
2683 void SetUp(unsigned min_entries, unsigned max_entries, unsigned dup_track) {
2684 constexpr size_t size = 10;
2685
2686 char min_entries_s[size];
2687 char max_entries_s[size];
2688 char dup_track_s[size];
2689
2690 snprintf(min_entries_s, size, "%u", min_entries);
2691 snprintf(max_entries_s, size, "%u", max_entries);
2692 snprintf(dup_track_s, size, "%u", dup_track);
2693
2694 cct->_conf.set_val_or_die("osd_min_pg_log_entries", min_entries_s);
2695 cct->_conf.set_val_or_die("osd_max_pg_log_entries", max_entries_s);
2696 cct->_conf.set_val_or_die("osd_pg_log_dups_tracked", dup_track_s);
2697 }
2698 }; // struct PGLogTrimTest
2699
2700
2701 TEST_F(PGLogTrimTest, TestMakingCephContext)
2702 {
2703 SetUp(1, 2, 5);
2704
2705 EXPECT_EQ(1u, cct->_conf->osd_min_pg_log_entries);
2706 EXPECT_EQ(2u, cct->_conf->osd_max_pg_log_entries);
2707 EXPECT_EQ(5u, cct->_conf->osd_pg_log_dups_tracked);
2708 }
2709
2710
2711 TEST_F(PGLogTrimTest, TestPartialTrim)
2712 {
2713 SetUp(1, 2, 20);
2714 PGLog::IndexedLog log;
2715 log.head = mk_evt(24, 0);
2716 log.skip_can_rollback_to_to_head();
2717 log.head = mk_evt(9, 0);
2718
2719 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2720 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2721 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2722 log.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2723 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2724 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2725
2726 std::set<eversion_t> trimmed;
2727 std::set<std::string> trimmed_dups;
2728 eversion_t write_from_dups = eversion_t::max();
2729
2730 log.trim(cct, mk_evt(19, 157), &trimmed, &trimmed_dups, &write_from_dups);
2731
2732 EXPECT_EQ(eversion_t(15, 150), write_from_dups);
2733 EXPECT_EQ(3u, log.log.size());
2734 EXPECT_EQ(3u, trimmed.size());
2735 EXPECT_EQ(2u, log.dups.size());
2736 EXPECT_EQ(0u, trimmed_dups.size());
2737
2738 SetUp(1, 2, 15);
2739
2740 std::set<eversion_t> trimmed2;
2741 std::set<std::string> trimmed_dups2;
2742 eversion_t write_from_dups2 = eversion_t::max();
2743
2744 log.trim(cct, mk_evt(20, 164), &trimmed2, &trimmed_dups2, &write_from_dups2);
2745
2746 EXPECT_EQ(eversion_t(19, 160), write_from_dups2);
2747 EXPECT_EQ(2u, log.log.size());
2748 EXPECT_EQ(1u, trimmed2.size());
2749 EXPECT_EQ(2u, log.dups.size());
2750 EXPECT_EQ(1u, trimmed_dups2.size());
2751 }
2752
2753
2754 TEST_F(PGLogTrimTest, TestTrimNoTrimmed) {
2755 SetUp(1, 2, 20);
2756 PGLog::IndexedLog log;
2757 log.head = mk_evt(20, 0);
2758 log.skip_can_rollback_to_to_head();
2759 log.head = mk_evt(9, 0);
2760
2761 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2762 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2763 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2764 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2765 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2766 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2767
2768 eversion_t write_from_dups = eversion_t::max();
2769
2770 log.trim(cct, mk_evt(19, 157), nullptr, nullptr, &write_from_dups);
2771
2772 EXPECT_EQ(eversion_t(15, 150), write_from_dups);
2773 EXPECT_EQ(3u, log.log.size());
2774 EXPECT_EQ(2u, log.dups.size());
2775 }
2776
2777
2778 TEST_F(PGLogTrimTest, TestTrimNoDups)
2779 {
2780 SetUp(1, 2, 10);
2781 PGLog::IndexedLog log;
2782 log.head = mk_evt(20, 0);
2783 log.skip_can_rollback_to_to_head();
2784 log.head = mk_evt(9, 0);
2785
2786 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2787 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2788 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2789 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2790 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2791 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2792
2793 std::set<eversion_t> trimmed;
2794 std::set<std::string> trimmed_dups;
2795 eversion_t write_from_dups = eversion_t::max();
2796
2797 log.trim(cct, mk_evt(19, 157), &trimmed, &trimmed_dups, &write_from_dups);
2798
2799 EXPECT_EQ(eversion_t::max(), write_from_dups);
2800 EXPECT_EQ(3u, log.log.size());
2801 EXPECT_EQ(3u, trimmed.size());
2802 EXPECT_EQ(0u, log.dups.size());
2803 EXPECT_EQ(0u, trimmed_dups.size());
2804 }
2805
2806 TEST_F(PGLogTrimTest, TestNoTrim)
2807 {
2808 SetUp(1, 2, 20);
2809 PGLog::IndexedLog log;
2810 log.head = mk_evt(24, 0);
2811 log.skip_can_rollback_to_to_head();
2812 log.head = mk_evt(9, 0);
2813
2814 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2815 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2816 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2817 log.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2818 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2819 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2820
2821 std::set<eversion_t> trimmed;
2822 std::set<std::string> trimmed_dups;
2823 eversion_t write_from_dups = eversion_t::max();
2824
2825 log.trim(cct, mk_evt(9, 99), &trimmed, &trimmed_dups, &write_from_dups);
2826
2827 EXPECT_EQ(eversion_t::max(), write_from_dups);
2828 EXPECT_EQ(6u, log.log.size());
2829 EXPECT_EQ(0u, trimmed.size());
2830 EXPECT_EQ(0u, log.dups.size());
2831 EXPECT_EQ(0u, trimmed_dups.size());
2832 }
2833
2834 TEST_F(PGLogTrimTest, TestTrimAll)
2835 {
2836 SetUp(1, 2, 20);
2837 PGLog::IndexedLog log;
2838 EXPECT_EQ(0u, log.dup_index.size()); // Sanity check
2839 log.head = mk_evt(24, 0);
2840 log.skip_can_rollback_to_to_head();
2841 log.head = mk_evt(9, 0);
2842
2843 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2844 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2845 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2846 log.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2847 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2848 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2849
2850 std::set<eversion_t> trimmed;
2851 std::set<std::string> trimmed_dups;
2852 eversion_t write_from_dups = eversion_t::max();
2853
2854 log.trim(cct, mk_evt(22, 180), &trimmed, &trimmed_dups, &write_from_dups);
2855
2856 EXPECT_EQ(eversion_t(15, 150), write_from_dups);
2857 EXPECT_EQ(0u, log.log.size());
2858 EXPECT_EQ(6u, trimmed.size());
2859 EXPECT_EQ(5u, log.dups.size());
2860 EXPECT_EQ(0u, trimmed_dups.size());
2861 EXPECT_EQ(0u, log.dup_index.size()); // dup_index entry should be trimmed
2862 }
2863
2864
2865 TEST_F(PGLogTrimTest, TestGetRequest) {
2866 SetUp(1, 2, 20);
2867 PGLog::IndexedLog log;
2868 log.head = mk_evt(20, 0);
2869 log.skip_can_rollback_to_to_head();
2870 log.head = mk_evt(9, 0);
2871
2872 entity_name_t client = entity_name_t::CLIENT(777);
2873
2874 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70),
2875 osd_reqid_t(client, 8, 1)));
2876 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100),
2877 osd_reqid_t(client, 8, 2)));
2878 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150),
2879 osd_reqid_t(client, 8, 3)));
2880 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152),
2881 osd_reqid_t(client, 8, 4)));
2882 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160),
2883 osd_reqid_t(client, 8, 5)));
2884 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166),
2885 osd_reqid_t(client, 8, 6)));
2886
2887 eversion_t write_from_dups = eversion_t::max();
2888
2889 log.trim(cct, mk_evt(19, 157), nullptr, nullptr, &write_from_dups);
2890
2891 EXPECT_EQ(eversion_t(15, 150), write_from_dups);
2892 EXPECT_EQ(3u, log.log.size());
2893 EXPECT_EQ(2u, log.dups.size());
2894
2895 eversion_t version;
2896 version_t user_version;
2897 int return_code;
2898
2899 osd_reqid_t log_reqid = osd_reqid_t(client, 8, 5);
2900 osd_reqid_t dup_reqid = osd_reqid_t(client, 8, 3);
2901 osd_reqid_t bad_reqid = osd_reqid_t(client, 8, 1);
2902
2903 bool result;
2904
2905 result = log.get_request(log_reqid, &version, &user_version, &return_code);
2906 EXPECT_EQ(true, result);
2907 EXPECT_EQ(mk_evt(21, 165), version);
2908
2909 result = log.get_request(dup_reqid, &version, &user_version, &return_code);
2910 EXPECT_EQ(true, result);
2911 EXPECT_EQ(mk_evt(15, 155), version);
2912
2913 result = log.get_request(bad_reqid, &version, &user_version, &return_code);
2914 EXPECT_FALSE(result);
2915 }
2916
2917 TEST_F(PGLogTest, _merge_object_divergent_entries) {
2918 {
2919 // Test for issue 20843
2920 clear();
2921 hobject_t hoid(object_t(/*name*/"notify.7"),
2922 /*key*/string(""),
2923 /*snap*/7,
2924 /*hash*/77,
2925 /*pool*/5,
2926 /*nspace*/string(""));
2927 mempool::osd_pglog::list<pg_log_entry_t> orig_entries;
2928 orig_entries.push_back(mk_ple_mod(hoid, eversion_t(8336, 957), eversion_t(8336, 952)));
2929 orig_entries.push_back(mk_ple_err(hoid, eversion_t(8336, 958)));
2930 orig_entries.push_back(mk_ple_err(hoid, eversion_t(8336, 959)));
2931 orig_entries.push_back(mk_ple_mod(hoid, eversion_t(8336, 960), eversion_t(8336, 957)));
2932 log.add(mk_ple_mod(hoid, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2933 missing.add(hoid,
2934 /*need*/eversion_t(8971, 1070),
2935 /*have*/eversion_t(8336, 952),
2936 false);
2937 pg_info_t oinfo;
2938 LogHandler rollbacker;
2939 _merge_object_divergent_entries(log, hoid,
2940 orig_entries, oinfo,
2941 log.get_can_rollback_to(),
2942 missing, &rollbacker,
2943 this);
2944 // No core dump
2945 }
2946 {
2947 // skip leading error entries
2948 clear();
2949 hobject_t hoid(object_t(/*name*/"notify.7"),
2950 /*key*/string(""),
2951 /*snap*/7,
2952 /*hash*/77,
2953 /*pool*/5,
2954 /*nspace*/string(""));
2955 mempool::osd_pglog::list<pg_log_entry_t> orig_entries;
2956 orig_entries.push_back(mk_ple_err(hoid, eversion_t(8336, 956)));
2957 orig_entries.push_back(mk_ple_mod(hoid, eversion_t(8336, 957), eversion_t(8336, 952)));
2958 log.add(mk_ple_mod(hoid, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2959 missing.add(hoid,
2960 /*need*/eversion_t(8971, 1070),
2961 /*have*/eversion_t(8336, 952),
2962 false);
2963 pg_info_t oinfo;
2964 LogHandler rollbacker;
2965 _merge_object_divergent_entries(log, hoid,
2966 orig_entries, oinfo,
2967 log.get_can_rollback_to(),
2968 missing, &rollbacker,
2969 this);
2970 // No core dump
2971 }
2972 }
2973
2974 TEST(eversion_t, get_key_name) {
2975 eversion_t a(1234, 5678);
2976 std::string a_key_name = a.get_key_name();
2977 EXPECT_EQ("0000001234.00000000000000005678", a_key_name);
2978 }
2979
2980 TEST(pg_log_dup_t, get_key_name) {
2981 pg_log_dup_t a(eversion_t(1234, 5678),
2982 13,
2983 osd_reqid_t(entity_name_t::CLIENT(777), 8, 999),
2984 15);
2985 std::string a_key_name = a.get_key_name();
2986 EXPECT_EQ("dup_0000001234.00000000000000005678", a_key_name);
2987 }
2988
2989 // Local Variables:
2990 // compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "
2991 // End: