]> git.proxmox.com Git - ceph.git/blame - ceph/src/librados/snap_set_diff.cc
update sources to v12.2.5
[ceph.git] / ceph / src / librados / snap_set_diff.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include <vector>
5
6#include "snap_set_diff.h"
7#include "common/ceph_context.h"
8#include "include/rados/librados.hpp"
9#include "include/interval_set.h"
10#include "common/debug.h"
11
12#define dout_subsys ceph_subsys_rados
13
14/**
15 * calculate intervals/extents that vary between two snapshots
16 */
17void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set,
18 librados::snap_t start, librados::snap_t end,
19 interval_set<uint64_t> *diff, uint64_t *end_size,
94b18763
FG
20 bool *end_exists, librados::snap_t *clone_end_snap_id,
21 bool *whole_object)
7c673cae
FG
22{
23 ldout(cct, 10) << "calc_snap_set_diff start " << start << " end " << end
24 << ", snap_set seq " << snap_set.seq << dendl;
25 bool saw_start = false;
26 uint64_t start_size = 0;
27 diff->clear();
28 *end_size = 0;
29 *end_exists = false;
30 *clone_end_snap_id = 0;
94b18763 31 *whole_object = false;
7c673cae
FG
32
33 for (vector<librados::clone_info_t>::const_iterator r = snap_set.clones.begin();
34 r != snap_set.clones.end();
35 ) {
36 // make an interval, and hide the fact that the HEAD doesn't
37 // include itself in the snaps list
38 librados::snap_t a, b;
39 if (r->cloneid == librados::SNAP_HEAD) {
40 // head is valid starting from right after the last seen seq
41 a = snap_set.seq + 1;
42 b = librados::SNAP_HEAD;
94b18763
FG
43 } else if (r->snaps.empty()) {
44 ldout(cct, 1) << "clone " << r->cloneid
45 << ": empty snaps, return whole object" << dendl;
46 *whole_object = true;
47 return;
7c673cae
FG
48 } else {
49 a = r->snaps[0];
50 // note: b might be < r->cloneid if a snap has been trimmed.
51 b = r->snaps[r->snaps.size()-1];
52 }
53 ldout(cct, 20) << " clone " << r->cloneid << " snaps " << r->snaps
54 << " -> [" << a << "," << b << "]"
55 << " size " << r->size << " overlap to next " << r->overlap << dendl;
56
57 if (b < start) {
58 // this is before start
59 ++r;
60 continue;
61 }
62
63 if (!saw_start) {
64 if (start < a) {
65 ldout(cct, 20) << " start, after " << start << dendl;
66 // this means the object didn't exist at start
67 if (r->size)
68 diff->insert(0, r->size);
69 start_size = 0;
70 } else {
71 ldout(cct, 20) << " start" << dendl;
72 start_size = r->size;
73 }
74 saw_start = true;
75 }
76
77 *end_size = r->size;
78 if (end < a) {
79 ldout(cct, 20) << " past end " << end << ", end object does not exist" << dendl;
80 *end_exists = false;
81 diff->clear();
82 if (start_size) {
83 diff->insert(0, start_size);
84 }
85 break;
86 }
87 if (end <= b) {
88 ldout(cct, 20) << " end" << dendl;
89 *end_exists = true;
90 *clone_end_snap_id = b;
91 break;
92 }
93
94 // start with the max(this size, next size), and subtract off any
95 // overlap
96 const vector<pair<uint64_t, uint64_t> > *overlap = &r->overlap;
97 interval_set<uint64_t> diff_to_next;
98 uint64_t max_size = r->size;
99 ++r;
100 if (r != snap_set.clones.end()) {
101 if (r->size > max_size)
102 max_size = r->size;
103 }
104 if (max_size)
105 diff_to_next.insert(0, max_size);
106 for (vector<pair<uint64_t, uint64_t> >::const_iterator p = overlap->begin();
107 p != overlap->end();
108 ++p) {
109 diff_to_next.erase(p->first, p->second);
110 }
111 ldout(cct, 20) << " diff_to_next " << diff_to_next << dendl;
112 diff->union_of(diff_to_next);
113 ldout(cct, 20) << " diff now " << *diff << dendl;
114 }
115}