]>
Commit | Line | Data |
---|---|---|
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 | ||
20effc67 | 14 | using namespace std; |
7c673cae FG |
15 | /** |
16 | * calculate intervals/extents that vary between two snapshots | |
17 | */ | |
18 | void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set, | |
19 | librados::snap_t start, librados::snap_t end, | |
20 | interval_set<uint64_t> *diff, uint64_t *end_size, | |
94b18763 FG |
21 | bool *end_exists, librados::snap_t *clone_end_snap_id, |
22 | bool *whole_object) | |
7c673cae FG |
23 | { |
24 | ldout(cct, 10) << "calc_snap_set_diff start " << start << " end " << end | |
25 | << ", snap_set seq " << snap_set.seq << dendl; | |
26 | bool saw_start = false; | |
27 | uint64_t start_size = 0; | |
28 | diff->clear(); | |
29 | *end_size = 0; | |
30 | *end_exists = false; | |
31 | *clone_end_snap_id = 0; | |
94b18763 | 32 | *whole_object = false; |
7c673cae | 33 | |
f38dd50b TL |
34 | auto r = snap_set.clones.begin(); |
35 | while (r != snap_set.clones.end()) { | |
7c673cae FG |
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; | |
11fdf7f2 | 46 | diff->clear(); |
94b18763 FG |
47 | *whole_object = true; |
48 | return; | |
7c673cae FG |
49 | } else { |
50 | a = r->snaps[0]; | |
51 | // note: b might be < r->cloneid if a snap has been trimmed. | |
52 | b = r->snaps[r->snaps.size()-1]; | |
53 | } | |
54 | ldout(cct, 20) << " clone " << r->cloneid << " snaps " << r->snaps | |
55 | << " -> [" << a << "," << b << "]" | |
56 | << " size " << r->size << " overlap to next " << r->overlap << dendl; | |
57 | ||
58 | if (b < start) { | |
59 | // this is before start | |
60 | ++r; | |
61 | continue; | |
62 | } | |
63 | ||
64 | if (!saw_start) { | |
65 | if (start < a) { | |
66 | ldout(cct, 20) << " start, after " << start << dendl; | |
67 | // this means the object didn't exist at start | |
68 | if (r->size) | |
69 | diff->insert(0, r->size); | |
70 | start_size = 0; | |
71 | } else { | |
72 | ldout(cct, 20) << " start" << dendl; | |
73 | start_size = r->size; | |
74 | } | |
75 | saw_start = true; | |
76 | } | |
77 | ||
7c673cae | 78 | if (end < a) { |
7c673cae FG |
79 | break; |
80 | } | |
81 | if (end <= b) { | |
82 | ldout(cct, 20) << " end" << dendl; | |
f38dd50b | 83 | *end_size = r->size; |
7c673cae FG |
84 | *end_exists = true; |
85 | *clone_end_snap_id = b; | |
f38dd50b | 86 | return; |
7c673cae FG |
87 | } |
88 | ||
f38dd50b TL |
89 | // start with the largest possible diff to next, and subtract off |
90 | // any overlap | |
7c673cae FG |
91 | const vector<pair<uint64_t, uint64_t> > *overlap = &r->overlap; |
92 | interval_set<uint64_t> diff_to_next; | |
f38dd50b TL |
93 | uint64_t diff_boundary; |
94 | uint64_t prev_size = r->size; | |
7c673cae FG |
95 | ++r; |
96 | if (r != snap_set.clones.end()) { | |
f38dd50b TL |
97 | if (r->size >= prev_size) { |
98 | diff_boundary = r->size; | |
99 | } else if (prev_size <= start_size) { | |
100 | // truncated range below size at start | |
101 | diff_boundary = prev_size; | |
102 | } else { | |
103 | // truncated range (partially) above size at start -- drop that | |
104 | // part from the running diff | |
105 | diff_boundary = std::max(r->size, start_size); | |
106 | ldout(cct, 20) << " no more diff beyond " << diff_boundary << dendl; | |
107 | diff->erase(diff_boundary, prev_size - diff_boundary); | |
108 | } | |
109 | if (diff_boundary) { | |
110 | diff_to_next.insert(0, diff_boundary); | |
111 | } | |
112 | for (auto p = overlap->begin(); p != overlap->end(); ++p) { | |
113 | diff_to_next.erase(p->first, p->second); | |
114 | } | |
115 | ldout(cct, 20) << " diff_to_next " << diff_to_next << dendl; | |
116 | diff->union_of(diff_to_next); | |
117 | ldout(cct, 20) << " diff now " << *diff << dendl; | |
7c673cae | 118 | } |
f38dd50b TL |
119 | } |
120 | ||
121 | if (r != snap_set.clones.end()) { | |
122 | ldout(cct, 20) << " past end " << end | |
123 | << ", end object does not exist" << dendl; | |
124 | } else { | |
125 | ldout(cct, 20) << " ran out of clones before reaching end " << end | |
126 | << ", end object does not exist" << dendl; | |
127 | } | |
128 | diff->clear(); | |
129 | if (start_size) { | |
130 | diff->insert(0, start_size); | |
7c673cae FG |
131 | } |
132 | } |