]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/osd/TestPGLog.cc
update sources to v12.1.3
[ceph.git] / ceph / src / test / osd / TestPGLog.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
7 *
8 * Author: Loic Dachary <loic@dachary.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Library Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library Public License for more details.
19 *
20 */
21
22 #include <stdio.h>
23 #include <signal.h>
24 #include "gtest/gtest.h"
25 #include "osd/PGLog.h"
26 #include "osd/OSDMap.h"
27 #include "include/coredumpctl.h"
28 #include "../objectstore/store_test_fixture.h"
29
30
31 struct PGLogTestBase {
32 static hobject_t mk_obj(unsigned id) {
33 hobject_t hoid;
34 stringstream ss;
35 ss << "obj_" << id;
36 hoid.oid = ss.str();
37 hoid.set_hash(id);
38 hoid.pool = 1;
39 return hoid;
40 }
41 static eversion_t mk_evt(unsigned ep, unsigned v) {
42 return eversion_t(ep, v);
43 }
44 static pg_log_entry_t mk_ple_mod(
45 const hobject_t &hoid, eversion_t v, eversion_t pv, osd_reqid_t reqid) {
46 pg_log_entry_t e;
47 e.mark_unrollbackable();
48 e.op = pg_log_entry_t::MODIFY;
49 e.soid = hoid;
50 e.version = v;
51 e.prior_version = pv;
52 e.reqid = reqid;
53 return e;
54 }
55 static pg_log_entry_t mk_ple_dt(
56 const hobject_t &hoid, eversion_t v, eversion_t pv, osd_reqid_t reqid) {
57 pg_log_entry_t e;
58 e.mark_unrollbackable();
59 e.op = pg_log_entry_t::DELETE;
60 e.soid = hoid;
61 e.version = v;
62 e.prior_version = pv;
63 e.reqid = reqid;
64 return e;
65 }
66 static pg_log_entry_t mk_ple_ldt(
67 const hobject_t &hoid, eversion_t v, eversion_t pv) {
68 pg_log_entry_t e;
69 e.mark_unrollbackable();
70 e.op = pg_log_entry_t::LOST_DELETE;
71 e.soid = hoid;
72 e.version = v;
73 e.prior_version = pv;
74 return e;
75 }
76 static pg_log_entry_t mk_ple_mod_rb(
77 const hobject_t &hoid, eversion_t v, eversion_t pv, osd_reqid_t reqid) {
78 pg_log_entry_t e;
79 e.op = pg_log_entry_t::MODIFY;
80 e.soid = hoid;
81 e.version = v;
82 e.prior_version = pv;
83 e.reqid = reqid;
84 return e;
85 }
86 static pg_log_entry_t mk_ple_dt_rb(
87 const hobject_t &hoid, eversion_t v, eversion_t pv, osd_reqid_t reqid) {
88 pg_log_entry_t e;
89 e.op = pg_log_entry_t::DELETE;
90 e.soid = hoid;
91 e.version = v;
92 e.prior_version = pv;
93 e.reqid = reqid;
94 return e;
95 }
96 static pg_log_entry_t mk_ple_err(
97 const hobject_t &hoid, eversion_t v, osd_reqid_t reqid) {
98 pg_log_entry_t e;
99 e.op = pg_log_entry_t::ERROR;
100 e.soid = hoid;
101 e.version = v;
102 e.prior_version = eversion_t(0, 0);
103 e.reqid = reqid;
104 return e;
105 }
106 static pg_log_entry_t mk_ple_mod(
107 const hobject_t &hoid, eversion_t v, eversion_t pv) {
108 return mk_ple_mod(hoid, v, pv, osd_reqid_t());
109 }
110 static pg_log_entry_t mk_ple_dt(
111 const hobject_t &hoid, eversion_t v, eversion_t pv) {
112 return mk_ple_dt(hoid, v, pv, osd_reqid_t());
113 }
114 static pg_log_entry_t mk_ple_mod_rb(
115 const hobject_t &hoid, eversion_t v, eversion_t pv) {
116 return mk_ple_mod_rb(hoid, v, pv, osd_reqid_t());
117 }
118 static pg_log_entry_t mk_ple_dt_rb(
119 const hobject_t &hoid, eversion_t v, eversion_t pv) {
120 return mk_ple_dt_rb(hoid, v, pv, osd_reqid_t());
121 }
122 static pg_log_entry_t mk_ple_err(
123 const hobject_t &hoid, eversion_t v) {
124 return mk_ple_err(hoid, v, osd_reqid_t());
125 }
126 }; // PGLogTestBase
127
128
129 class PGLogTest : virtual public ::testing::Test, protected PGLog, public PGLogTestBase {
130 public:
131 PGLogTest() : PGLog(g_ceph_context) {}
132 void SetUp() override {
133 missing.may_include_deletes = true;
134 }
135
136 #include "common/ceph_context.h"
137 #include "common/config.h"
138
139 void TearDown() override {
140 clear();
141 }
142
143
144 struct TestCase {
145 list<pg_log_entry_t> base;
146 list<pg_log_entry_t> auth;
147 list<pg_log_entry_t> div;
148
149 pg_missing_t init;
150 pg_missing_t final;
151
152 set<hobject_t> toremove;
153 list<pg_log_entry_t> torollback;
154 bool deletes_during_peering;
155
156 private:
157 IndexedLog fullauth;
158 IndexedLog fulldiv;
159 pg_info_t authinfo;
160 pg_info_t divinfo;
161 public:
162 TestCase() : deletes_during_peering(false) {}
163 void setup() {
164 init.may_include_deletes = !deletes_during_peering;
165 final.may_include_deletes = !deletes_during_peering;
166 fullauth.log.insert(fullauth.log.end(), base.begin(), base.end());
167 fullauth.log.insert(fullauth.log.end(), auth.begin(), auth.end());
168 fulldiv.log.insert(fulldiv.log.end(), base.begin(), base.end());
169 fulldiv.log.insert(fulldiv.log.end(), div.begin(), div.end());
170
171 fullauth.head = authinfo.last_update = fullauth.log.rbegin()->version;
172 authinfo.last_complete = fullauth.log.rbegin()->version;
173 authinfo.log_tail = fullauth.log.begin()->version;
174 authinfo.log_tail.version--;
175 fullauth.tail = authinfo.log_tail;
176 authinfo.last_backfill = hobject_t::get_max();
177
178 fulldiv.head = divinfo.last_update = fulldiv.log.rbegin()->version;
179 divinfo.last_complete = eversion_t();
180 divinfo.log_tail = fulldiv.log.begin()->version;
181 divinfo.log_tail.version--;
182 fulldiv.tail = divinfo.log_tail;
183 divinfo.last_backfill = hobject_t::get_max();
184
185 if (init.get_items().empty()) {
186 divinfo.last_complete = divinfo.last_update;
187 } else {
188 eversion_t fmissing = init.get_items().at(init.get_rmissing().begin()->second).need;
189 for (list<pg_log_entry_t>::const_iterator i = fulldiv.log.begin();
190 i != fulldiv.log.end();
191 ++i) {
192 if (i->version < fmissing)
193 divinfo.last_complete = i->version;
194 else
195 break;
196 }
197 }
198
199 fullauth.index();
200 fulldiv.index();
201 }
202 void set_div_bounds(eversion_t head, eversion_t tail) {
203 fulldiv.tail = divinfo.log_tail = tail;
204 fulldiv.head = divinfo.last_update = head;
205 }
206 void set_auth_bounds(eversion_t head, eversion_t tail) {
207 fullauth.tail = authinfo.log_tail = tail;
208 fullauth.head = authinfo.last_update = head;
209 }
210 const IndexedLog &get_fullauth() const { return fullauth; }
211 const IndexedLog &get_fulldiv() const { return fulldiv; }
212 const pg_info_t &get_authinfo() const { return authinfo; }
213 const pg_info_t &get_divinfo() const { return divinfo; }
214 }; // struct TestCase
215
216 struct LogHandler : public PGLog::LogEntryHandler {
217 set<hobject_t> removed;
218 list<pg_log_entry_t> rolledback;
219
220 void rollback(
221 const pg_log_entry_t &entry) override {
222 rolledback.push_back(entry);
223 }
224 void rollforward(
225 const pg_log_entry_t &entry) override {}
226 void remove(
227 const hobject_t &hoid) override {
228 removed.insert(hoid);
229 }
230 void try_stash(const hobject_t &, version_t) override {
231 // lost/unfound cases are not tested yet
232 }
233 void trim(
234 const pg_log_entry_t &entry) override {}
235 };
236
237 template <typename missing_t>
238 void verify_missing(
239 const TestCase &tcase,
240 const missing_t &missing) {
241 ASSERT_EQ(tcase.final.get_items().size(), missing.get_items().size());
242 for (auto i = missing.get_items().begin();
243 i != missing.get_items().end();
244 ++i) {
245 EXPECT_TRUE(tcase.final.get_items().count(i->first));
246 EXPECT_EQ(tcase.final.get_items().find(i->first)->second.need, i->second.need);
247 EXPECT_EQ(tcase.final.get_items().find(i->first)->second.have, i->second.have);
248 }
249 bool correct = missing.debug_verify_from_init(tcase.init, &(std::cout));
250 ASSERT_TRUE(correct);
251 }
252
253 void verify_sideeffects(
254 const TestCase &tcase,
255 const LogHandler &handler) {
256 ASSERT_EQ(tcase.toremove.size(), handler.removed.size());
257 ASSERT_EQ(tcase.torollback.size(), handler.rolledback.size());
258
259 {
260 list<pg_log_entry_t>::const_iterator titer = tcase.torollback.begin();
261 list<pg_log_entry_t>::const_iterator hiter = handler.rolledback.begin();
262 for (; titer != tcase.torollback.end(); ++titer, ++hiter) {
263 EXPECT_EQ(titer->version, hiter->version);
264 }
265 }
266
267 {
268 set<hobject_t>::const_iterator titer = tcase.toremove.begin();
269 set<hobject_t>::const_iterator hiter = handler.removed.begin();
270 for (; titer != tcase.toremove.end(); ++titer, ++hiter) {
271 EXPECT_EQ(*titer, *hiter);
272 }
273 }
274 }
275
276 void test_merge_log(const TestCase &tcase) {
277 clear();
278 log = tcase.get_fulldiv();
279 pg_info_t info = tcase.get_divinfo();
280
281 missing = tcase.init;
282 missing.flush();
283
284 IndexedLog olog;
285 olog = tcase.get_fullauth();
286 pg_info_t oinfo = tcase.get_authinfo();
287
288 LogHandler h;
289 bool dirty_info = false;
290 bool dirty_big_info = false;
291 merge_log(
292 oinfo, olog, pg_shard_t(1, shard_id_t(0)), info,
293 &h, dirty_info, dirty_big_info);
294
295 ASSERT_EQ(info.last_update, oinfo.last_update);
296 verify_missing(tcase, missing);
297 verify_sideeffects(tcase, h);
298 }
299
300 void test_proc_replica_log(const TestCase &tcase) {
301 clear();
302 log = tcase.get_fullauth();
303 pg_info_t info = tcase.get_authinfo();
304
305 pg_missing_t omissing = tcase.init;
306
307 IndexedLog olog;
308 olog = tcase.get_fulldiv();
309 pg_info_t oinfo = tcase.get_divinfo();
310
311 proc_replica_log(
312 oinfo, olog, omissing, pg_shard_t(1, shard_id_t(0)));
313
314 assert(oinfo.last_update >= log.tail);
315
316 if (!tcase.base.empty()) {
317 ASSERT_EQ(tcase.base.rbegin()->version, oinfo.last_update);
318 }
319
320 for (list<pg_log_entry_t>::const_iterator i = tcase.auth.begin();
321 i != tcase.auth.end();
322 ++i) {
323 if (i->version > oinfo.last_update) {
324 if (i->is_delete() && tcase.deletes_during_peering) {
325 omissing.rm(i->soid, i->version);
326 } else {
327 omissing.add_next_event(*i);
328 }
329 }
330 }
331 verify_missing(tcase, omissing);
332 } // test_proc_replica_log
333
334 void run_test_case(const TestCase &tcase) {
335 test_merge_log(tcase);
336 test_proc_replica_log(tcase);
337 }
338 }; // class PGLogTest
339
340 struct TestHandler : public PGLog::LogEntryHandler {
341 list<hobject_t> &removed;
342 explicit TestHandler(list<hobject_t> &removed) : removed(removed) {}
343
344 void rollback(
345 const pg_log_entry_t &entry) override {}
346 void rollforward(
347 const pg_log_entry_t &entry) override {}
348 void remove(
349 const hobject_t &hoid) override {
350 removed.push_back(hoid);
351 }
352 void cant_rollback(const pg_log_entry_t &entry) {}
353 void try_stash(const hobject_t &, version_t) override {
354 // lost/unfound cases are not tested yet
355 }
356 void trim(
357 const pg_log_entry_t &entry) override {}
358 };
359
360 TEST_F(PGLogTest, rewind_divergent_log) {
361 /* +----------------+
362 | log |
363 +--------+-------+
364 | |object |
365 |version | hash |
366 | | |
367 tail > (1,1) | x5 |
368 | | |
369 | | |
370 | (1,4) | x9 < newhead
371 | MODIFY | |
372 | | |
373 head > (1,5) | x9 |
374 | DELETE | |
375 | | |
376 +--------+-------+
377
378 */
379 {
380 clear();
381
382 pg_info_t info;
383 list<hobject_t> remove_snap;
384 bool dirty_info = false;
385 bool dirty_big_info = false;
386
387 hobject_t divergent_object;
388 eversion_t divergent_version;
389 eversion_t newhead;
390
391 hobject_t divergent;
392 divergent.set_hash(0x9);
393
394 {
395 pg_log_entry_t e;
396 e.mark_unrollbackable();
397
398 e.version = eversion_t(1, 1);
399 e.soid.set_hash(0x5);
400 log.tail = e.version;
401 log.log.push_back(e);
402 e.version = newhead = eversion_t(1, 4);
403 e.soid = divergent;
404 e.op = pg_log_entry_t::MODIFY;
405 log.log.push_back(e);
406 e.version = divergent_version = eversion_t(1, 5);
407 e.prior_version = eversion_t(1, 4);
408 e.soid = divergent;
409 divergent_object = e.soid;
410 e.op = pg_log_entry_t::DELETE;
411 log.log.push_back(e);
412 log.head = e.version;
413 log.index();
414
415 info.last_update = log.head;
416 info.last_complete = log.head;
417 }
418
419 EXPECT_FALSE(missing.have_missing());
420 EXPECT_EQ(3U, log.log.size());
421 EXPECT_TRUE(remove_snap.empty());
422 EXPECT_EQ(log.head, info.last_update);
423 EXPECT_EQ(log.head, info.last_complete);
424 EXPECT_FALSE(is_dirty());
425 EXPECT_FALSE(dirty_info);
426 EXPECT_FALSE(dirty_big_info);
427
428 TestHandler h(remove_snap);
429 rewind_divergent_log(newhead, info, &h,
430 dirty_info, dirty_big_info);
431
432 EXPECT_TRUE(log.objects.count(divergent));
433 EXPECT_TRUE(missing.is_missing(divergent_object));
434 EXPECT_EQ(1U, log.objects.count(divergent_object));
435 EXPECT_EQ(2U, log.log.size());
436 EXPECT_TRUE(remove_snap.empty());
437 EXPECT_EQ(newhead, info.last_update);
438 EXPECT_EQ(newhead, info.last_complete);
439 EXPECT_TRUE(is_dirty());
440 EXPECT_TRUE(dirty_info);
441 EXPECT_TRUE(dirty_big_info);
442 }
443
444 /* +----------------+
445 | log |
446 +--------+-------+
447 | |object |
448 |version | hash |
449 | | |
450 tail > (1,1) | NULL |
451 | | |
452 | (1,4) | NULL < newhead
453 | | |
454 head > (1,5) | x9 |
455 | | |
456 +--------+-------+
457
458 */
459 {
460 clear();
461
462 pg_info_t info;
463 list<hobject_t> remove_snap;
464 bool dirty_info = false;
465 bool dirty_big_info = false;
466
467 hobject_t divergent_object;
468 eversion_t divergent_version;
469 eversion_t prior_version;
470 eversion_t newhead;
471 {
472 pg_log_entry_t e;
473 e.mark_unrollbackable();
474
475 info.log_tail = log.tail = eversion_t(1, 1);
476 newhead = eversion_t(1, 3);
477 e.version = divergent_version = eversion_t(1, 5);
478 e.soid.set_hash(0x9);
479 divergent_object = e.soid;
480 e.op = pg_log_entry_t::DELETE;
481 e.prior_version = prior_version = eversion_t(0, 2);
482 log.log.push_back(e);
483 log.head = e.version;
484 }
485
486 EXPECT_FALSE(missing.have_missing());
487 EXPECT_EQ(1U, log.log.size());
488 EXPECT_TRUE(remove_snap.empty());
489 EXPECT_FALSE(is_dirty());
490 EXPECT_FALSE(dirty_info);
491 EXPECT_FALSE(dirty_big_info);
492
493 TestHandler h(remove_snap);
494 rewind_divergent_log(newhead, info, &h,
495 dirty_info, dirty_big_info);
496
497 EXPECT_TRUE(missing.is_missing(divergent_object));
498 EXPECT_EQ(0U, log.objects.count(divergent_object));
499 EXPECT_TRUE(log.empty());
500 EXPECT_TRUE(remove_snap.empty());
501 EXPECT_TRUE(is_dirty());
502 EXPECT_TRUE(dirty_info);
503 EXPECT_TRUE(dirty_big_info);
504 }
505
506 // Test for 13965
507 {
508 clear();
509
510 list<hobject_t> remove_snap;
511 pg_info_t info;
512 info.log_tail = log.tail = eversion_t(1, 5);
513 info.last_update = eversion_t(1, 6);
514 bool dirty_info = false;
515 bool dirty_big_info = false;
516
517 {
518 pg_log_entry_t e;
519 e.mark_unrollbackable();
520 e.version = eversion_t(1, 5);
521 e.soid.set_hash(0x9);
522 add(e);
523 }
524 {
525 pg_log_entry_t e;
526 e.mark_unrollbackable();
527 e.version = eversion_t(1, 6);
528 e.soid.set_hash(0x10);
529 add(e);
530 }
531 TestHandler h(remove_snap);
532 roll_forward_to(eversion_t(1, 6), &h);
533 rewind_divergent_log(eversion_t(1, 5), info, &h,
534 dirty_info, dirty_big_info);
535 pg_log_t log;
536 reset_backfill_claim_log(log, &h);
537 }
538 }
539
540 TEST_F(PGLogTest, merge_old_entry) {
541 // entries > last_backfill are silently ignored
542 {
543 clear();
544
545 ObjectStore::Transaction t;
546 pg_log_entry_t oe;
547 oe.mark_unrollbackable();
548 pg_info_t info;
549 list<hobject_t> remove_snap;
550
551 info.last_backfill = hobject_t();
552 info.last_backfill.set_hash(100);
553 oe.soid.set_hash(2);
554 ASSERT_GT(oe.soid, info.last_backfill);
555
556 EXPECT_FALSE(is_dirty());
557 EXPECT_TRUE(remove_snap.empty());
558 EXPECT_TRUE(t.empty());
559 EXPECT_FALSE(missing.have_missing());
560 EXPECT_TRUE(log.empty());
561
562 TestHandler h(remove_snap);
563 merge_old_entry(t, oe, info, &h);
564
565 EXPECT_FALSE(is_dirty());
566 EXPECT_TRUE(remove_snap.empty());
567 EXPECT_TRUE(t.empty());
568 EXPECT_FALSE(missing.have_missing());
569 EXPECT_TRUE(log.empty());
570 }
571
572 // the new entry (from the logs) has a version that is higher than
573 // the old entry (from the log entry given in argument) : do
574 // nothing and return false
575 {
576 clear();
577
578 ObjectStore::Transaction t;
579 pg_info_t info;
580 list<hobject_t> remove_snap;
581
582 pg_log_entry_t ne;
583 ne.mark_unrollbackable();
584 ne.version = eversion_t(2,1);
585 log.add(ne);
586
587 EXPECT_FALSE(is_dirty());
588 EXPECT_TRUE(remove_snap.empty());
589 EXPECT_TRUE(t.empty());
590 EXPECT_FALSE(missing.have_missing());
591 EXPECT_EQ(1U, log.log.size());
592 EXPECT_EQ(ne.version, log.log.front().version);
593
594 // the newer entry ( from the logs ) can be DELETE
595 {
596 log.log.front().op = pg_log_entry_t::DELETE;
597 pg_log_entry_t oe;
598 oe.mark_unrollbackable();
599 oe.version = eversion_t(1,1);
600
601 TestHandler h(remove_snap);
602 merge_old_entry(t, oe, info, &h);
603 }
604
605 // if the newer entry is not DELETE, the object must be in missing
606 {
607 pg_log_entry_t &ne = log.log.front();
608 ne.op = pg_log_entry_t::MODIFY;
609 missing.add_next_event(ne);
610 pg_log_entry_t oe;
611 oe.mark_unrollbackable();
612 oe.version = eversion_t(1,1);
613
614 TestHandler h(remove_snap);
615 merge_old_entry(t, oe, info, &h);
616
617 missing.rm(ne.soid, ne.version);
618 }
619
620 missing.flush();
621 EXPECT_FALSE(is_dirty());
622 EXPECT_FALSE(remove_snap.empty());
623 EXPECT_TRUE(t.empty());
624 EXPECT_FALSE(missing.have_missing());
625 EXPECT_EQ(1U, log.log.size());
626 EXPECT_EQ(ne.version, log.log.front().version);
627
628 }
629
630 // the new entry (from the logs) has a version that is lower than
631 // the old entry (from the log entry given in argument) and
632 // old and new are delete : do nothing and return false
633 {
634 clear();
635
636 ObjectStore::Transaction t;
637 pg_log_entry_t oe;
638 oe.mark_unrollbackable();
639 pg_info_t info;
640 list<hobject_t> remove_snap;
641
642 pg_log_entry_t ne;
643 ne.mark_unrollbackable();
644 ne.version = eversion_t(1,1);
645 ne.op = pg_log_entry_t::DELETE;
646 log.add(ne);
647
648 oe.version = eversion_t(2,1);
649 oe.op = pg_log_entry_t::DELETE;
650
651 EXPECT_FALSE(is_dirty());
652 EXPECT_TRUE(remove_snap.empty());
653 EXPECT_TRUE(t.empty());
654 EXPECT_FALSE(missing.have_missing());
655 EXPECT_EQ(1U, log.log.size());
656
657 TestHandler h(remove_snap);
658 merge_old_entry(t, oe, info, &h);
659
660 EXPECT_FALSE(is_dirty());
661 EXPECT_TRUE(remove_snap.empty());
662 EXPECT_TRUE(t.empty());
663 EXPECT_FALSE(missing.have_missing());
664 EXPECT_EQ(1U, log.log.size());
665 }
666
667 // the new entry (from the logs) has a version that is lower than
668 // the old entry (from the log entry given in argument) and
669 // old is update and new is DELETE :
670 // if the object is in missing, it is removed
671 {
672 clear();
673
674 ObjectStore::Transaction t;
675 pg_log_entry_t oe;
676 oe.mark_unrollbackable();
677 pg_info_t info;
678 list<hobject_t> remove_snap;
679
680 pg_log_entry_t ne;
681 ne.mark_unrollbackable();
682 ne.version = eversion_t(1,1);
683 ne.op = pg_log_entry_t::DELETE;
684 log.add(ne);
685
686 oe.version = eversion_t(2,1);
687 oe.op = pg_log_entry_t::MODIFY;
688 missing.add_next_event(oe);
689
690 missing.flush();
691 EXPECT_FALSE(is_dirty());
692 EXPECT_TRUE(remove_snap.empty());
693 EXPECT_TRUE(t.empty());
694 EXPECT_TRUE(missing.is_missing(oe.soid));
695 EXPECT_EQ(1U, log.log.size());
696
697 TestHandler h(remove_snap);
698 merge_old_entry(t, oe, info, &h);
699
700 missing.flush();
701 EXPECT_FALSE(is_dirty());
702 EXPECT_TRUE(remove_snap.size() > 0);
703 EXPECT_TRUE(t.empty());
704 EXPECT_FALSE(missing.have_missing());
705 EXPECT_EQ(1U, log.log.size());
706 }
707
708 // there is no new entry (from the logs) and
709 // the old entry (from the log entry given in argument) is not a CLONE and
710 // the old entry prior_version is greater than the tail of the log :
711 // do nothing and return false
712 {
713 clear();
714
715 ObjectStore::Transaction t;
716 pg_log_entry_t oe;
717 oe.mark_unrollbackable();
718 pg_info_t info;
719 list<hobject_t> remove_snap;
720
721 info.log_tail = eversion_t(1,1);
722 oe.op = pg_log_entry_t::MODIFY;
723 oe.prior_version = eversion_t(2,1);
724 missing_add(oe.soid, oe.prior_version, eversion_t());
725
726 missing.flush();
727 EXPECT_FALSE(is_dirty());
728 EXPECT_TRUE(remove_snap.empty());
729 EXPECT_TRUE(t.empty());
730 EXPECT_TRUE(log.empty());
731
732 TestHandler h(remove_snap);
733 merge_old_entry(t, oe, info, &h);
734
735 missing.flush();
736 EXPECT_FALSE(is_dirty());
737 EXPECT_TRUE(remove_snap.empty());
738 EXPECT_TRUE(t.empty());
739 EXPECT_TRUE(log.empty());
740 }
741
742 // there is no new entry (from the logs) and
743 // the old entry (from the log entry given in argument) is not a CLONE and
744 // the old entry (from the log entry given in argument) is not a DELETE and
745 // the old entry prior_version is lower than the tail of the log :
746 // add the old object to the remove_snap list and
747 // add the old object to divergent priors and
748 // add or update the prior_version of the object to missing and
749 // return false
750 {
751 clear();
752
753 ObjectStore::Transaction t;
754 pg_log_entry_t oe;
755 oe.mark_unrollbackable();
756 pg_info_t info;
757 list<hobject_t> remove_snap;
758
759 info.log_tail = eversion_t(2,1);
760 oe.soid.set_hash(1);
761 oe.op = pg_log_entry_t::MODIFY;
762 oe.prior_version = eversion_t(1,1);
763
764 EXPECT_FALSE(is_dirty());
765 EXPECT_TRUE(remove_snap.empty());
766 EXPECT_TRUE(t.empty());
767 EXPECT_FALSE(missing.have_missing());
768 EXPECT_TRUE(log.empty());
769
770 TestHandler h(remove_snap);
771 merge_old_entry(t, oe, info, &h);
772
773 EXPECT_TRUE(is_dirty());
774 EXPECT_EQ(oe.soid, remove_snap.front());
775 EXPECT_TRUE(t.empty());
776 EXPECT_TRUE(missing.is_missing(oe.soid));
777 EXPECT_TRUE(log.empty());
778 }
779
780 // there is no new entry (from the logs) and
781 // the old entry (from the log entry given in argument) is not a CLONE and
782 // the old entry (from the log entry given in argument) is a DELETE and
783 // the old entry prior_version is lower than the tail of the log :
784 // add the old object to divergent priors and
785 // add or update the prior_version of the object to missing and
786 // return false
787 {
788 clear();
789
790 ObjectStore::Transaction t;
791 pg_log_entry_t oe;
792 oe.mark_unrollbackable();
793 pg_info_t info;
794 list<hobject_t> remove_snap;
795
796 info.log_tail = eversion_t(2,1);
797 oe.soid.set_hash(1);
798 oe.op = pg_log_entry_t::DELETE;
799 oe.prior_version = eversion_t(1,1);
800
801 EXPECT_FALSE(is_dirty());
802 EXPECT_TRUE(remove_snap.empty());
803 EXPECT_TRUE(t.empty());
804 EXPECT_FALSE(missing.have_missing());
805 EXPECT_TRUE(log.empty());
806
807 TestHandler h(remove_snap);
808 merge_old_entry(t, oe, info, &h);
809
810 EXPECT_TRUE(is_dirty());
811 EXPECT_TRUE(remove_snap.empty());
812 EXPECT_TRUE(t.empty());
813 EXPECT_TRUE(missing.is_missing(oe.soid));
814 EXPECT_TRUE(log.empty());
815 }
816
817
818 // there is no new entry (from the logs) and
819 // the old entry (from the log entry given in argument) is not a CLONE and
820 // the old entry (from the log entry given in argument) is not a DELETE and
821 // the old entry prior_version is eversion_t() :
822 // add the old object to the remove_snap list and
823 // remove the prior_version of the object from missing, if any and
824 // return false
825 {
826 clear();
827
828 ObjectStore::Transaction t;
829 pg_log_entry_t oe;
830 oe.mark_unrollbackable();
831 pg_info_t info;
832 list<hobject_t> remove_snap;
833
834 info.log_tail = eversion_t(10,1);
835 oe.soid.set_hash(1);
836 oe.op = pg_log_entry_t::MODIFY;
837 oe.prior_version = eversion_t();
838
839 missing.add(oe.soid, eversion_t(1,1), eversion_t(), false);
840
841 missing.flush();
842 EXPECT_FALSE(is_dirty());
843 EXPECT_TRUE(remove_snap.empty());
844 EXPECT_TRUE(t.empty());
845 EXPECT_TRUE(missing.is_missing(oe.soid));
846 EXPECT_TRUE(log.empty());
847
848 TestHandler h(remove_snap);
849 merge_old_entry(t, oe, info, &h);
850
851 missing.flush();
852 EXPECT_FALSE(is_dirty());
853 EXPECT_EQ(oe.soid, remove_snap.front());
854 EXPECT_TRUE(t.empty());
855 EXPECT_FALSE(missing.have_missing());
856 EXPECT_TRUE(log.empty());
857 }
858
859 }
860
861 TEST_F(PGLogTest, merge_log) {
862 // head and tail match, last_backfill is set:
863 // noop
864 {
865 clear();
866
867 pg_log_t olog;
868 pg_info_t oinfo;
869 pg_shard_t fromosd;
870 pg_info_t info;
871 list<hobject_t> remove_snap;
872 bool dirty_info = false;
873 bool dirty_big_info = false;
874
875 hobject_t last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
876 info.last_backfill = last_backfill;
877 eversion_t stat_version(10, 1);
878 info.stats.version = stat_version;
879 log.tail = olog.tail = eversion_t(1, 1);
880 log.head = olog.head = eversion_t(2, 1);
881
882 EXPECT_FALSE(missing.have_missing());
883 EXPECT_EQ(0U, log.log.size());
884 EXPECT_EQ(stat_version, info.stats.version);
885 EXPECT_TRUE(remove_snap.empty());
886 EXPECT_EQ(last_backfill, info.last_backfill);
887 EXPECT_TRUE(info.purged_snaps.empty());
888 EXPECT_FALSE(is_dirty());
889 EXPECT_FALSE(dirty_info);
890 EXPECT_FALSE(dirty_big_info);
891
892 TestHandler h(remove_snap);
893 merge_log(oinfo, olog, fromosd, info, &h,
894 dirty_info, dirty_big_info);
895
896 EXPECT_FALSE(missing.have_missing());
897 EXPECT_EQ(0U, log.log.size());
898 EXPECT_EQ(stat_version, info.stats.version);
899 EXPECT_TRUE(remove_snap.empty());
900 EXPECT_TRUE(info.purged_snaps.empty());
901 EXPECT_FALSE(is_dirty());
902 EXPECT_FALSE(dirty_info);
903 EXPECT_FALSE(dirty_big_info);
904 }
905
906 // head and tail match, last_backfill is not set: info.stats is
907 // copied from oinfo.stats but info.stats.reported_* is guaranteed to
908 // never be replaced by a lower version
909 {
910 clear();
911
912 pg_log_t olog;
913 pg_info_t oinfo;
914 pg_shard_t fromosd;
915 pg_info_t info;
916 list<hobject_t> remove_snap;
917 bool dirty_info = false;
918 bool dirty_big_info = false;
919
920 eversion_t stat_version(10, 1);
921 oinfo.stats.version = stat_version;
922 info.stats.reported_seq = 1;
923 info.stats.reported_epoch = 10;
924 oinfo.stats.reported_seq = 1;
925 oinfo.stats.reported_epoch = 1;
926 log.tail = olog.tail = eversion_t(1, 1);
927 log.head = olog.head = eversion_t(2, 1);
928 missing.may_include_deletes = false;
929
930 EXPECT_FALSE(missing.have_missing());
931 EXPECT_EQ(0U, log.log.size());
932 EXPECT_EQ(eversion_t(), info.stats.version);
933 EXPECT_EQ(1ull, info.stats.reported_seq);
934 EXPECT_EQ(10u, info.stats.reported_epoch);
935 EXPECT_TRUE(remove_snap.empty());
936 EXPECT_TRUE(info.last_backfill.is_max());
937 EXPECT_TRUE(info.purged_snaps.empty());
938 EXPECT_FALSE(is_dirty());
939 EXPECT_FALSE(dirty_info);
940 EXPECT_FALSE(dirty_big_info);
941
942 TestHandler h(remove_snap);
943 merge_log(oinfo, olog, fromosd, info, &h,
944 dirty_info, dirty_big_info);
945
946 EXPECT_FALSE(missing.have_missing());
947 EXPECT_EQ(0U, log.log.size());
948 EXPECT_EQ(stat_version, info.stats.version);
949 EXPECT_EQ(1ull, info.stats.reported_seq);
950 EXPECT_EQ(10u, info.stats.reported_epoch);
951 EXPECT_TRUE(remove_snap.empty());
952 EXPECT_TRUE(info.purged_snaps.empty());
953 EXPECT_FALSE(is_dirty());
954 EXPECT_FALSE(dirty_info);
955 EXPECT_FALSE(dirty_big_info);
956 }
957
958 /* Before
959 +--------------------------+
960 | log olog |
961 +--------+-------+---------+
962 | |object | |
963 |version | hash | version |
964 | | | |
965 | | x5 | (1,1) < tail
966 | | | |
967 | | | |
968 tail > (1,4) | x7 | |
969 | | | |
970 | | | |
971 head > (1,5) | x9 | (1,5) < head
972 | | | |
973 | | | |
974 +--------+-------+---------+
975
976 After
977 +-----------------
978 | log |
979 +--------+-------+
980 | |object |
981 |version | hash |
982 | | |
983 tail > (1,1) | x5 |
984 | | |
985 | | |
986 | (1,4) | x7 |
987 | | |
988 | | |
989 head > (1,5) | x9 |
990 | | |
991 | | |
992 +--------+-------+
993 */
994 {
995 clear();
996
997 pg_log_t olog;
998 pg_info_t oinfo;
999 pg_shard_t fromosd;
1000 pg_info_t info;
1001 list<hobject_t> remove_snap;
1002 bool dirty_info = false;
1003 bool dirty_big_info = false;
1004 missing.may_include_deletes = false;
1005
1006 {
1007 pg_log_entry_t e;
1008 e.mark_unrollbackable();
1009
1010 e.version = eversion_t(1, 4);
1011 e.soid.set_hash(0x5);
1012 log.tail = e.version;
1013 log.log.push_back(e);
1014 e.version = eversion_t(1, 5);
1015 e.soid.set_hash(0x9);
1016 log.log.push_back(e);
1017 log.head = e.version;
1018 log.index();
1019
1020 info.last_update = log.head;
1021
1022 e.version = eversion_t(1, 1);
1023 e.soid.set_hash(0x5);
1024 olog.tail = e.version;
1025 olog.log.push_back(e);
1026 e.version = eversion_t(1, 5);
1027 e.soid.set_hash(0x9);
1028 olog.log.push_back(e);
1029 olog.head = e.version;
1030 }
1031
1032 hobject_t last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
1033 info.last_backfill = last_backfill;
1034 eversion_t stat_version(10, 1);
1035 info.stats.version = stat_version;
1036
1037 EXPECT_FALSE(missing.have_missing());
1038 EXPECT_EQ(2U, log.log.size());
1039 EXPECT_EQ(stat_version, info.stats.version);
1040 EXPECT_TRUE(remove_snap.empty());
1041 EXPECT_EQ(last_backfill, info.last_backfill);
1042 EXPECT_TRUE(info.purged_snaps.empty());
1043 EXPECT_FALSE(is_dirty());
1044 EXPECT_FALSE(dirty_info);
1045 EXPECT_FALSE(dirty_big_info);
1046
1047 TestHandler h(remove_snap);
1048 merge_log(oinfo, olog, fromosd, info, &h,
1049 dirty_info, dirty_big_info);
1050
1051 EXPECT_FALSE(missing.have_missing());
1052 EXPECT_EQ(3U, log.log.size());
1053 EXPECT_EQ(stat_version, info.stats.version);
1054 EXPECT_TRUE(remove_snap.empty());
1055 EXPECT_TRUE(info.purged_snaps.empty());
1056 EXPECT_TRUE(is_dirty());
1057 EXPECT_TRUE(dirty_info);
1058 EXPECT_TRUE(dirty_big_info);
1059 }
1060
1061 /* +--------------------------+
1062 | log olog |
1063 +--------+-------+---------+
1064 | |object | |
1065 |version | hash | version |
1066 | | | |
1067 tail > (1,1) | x5 | (1,1) < tail
1068 | | | |
1069 | | | |
1070 | (1,2) | x3 | (1,2) < lower_bound
1071 | | | |
1072 | | | |
1073 head > (1,3) | x9 | |
1074 | DELETE | | |
1075 | | | |
1076 | | x9 | (2,3) |
1077 | | | MODIFY |
1078 | | | |
1079 | | x7 | (2,4) < head
1080 | | | DELETE |
1081 +--------+-------+---------+
1082
1083 The log entry (1,3) deletes the object x9 but the olog entry (2,3) modifies
1084 it and is authoritative : the log entry (1,3) is divergent.
1085
1086 */
1087 {
1088 clear();
1089
1090 pg_log_t olog;
1091 pg_info_t oinfo;
1092 pg_shard_t fromosd;
1093 pg_info_t info;
1094 list<hobject_t> remove_snap;
1095 bool dirty_info = false;
1096 bool dirty_big_info = false;
1097
1098 hobject_t divergent_object;
1099 missing.may_include_deletes = true;
1100
1101 {
1102 pg_log_entry_t e;
1103 e.mark_unrollbackable();
1104
1105 e.version = eversion_t(1, 1);
1106 e.soid.set_hash(0x5);
1107 log.tail = e.version;
1108 log.log.push_back(e);
1109 e.version = eversion_t(1, 2);
1110 e.soid.set_hash(0x3);
1111 log.log.push_back(e);
1112 e.version = eversion_t(1,3);
1113 e.soid.set_hash(0x9);
1114 divergent_object = e.soid;
1115 e.op = pg_log_entry_t::DELETE;
1116 log.log.push_back(e);
1117 log.head = e.version;
1118 log.index();
1119
1120 info.last_update = log.head;
1121
1122 e.version = eversion_t(1, 1);
1123 e.soid.set_hash(0x5);
1124 olog.tail = e.version;
1125 olog.log.push_back(e);
1126 e.version = eversion_t(1, 2);
1127 e.soid.set_hash(0x3);
1128 olog.log.push_back(e);
1129 e.version = eversion_t(2, 3);
1130 e.soid.set_hash(0x9);
1131 e.op = pg_log_entry_t::MODIFY;
1132 olog.log.push_back(e);
1133 e.version = eversion_t(2, 4);
1134 e.soid.set_hash(0x7);
1135 e.op = pg_log_entry_t::DELETE;
1136 olog.log.push_back(e);
1137 olog.head = e.version;
1138 }
1139
1140 snapid_t purged_snap(1);
1141 {
1142 oinfo.last_update = olog.head;
1143 oinfo.purged_snaps.insert(purged_snap);
1144 }
1145
1146 EXPECT_FALSE(missing.have_missing());
1147 EXPECT_EQ(1U, log.objects.count(divergent_object));
1148 EXPECT_EQ(3U, log.log.size());
1149 EXPECT_TRUE(remove_snap.empty());
1150 EXPECT_EQ(log.head, info.last_update);
1151 EXPECT_TRUE(info.purged_snaps.empty());
1152 EXPECT_FALSE(is_dirty());
1153 EXPECT_FALSE(dirty_info);
1154 EXPECT_FALSE(dirty_big_info);
1155
1156 TestHandler h(remove_snap);
1157 merge_log(oinfo, olog, fromosd, info, &h,
1158 dirty_info, dirty_big_info);
1159
1160 /* When the divergent entry is a DELETE and the authoritative
1161 entry is a MODIFY, the object will be added to missing : it is
1162 a verifiable side effect proving the entry was identified
1163 to be divergent.
1164 */
1165 EXPECT_TRUE(missing.is_missing(divergent_object));
1166 EXPECT_EQ(1U, log.objects.count(divergent_object));
1167 EXPECT_EQ(4U, log.log.size());
1168 /* DELETE entries from olog that are appended to the hed of the
1169 log, and the divergent version of the object is removed (added
1170 to remove_snap)
1171 */
1172 EXPECT_EQ(0x9U, remove_snap.front().get_hash());
1173 EXPECT_EQ(log.head, info.last_update);
1174 EXPECT_TRUE(info.purged_snaps.contains(purged_snap));
1175 EXPECT_TRUE(is_dirty());
1176 EXPECT_TRUE(dirty_info);
1177 EXPECT_TRUE(dirty_big_info);
1178 }
1179
1180 /* +--------------------------+
1181 | log olog |
1182 +--------+-------+---------+
1183 | |object | |
1184 |version | hash | version |
1185 | | | |
1186 tail > (1,1) | x5 | (1,1) < tail
1187 | | | |
1188 | | | |
1189 | (1,2) | x3 | (1,2) < lower_bound
1190 | | | |
1191 | | | |
1192 head > (1,3) | x9 | |
1193 | DELETE | | |
1194 | | | |
1195 | | x9 | (2,3) |
1196 | | | MODIFY |
1197 | | | |
1198 | | x7 | (2,4) < head
1199 | | | DELETE |
1200 +--------+-------+---------+
1201
1202 The log entry (1,3) deletes the object x9 but the olog entry (2,3) modifies
1203 it and is authoritative : the log entry (1,3) is divergent.
1204
1205 */
1206 {
1207 clear();
1208
1209 pg_log_t olog;
1210 pg_info_t oinfo;
1211 pg_shard_t fromosd;
1212 pg_info_t info;
1213 list<hobject_t> remove_snap;
1214 bool dirty_info = false;
1215 bool dirty_big_info = false;
1216
1217 hobject_t divergent_object;
1218
1219 {
1220 pg_log_entry_t e;
1221 e.mark_unrollbackable();
1222
1223 e.version = eversion_t(1, 1);
1224 e.soid.set_hash(0x5);
1225 log.tail = e.version;
1226 log.log.push_back(e);
1227 e.version = eversion_t(1, 2);
1228 e.soid.set_hash(0x3);
1229 log.log.push_back(e);
1230 e.version = eversion_t(1,3);
1231 e.soid.set_hash(0x9);
1232 divergent_object = e.soid;
1233 e.op = pg_log_entry_t::DELETE;
1234 log.log.push_back(e);
1235 log.head = e.version;
1236 log.index();
1237
1238 info.last_update = log.head;
1239
1240 e.version = eversion_t(1, 1);
1241 e.soid.set_hash(0x5);
1242 olog.tail = e.version;
1243 olog.log.push_back(e);
1244 e.version = eversion_t(1, 2);
1245 e.soid.set_hash(0x3);
1246 olog.log.push_back(e);
1247 e.version = eversion_t(2, 3);
1248 e.soid.set_hash(0x9);
1249 e.op = pg_log_entry_t::MODIFY;
1250 olog.log.push_back(e);
1251 e.version = eversion_t(2, 4);
1252 e.soid.set_hash(0x7);
1253 e.op = pg_log_entry_t::DELETE;
1254 olog.log.push_back(e);
1255 olog.head = e.version;
1256 }
1257
1258 snapid_t purged_snap(1);
1259 {
1260 oinfo.last_update = olog.head;
1261 oinfo.purged_snaps.insert(purged_snap);
1262 }
1263
1264 EXPECT_FALSE(missing.have_missing());
1265 EXPECT_EQ(1U, log.objects.count(divergent_object));
1266 EXPECT_EQ(3U, log.log.size());
1267 EXPECT_TRUE(remove_snap.empty());
1268 EXPECT_EQ(log.head, info.last_update);
1269 EXPECT_TRUE(info.purged_snaps.empty());
1270 EXPECT_FALSE(is_dirty());
1271 EXPECT_FALSE(dirty_info);
1272 EXPECT_FALSE(dirty_big_info);
1273
1274 TestHandler h(remove_snap);
1275 missing.may_include_deletes = false;
1276 merge_log(oinfo, olog, fromosd, info, &h,
1277 dirty_info, dirty_big_info);
1278
1279 /* When the divergent entry is a DELETE and the authoritative
1280 entry is a MODIFY, the object will be added to missing : it is
1281 a verifiable side effect proving the entry was identified
1282 to be divergent.
1283 */
1284 EXPECT_TRUE(missing.is_missing(divergent_object));
1285 EXPECT_EQ(1U, log.objects.count(divergent_object));
1286 EXPECT_EQ(4U, log.log.size());
1287 /* DELETE entries from olog that are appended to the hed of the
1288 log, and the divergent version of the object is removed (added
1289 to remove_snap). When peering handles deletes, it is the earlier
1290 version that is in the removed list.
1291 */
1292 EXPECT_EQ(0x7U, remove_snap.front().get_hash());
1293 EXPECT_EQ(log.head, info.last_update);
1294 EXPECT_TRUE(info.purged_snaps.contains(purged_snap));
1295 EXPECT_TRUE(is_dirty());
1296 EXPECT_TRUE(dirty_info);
1297 EXPECT_TRUE(dirty_big_info);
1298 }
1299
1300 /* +--------------------------+
1301 | log olog |
1302 +--------+-------+---------+
1303 | |object | |
1304 |version | hash | version |
1305 | | | |
1306 tail > (1,1) | x5 | (1,1) < tail
1307 | | | |
1308 | | | |
1309 | (1,4) | x7 | (1,4) < head
1310 | | | |
1311 | | | |
1312 head > (1,5) | x9 | |
1313 | | | |
1314 | | | |
1315 +--------+-------+---------+
1316
1317 The head of the log entry (1,5) is divergent because it is greater than the
1318 head of olog.
1319
1320 */
1321 {
1322 clear();
1323
1324 pg_log_t olog;
1325 pg_info_t oinfo;
1326 pg_shard_t fromosd;
1327 pg_info_t info;
1328 list<hobject_t> remove_snap;
1329 bool dirty_info = false;
1330 bool dirty_big_info = false;
1331
1332 {
1333 pg_log_entry_t e;
1334 e.mark_unrollbackable();
1335
1336 e.version = eversion_t(1, 1);
1337 e.soid.set_hash(0x5);
1338 log.tail = e.version;
1339 log.log.push_back(e);
1340 e.version = eversion_t(1, 4);
1341 e.soid.set_hash(0x7);
1342 log.log.push_back(e);
1343 e.version = eversion_t(1, 5);
1344 e.soid.set_hash(0x9);
1345 log.log.push_back(e);
1346 log.head = e.version;
1347 log.index();
1348
1349 info.last_update = log.head;
1350
1351 e.version = eversion_t(1, 1);
1352 e.soid.set_hash(0x5);
1353 olog.tail = e.version;
1354 olog.log.push_back(e);
1355 e.version = eversion_t(1, 4);
1356 e.soid.set_hash(0x7);
1357 olog.log.push_back(e);
1358 olog.head = e.version;
1359 }
1360
1361 hobject_t last_backfill(object_t("oname"), string("key"), 1, 234, 1, "");
1362 info.last_backfill = last_backfill;
1363 eversion_t stat_version(10, 1);
1364 info.stats.version = stat_version;
1365
1366 EXPECT_FALSE(missing.have_missing());
1367 EXPECT_EQ(3U, log.log.size());
1368 EXPECT_EQ(stat_version, info.stats.version);
1369 EXPECT_TRUE(remove_snap.empty());
1370 EXPECT_EQ(last_backfill, info.last_backfill);
1371 EXPECT_TRUE(info.purged_snaps.empty());
1372 EXPECT_FALSE(is_dirty());
1373 EXPECT_FALSE(dirty_info);
1374 EXPECT_FALSE(dirty_big_info);
1375
1376 TestHandler h(remove_snap);
1377 missing.may_include_deletes = false;
1378 merge_log(oinfo, olog, fromosd, info, &h,
1379 dirty_info, dirty_big_info);
1380
1381 EXPECT_FALSE(missing.have_missing());
1382 EXPECT_EQ(2U, log.log.size());
1383 EXPECT_EQ(stat_version, info.stats.version);
1384 EXPECT_EQ(0x9U, remove_snap.front().get_hash());
1385 EXPECT_TRUE(info.purged_snaps.empty());
1386 EXPECT_TRUE(is_dirty());
1387 EXPECT_TRUE(dirty_info);
1388 EXPECT_TRUE(dirty_big_info);
1389 }
1390
1391 // If our log is empty, the incoming log needs to have not been trimmed.
1392 {
1393 clear();
1394
1395 pg_log_t olog;
1396 pg_info_t oinfo;
1397 pg_shard_t fromosd;
1398 pg_info_t info;
1399 list<hobject_t> remove_snap;
1400 bool dirty_info = false;
1401 bool dirty_big_info = false;
1402
1403 // olog has been trimmed
1404 olog.tail = eversion_t(1, 1);
1405
1406 TestHandler h(remove_snap);
1407 PrCtl unset_dumpable;
1408 ASSERT_DEATH(merge_log(oinfo, olog, fromosd, info, &h,
1409 dirty_info, dirty_big_info), "");
1410 }
1411
1412 }
1413
1414 TEST_F(PGLogTest, proc_replica_log) {
1415 // empty log : no side effect
1416 {
1417 clear();
1418
1419 pg_log_t olog;
1420 pg_info_t oinfo;
1421 pg_missing_t omissing;
1422 pg_shard_t from;
1423
1424 eversion_t last_update(1, 1);
1425 log.head = olog.head = oinfo.last_update = last_update;
1426 eversion_t last_complete(1, 1);
1427 oinfo.last_complete = last_complete;
1428
1429 EXPECT_FALSE(omissing.have_missing());
1430 EXPECT_EQ(last_update, oinfo.last_update);
1431 EXPECT_EQ(last_complete, oinfo.last_complete);
1432
1433 missing.may_include_deletes = false;
1434 proc_replica_log(oinfo, olog, omissing, from);
1435
1436 EXPECT_FALSE(omissing.have_missing());
1437 EXPECT_EQ(last_update, oinfo.last_update);
1438 EXPECT_EQ(last_update, oinfo.last_complete);
1439 }
1440
1441 /* +--------------------------+
1442 | log olog |
1443 +--------+-------+---------+
1444 | |object | |
1445 |version | hash | version |
1446 | | | |
1447 | | x3 | (1,1) < tail
1448 | | | |
1449 | | | |
1450 tail > (1,2) | x5 | |
1451 | | | |
1452 | | | |
1453 head > (1,3) | x9 | |
1454 | DELETE | | |
1455 | | | |
1456 | | x9 | (2,3) < head
1457 | | | DELETE |
1458 | | | |
1459 +--------+-------+---------+
1460
1461 The log entry (1,3) deletes the object x9 and the olog entry
1462 (2,3) also deletes it : do nothing. The olog tail is ignored
1463 because it is before the log tail.
1464
1465 */
1466 {
1467 clear();
1468
1469 pg_log_t olog;
1470 pg_info_t oinfo;
1471 pg_missing_t omissing;
1472 pg_shard_t from;
1473
1474 {
1475 pg_log_entry_t e;
1476 e.mark_unrollbackable();
1477
1478 e.version = eversion_t(1, 2);
1479 e.soid.set_hash(0x5);
1480 log.tail = e.version;
1481 log.log.push_back(e);
1482 e.version = eversion_t(1, 3);
1483 e.soid.set_hash(0x9);
1484 e.op = pg_log_entry_t::DELETE;
1485 log.log.push_back(e);
1486 log.head = e.version;
1487 log.index();
1488
1489 e.version = eversion_t(1, 1);
1490 e.soid.set_hash(0x3);
1491 olog.tail = e.version;
1492 olog.log.push_back(e);
1493 e.version = eversion_t(2, 3);
1494 e.soid.set_hash(0x9);
1495 e.op = pg_log_entry_t::DELETE;
1496 olog.log.push_back(e);
1497 olog.head = e.version;
1498
1499 oinfo.last_update = olog.head;
1500 oinfo.last_complete = olog.head;
1501 }
1502
1503 EXPECT_FALSE(omissing.have_missing());
1504 EXPECT_EQ(olog.head, oinfo.last_update);
1505 EXPECT_EQ(olog.head, oinfo.last_complete);
1506
1507 missing.may_include_deletes = false;
1508 proc_replica_log(oinfo, olog, omissing, from);
1509
1510 EXPECT_FALSE(omissing.have_missing());
1511 }
1512
1513 {
1514 clear();
1515
1516 pg_log_t olog;
1517 pg_info_t oinfo;
1518 pg_missing_t omissing;
1519 pg_shard_t from;
1520
1521 hobject_t divergent_object;
1522
1523 {
1524 pg_log_entry_t e;
1525 e.mark_unrollbackable();
1526
1527 {
1528 e.soid = divergent_object;
1529 e.soid.set_hash(0x1);
1530 e.version = eversion_t(1, 1);
1531 log.tail = e.version;
1532 log.log.push_back(e);
1533
1534 e.soid = divergent_object;
1535 e.prior_version = eversion_t(1, 1);
1536 e.version = eversion_t(1, 2);
1537 log.tail = e.version;
1538 log.log.push_back(e);
1539
1540 e.soid.set_hash(0x3);
1541 e.version = eversion_t(1, 4);
1542 log.log.push_back(e);
1543
1544 e.soid.set_hash(0x7);
1545 e.version = eversion_t(1, 5);
1546 log.log.push_back(e);
1547
1548 e.soid.set_hash(0x8);
1549 e.version = eversion_t(1, 6);
1550 log.log.push_back(e);
1551
1552 e.soid.set_hash(0x9);
1553 e.op = pg_log_entry_t::DELETE;
1554 e.version = eversion_t(2, 7);
1555 log.log.push_back(e);
1556
1557 e.soid.set_hash(0xa);
1558 e.version = eversion_t(2, 8);
1559 log.head = e.version;
1560 log.log.push_back(e);
1561 }
1562 log.index();
1563
1564 {
1565 e.soid = divergent_object;
1566 e.soid.set_hash(0x1);
1567 e.version = eversion_t(1, 1);
1568 olog.tail = e.version;
1569 olog.log.push_back(e);
1570
1571 e.soid = divergent_object;
1572 e.prior_version = eversion_t(1, 1);
1573 e.version = eversion_t(1, 2);
1574 olog.log.push_back(e);
1575
1576 e.prior_version = eversion_t(0, 0);
1577 e.soid.set_hash(0x3);
1578 e.version = eversion_t(1, 4);
1579 olog.log.push_back(e);
1580
1581 e.soid.set_hash(0x7);
1582 e.version = eversion_t(1, 5);
1583 olog.log.push_back(e);
1584
1585 e.soid.set_hash(0x8);
1586 e.version = eversion_t(1, 6);
1587 olog.log.push_back(e);
1588
1589 e.soid.set_hash(0x9); // should not be added to missing, create
1590 e.op = pg_log_entry_t::MODIFY;
1591 e.version = eversion_t(1, 7);
1592 olog.log.push_back(e);
1593
1594 e.soid = divergent_object; // should be added to missing at 1,2
1595 e.op = pg_log_entry_t::MODIFY;
1596 e.version = eversion_t(1, 8);
1597 e.prior_version = eversion_t(1, 2);
1598 olog.log.push_back(e);
1599 olog.head = e.version;
1600 }
1601 oinfo.last_update = olog.head;
1602 oinfo.last_complete = olog.head;
1603 }
1604
1605 EXPECT_FALSE(omissing.have_missing());
1606 EXPECT_EQ(olog.head, oinfo.last_update);
1607 EXPECT_EQ(olog.head, oinfo.last_complete);
1608
1609 missing.may_include_deletes = false;
1610 proc_replica_log(oinfo, olog, omissing, from);
1611
1612 EXPECT_TRUE(omissing.have_missing());
1613 EXPECT_TRUE(omissing.is_missing(divergent_object));
1614 EXPECT_EQ(eversion_t(1, 2), omissing.get_items().at(divergent_object).need);
1615 EXPECT_EQ(eversion_t(1, 6), oinfo.last_update);
1616 EXPECT_EQ(eversion_t(1, 1), oinfo.last_complete);
1617 }
1618
1619 /* +--------------------------+
1620 | olog log |
1621 +--------+-------+---------+
1622 | |object | |
1623 |version | hash | version |
1624 | | | |
1625 tail > (1,1) | x9 | (1,1) < tail
1626 | | | |
1627 | | | |
1628 | (1,2) | x3 | (1,2) |
1629 | | | |
1630 | | | |
1631 head > (1,3) | x9 | |
1632 | DELETE | | |
1633 | | | |
1634 | | x9 | (2,3) < head
1635 | | | DELETE |
1636 | | | |
1637 +--------+-------+---------+
1638
1639 The log entry (1,3) deletes the object x9 and the olog entry
1640 (2,3) also deletes it : do nothing.
1641
1642 */
1643 {
1644 clear();
1645
1646 pg_log_t olog;
1647 pg_info_t oinfo;
1648 pg_missing_t omissing;
1649 pg_shard_t from;
1650
1651 eversion_t last_update(1, 2);
1652 hobject_t divergent_object;
1653 divergent_object.set_hash(0x9);
1654
1655 {
1656 pg_log_entry_t e;
1657 e.mark_unrollbackable();
1658
1659 e.version = eversion_t(1, 1);
1660 e.soid = divergent_object;
1661 log.tail = e.version;
1662 log.log.push_back(e);
1663 e.version = last_update;
1664 e.soid.set_hash(0x3);
1665 log.log.push_back(e);
1666 e.version = eversion_t(2, 3);
1667 e.prior_version = eversion_t(1, 1);
1668 e.soid = divergent_object;
1669 e.op = pg_log_entry_t::DELETE;
1670 log.log.push_back(e);
1671 log.head = e.version;
1672 log.index();
1673
1674 e.version = eversion_t(1, 1);
1675 e.soid = divergent_object;
1676 olog.tail = e.version;
1677 olog.log.push_back(e);
1678 e.version = last_update;
1679 e.soid.set_hash(0x3);
1680 olog.log.push_back(e);
1681 e.version = eversion_t(1, 3);
1682 e.prior_version = eversion_t(1, 1);
1683 e.soid = divergent_object;
1684 e.op = pg_log_entry_t::DELETE;
1685 olog.log.push_back(e);
1686 olog.head = e.version;
1687
1688 oinfo.last_update = olog.head;
1689 oinfo.last_complete = olog.head;
1690 }
1691
1692 EXPECT_FALSE(omissing.have_missing());
1693 EXPECT_EQ(olog.head, oinfo.last_update);
1694 EXPECT_EQ(olog.head, oinfo.last_complete);
1695
1696 missing.may_include_deletes = false;
1697 proc_replica_log(oinfo, olog, omissing, from);
1698
1699 EXPECT_TRUE(omissing.have_missing());
1700 EXPECT_TRUE(omissing.is_missing(divergent_object));
1701 EXPECT_EQ(omissing.get_items().at(divergent_object).have, eversion_t(0, 0));
1702 EXPECT_EQ(omissing.get_items().at(divergent_object).need, eversion_t(1, 1));
1703 EXPECT_EQ(last_update, oinfo.last_update);
1704 }
1705
1706 /* +--------------------------+
1707 | olog log |
1708 +--------+-------+---------+
1709 | |object | |
1710 |version | hash | version |
1711 | | | |
1712 tail > (1,1) | x9 | (1,1) < tail
1713 | | | |
1714 | | | |
1715 | (1,2) | x3 | (1,2) |
1716 | | | |
1717 | | | |
1718 head > (1,3) | x9 | |
1719 | MODIFY | | |
1720 | | | |
1721 | | x9 | (2,3) < head
1722 | | | DELETE |
1723 | | | |
1724 +--------+-------+---------+
1725
1726 The log entry (1,3) deletes the object x9 but the olog entry
1727 (2,3) modifies it : remove it from omissing.
1728
1729 */
1730 {
1731 clear();
1732
1733 pg_log_t olog;
1734 pg_info_t oinfo;
1735 pg_missing_t omissing;
1736 pg_shard_t from;
1737
1738 eversion_t last_update(1, 2);
1739 hobject_t divergent_object;
1740
1741 {
1742 pg_log_entry_t e;
1743 e.mark_unrollbackable();
1744
1745 e.version = eversion_t(1, 1);
1746 e.soid = divergent_object;
1747 log.tail = e.version;
1748 log.log.push_back(e);
1749 e.version = last_update;
1750 e.soid.set_hash(0x3);
1751 log.log.push_back(e);
1752 e.version = eversion_t(2, 3);
1753 e.prior_version = eversion_t(1, 1);
1754 e.soid = divergent_object;
1755 e.op = pg_log_entry_t::DELETE;
1756 log.log.push_back(e);
1757 log.head = e.version;
1758 log.index();
1759
1760 e.version = eversion_t(1, 1);
1761 e.soid = divergent_object;
1762 olog.tail = e.version;
1763 olog.log.push_back(e);
1764 e.version = last_update;
1765 e.soid.set_hash(0x3);
1766 olog.log.push_back(e);
1767 e.version = eversion_t(1, 3);
1768 e.prior_version = eversion_t(1, 1);
1769 e.soid = divergent_object;
1770 divergent_object = e.soid;
1771 omissing.add(divergent_object, e.version, eversion_t(), false);
1772 e.op = pg_log_entry_t::MODIFY;
1773 olog.log.push_back(e);
1774 olog.head = e.version;
1775
1776 oinfo.last_update = olog.head;
1777 oinfo.last_complete = olog.head;
1778 }
1779
1780 EXPECT_TRUE(omissing.have_missing());
1781 EXPECT_TRUE(omissing.is_missing(divergent_object));
1782 EXPECT_EQ(eversion_t(1, 3), omissing.get_items().at(divergent_object).need);
1783 EXPECT_EQ(olog.head, oinfo.last_update);
1784 EXPECT_EQ(olog.head, oinfo.last_complete);
1785
1786 missing.may_include_deletes = false;
1787 proc_replica_log(oinfo, olog, omissing, from);
1788
1789 EXPECT_TRUE(omissing.have_missing());
1790 EXPECT_TRUE(omissing.is_missing(divergent_object));
1791 EXPECT_EQ(omissing.get_items().at(divergent_object).have, eversion_t(0, 0));
1792 EXPECT_EQ(omissing.get_items().at(divergent_object).need, eversion_t(1, 1));
1793 EXPECT_EQ(last_update, oinfo.last_update);
1794 }
1795
1796 /* +--------------------------+
1797 | log olog |
1798 +--------+-------+---------+
1799 | |object | |
1800 |version | hash | version |
1801 | | | |
1802 tail > (1,1) | x9 | (1,1) < tail
1803 | | | |
1804 | | | |
1805 | (1,2) | x3 | (1,2) |
1806 | | | |
1807 | | | |
1808 | | x9 | (1,3) < head
1809 | | | MODIFY |
1810 | | | |
1811 head > (2,3) | x9 | |
1812 | DELETE | | |
1813 | | | |
1814 +--------+-------+---------+
1815
1816 The log entry (2,3) deletes the object x9 but the olog entry
1817 (1,3) modifies it : proc_replica_log should adjust missing to
1818 1,1 for that object until add_next_event in PG::activate processes
1819 the delete.
1820 */
1821 {
1822 clear();
1823
1824 pg_log_t olog;
1825 pg_info_t oinfo;
1826 pg_missing_t omissing;
1827 pg_shard_t from;
1828
1829 eversion_t last_update(1, 2);
1830 hobject_t divergent_object;
1831 eversion_t new_version(2, 3);
1832 eversion_t divergent_version(1, 3);
1833
1834 {
1835 pg_log_entry_t e;
1836 e.mark_unrollbackable();
1837
1838 e.version = eversion_t(1, 1);
1839 e.soid.set_hash(0x9);
1840 log.tail = e.version;
1841 log.log.push_back(e);
1842 e.version = last_update;
1843 e.soid.set_hash(0x3);
1844 log.log.push_back(e);
1845 e.version = new_version;
1846 e.prior_version = eversion_t(1, 1);
1847 e.soid.set_hash(0x9);
1848 e.op = pg_log_entry_t::DELETE;
1849 log.log.push_back(e);
1850 log.head = e.version;
1851 log.index();
1852
1853 e.op = pg_log_entry_t::MODIFY;
1854 e.version = eversion_t(1, 1);
1855 e.soid.set_hash(0x9);
1856 olog.tail = e.version;
1857 olog.log.push_back(e);
1858 e.version = last_update;
1859 e.soid.set_hash(0x3);
1860 olog.log.push_back(e);
1861 e.version = divergent_version;
1862 e.prior_version = eversion_t(1, 1);
1863 e.soid.set_hash(0x9);
1864 divergent_object = e.soid;
1865 omissing.add(divergent_object, e.version, eversion_t(), false);
1866 e.op = pg_log_entry_t::MODIFY;
1867 olog.log.push_back(e);
1868 olog.head = e.version;
1869
1870 oinfo.last_update = olog.head;
1871 oinfo.last_complete = olog.head;
1872 }
1873
1874 EXPECT_TRUE(omissing.have_missing());
1875 EXPECT_TRUE(omissing.is_missing(divergent_object));
1876 EXPECT_EQ(divergent_version, omissing.get_items().at(divergent_object).need);
1877 EXPECT_EQ(olog.head, oinfo.last_update);
1878 EXPECT_EQ(olog.head, oinfo.last_complete);
1879
1880 missing.may_include_deletes = false;
1881 proc_replica_log(oinfo, olog, omissing, from);
1882
1883 EXPECT_TRUE(omissing.have_missing());
1884 EXPECT_TRUE(omissing.get_items().begin()->second.need == eversion_t(1, 1));
1885 EXPECT_EQ(last_update, oinfo.last_update);
1886 EXPECT_EQ(eversion_t(0, 0), oinfo.last_complete);
1887 }
1888
1889 }
1890
1891 TEST_F(PGLogTest, merge_log_1) {
1892 TestCase t;
1893 t.base.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1894
1895 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1896
1897 t.final.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1898
1899 t.toremove.insert(mk_obj(1));
1900
1901 t.setup();
1902 run_test_case(t);
1903 }
1904
1905 TEST_F(PGLogTest, merge_log_2) {
1906 TestCase t;
1907 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1908
1909 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1910 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1911
1912 t.torollback.insert(
1913 t.torollback.begin(), t.div.rbegin(), t.div.rend());
1914
1915 t.setup();
1916 run_test_case(t);
1917 }
1918
1919 TEST_F(PGLogTest, merge_log_3) {
1920 TestCase t;
1921 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1922
1923 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1924 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1925
1926 t.final.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1927
1928 t.toremove.insert(mk_obj(1));
1929
1930 t.setup();
1931 run_test_case(t);
1932 }
1933
1934 TEST_F(PGLogTest, merge_log_4) {
1935 TestCase t;
1936 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1937
1938 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1939 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1940
1941 t.init.add(mk_obj(1), mk_evt(10, 102), mk_evt(0, 0), false);
1942 t.final.add(mk_obj(1), mk_evt(10, 100), mk_evt(0, 0), false);
1943
1944 t.setup();
1945 run_test_case(t);
1946 }
1947
1948 TEST_F(PGLogTest, merge_log_5) {
1949 TestCase t;
1950 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1951
1952 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
1953 t.div.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 102), mk_evt(10, 101)));
1954
1955 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1956
1957 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(0, 0), false);
1958
1959 t.toremove.insert(mk_obj(1));
1960
1961 t.setup();
1962 run_test_case(t);
1963 }
1964
1965 TEST_F(PGLogTest, merge_log_6) {
1966 TestCase t;
1967 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1968
1969 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1970
1971 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100), false);
1972
1973 t.setup();
1974 run_test_case(t);
1975 }
1976
1977 TEST_F(PGLogTest, merge_log_7) {
1978 TestCase t;
1979 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1980
1981 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1982
1983 t.init.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1984 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), false);
1985
1986 t.setup();
1987 run_test_case(t);
1988 }
1989
1990 TEST_F(PGLogTest, merge_log_8) {
1991 TestCase t;
1992 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
1993
1994 t.auth.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
1995
1996 t.init.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
1997 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), true);
1998
1999 t.setup();
2000 run_test_case(t);
2001 }
2002
2003 TEST_F(PGLogTest, merge_log_9) {
2004 TestCase t;
2005 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2006
2007 t.auth.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
2008
2009 t.init.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
2010 t.toremove.insert(mk_obj(1));
2011 t.deletes_during_peering = true;
2012
2013 t.setup();
2014 run_test_case(t);
2015 }
2016
2017 TEST_F(PGLogTest, merge_log_10) {
2018 TestCase t;
2019 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2020
2021 t.auth.push_back(mk_ple_ldt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100)));
2022
2023 t.init.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false);
2024 t.final.add(mk_obj(1), mk_evt(11, 101), mk_evt(8, 80), true);
2025
2026 t.setup();
2027 run_test_case(t);
2028 }
2029
2030 TEST_F(PGLogTest, merge_log_prior_version_have) {
2031 TestCase t;
2032 t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80)));
2033
2034 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100)));
2035
2036 t.init.add(mk_obj(1), mk_evt(10, 101), mk_evt(10, 100), false);
2037
2038 t.setup();
2039 run_test_case(t);
2040 }
2041
2042 TEST_F(PGLogTest, merge_log_split_missing_entries_at_head) {
2043 TestCase t;
2044 t.auth.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2045 t.auth.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2046
2047 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(8, 70), mk_evt(8, 65)));
2048
2049 t.setup();
2050 t.set_div_bounds(mk_evt(9, 79), mk_evt(8, 69));
2051 t.set_auth_bounds(mk_evt(15, 160), mk_evt(9, 77));
2052 t.final.add(mk_obj(1), mk_evt(15, 150), mk_evt(8, 70), false);
2053 run_test_case(t);
2054 }
2055
2056 TEST_F(PGLogTest, olog_tail_gt_log_tail_split) {
2057 TestCase t;
2058 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2059 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2060 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150)));
2061
2062 t.setup();
2063 t.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
2064 t.set_auth_bounds(mk_evt(15, 156), mk_evt(10, 99));
2065 t.final.add(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150), false);
2066 run_test_case(t);
2067 }
2068
2069 TEST_F(PGLogTest, olog_tail_gt_log_tail_split2) {
2070 TestCase t;
2071 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2072 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2073 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(16, 155), mk_evt(15, 150)));
2074 t.div.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 153), mk_evt(15, 150)));
2075
2076 t.setup();
2077 t.set_div_bounds(mk_evt(15, 153), mk_evt(15, 151));
2078 t.set_auth_bounds(mk_evt(16, 156), mk_evt(10, 99));
2079 t.final.add(mk_obj(1), mk_evt(16, 155), mk_evt(0, 0), false);
2080 t.toremove.insert(mk_obj(1));
2081 run_test_case(t);
2082 }
2083
2084 TEST_F(PGLogTest, filter_log_1) {
2085 {
2086 clear();
2087
2088 int osd_id = 1;
2089 epoch_t epoch = 40;
2090 int64_t pool_id = 1;
2091 int bits = 2;
2092 int max_osd = 4;
2093 int pg_num = max_osd << bits;
2094 int num_objects = 1000;
2095 int num_internal = 10;
2096
2097 // Set up splitting map
2098 OSDMap *osdmap = new OSDMap;
2099 uuid_d test_uuid;
2100 test_uuid.generate_random();
2101 osdmap->build_simple_with_pool(g_ceph_context, epoch, test_uuid, max_osd, bits, bits);
2102 osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
2103
2104 const string hit_set_namespace("internal");
2105
2106 {
2107 pg_log_entry_t e;
2108 e.mark_unrollbackable();
2109 e.op = pg_log_entry_t::MODIFY;
2110 e.soid.pool = pool_id;
2111
2112 uuid_d uuid_name;
2113 int i;
2114 for (i = 1; i <= num_objects; ++i) {
2115 e.version = eversion_t(epoch, i);
2116 // Use this to generate random file names
2117 uuid_name.generate_random();
2118 ostringstream name;
2119 name << uuid_name;
2120 e.soid.oid.name = name.str();
2121 // First has no namespace
2122 if (i != 1) {
2123 // num_internal have the internal namspace
2124 if (i <= num_internal + 1) {
2125 e.soid.nspace = hit_set_namespace;
2126 } else { // rest have different namespaces
2127 ostringstream ns;
2128 ns << "ns" << i;
2129 e.soid.nspace = ns.str();
2130 }
2131 }
2132 log.log.push_back(e);
2133 if (i == 1)
2134 log.tail = e.version;
2135 }
2136 log.head = e.version;
2137 log.index();
2138 }
2139
2140 spg_t pgid(pg_t(2, pool_id), shard_id_t::NO_SHARD);
2141
2142 // See if we created the right number of entries
2143 int total = log.log.size();
2144 ASSERT_EQ(total, num_objects);
2145
2146 // Some should be removed
2147 {
2148 pg_log_t filtered, reject;
2149 pg_log_t::filter_log(
2150 pgid, *osdmap, hit_set_namespace, log, filtered, reject);
2151 log = IndexedLog(filtered);
2152 }
2153 EXPECT_LE(log.log.size(), (size_t)total);
2154
2155 // If we filter a second time, there should be the same total
2156 total = log.log.size();
2157 {
2158 pg_log_t filtered, reject;
2159 pg_log_t::filter_log(
2160 pgid, *osdmap, hit_set_namespace, log, filtered, reject);
2161 log = IndexedLog(filtered);
2162 }
2163 EXPECT_EQ(log.log.size(), (size_t)total);
2164
2165 // Increase pg_num as if there would be a split
2166 int new_pg_num = pg_num * 16;
2167 OSDMap::Incremental inc(epoch + 1);
2168 inc.fsid = test_uuid;
2169 const pg_pool_t *pool = osdmap->get_pg_pool(pool_id);
2170 pg_pool_t newpool;
2171 newpool = *pool;
2172 newpool.set_pg_num(new_pg_num);
2173 newpool.set_pgp_num(new_pg_num);
2174 inc.new_pools[pool_id] = newpool;
2175 int ret = osdmap->apply_incremental(inc);
2176 ASSERT_EQ(ret, 0);
2177
2178 // We should have fewer entries after a filter
2179 {
2180 pg_log_t filtered, reject;
2181 pg_log_t::filter_log(
2182 pgid, *osdmap, hit_set_namespace, log, filtered, reject);
2183 log = IndexedLog(filtered);
2184 }
2185 EXPECT_LE(log.log.size(), (size_t)total);
2186
2187 // Make sure all internal entries are retained
2188 int count = 0;
2189 for (list<pg_log_entry_t>::iterator i = log.log.begin();
2190 i != log.log.end(); ++i) {
2191 if (i->soid.nspace == hit_set_namespace) count++;
2192 }
2193 EXPECT_EQ(count, num_internal);
2194 }
2195 }
2196
2197 TEST_F(PGLogTest, get_request) {
2198 clear();
2199
2200 // make sure writes, deletes, and errors are found
2201 vector<pg_log_entry_t> entries;
2202 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
2203 entries.push_back(
2204 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(6,2), eversion_t(3,4),
2205 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2206 utime_t(0,1), -ENOENT));
2207 entries.push_back(
2208 pg_log_entry_t(pg_log_entry_t::MODIFY, oid, eversion_t(6,3), eversion_t(3,4),
2209 2, osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2210 utime_t(1,2), 0));
2211 entries.push_back(
2212 pg_log_entry_t(pg_log_entry_t::DELETE, oid, eversion_t(7,4), eversion_t(7,4),
2213 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2214 utime_t(10,2), 0));
2215 entries.push_back(
2216 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(7,5), eversion_t(7,4),
2217 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2218 utime_t(20,1), -ENOENT));
2219
2220 for (auto &entry : entries) {
2221 log.add(entry);
2222 }
2223
2224 for (auto &entry : entries) {
2225 eversion_t replay_version;
2226 version_t user_version;
2227 int return_code = 0;
2228 bool got = log.get_request(
2229 entry.reqid, &replay_version, &user_version, &return_code);
2230 EXPECT_TRUE(got);
2231 EXPECT_EQ(entry.return_code, return_code);
2232 EXPECT_EQ(entry.version, replay_version);
2233 EXPECT_EQ(entry.user_version, user_version);
2234 }
2235 }
2236
2237 TEST_F(PGLogTest, ErrorNotIndexedByObject) {
2238 clear();
2239
2240 // make sure writes, deletes, and errors are found
2241 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
2242 log.add(
2243 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(6,2), eversion_t(3,4),
2244 1, osd_reqid_t(entity_name_t::CLIENT(777), 8, 1),
2245 utime_t(0,1), -ENOENT));
2246
2247 EXPECT_FALSE(log.logged_object(oid));
2248
2249 pg_log_entry_t modify(pg_log_entry_t::MODIFY, oid, eversion_t(6,3),
2250 eversion_t(3,4), 2,
2251 osd_reqid_t(entity_name_t::CLIENT(777), 8, 2),
2252 utime_t(1,2), 0);
2253 log.add(modify);
2254
2255 EXPECT_TRUE(log.logged_object(oid));
2256 pg_log_entry_t *entry = log.objects[oid];
2257 EXPECT_EQ(modify.op, entry->op);
2258 EXPECT_EQ(modify.version, entry->version);
2259 EXPECT_EQ(modify.prior_version, entry->prior_version);
2260 EXPECT_EQ(modify.user_version, entry->user_version);
2261 EXPECT_EQ(modify.reqid, entry->reqid);
2262
2263 pg_log_entry_t del(pg_log_entry_t::DELETE, oid, eversion_t(7,4),
2264 eversion_t(7,4), 3,
2265 osd_reqid_t(entity_name_t::CLIENT(777), 8, 3),
2266 utime_t(10,2), 0);
2267 log.add(del);
2268
2269 EXPECT_TRUE(log.logged_object(oid));
2270 entry = log.objects[oid];
2271 EXPECT_EQ(del.op, entry->op);
2272 EXPECT_EQ(del.version, entry->version);
2273 EXPECT_EQ(del.prior_version, entry->prior_version);
2274 EXPECT_EQ(del.user_version, entry->user_version);
2275 EXPECT_EQ(del.reqid, entry->reqid);
2276
2277 log.add(
2278 pg_log_entry_t(pg_log_entry_t::ERROR, oid, eversion_t(7,5), eversion_t(7,4),
2279 3, osd_reqid_t(entity_name_t::CLIENT(777), 8, 4),
2280 utime_t(20,1), -ENOENT));
2281
2282 EXPECT_TRUE(log.logged_object(oid));
2283 entry = log.objects[oid];
2284 EXPECT_EQ(del.op, entry->op);
2285 EXPECT_EQ(del.version, entry->version);
2286 EXPECT_EQ(del.prior_version, entry->prior_version);
2287 EXPECT_EQ(del.user_version, entry->user_version);
2288 EXPECT_EQ(del.reqid, entry->reqid);
2289 }
2290
2291 TEST_F(PGLogTest, split_into_preserves_may_include_deletes) {
2292 clear();
2293
2294 {
2295 rebuilt_missing_with_deletes = false;
2296 missing.may_include_deletes = true;
2297 PGLog child_log(cct, prefix_provider);
2298 pg_t child_pg;
2299 split_into(child_pg, 6, &child_log);
2300 ASSERT_TRUE(child_log.get_missing().may_include_deletes);
2301 ASSERT_TRUE(child_log.get_rebuilt_missing_with_deletes());
2302 }
2303
2304 {
2305 rebuilt_missing_with_deletes = false;
2306 missing.may_include_deletes = false;
2307 PGLog child_log(cct, prefix_provider);
2308 pg_t child_pg;
2309 split_into(child_pg, 6, &child_log);
2310 ASSERT_FALSE(child_log.get_missing().may_include_deletes);
2311 ASSERT_FALSE(child_log.get_rebuilt_missing_with_deletes());
2312 }
2313 }
2314
2315 class PGLogTestRebuildMissing : public PGLogTest, public StoreTestFixture {
2316 public:
2317 PGLogTestRebuildMissing() : PGLogTest(), StoreTestFixture("memstore") {}
2318 void SetUp() override {
2319 StoreTestFixture::SetUp();
2320 ObjectStore::Sequencer osr(__func__);
2321 ObjectStore::Transaction t;
2322 test_coll = coll_t(spg_t(pg_t(1, 1)));
2323 t.create_collection(test_coll, 0);
2324 store->apply_transaction(&osr, std::move(t));
2325 existing_oid = mk_obj(0);
2326 nonexistent_oid = mk_obj(1);
2327 ghobject_t existing_ghobj(existing_oid);
2328 object_info_t existing_info;
2329 existing_info.version = eversion_t(6, 2);
2330 bufferlist enc_oi;
2331 ::encode(existing_info, enc_oi, 0);
2332 ObjectStore::Transaction t2;
2333 t2.touch(test_coll, ghobject_t(existing_oid));
2334 t2.setattr(test_coll, ghobject_t(existing_oid), OI_ATTR, enc_oi);
2335 ASSERT_EQ(0u, store->apply_transaction(&osr, std::move(t2)));
2336 info.last_backfill = hobject_t::get_max();
2337 info.last_complete = eversion_t();
2338 }
2339
2340 void TearDown() override {
2341 clear();
2342 missing.may_include_deletes = false;
2343 StoreTestFixture::TearDown();
2344 }
2345
2346 pg_info_t info;
2347 coll_t test_coll;
2348 hobject_t existing_oid, nonexistent_oid;
2349
2350 void run_rebuild_missing_test(const map<hobject_t, pg_missing_item> &expected_missing_items) {
2351 rebuild_missing_set_with_deletes(store.get(), test_coll, info);
2352 ASSERT_EQ(expected_missing_items, missing.get_items());
2353 }
2354 };
2355
2356 TEST_F(PGLogTestRebuildMissing, EmptyLog) {
2357 missing.add(existing_oid, mk_evt(6, 2), mk_evt(6, 3), false);
2358 missing.add(nonexistent_oid, mk_evt(7, 4), mk_evt(0, 0), false);
2359 map<hobject_t, pg_missing_item> orig_missing = missing.get_items();
2360 run_rebuild_missing_test(orig_missing);
2361 }
2362
2363 TEST_F(PGLogTestRebuildMissing, SameVersionMod) {
2364 missing.add(existing_oid, mk_evt(6, 2), mk_evt(6, 1), false);
2365 log.add(mk_ple_mod(existing_oid, mk_evt(6, 2), mk_evt(6, 1)));
2366 map<hobject_t, pg_missing_item> empty_missing;
2367 run_rebuild_missing_test(empty_missing);
2368 }
2369
2370 TEST_F(PGLogTestRebuildMissing, DelExisting) {
2371 missing.add(existing_oid, mk_evt(6, 3), mk_evt(6, 2), false);
2372 log.add(mk_ple_dt(existing_oid, mk_evt(7, 5), mk_evt(7, 4)));
2373 map<hobject_t, pg_missing_item> expected;
2374 expected[existing_oid] = pg_missing_item(mk_evt(7, 5), mk_evt(6, 2), true);
2375 run_rebuild_missing_test(expected);
2376 }
2377
2378 TEST_F(PGLogTestRebuildMissing, DelNonexistent) {
2379 log.add(mk_ple_dt(nonexistent_oid, mk_evt(7, 5), mk_evt(7, 4)));
2380 map<hobject_t, pg_missing_item> expected;
2381 expected[nonexistent_oid] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2382 run_rebuild_missing_test(expected);
2383 }
2384
2385 TEST_F(PGLogTestRebuildMissing, MissingNotInLog) {
2386 missing.add(mk_obj(10), mk_evt(8, 12), mk_evt(8, 10), false);
2387 log.add(mk_ple_dt(nonexistent_oid, mk_evt(7, 5), mk_evt(7, 4)));
2388 map<hobject_t, pg_missing_item> expected;
2389 expected[nonexistent_oid] = pg_missing_item(mk_evt(7, 5), mk_evt(0, 0), true);
2390 expected[mk_obj(10)] = pg_missing_item(mk_evt(8, 12), mk_evt(8, 10), false);
2391 run_rebuild_missing_test(expected);
2392 }
2393
2394
2395 class PGLogMergeDupsTest : public ::testing::Test, protected PGLog {
2396
2397 public:
2398
2399 PGLogMergeDupsTest() : PGLog(g_ceph_context) { }
2400
2401 void SetUp() override { }
2402
2403 void TearDown() override {
2404 clear();
2405 }
2406
2407 static pg_log_dup_t create_dup_entry(uint a, uint b) {
2408 // make each dup_entry unique by using different client id's
2409 static uint client_id = 777;
2410 return pg_log_dup_t(eversion_t(a, b),
2411 a,
2412 osd_reqid_t(entity_name_t::CLIENT(client_id++), 8, 1),
2413 0);
2414 }
2415
2416 static std::vector<pg_log_dup_t> example_dups_1() {
2417 std::vector<pg_log_dup_t> result = {
2418 create_dup_entry(10, 11),
2419 create_dup_entry(10, 12),
2420 create_dup_entry(11, 1),
2421 create_dup_entry(12, 3),
2422 create_dup_entry(13, 99)
2423 };
2424 return result;
2425 }
2426
2427 static std::vector<pg_log_dup_t> example_dups_2() {
2428 std::vector<pg_log_dup_t> result = {
2429 create_dup_entry(12, 3),
2430 create_dup_entry(13, 99),
2431 create_dup_entry(15, 11),
2432 create_dup_entry(16, 14),
2433 create_dup_entry(16, 32)
2434 };
2435 return result;
2436 }
2437
2438 void add_dups(uint a, uint b) {
2439 log.dups.push_back(create_dup_entry(a, b));
2440 }
2441
2442 void add_dups(const std::vector<pg_log_dup_t>& l) {
2443 for (auto& i : l) {
2444 log.dups.push_back(i);
2445 }
2446 }
2447
2448 static void add_dups(IndexedLog& log, const std::vector<pg_log_dup_t>& dups) {
2449 for (auto& i : dups) {
2450 log.dups.push_back(i);
2451 }
2452 }
2453
2454 void check_order() {
2455 eversion_t prev(0, 0);
2456
2457 for (auto& i : log.dups) {
2458 EXPECT_LT(prev, i.version) << "verify versions monotonically increase";
2459 prev = i.version;
2460 }
2461 }
2462
2463 void check_index() {
2464 EXPECT_EQ(log.dups.size(), log.dup_index.size());
2465 for (auto& i : log.dups) {
2466 EXPECT_EQ(1u, log.dup_index.count(i.reqid));
2467 }
2468 }
2469 };
2470
2471 TEST_F(PGLogMergeDupsTest, OtherEmpty) {
2472 log.tail = eversion_t(14, 5);
2473
2474 IndexedLog olog;
2475
2476 add_dups(example_dups_1());
2477 index();
2478
2479 bool changed = merge_log_dups(olog);
2480
2481 EXPECT_FALSE(changed);
2482 EXPECT_EQ(5u, log.dups.size());
2483
2484 if (5 == log.dups.size()) {
2485 EXPECT_EQ(10u, log.dups.front().version.epoch);
2486 EXPECT_EQ(11u, log.dups.front().version.version);
2487 EXPECT_EQ(13u, log.dups.back().version.epoch);
2488 EXPECT_EQ(99u, log.dups.back().version.version);
2489 }
2490
2491 check_order();
2492 check_index();
2493 }
2494
2495 TEST_F(PGLogMergeDupsTest, AmEmpty) {
2496 log.tail = eversion_t(14, 5);
2497 index();
2498
2499 IndexedLog olog;
2500
2501 add_dups(olog, example_dups_1());
2502
2503 bool changed = merge_log_dups(olog);
2504
2505 EXPECT_TRUE(changed);
2506 EXPECT_EQ(5u, log.dups.size());
2507
2508 if (5 == log.dups.size()) {
2509 EXPECT_EQ(10u, log.dups.front().version.epoch);
2510 EXPECT_EQ(11u, log.dups.front().version.version);
2511
2512 EXPECT_EQ(13u, log.dups.back().version.epoch);
2513 EXPECT_EQ(99u, log.dups.back().version.version);
2514 }
2515
2516 check_order();
2517 check_index();
2518 }
2519
2520 TEST_F(PGLogMergeDupsTest, AmEmptyOverlap) {
2521 log.tail = eversion_t(12, 3);
2522 index();
2523
2524 IndexedLog olog;
2525
2526 add_dups(olog, example_dups_1());
2527
2528 bool changed = merge_log_dups(olog);
2529
2530 EXPECT_TRUE(changed);
2531 EXPECT_EQ(3u, log.dups.size());
2532
2533 if (3 == log.dups.size()) {
2534 EXPECT_EQ(10u, log.dups.front().version.epoch);
2535 EXPECT_EQ(11u, log.dups.front().version.version);
2536
2537 EXPECT_EQ(11u, log.dups.back().version.epoch);
2538 EXPECT_EQ(1u, log.dups.back().version.version);
2539 }
2540
2541 check_order();
2542 check_index();
2543 }
2544
2545 TEST_F(PGLogMergeDupsTest, Same) {
2546 log.tail = eversion_t(14, 1);
2547
2548 IndexedLog olog;
2549
2550 add_dups(example_dups_1());
2551 index();
2552 add_dups(olog, example_dups_1());
2553
2554 bool changed = merge_log_dups(olog);
2555
2556 EXPECT_FALSE(changed);
2557 EXPECT_EQ(5u, log.dups.size());
2558
2559 if (5 == log.dups.size()) {
2560 EXPECT_EQ(10u, log.dups.front().version.epoch);
2561 EXPECT_EQ(11u, log.dups.front().version.version);
2562
2563 EXPECT_EQ(13u, log.dups.back().version.epoch);
2564 EXPECT_EQ(99u, log.dups.back().version.version);
2565 }
2566
2567 check_order();
2568 check_index();
2569 }
2570
2571
2572 TEST_F(PGLogMergeDupsTest, Later) {
2573 log.tail = eversion_t(16, 14);
2574
2575 IndexedLog olog;
2576
2577 add_dups(example_dups_1());
2578 index();
2579 add_dups(olog, example_dups_2());
2580
2581 bool changed = merge_log_dups(olog);
2582
2583 EXPECT_TRUE(changed);
2584 EXPECT_EQ(6u, log.dups.size());
2585
2586 if (6 == log.dups.size()) {
2587 EXPECT_EQ(10u, log.dups.front().version.epoch);
2588 EXPECT_EQ(11u, log.dups.front().version.version);
2589
2590 EXPECT_EQ(15u, log.dups.back().version.epoch);
2591 EXPECT_EQ(11u, log.dups.back().version.version);
2592 }
2593
2594 check_order();
2595 check_index();
2596 }
2597
2598
2599 TEST_F(PGLogMergeDupsTest, Earlier) {
2600 log.tail = eversion_t(17, 2);
2601
2602 IndexedLog olog;
2603
2604 add_dups(example_dups_2());
2605 index();
2606 add_dups(olog, example_dups_1());
2607
2608 bool changed = merge_log_dups(olog);
2609
2610 EXPECT_TRUE(changed);
2611 EXPECT_EQ(8u, log.dups.size());
2612
2613 if (6 == log.dups.size()) {
2614 EXPECT_EQ(10u, log.dups.front().version.epoch);
2615 EXPECT_EQ(11u, log.dups.front().version.version);
2616
2617 EXPECT_EQ(16u, log.dups.back().version.epoch);
2618 EXPECT_EQ(32u, log.dups.back().version.version);
2619 }
2620
2621 check_order();
2622 check_index();
2623 }
2624
2625
2626 TEST_F(PGLogMergeDupsTest, Superset) {
2627 log.tail = eversion_t(17, 2);
2628
2629 IndexedLog olog;
2630
2631 add_dups(example_dups_1());
2632 index();
2633
2634 olog.dups.push_back(create_dup_entry(9, 5));
2635 olog.dups.push_back(create_dup_entry(15, 11));
2636
2637 bool changed = merge_log_dups(olog);
2638
2639 EXPECT_TRUE(changed);
2640 EXPECT_EQ(7u, log.dups.size());
2641
2642 if (7 == log.dups.size()) {
2643 EXPECT_EQ(9u, log.dups.front().version.epoch);
2644 EXPECT_EQ(5u, log.dups.front().version.version);
2645
2646 EXPECT_EQ(15u, log.dups.back().version.epoch);
2647 EXPECT_EQ(11u, log.dups.back().version.version);
2648 }
2649
2650 check_order();
2651 check_index();
2652 }
2653
2654
2655 struct PGLogTrimTest :
2656 public ::testing::Test,
2657 public PGLogTestBase,
2658 public PGLog::IndexedLog
2659 {
2660 std::list<hobject_t*> test_hobjects;
2661 CephContext *cct;
2662
2663 void SetUp() override {
2664 cct = (new CephContext(CEPH_ENTITY_TYPE_OSD))->get();
2665
2666 hobject_t::generate_test_instances(test_hobjects);
2667 }
2668
2669 void SetUp(unsigned min_entries, unsigned max_entries, unsigned dup_track) {
2670 constexpr size_t size = 10;
2671
2672 char min_entries_s[size];
2673 char max_entries_s[size];
2674 char dup_track_s[size];
2675
2676 snprintf(min_entries_s, size, "%u", min_entries);
2677 snprintf(max_entries_s, size, "%u", max_entries);
2678 snprintf(dup_track_s, size, "%u", dup_track);
2679
2680 cct->_conf->set_val_or_die("osd_min_pg_log_entries", min_entries_s);
2681 cct->_conf->set_val_or_die("osd_max_pg_log_entries", max_entries_s);
2682 cct->_conf->set_val_or_die("osd_pg_log_dups_tracked", dup_track_s);
2683 }
2684
2685 void TearDown() override {
2686 while (!test_hobjects.empty()) {
2687 delete test_hobjects.front();
2688 test_hobjects.pop_front();
2689 }
2690
2691 cct->put();
2692 }
2693 }; // struct PGLogTrimTest
2694
2695
2696 # if 0
2697 TEST_F(PGLogTest, Trim1) {
2698 TestCase t;
2699
2700 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2701 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 150), mk_evt(10, 100)));
2702 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(15, 155), mk_evt(15, 150)));
2703 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2704 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(21, 165), mk_evt(26, 160)));
2705 t.auth.push_back(mk_ple_mod(mk_obj(1), mk_evt(21, 165), mk_evt(31, 171)));
2706
2707 t.setup();
2708 }
2709 #endif
2710
2711
2712 TEST_F(PGLogTrimTest, TestMakingCephContext)
2713 {
2714 SetUp(1, 2, 5);
2715
2716 EXPECT_EQ(1u, cct->_conf->osd_min_pg_log_entries);
2717 EXPECT_EQ(2u, cct->_conf->osd_max_pg_log_entries);
2718 EXPECT_EQ(5u, cct->_conf->osd_pg_log_dups_tracked);
2719 }
2720
2721
2722 TEST_F(PGLogTrimTest, TestPartialTrim)
2723 {
2724 SetUp(1, 2, 20);
2725 PGLog::IndexedLog log;
2726 log.head = mk_evt(24, 0);
2727 log.skip_can_rollback_to_to_head();
2728 log.head = mk_evt(9, 0);
2729
2730 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2731 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2732 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2733 log.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2734 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2735 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2736
2737 std::set<eversion_t> trimmed;
2738 std::set<std::string> trimmed_dups;
2739 bool dirty_dups = false;
2740
2741 log.trim(cct, mk_evt(19, 157), &trimmed, &trimmed_dups, &dirty_dups);
2742
2743 EXPECT_EQ(true, dirty_dups);
2744 EXPECT_EQ(3u, log.log.size());
2745 EXPECT_EQ(3u, trimmed.size());
2746 EXPECT_EQ(2u, log.dups.size());
2747 EXPECT_EQ(0u, trimmed_dups.size());
2748
2749 SetUp(1, 2, 15);
2750
2751 std::set<eversion_t> trimmed2;
2752 std::set<std::string> trimmed_dups2;
2753 bool dirty_dups2 = false;
2754
2755 log.trim(cct, mk_evt(20, 164), &trimmed2, &trimmed_dups2, &dirty_dups2);
2756
2757 EXPECT_EQ(true, dirty_dups2);
2758 EXPECT_EQ(2u, log.log.size());
2759 EXPECT_EQ(1u, trimmed2.size());
2760 EXPECT_EQ(2u, log.dups.size());
2761 EXPECT_EQ(1u, trimmed_dups2.size());
2762 }
2763
2764
2765 TEST_F(PGLogTrimTest, TestTrimNoTrimmed) {
2766 SetUp(1, 2, 20);
2767 PGLog::IndexedLog log;
2768 log.head = mk_evt(20, 0);
2769 log.skip_can_rollback_to_to_head();
2770 log.head = mk_evt(9, 0);
2771
2772 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2773 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2774 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2775 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2776 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2777 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2778
2779 bool dirty_dups = false;
2780
2781 log.trim(cct, mk_evt(19, 157), nullptr, nullptr, &dirty_dups);
2782
2783 EXPECT_EQ(true, dirty_dups);
2784 EXPECT_EQ(3u, log.log.size());
2785 EXPECT_EQ(2u, log.dups.size());
2786 }
2787
2788
2789 TEST_F(PGLogTrimTest, TestTrimNoDups)
2790 {
2791 SetUp(1, 2, 10);
2792 PGLog::IndexedLog log;
2793 log.head = mk_evt(20, 0);
2794 log.skip_can_rollback_to_to_head();
2795 log.head = mk_evt(9, 0);
2796
2797 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2798 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2799 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2800 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152)));
2801 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2802 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2803
2804 std::set<eversion_t> trimmed;
2805 std::set<std::string> trimmed_dups;
2806 bool dirty_dups = false;
2807
2808 log.trim(cct, mk_evt(19, 157), &trimmed, &trimmed_dups, &dirty_dups);
2809
2810 EXPECT_FALSE(dirty_dups);
2811 EXPECT_EQ(3u, log.log.size());
2812 EXPECT_EQ(3u, trimmed.size());
2813 EXPECT_EQ(0u, log.dups.size());
2814 EXPECT_EQ(0u, trimmed_dups.size());
2815 }
2816
2817 TEST_F(PGLogTrimTest, TestNoTrim)
2818 {
2819 SetUp(1, 2, 20);
2820 PGLog::IndexedLog log;
2821 log.head = mk_evt(24, 0);
2822 log.skip_can_rollback_to_to_head();
2823 log.head = mk_evt(9, 0);
2824
2825 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2826 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2827 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2828 log.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2829 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2830 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2831
2832 std::set<eversion_t> trimmed;
2833 std::set<std::string> trimmed_dups;
2834 bool dirty_dups = false;
2835
2836 log.trim(cct, mk_evt(9, 99), &trimmed, &trimmed_dups, &dirty_dups);
2837
2838 EXPECT_FALSE(dirty_dups);
2839 EXPECT_EQ(6u, log.log.size());
2840 EXPECT_EQ(0u, trimmed.size());
2841 EXPECT_EQ(0u, log.dups.size());
2842 EXPECT_EQ(0u, trimmed_dups.size());
2843 }
2844
2845 TEST_F(PGLogTrimTest, TestTrimAll)
2846 {
2847 SetUp(1, 2, 20);
2848 PGLog::IndexedLog log;
2849 log.head = mk_evt(24, 0);
2850 log.skip_can_rollback_to_to_head();
2851 log.head = mk_evt(9, 0);
2852
2853 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70)));
2854 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100)));
2855 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150)));
2856 log.add(mk_ple_mod(mk_obj(1), mk_evt(19, 160), mk_evt(25, 152)));
2857 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160)));
2858 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166)));
2859
2860 std::set<eversion_t> trimmed;
2861 std::set<std::string> trimmed_dups;
2862 bool dirty_dups = false;
2863
2864 log.trim(cct, mk_evt(22, 180), &trimmed, &trimmed_dups, &dirty_dups);
2865
2866 EXPECT_EQ(true, dirty_dups);
2867 EXPECT_EQ(0u, log.log.size());
2868 EXPECT_EQ(6u, trimmed.size());
2869 EXPECT_EQ(5u, log.dups.size());
2870 EXPECT_EQ(0u, trimmed_dups.size());
2871 }
2872
2873
2874 TEST_F(PGLogTrimTest, TestGetRequest) {
2875 SetUp(1, 2, 20);
2876 PGLog::IndexedLog log;
2877 log.head = mk_evt(20, 0);
2878 log.skip_can_rollback_to_to_head();
2879 log.head = mk_evt(9, 0);
2880
2881 entity_name_t client = entity_name_t::CLIENT(777);
2882
2883 log.add(mk_ple_mod(mk_obj(1), mk_evt(10, 100), mk_evt(8, 70),
2884 osd_reqid_t(client, 8, 1)));
2885 log.add(mk_ple_dt(mk_obj(2), mk_evt(15, 150), mk_evt(10, 100),
2886 osd_reqid_t(client, 8, 2)));
2887 log.add(mk_ple_mod_rb(mk_obj(3), mk_evt(15, 155), mk_evt(15, 150),
2888 osd_reqid_t(client, 8, 3)));
2889 log.add(mk_ple_mod(mk_obj(1), mk_evt(20, 160), mk_evt(25, 152),
2890 osd_reqid_t(client, 8, 4)));
2891 log.add(mk_ple_mod(mk_obj(4), mk_evt(21, 165), mk_evt(26, 160),
2892 osd_reqid_t(client, 8, 5)));
2893 log.add(mk_ple_dt_rb(mk_obj(5), mk_evt(21, 167), mk_evt(31, 166),
2894 osd_reqid_t(client, 8, 6)));
2895
2896 bool dirty_dups = false;
2897
2898 log.trim(cct, mk_evt(19, 157), nullptr, nullptr, &dirty_dups);
2899
2900 EXPECT_EQ(true, dirty_dups);
2901 EXPECT_EQ(3u, log.log.size());
2902 EXPECT_EQ(2u, log.dups.size());
2903
2904 eversion_t version;
2905 version_t user_version;
2906 int return_code;
2907
2908 osd_reqid_t log_reqid = osd_reqid_t(client, 8, 5);
2909 osd_reqid_t dup_reqid = osd_reqid_t(client, 8, 3);
2910 osd_reqid_t bad_reqid = osd_reqid_t(client, 8, 1);
2911
2912 bool result;
2913
2914 result = log.get_request(log_reqid, &version, &user_version, &return_code);
2915 EXPECT_EQ(true, result);
2916 EXPECT_EQ(mk_evt(21, 165), version);
2917
2918 result = log.get_request(dup_reqid, &version, &user_version, &return_code);
2919 EXPECT_EQ(true, result);
2920 EXPECT_EQ(mk_evt(15, 155), version);
2921
2922 result = log.get_request(bad_reqid, &version, &user_version, &return_code);
2923 EXPECT_FALSE(result);
2924 }
2925
2926 TEST_F(PGLogTest, _merge_object_divergent_entries) {
2927 {
2928 // Test for issue 20843
2929 clear();
2930 hobject_t hoid(object_t(/*name*/"notify.7"),
2931 /*key*/string(""),
2932 /*snap*/7,
2933 /*hash*/77,
2934 /*pool*/5,
2935 /*nspace*/string(""));
2936 mempool::osd_pglog::list<pg_log_entry_t> orig_entries;
2937 orig_entries.push_back(mk_ple_mod(hoid, eversion_t(8336, 957), eversion_t(8336, 952)));
2938 orig_entries.push_back(mk_ple_err(hoid, eversion_t(8336, 958)));
2939 orig_entries.push_back(mk_ple_err(hoid, eversion_t(8336, 959)));
2940 orig_entries.push_back(mk_ple_mod(hoid, eversion_t(8336, 960), eversion_t(8336, 957)));
2941 log.add(mk_ple_mod(hoid, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2942 missing.add(hoid,
2943 /*need*/eversion_t(8971, 1070),
2944 /*have*/eversion_t(8336, 952),
2945 false);
2946 pg_info_t oinfo;
2947 LogHandler rollbacker;
2948 _merge_object_divergent_entries(log, hoid,
2949 orig_entries, oinfo,
2950 log.get_can_rollback_to(),
2951 missing, &rollbacker,
2952 this);
2953 // No core dump
2954 }
2955 {
2956 // skip leading error entries
2957 clear();
2958 hobject_t hoid(object_t(/*name*/"notify.7"),
2959 /*key*/string(""),
2960 /*snap*/7,
2961 /*hash*/77,
2962 /*pool*/5,
2963 /*nspace*/string(""));
2964 mempool::osd_pglog::list<pg_log_entry_t> orig_entries;
2965 orig_entries.push_back(mk_ple_err(hoid, eversion_t(8336, 956)));
2966 orig_entries.push_back(mk_ple_mod(hoid, eversion_t(8336, 957), eversion_t(8336, 952)));
2967 log.add(mk_ple_mod(hoid, eversion_t(8973, 1075), eversion_t(8971, 1070)));
2968 missing.add(hoid,
2969 /*need*/eversion_t(8971, 1070),
2970 /*have*/eversion_t(8336, 952),
2971 false);
2972 pg_info_t oinfo;
2973 LogHandler rollbacker;
2974 _merge_object_divergent_entries(log, hoid,
2975 orig_entries, oinfo,
2976 log.get_can_rollback_to(),
2977 missing, &rollbacker,
2978 this);
2979 // No core dump
2980 }
2981 }
2982
2983 // Local Variables:
2984 // compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "
2985 // End: