]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/osd/TestPGLog.cc
update source to Ceph Pacific 16.2.2
[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, std::move(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, std::move(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, std::move(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, std::move(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, std::move(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, std::move(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, std::move(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 vector<pg_log_op_return_item_t> op_returns;
2208 bool got = log.get_request(
2209 entry.reqid, &replay_version, &user_version, &return_code, &op_returns);
2210 EXPECT_TRUE(got);
2211 EXPECT_EQ(entry.return_code, return_code);
2212 EXPECT_EQ(entry.version, replay_version);
2213 EXPECT_EQ(entry.user_version, user_version);
2214 }
2215 }
2216
2217 TEST_F(PGLogTest, ErrorNotIndexedByObject) {
2218 clear();
2219
2220 // make sure writes, deletes, and errors are found
2221 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
2222 log.add(
2223 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(6,2), eversion_t(3,4),
2224 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2225 utime_t(0,1), -ENOENT));
2226
2227 EXPECT_FALSE(log.logged_object(oid));
2228
2229 pg_log_entry_t modify(pg_log_entry_t::MODIFY, oid, eversion_t(6,3),
2230 eversion_t(3,4), 2,
2231 osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2232 utime_t(1,2), 0);
2233 log.add(modify);
2234
2235 EXPECT_TRUE(log.logged_object(oid));
2236 pg_log_entry_t *entry = log.objects[oid];
2237 EXPECT_EQ(modify.op, entry->op);
2238 EXPECT_EQ(modify.version, entry->version);
2239 EXPECT_EQ(modify.prior_version, entry->prior_version);
2240 EXPECT_EQ(modify.user_version, entry->user_version);
2241 EXPECT_EQ(modify.reqid, entry->reqid);
2242
2243 pg_log_entry_t del(pg_log_entry_t::DELETE, oid, eversion_t(7,4),
2244 eversion_t(7,4), 3,
2245 osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2246 utime_t(10,2), 0);
2247 log.add(del);
2248
2249 EXPECT_TRUE(log.logged_object(oid));
2250 entry = log.objects[oid];
2251 EXPECT_EQ(del.op, entry->op);
2252 EXPECT_EQ(del.version, entry->version);
2253 EXPECT_EQ(del.prior_version, entry->prior_version);
2254 EXPECT_EQ(del.user_version, entry->user_version);
2255 EXPECT_EQ(del.reqid, entry->reqid);
2256
2257 log.add(
2258 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(7,5), eversion_t(7,4),
2259 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2260 utime_t(20,1), -ENOENT));
2261
2262 EXPECT_TRUE(log.logged_object(oid));
2263 entry = log.objects[oid];
2264 EXPECT_EQ(del.op, entry->op);
2265 EXPECT_EQ(del.version, entry->version);
2266 EXPECT_EQ(del.prior_version, entry->prior_version);
2267 EXPECT_EQ(del.user_version, entry->user_version);
2268 EXPECT_EQ(del.reqid, entry->reqid);
2269 }
2270
2271 TEST_F(PGLogTest, split_into_preserves_may_include_deletes) {
2272 clear();
2273
2274 {
2275 may_include_deletes_in_missing_dirty = false;
2276 missing.may_include_deletes = true;
2277 PGLog child_log(cct);
2278 pg_t child_pg;
2279 split_into(child_pg, 6, &child_log);
2280 ASSERT_TRUE(child_log.get_missing().may_include_deletes);
2281 ASSERT_TRUE(child_log.get_may_include_deletes_in_missing_dirty());
2282 }
2283
2284 {
2285 may_include_deletes_in_missing_dirty = false;
2286 missing.may_include_deletes = false;
2287 PGLog child_log(cct);
2288 pg_t child_pg;
2289 split_into(child_pg, 6, &child_log);
2290 ASSERT_FALSE(child_log.get_missing().may_include_deletes);
2291 ASSERT_FALSE(child_log.get_may_include_deletes_in_missing_dirty());
2292 }
2293 }
2294
2295 class PGLogTestRebuildMissing : public PGLogTest, public StoreTestFixture {
2296 public:
2297 PGLogTestRebuildMissing() : PGLogTest(), StoreTestFixture("memstore") {}
2298 void SetUp() override {
2299 StoreTestFixture::SetUp();
2300 ObjectStore::Transaction t;
2301 test_coll = coll_t(spg_t(pg_t(1, 1)));
2302 ch = store->create_new_collection(test_coll);
2303 t.create_collection(test_coll, 0);
2304 store->queue_transaction(ch, std::move(t));
2305 existing_oid = mk_obj(0);
2306 nonexistent_oid = mk_obj(1);
2307 ghobject_t existing_ghobj(existing_oid);
2308 object_info_t existing_info;
2309 existing_info.version = eversion_t(6, 2);
2310 bufferlist enc_oi;
2311 encode(existing_info, enc_oi, 0);
2312 ObjectStore::Transaction t2;
2313 t2.touch(test_coll, ghobject_t(existing_oid));
2314 t2.setattr(test_coll, ghobject_t(existing_oid), OI_ATTR, enc_oi);
2315 ASSERT_EQ(0, store->queue_transaction(ch, std::move(t2)));
2316 info.last_backfill = hobject_t::get_max();
2317 info.last_complete = eversion_t();
2318 }
2319
2320 void TearDown() override {
2321 clear();
2322 missing.may_include_deletes = false;
2323 StoreTestFixture::TearDown();
2324 }
2325
2326 pg_info_t info;
2327 coll_t test_coll;
2328 hobject_t existing_oid, nonexistent_oid;
2329
2330 void run_rebuild_missing_test(const map<hobject_t, pg_missing_item> &expected_missing_items) {
2331 rebuild_missing_set_with_deletes(store.get(), ch, info);
2332 ASSERT_EQ(expected_missing_items, missing.get_items());
2333 }
2334 };
2335
2336 TEST_F(PGLogTestRebuildMissing, EmptyLog) {
2337 missing.add(existing_oid, mk_evt(6, 2), mk_evt(6, 3), false);
2338 missing.add(nonexistent_oid, mk_evt(7, 4), mk_evt(0, 0), false);
2339 map<hobject_t, pg_missing_item> orig_missing = missing.get_items();
2340 run_rebuild_missing_test(orig_missing);
2341 }
2342
2343 TEST_F(PGLogTestRebuildMissing, SameVersionMod) {
2344 missing.add(existing_oid, mk_evt(6, 2), mk_evt(6, 1), false);
2345 log.add(mk_ple_mod(existing_oid, mk_evt(6, 2), mk_evt(6, 1)));
2346 map<hobject_t, pg_missing_item> empty_missing;
2347 run_rebuild_missing_test(empty_missing);
2348 }
2349
2350 TEST_F(PGLogTestRebuildMissing, DelExisting) {
2351 missing.add(existing_oid, mk_evt(6, 3), mk_evt(6, 2), false);
2352 log.add(mk_ple_dt(existing_oid, mk_evt(7, 5), mk_evt(7, 4)));
2353 map<hobject_t, pg_missing_item> expected;
2354 expected[existing_oid] = pg_missing_item(mk_evt(7, 5), mk_evt(6, 2), true);
2355 run_rebuild_missing_test(expected);
2356 }
2357
2358 TEST_F(PGLogTestRebuildMissing, DelNonexistent) {
2359 log.add(mk_ple_dt(nonexistent_oid, mk_evt(7, 5), mk_evt(7, 4)));
2360 map<hobject_t, pg_missing_item> expected;
2361 expected[nonexistent_oid] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2362 run_rebuild_missing_test(expected);
2363 }
2364
2365 TEST_F(PGLogTestRebuildMissing, MissingNotInLog) {
2366 missing.add(mk_obj(10), mk_evt(8, 12), mk_evt(8, 10), false);
2367 log.add(mk_ple_dt(nonexistent_oid, mk_evt(7, 5), mk_evt(7, 4)));
2368 map<hobject_t, pg_missing_item> expected;
2369 expected[nonexistent_oid] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2370 expected[mk_obj(10)] = pg_missing_item(mk_evt(8, 12), mk_evt(8, 10), false);
2371 run_rebuild_missing_test(expected);
2372 }
2373
2374
2375 class PGLogMergeDupsTest : protected PGLog, public StoreTestFixture {
2376
2377 public:
2378
2379 PGLogMergeDupsTest() : PGLog(g_ceph_context), StoreTestFixture("memstore") { }
2380
2381 void SetUp() override {
2382 StoreTestFixture::SetUp();
2383 ObjectStore::Transaction t;
2384 test_coll = coll_t(spg_t(pg_t(1, 1)));
2385 auto ch = store->create_new_collection(test_coll);
2386 t.create_collection(test_coll, 0);
2387 store->queue_transaction(ch, std::move(t));
2388 }
2389
2390 void TearDown() override {
2391 test_disk_roundtrip();
2392 clear();
2393 StoreTestFixture::TearDown();
2394 }
2395
2396 static pg_log_dup_t create_dup_entry(uint a, uint b) {
2397 // make each dup_entry unique by using different client id's
2398 static uint client_id = 777;
2399 return pg_log_dup_t(eversion_t(a, b),
2400 a,
2401 osd_reqid_t(entity_name_t::CLIENT(client_id++), 8, 1),
2402 0);
2403 }
2404
2405 static std::vector<pg_log_dup_t> example_dups_1() {
2406 std::vector<pg_log_dup_t> result = {
2407 create_dup_entry(10, 11),
2408 create_dup_entry(10, 12),
2409 create_dup_entry(11, 1),
2410 create_dup_entry(12, 3),
2411 create_dup_entry(13, 99)
2412 };
2413 return result;
2414 }
2415
2416 static std::vector<pg_log_dup_t> example_dups_2() {
2417 std::vector<pg_log_dup_t> result = {
2418 create_dup_entry(12, 3),
2419 create_dup_entry(13, 99),
2420 create_dup_entry(15, 11),
2421 create_dup_entry(16, 14),
2422 create_dup_entry(16, 32)
2423 };
2424 return result;
2425 }
2426
2427 void add_dups(uint a, uint b) {
2428 log.dups.push_back(create_dup_entry(a, b));
2429 write_from_dups = std::min(write_from_dups, log.dups.back().version);
2430 }
2431
2432 void add_dups(const std::vector<pg_log_dup_t>& l) {
2433 for (auto& i : l) {
2434 log.dups.push_back(i);
2435 write_from_dups = std::min(write_from_dups, log.dups.back().version);
2436 }
2437 }
2438
2439 static void add_dups(IndexedLog& log, const std::vector<pg_log_dup_t>& dups) {
2440 for (auto& i : dups) {
2441 log.dups.push_back(i);
2442 }
2443 }
2444
2445 void check_order() {
2446 eversion_t prev(0, 0);
2447
2448 for (auto& i : log.dups) {
2449 EXPECT_LT(prev, i.version) << "verify versions monotonically increase";
2450 prev = i.version;
2451 }
2452 }
2453
2454 void check_index() {
2455 EXPECT_EQ(log.dups.size(), log.dup_index.size());
2456 for (auto& i : log.dups) {
2457 EXPECT_EQ(1u, log.dup_index.count(i.reqid));
2458 }
2459 }
2460
2461 void test_disk_roundtrip() {
2462 ObjectStore::Transaction t;
2463 hobject_t hoid;
2464 hoid.pool = 1;
2465 hoid.oid = "log";
2466 ghobject_t log_oid(hoid);
2467 map<string, bufferlist> km;
2468 write_log_and_missing(t, &km, test_coll, log_oid, false);
2469 if (!km.empty()) {
2470 t.omap_setkeys(test_coll, log_oid, km);
2471 }
2472 auto ch = store->open_collection(test_coll);
2473 ASSERT_EQ(0, store->queue_transaction(ch, std::move(t)));
2474
2475 auto orig_dups = log.dups;
2476 clear();
2477 ostringstream err;
2478 read_log_and_missing(store.get(), ch, log_oid,
2479 pg_info_t(), err, false);
2480 ASSERT_EQ(orig_dups.size(), log.dups.size());
2481 ASSERT_EQ(orig_dups, log.dups);
2482 auto dups_it = log.dups.begin();
2483 for (auto orig_dup : orig_dups) {
2484 ASSERT_EQ(orig_dup, *dups_it);
2485 ++dups_it;
2486 }
2487 }
2488
2489 coll_t test_coll;
2490 };
2491
2492 TEST_F(PGLogMergeDupsTest, OtherEmpty) {
2493 log.tail = eversion_t(14, 5);
2494
2495 IndexedLog olog;
2496
2497 add_dups(example_dups_1());
2498 index();
2499
2500 bool changed = merge_log_dups(olog);
2501
2502 EXPECT_FALSE(changed);
2503 EXPECT_EQ(5u, log.dups.size());
2504
2505 if (5 == log.dups.size()) {
2506 EXPECT_EQ(10u, log.dups.front().version.epoch);
2507 EXPECT_EQ(11u, log.dups.front().version.version);
2508 EXPECT_EQ(13u, log.dups.back().version.epoch);
2509 EXPECT_EQ(99u, log.dups.back().version.version);
2510 }
2511
2512 check_order();
2513 check_index();
2514 }
2515
2516 TEST_F(PGLogMergeDupsTest, AmEmpty) {
2517 log.tail = eversion_t(14, 5);
2518 index();
2519
2520 IndexedLog olog;
2521
2522 add_dups(olog, example_dups_1());
2523
2524 bool changed = merge_log_dups(olog);
2525
2526 EXPECT_TRUE(changed);
2527 EXPECT_EQ(5u, log.dups.size());
2528
2529 if (5 == log.dups.size()) {
2530 EXPECT_EQ(10u, log.dups.front().version.epoch);
2531 EXPECT_EQ(11u, log.dups.front().version.version);
2532
2533 EXPECT_EQ(13u, log.dups.back().version.epoch);
2534 EXPECT_EQ(99u, log.dups.back().version.version);
2535 }
2536
2537 check_order();
2538 check_index();
2539 }
2540
2541 TEST_F(PGLogMergeDupsTest, AmEmptyOverlap) {
2542 log.tail = eversion_t(12, 3);
2543 index();
2544
2545 IndexedLog olog;
2546
2547 add_dups(olog, example_dups_1());
2548
2549 bool changed = merge_log_dups(olog);
2550
2551 EXPECT_TRUE(changed);
2552 EXPECT_EQ(4u, log.dups.size());
2553
2554 if (4 == log.dups.size()) {
2555 EXPECT_EQ(10u, log.dups.front().version.epoch);
2556 EXPECT_EQ(11u, log.dups.front().version.version);
2557
2558 EXPECT_EQ(12u, log.dups.back().version.epoch);
2559 EXPECT_EQ(3u, log.dups.back().version.version);
2560 }
2561
2562 check_order();
2563 check_index();
2564 }
2565
2566 TEST_F(PGLogMergeDupsTest, Same) {
2567 log.tail = eversion_t(14, 1);
2568
2569 IndexedLog olog;
2570
2571 add_dups(example_dups_1());
2572 index();
2573 add_dups(olog, example_dups_1());
2574
2575 bool changed = merge_log_dups(olog);
2576
2577 EXPECT_FALSE(changed);
2578 EXPECT_EQ(5u, log.dups.size());
2579
2580 if (5 == log.dups.size()) {
2581 EXPECT_EQ(10u, log.dups.front().version.epoch);
2582 EXPECT_EQ(11u, log.dups.front().version.version);
2583
2584 EXPECT_EQ(13u, log.dups.back().version.epoch);
2585 EXPECT_EQ(99u, log.dups.back().version.version);
2586 }
2587
2588 check_order();
2589 check_index();
2590 }
2591
2592
2593 TEST_F(PGLogMergeDupsTest, Later) {
2594 log.tail = eversion_t(16, 14);
2595
2596 IndexedLog olog;
2597
2598 add_dups(example_dups_1());
2599 index();
2600 add_dups(olog, example_dups_2());
2601
2602 bool changed = merge_log_dups(olog);
2603
2604 EXPECT_TRUE(changed);
2605 EXPECT_EQ(7u, log.dups.size());
2606
2607 if (7 == log.dups.size()) {
2608 EXPECT_EQ(10u, log.dups.front().version.epoch);
2609 EXPECT_EQ(11u, log.dups.front().version.version);
2610
2611 EXPECT_EQ(16u, log.dups.back().version.epoch);
2612 EXPECT_EQ(14u, log.dups.back().version.version);
2613 }
2614
2615 check_order();
2616 check_index();
2617 }
2618
2619
2620 TEST_F(PGLogMergeDupsTest, Earlier) {
2621 log.tail = eversion_t(17, 2);
2622
2623 IndexedLog olog;
2624
2625 add_dups(example_dups_2());
2626 index();
2627 add_dups(olog, example_dups_1());
2628
2629 bool changed = merge_log_dups(olog);
2630
2631 EXPECT_TRUE(changed);
2632 EXPECT_EQ(8u, log.dups.size());
2633
2634 if (6 == log.dups.size()) {
2635 EXPECT_EQ(10u, log.dups.front().version.epoch);
2636 EXPECT_EQ(11u, log.dups.front().version.version);
2637
2638 EXPECT_EQ(16u, log.dups.back().version.epoch);
2639 EXPECT_EQ(32u, log.dups.back().version.version);
2640 }
2641
2642 check_order();
2643 check_index();
2644 }
2645
2646
2647 TEST_F(PGLogMergeDupsTest, Superset) {
2648 log.tail = eversion_t(17, 2);
2649
2650 IndexedLog olog;
2651
2652 add_dups(example_dups_1());
2653 index();
2654
2655 olog.dups.push_back(create_dup_entry(9, 5));
2656 olog.dups.push_back(create_dup_entry(15, 11));
2657
2658 bool changed = merge_log_dups(olog);
2659
2660 EXPECT_TRUE(changed);
2661 EXPECT_EQ(7u, log.dups.size());
2662
2663 if (7 == log.dups.size()) {
2664 EXPECT_EQ(9u, log.dups.front().version.epoch);
2665 EXPECT_EQ(5u, log.dups.front().version.version);
2666
2667 EXPECT_EQ(15u, log.dups.back().version.epoch);
2668 EXPECT_EQ(11u, log.dups.back().version.version);
2669 }
2670
2671 check_order();
2672 check_index();
2673 }
2674
2675
2676 struct PGLogTrimTest :
2677 public ::testing::Test,
2678 public PGLogTestBase,
2679 public PGLog::IndexedLog
2680 {
2681 CephContext *cct = g_ceph_context;
2682
2683 using ::testing::Test::SetUp;
2684 void SetUp(unsigned dup_track) {
2685 constexpr size_t size = 10;
2686
2687 char dup_track_s[size];
2688
2689 snprintf(dup_track_s, size, "%u", dup_track);
2690
2691 cct->_conf.set_val_or_die("osd_pg_log_dups_tracked", dup_track_s);
2692 }
2693 }; // struct PGLogTrimTest
2694
2695
2696 TEST_F(PGLogTrimTest, TestMakingCephContext)
2697 {
2698 SetUp(5);
2699
2700 EXPECT_EQ(5u, cct->_conf->osd_pg_log_dups_tracked);
2701 }
2702
2703
2704 TEST_F(PGLogTrimTest, TestPartialTrim)
2705 {
2706 SetUp(20);
2707 PGLog::IndexedLog log;
2708 log.head = mk_evt(24, 0);
2709 log.skip_can_rollback_to_to_head();
2710 log.head = mk_evt(9, 0);
2711
2712 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2713 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2714 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2715 log.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2716 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2717 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2718
2719 std::set<eversion_t> trimmed;
2720 std::set<std::string> trimmed_dups;
2721 eversion_t write_from_dups = eversion_t::max();
2722
2723 log.trim(cct, mk_evt(19, 157), &trimmed, &trimmed_dups, &write_from_dups);
2724
2725 EXPECT_EQ(eversion_t(15, 150), write_from_dups);
2726 EXPECT_EQ(3u, log.log.size());
2727 EXPECT_EQ(3u, trimmed.size());
2728 EXPECT_EQ(2u, log.dups.size());
2729 EXPECT_EQ(0u, trimmed_dups.size());
2730
2731 SetUp(15);
2732
2733 std::set<eversion_t> trimmed2;
2734 std::set<std::string> trimmed_dups2;
2735 eversion_t write_from_dups2 = eversion_t::max();
2736
2737 log.trim(cct, mk_evt(20, 164), &trimmed2, &trimmed_dups2, &write_from_dups2);
2738
2739 EXPECT_EQ(eversion_t(19, 160), write_from_dups2);
2740 EXPECT_EQ(2u, log.log.size());
2741 EXPECT_EQ(1u, trimmed2.size());
2742 EXPECT_EQ(2u, log.dups.size());
2743 EXPECT_EQ(1u, trimmed_dups2.size());
2744 }
2745
2746
2747 TEST_F(PGLogTrimTest, TestTrimNoTrimmed) {
2748 SetUp(20);
2749 PGLog::IndexedLog log;
2750 log.head = mk_evt(20, 0);
2751 log.skip_can_rollback_to_to_head();
2752 log.head = mk_evt(9, 0);
2753
2754 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2755 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2756 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2757 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2758 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2759 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2760
2761 eversion_t write_from_dups = eversion_t::max();
2762
2763 log.trim(cct, mk_evt(19, 157), nullptr, nullptr, &write_from_dups);
2764
2765 EXPECT_EQ(eversion_t(15, 150), write_from_dups);
2766 EXPECT_EQ(3u, log.log.size());
2767 EXPECT_EQ(2u, log.dups.size());
2768 }
2769
2770
2771 TEST_F(PGLogTrimTest, TestTrimNoDups)
2772 {
2773 SetUp(10);
2774 PGLog::IndexedLog log;
2775 log.head = mk_evt(20, 0);
2776 log.skip_can_rollback_to_to_head();
2777 log.head = mk_evt(9, 0);
2778
2779 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2780 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2781 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2782 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2783 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2784 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2785
2786 std::set<eversion_t> trimmed;
2787 std::set<std::string> trimmed_dups;
2788 eversion_t write_from_dups = eversion_t::max();
2789
2790 log.trim(cct, mk_evt(19, 157), &trimmed, &trimmed_dups, &write_from_dups);
2791
2792 EXPECT_EQ(eversion_t::max(), write_from_dups);
2793 EXPECT_EQ(3u, log.log.size());
2794 EXPECT_EQ(3u, trimmed.size());
2795 EXPECT_EQ(0u, log.dups.size());
2796 EXPECT_EQ(0u, trimmed_dups.size());
2797 }
2798
2799 TEST_F(PGLogTrimTest, TestNoTrim)
2800 {
2801 SetUp(20);
2802 PGLog::IndexedLog log;
2803 log.head = mk_evt(24, 0);
2804 log.skip_can_rollback_to_to_head();
2805 log.head = mk_evt(9, 0);
2806
2807 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2808 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2809 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2810 log.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2811 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2812 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2813
2814 std::set<eversion_t> trimmed;
2815 std::set<std::string> trimmed_dups;
2816 eversion_t write_from_dups = eversion_t::max();
2817
2818 log.trim(cct, mk_evt(9, 99), &trimmed, &trimmed_dups, &write_from_dups);
2819
2820 EXPECT_EQ(eversion_t::max(), write_from_dups);
2821 EXPECT_EQ(6u, log.log.size());
2822 EXPECT_EQ(0u, trimmed.size());
2823 EXPECT_EQ(0u, log.dups.size());
2824 EXPECT_EQ(0u, trimmed_dups.size());
2825 }
2826
2827 TEST_F(PGLogTrimTest, TestTrimAll)
2828 {
2829 SetUp(20);
2830 PGLog::IndexedLog log;
2831 EXPECT_EQ(0u, log.dup_index.size()); // Sanity check
2832 log.head = mk_evt(24, 0);
2833 log.skip_can_rollback_to_to_head();
2834 log.head = mk_evt(9, 0);
2835
2836 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2837 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2838 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2839 log.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2840 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2841 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2842
2843 std::set<eversion_t> trimmed;
2844 std::set<std::string> trimmed_dups;
2845 eversion_t write_from_dups = eversion_t::max();
2846
2847 log.trim(cct, mk_evt(22, 180), &trimmed, &trimmed_dups, &write_from_dups);
2848
2849 EXPECT_EQ(eversion_t(15, 150), write_from_dups);
2850 EXPECT_EQ(0u, log.log.size());
2851 EXPECT_EQ(6u, trimmed.size());
2852 EXPECT_EQ(5u, log.dups.size());
2853 EXPECT_EQ(0u, trimmed_dups.size());
2854 EXPECT_EQ(0u, log.dup_index.size()); // dup_index entry should be trimmed
2855 }
2856
2857
2858 TEST_F(PGLogTrimTest, TestGetRequest) {
2859 SetUp(20);
2860 PGLog::IndexedLog log;
2861 log.head = mk_evt(20, 0);
2862 log.skip_can_rollback_to_to_head();
2863 log.head = mk_evt(9, 0);
2864
2865 entity_name_t client = entity_name_t::CLIENT(777);
2866
2867 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70),
2868 osd_reqid_t(client, 8, 1)));
2869 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100),
2870 osd_reqid_t(client, 8, 2)));
2871 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150),
2872 osd_reqid_t(client, 8, 3)));
2873 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152),
2874 osd_reqid_t(client, 8, 4)));
2875 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160),
2876 osd_reqid_t(client, 8, 5)));
2877 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166),
2878 osd_reqid_t(client, 8, 6)));
2879
2880 eversion_t write_from_dups = eversion_t::max();
2881
2882 log.trim(cct, mk_evt(19, 157), nullptr, nullptr, &write_from_dups);
2883
2884 EXPECT_EQ(eversion_t(15, 150), write_from_dups);
2885 EXPECT_EQ(3u, log.log.size());
2886 EXPECT_EQ(2u, log.dups.size());
2887
2888 eversion_t version;
2889 version_t user_version;
2890 int return_code;
2891 vector<pg_log_op_return_item_t> op_returns;
2892
2893 osd_reqid_t log_reqid = osd_reqid_t(client, 8, 5);
2894 osd_reqid_t dup_reqid = osd_reqid_t(client, 8, 3);
2895 osd_reqid_t bad_reqid = osd_reqid_t(client, 8, 1);
2896
2897 bool result;
2898
2899 result = log.get_request(log_reqid, &version, &user_version, &return_code,
2900 &op_returns);
2901 EXPECT_EQ(true, result);
2902 EXPECT_EQ(mk_evt(21, 165), version);
2903
2904 result = log.get_request(dup_reqid, &version, &user_version, &return_code,
2905 &op_returns);
2906 EXPECT_EQ(true, result);
2907 EXPECT_EQ(mk_evt(15, 155), version);
2908
2909 result = log.get_request(bad_reqid, &version, &user_version, &return_code,
2910 &op_returns);
2911 EXPECT_FALSE(result);
2912 }
2913
2914 TEST_F(PGLogTest, _merge_object_divergent_entries) {
2915 {
2916 // Test for issue 20843
2917 clear();
2918 hobject_t hoid(object_t(/*name*/"notify.7"),
2919 /*key*/string(""),
2920 /*snap*/7,
2921 /*hash*/77,
2922 /*pool*/5,
2923 /*nspace*/string(""));
2924 mempool::osd_pglog::list<pg_log_entry_t> orig_entries;
2925 orig_entries.push_back(mk_ple_mod(hoid, eversion_t(8336, 957), eversion_t(8336, 952)));
2926 orig_entries.push_back(mk_ple_err(hoid, eversion_t(8336, 958)));
2927 orig_entries.push_back(mk_ple_err(hoid, eversion_t(8336, 959)));
2928 orig_entries.push_back(mk_ple_mod(hoid, eversion_t(8336, 960), eversion_t(8336, 957)));
2929 log.add(mk_ple_mod(hoid, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2930 missing.add(hoid,
2931 /*need*/eversion_t(8971, 1070),
2932 /*have*/eversion_t(8336, 952),
2933 false);
2934 pg_info_t oinfo;
2935 LogHandler rollbacker;
2936 _merge_object_divergent_entries(log, hoid,
2937 orig_entries, oinfo,
2938 log.get_can_rollback_to(),
2939 missing, &rollbacker,
2940 this);
2941 // No core dump
2942 }
2943 {
2944 // skip leading error entries
2945 clear();
2946 hobject_t hoid(object_t(/*name*/"notify.7"),
2947 /*key*/string(""),
2948 /*snap*/7,
2949 /*hash*/77,
2950 /*pool*/5,
2951 /*nspace*/string(""));
2952 mempool::osd_pglog::list<pg_log_entry_t> orig_entries;
2953 orig_entries.push_back(mk_ple_err(hoid, eversion_t(8336, 956)));
2954 orig_entries.push_back(mk_ple_mod(hoid, eversion_t(8336, 957), eversion_t(8336, 952)));
2955 log.add(mk_ple_mod(hoid, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2956 missing.add(hoid,
2957 /*need*/eversion_t(8971, 1070),
2958 /*have*/eversion_t(8336, 952),
2959 false);
2960 pg_info_t oinfo;
2961 LogHandler rollbacker;
2962 _merge_object_divergent_entries(log, hoid,
2963 orig_entries, oinfo,
2964 log.get_can_rollback_to(),
2965 missing, &rollbacker,
2966 this);
2967 // No core dump
2968 }
2969 }
2970
2971 TEST(eversion_t, get_key_name) {
2972 eversion_t a(1234, 5678);
2973 std::string a_key_name = a.get_key_name();
2974 EXPECT_EQ("0000001234.00000000000000005678", a_key_name);
2975 }
2976
2977 TEST(pg_log_dup_t, get_key_name) {
2978 pg_log_dup_t a(eversion_t(1234, 5678),
2979 13,
2980 osd_reqid_t(entity_name_t::CLIENT(777), 8, 999),
2981 15);
2982 std::string a_key_name = a.get_key_name();
2983 EXPECT_EQ("dup_0000001234.00000000000000005678", a_key_name);
2984 }
2985
2986
2987 // This tests trim() to make copies of
2988 // 2 log entries (107, 106) and 3 additional for a total
2989 // of 5 dups. Nothing from the original dups is copied.
2990 TEST_F(PGLogTrimTest, TestTrimDups) {
2991 SetUp(5);
2992 PGLog::IndexedLog log;
2993 log.head = mk_evt(21, 107);
2994 log.skip_can_rollback_to_to_head();
2995 log.tail = mk_evt(9, 99);
2996 log.head = mk_evt(9, 99);
2997
2998 entity_name_t client = entity_name_t::CLIENT(777);
2999
3000 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3001 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client, 8, 1))));
3002
3003 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3004 osd_reqid_t(client, 8, 1)));
3005 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3006 osd_reqid_t(client, 8, 2)));
3007 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3008 osd_reqid_t(client, 8, 3)));
3009 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3010 osd_reqid_t(client, 8, 4)));
3011 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3012 osd_reqid_t(client, 8, 5)));
3013 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3014 osd_reqid_t(client, 8, 6)));
3015 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3016 osd_reqid_t(client, 8, 6)));
3017 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3018 osd_reqid_t(client, 8, 6)));
3019
3020 eversion_t write_from_dups = eversion_t::max();
3021
3022 log.trim(cct, mk_evt(21, 105), nullptr, nullptr, &write_from_dups);
3023
3024 EXPECT_EQ(eversion_t(20, 103), write_from_dups) << log;
3025 EXPECT_EQ(2u, log.log.size()) << log;
3026 EXPECT_EQ(3u, log.dups.size()) << log;
3027 }
3028
3029 // This tests trim() to make copies of
3030 // 4 log entries (107, 106, 105, 104) and 5 additional for a total
3031 // of 9 dups. Only 1 of 2 existing dups are copied.
3032 TEST_F(PGLogTrimTest, TestTrimDups2) {
3033 SetUp(9);
3034 PGLog::IndexedLog log;
3035 log.head = mk_evt(21, 107);
3036 log.skip_can_rollback_to_to_head();
3037 log.tail = mk_evt(9, 99);
3038 log.head = mk_evt(9, 99);
3039
3040 entity_name_t client = entity_name_t::CLIENT(777);
3041
3042 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3043 mk_evt(9, 98), mk_evt(8, 97), osd_reqid_t(client, 8, 1))));
3044 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3045 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client, 8, 1))));
3046
3047 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3048 osd_reqid_t(client, 8, 1)));
3049 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3050 osd_reqid_t(client, 8, 2)));
3051 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3052 osd_reqid_t(client, 8, 3)));
3053 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3054 osd_reqid_t(client, 8, 4)));
3055 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3056 osd_reqid_t(client, 8, 5)));
3057 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3058 osd_reqid_t(client, 8, 6)));
3059 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3060 osd_reqid_t(client, 8, 6)));
3061 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3062 osd_reqid_t(client, 8, 6)));
3063
3064 eversion_t write_from_dups = eversion_t::max();
3065
3066 log.trim(cct, mk_evt(20, 103), nullptr, nullptr, &write_from_dups);
3067
3068 EXPECT_EQ(eversion_t(10, 100), write_from_dups) << log;
3069 EXPECT_EQ(4u, log.log.size()) << log;
3070 EXPECT_EQ(5u, log.dups.size()) << log;
3071 }
3072
3073 // This tests copy_up_to() to make copies of
3074 // 2 log entries (107, 106) and 3 additional for a total
3075 // of 5 dups. Nothing from the original dups is copied.
3076 TEST_F(PGLogTrimTest, TestCopyUpTo) {
3077 SetUp(5);
3078 PGLog::IndexedLog log, copy;
3079 log.tail = mk_evt(9, 99);
3080 log.head = mk_evt(9, 99);
3081
3082 entity_name_t client = entity_name_t::CLIENT(777);
3083
3084 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3085 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client, 8, 1))));
3086
3087 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3088 osd_reqid_t(client, 8, 1)));
3089 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3090 osd_reqid_t(client, 8, 2)));
3091 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3092 osd_reqid_t(client, 8, 3)));
3093 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3094 osd_reqid_t(client, 8, 4)));
3095 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3096 osd_reqid_t(client, 8, 5)));
3097 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3098 osd_reqid_t(client, 8, 6)));
3099 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3100 osd_reqid_t(client, 8, 6)));
3101 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3102 osd_reqid_t(client, 8, 6)));
3103
3104 copy.copy_up_to(cct, log, 2);
3105
3106 EXPECT_EQ(2u, copy.log.size()) << copy;
3107 EXPECT_EQ(copy.head, mk_evt(21, 107)) << copy;
3108 EXPECT_EQ(copy.tail, mk_evt(21, 105)) << copy;
3109 // Tracking 5 means 3 additional as dups
3110 EXPECT_EQ(3u, copy.dups.size()) << copy;
3111 }
3112
3113 // This tests copy_up_to() to make copies of
3114 // 4 log entries (107, 106, 105, 104) and 5 additional for a total
3115 // of 5 dups. Only 1 of 2 existing dups are copied.
3116 TEST_F(PGLogTrimTest, TestCopyUpTo2) {
3117 SetUp(9);
3118 PGLog::IndexedLog log, copy;
3119 log.tail = mk_evt(9, 99);
3120 log.head = mk_evt(9, 99);
3121
3122 entity_name_t client = entity_name_t::CLIENT(777);
3123
3124 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3125 mk_evt(8, 98), mk_evt(8, 97), osd_reqid_t(client, 8, 1))));
3126 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3127 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client, 8, 1))));
3128
3129 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3130 osd_reqid_t(client, 8, 1)));
3131 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3132 osd_reqid_t(client, 8, 2)));
3133 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3134 osd_reqid_t(client, 8, 3)));
3135 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3136 osd_reqid_t(client, 8, 4)));
3137 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3138 osd_reqid_t(client, 8, 5)));
3139 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3140 osd_reqid_t(client, 8, 6)));
3141 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3142 osd_reqid_t(client, 8, 6)));
3143 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3144 osd_reqid_t(client, 8, 6)));
3145
3146 copy.copy_up_to(cct, log, 4);
3147
3148 EXPECT_EQ(4u, copy.log.size()) << copy;
3149 EXPECT_EQ(copy.head, mk_evt(21, 107)) << copy;
3150 EXPECT_EQ(copy.tail, mk_evt(20, 103)) << copy;
3151 // Tracking 5 means 3 additional as dups
3152 EXPECT_EQ(5u, copy.dups.size()) << copy;
3153 }
3154
3155 // This tests copy_after() by specifying a version that copies
3156 // 2 log entries (107, 106) and 3 additional for a total
3157 // of 5 dups. Nothing of the original dups is copied.
3158 TEST_F(PGLogTrimTest, TestCopyAfter) {
3159 SetUp(5);
3160 PGLog::IndexedLog log, copy;
3161 log.tail = mk_evt(9, 99);
3162 log.head = mk_evt(9, 99);
3163
3164 entity_name_t client = entity_name_t::CLIENT(777);
3165
3166 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3167 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client, 8, 1))));
3168
3169 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3170 osd_reqid_t(client, 8, 1)));
3171 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3172 osd_reqid_t(client, 8, 2)));
3173 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3174 osd_reqid_t(client, 8, 3)));
3175 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3176 osd_reqid_t(client, 8, 4)));
3177 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3178 osd_reqid_t(client, 8, 5)));
3179 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3180 osd_reqid_t(client, 8, 6)));
3181 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3182 osd_reqid_t(client, 8, 6)));
3183 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3184 osd_reqid_t(client, 8, 6)));
3185
3186 copy.copy_after(cct, log, mk_evt(21, 105));
3187
3188 EXPECT_EQ(2u, copy.log.size()) << copy;
3189 EXPECT_EQ(copy.head, mk_evt(21, 107)) << copy;
3190 EXPECT_EQ(copy.tail, mk_evt(21, 105)) << copy;
3191 // Tracking 5 means 3 additional as dups
3192 EXPECT_EQ(3u, copy.dups.size()) << copy;
3193 }
3194
3195 // This copies everything dups and log because of the large max dups
3196 // and value passed to copy_after().
3197 TEST_F(PGLogTrimTest, TestCopyAfter2) {
3198 SetUp(3000);
3199 PGLog::IndexedLog log, copy;
3200 log.tail = mk_evt(9, 99);
3201 log.head = mk_evt(9, 99);
3202
3203 entity_name_t client = entity_name_t::CLIENT(777);
3204
3205 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3206 mk_evt(8, 93), mk_evt(8, 92), osd_reqid_t(client, 8, 1))));
3207 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3208 mk_evt(8, 94), mk_evt(8, 93), osd_reqid_t(client, 8, 1))));
3209 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3210 mk_evt(8, 95), mk_evt(8, 94), osd_reqid_t(client, 8, 1))));
3211 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3212 mk_evt(8, 96), mk_evt(8, 95), osd_reqid_t(client, 8, 1))));
3213 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3214 mk_evt(8, 97), mk_evt(8, 96), osd_reqid_t(client, 8, 1))));
3215 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3216 mk_evt(8, 98), mk_evt(8, 97), osd_reqid_t(client, 8, 1))));
3217 log.dups.push_back(pg_log_dup_t(mk_ple_mod(mk_obj(1),
3218 mk_evt(9, 99), mk_evt(8, 98), osd_reqid_t(client, 8, 1))));
3219
3220 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(9, 99),
3221 osd_reqid_t(client, 8, 1)));
3222 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 101), mk_evt(10, 100),
3223 osd_reqid_t(client, 8, 2)));
3224 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 102), mk_evt(15, 101),
3225 osd_reqid_t(client, 8, 3)));
3226 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 103), mk_evt(15, 102),
3227 osd_reqid_t(client, 8, 4)));
3228 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 104), mk_evt(20, 103),
3229 osd_reqid_t(client, 8, 5)));
3230 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 105), mk_evt(21, 104),
3231 osd_reqid_t(client, 8, 6)));
3232 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 106), mk_evt(21, 105),
3233 osd_reqid_t(client, 8, 6)));
3234 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 107), mk_evt(21, 106),
3235 osd_reqid_t(client, 8, 6)));
3236
3237 copy.copy_after(cct, log, mk_evt(9, 99));
3238
3239 EXPECT_EQ(8u, copy.log.size()) << copy;
3240 EXPECT_EQ(copy.head, mk_evt(21, 107)) << copy;
3241 EXPECT_EQ(copy.tail, mk_evt(9, 99)) << copy;
3242 // Tracking 3000 is larger than all entries, so all dups copied
3243 EXPECT_EQ(7u, copy.dups.size()) << copy;
3244 }
3245
3246 // Local Variables:
3247 // compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "
3248 // End: