Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librados / snap_set_diff.cc
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  */
17 void 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,
20                         bool *end_exists, librados::snap_t *clone_end_snap_id)
21 {
22   ldout(cct, 10) << "calc_snap_set_diff start " << start << " end " << end
23                  << ", snap_set seq " << snap_set.seq << dendl;
24   bool saw_start = false;
25   uint64_t start_size = 0;
26   diff->clear();
27   *end_size = 0;
28   *end_exists = false;
29   *clone_end_snap_id = 0;
30
31   for (vector<librados::clone_info_t>::const_iterator r = snap_set.clones.begin();
32        r != snap_set.clones.end();
33        ) {
34     // make an interval, and hide the fact that the HEAD doesn't
35     // include itself in the snaps list
36     librados::snap_t a, b;
37     if (r->cloneid == librados::SNAP_HEAD) {
38       // head is valid starting from right after the last seen seq
39       a = snap_set.seq + 1;
40       b = librados::SNAP_HEAD;
41     } else {
42       a = r->snaps[0];
43       // note: b might be < r->cloneid if a snap has been trimmed.
44       b = r->snaps[r->snaps.size()-1];
45     }
46     ldout(cct, 20) << " clone " << r->cloneid << " snaps " << r->snaps
47                    << " -> [" << a << "," << b << "]"
48                    << " size " << r->size << " overlap to next " << r->overlap << dendl;
49
50     if (b < start) {
51       // this is before start
52       ++r;
53       continue;
54     }
55
56     if (!saw_start) {
57       if (start < a) {
58         ldout(cct, 20) << "  start, after " << start << dendl;
59         // this means the object didn't exist at start
60         if (r->size)
61           diff->insert(0, r->size);
62         start_size = 0;
63       } else {
64         ldout(cct, 20) << "  start" << dendl;
65         start_size = r->size;
66       }
67       saw_start = true;
68     }
69
70     *end_size = r->size;
71     if (end < a) {
72       ldout(cct, 20) << " past end " << end << ", end object does not exist" << dendl;
73       *end_exists = false;
74       diff->clear();
75       if (start_size) {
76         diff->insert(0, start_size);
77       }
78       break;
79     }
80     if (end <= b) {
81       ldout(cct, 20) << " end" << dendl;
82       *end_exists = true;
83       *clone_end_snap_id = b;
84       break;
85     }
86
87     // start with the max(this size, next size), and subtract off any
88     // overlap
89     const vector<pair<uint64_t, uint64_t> > *overlap = &r->overlap;
90     interval_set<uint64_t> diff_to_next;
91     uint64_t max_size = r->size;
92     ++r;
93     if (r != snap_set.clones.end()) {
94       if (r->size > max_size)
95         max_size = r->size;
96     }
97     if (max_size)
98       diff_to_next.insert(0, max_size);
99     for (vector<pair<uint64_t, uint64_t> >::const_iterator p = overlap->begin();
100          p != overlap->end();
101          ++p) {
102       diff_to_next.erase(p->first, p->second);
103     }
104     ldout(cct, 20) << "  diff_to_next " << diff_to_next << dendl;
105     diff->union_of(diff_to_next);
106     ldout(cct, 20) << "  diff now " << *diff << dendl;
107   }
108 }