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