]>
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 "ScrubStore.h" | |
5 | #include "osd_types.h" | |
6 | #include "common/scrub_types.h" | |
7 | #include "include/rados/rados_types.hpp" | |
8 | ||
f67539c2 TL |
9 | using std::ostringstream; |
10 | using std::string; | |
11 | using std::vector; | |
12 | ||
13 | using ceph::bufferlist; | |
14 | ||
7c673cae FG |
15 | namespace { |
16 | ghobject_t make_scrub_object(const spg_t& pgid) | |
17 | { | |
18 | ostringstream ss; | |
19 | ss << "scrub_" << pgid; | |
20 | return pgid.make_temp_ghobject(ss.str()); | |
21 | } | |
22 | ||
23 | string first_object_key(int64_t pool) | |
24 | { | |
25 | auto hoid = hobject_t(object_t(), | |
26 | "", | |
27 | 0, | |
28 | 0x00000000, | |
29 | pool, | |
30 | ""); | |
31 | hoid.build_hash_cache(); | |
32 | return "SCRUB_OBJ_" + hoid.to_str(); | |
33 | } | |
34 | ||
35 | // the object_key should be unique across pools | |
36 | string to_object_key(int64_t pool, const librados::object_id_t& oid) | |
37 | { | |
38 | auto hoid = hobject_t(object_t(oid.name), | |
39 | oid.locator, // key | |
40 | oid.snap, | |
41 | 0, // hash | |
42 | pool, | |
43 | oid.nspace); | |
44 | hoid.build_hash_cache(); | |
45 | return "SCRUB_OBJ_" + hoid.to_str(); | |
46 | } | |
47 | ||
48 | string last_object_key(int64_t pool) | |
49 | { | |
50 | auto hoid = hobject_t(object_t(), | |
51 | "", | |
52 | 0, | |
53 | 0xffffffff, | |
54 | pool, | |
55 | ""); | |
56 | hoid.build_hash_cache(); | |
57 | return "SCRUB_OBJ_" + hoid.to_str(); | |
58 | } | |
59 | ||
60 | string first_snap_key(int64_t pool) | |
61 | { | |
62 | // scrub object is per spg_t object, so we can misuse the hash (pg.seed) for | |
63 | // the representing the minimal and maximum keys. and this relies on how | |
64 | // hobject_t::to_str() works: hex(pool).hex(revhash). | |
65 | auto hoid = hobject_t(object_t(), | |
66 | "", | |
67 | 0, | |
68 | 0x00000000, | |
69 | pool, | |
70 | ""); | |
71 | hoid.build_hash_cache(); | |
72 | return "SCRUB_SS_" + hoid.to_str(); | |
73 | } | |
74 | ||
75 | string to_snap_key(int64_t pool, const librados::object_id_t& oid) | |
76 | { | |
77 | auto hoid = hobject_t(object_t(oid.name), | |
78 | oid.locator, // key | |
79 | oid.snap, | |
80 | 0x77777777, // hash | |
81 | pool, | |
82 | oid.nspace); | |
83 | hoid.build_hash_cache(); | |
84 | return "SCRUB_SS_" + hoid.to_str(); | |
85 | } | |
86 | ||
87 | string last_snap_key(int64_t pool) | |
88 | { | |
89 | auto hoid = hobject_t(object_t(), | |
90 | "", | |
91 | 0, | |
92 | 0xffffffff, | |
93 | pool, | |
94 | ""); | |
95 | hoid.build_hash_cache(); | |
96 | return "SCRUB_SS_" + hoid.to_str(); | |
97 | } | |
98 | } | |
99 | ||
100 | namespace Scrub { | |
101 | ||
102 | Store* | |
103 | Store::create(ObjectStore* store, | |
104 | ObjectStore::Transaction* t, | |
105 | const spg_t& pgid, | |
106 | const coll_t& coll) | |
107 | { | |
11fdf7f2 TL |
108 | ceph_assert(store); |
109 | ceph_assert(t); | |
7c673cae FG |
110 | ghobject_t oid = make_scrub_object(pgid); |
111 | t->touch(coll, oid); | |
112 | return new Store{coll, oid, store}; | |
113 | } | |
114 | ||
115 | Store::Store(const coll_t& coll, const ghobject_t& oid, ObjectStore* store) | |
116 | : coll(coll), | |
117 | hoid(oid), | |
118 | driver(store, coll, hoid), | |
119 | backend(&driver) | |
120 | {} | |
121 | ||
122 | Store::~Store() | |
123 | { | |
11fdf7f2 | 124 | ceph_assert(results.empty()); |
7c673cae FG |
125 | } |
126 | ||
127 | void Store::add_object_error(int64_t pool, const inconsistent_obj_wrapper& e) | |
128 | { | |
129 | bufferlist bl; | |
130 | e.encode(bl); | |
131 | results[to_object_key(pool, e.object)] = bl; | |
132 | } | |
133 | ||
134 | void Store::add_snap_error(int64_t pool, const inconsistent_snapset_wrapper& e) | |
135 | { | |
136 | bufferlist bl; | |
137 | e.encode(bl); | |
138 | results[to_snap_key(pool, e.object)] = bl; | |
139 | } | |
140 | ||
141 | bool Store::empty() const | |
142 | { | |
143 | return results.empty(); | |
144 | } | |
145 | ||
146 | void Store::flush(ObjectStore::Transaction* t) | |
147 | { | |
148 | if (t) { | |
149 | OSDriver::OSTransaction txn = driver.get_transaction(t); | |
150 | backend.set_keys(results, &txn); | |
151 | } | |
152 | results.clear(); | |
153 | } | |
154 | ||
155 | void Store::cleanup(ObjectStore::Transaction* t) | |
156 | { | |
157 | t->remove(coll, hoid); | |
158 | } | |
159 | ||
160 | std::vector<bufferlist> | |
f67539c2 | 161 | Store::get_snap_errors(int64_t pool, |
7c673cae | 162 | const librados::object_id_t& start, |
f67539c2 | 163 | uint64_t max_return) const |
7c673cae FG |
164 | { |
165 | const string begin = (start.name.empty() ? | |
166 | first_snap_key(pool) : to_snap_key(pool, start)); | |
167 | const string end = last_snap_key(pool); | |
f67539c2 | 168 | return get_errors(begin, end, max_return); |
7c673cae FG |
169 | } |
170 | ||
171 | std::vector<bufferlist> | |
f67539c2 | 172 | Store::get_object_errors(int64_t pool, |
7c673cae | 173 | const librados::object_id_t& start, |
f67539c2 | 174 | uint64_t max_return) const |
7c673cae FG |
175 | { |
176 | const string begin = (start.name.empty() ? | |
177 | first_object_key(pool) : to_object_key(pool, start)); | |
178 | const string end = last_object_key(pool); | |
f67539c2 | 179 | return get_errors(begin, end, max_return); |
7c673cae FG |
180 | } |
181 | ||
182 | std::vector<bufferlist> | |
f67539c2 | 183 | Store::get_errors(const string& begin, |
7c673cae | 184 | const string& end, |
f67539c2 | 185 | uint64_t max_return) const |
7c673cae FG |
186 | { |
187 | vector<bufferlist> errors; | |
188 | auto next = std::make_pair(begin, bufferlist{}); | |
189 | while (max_return && !backend.get_next(next.first, &next)) { | |
190 | if (next.first >= end) | |
191 | break; | |
192 | errors.push_back(next.second); | |
193 | max_return--; | |
194 | } | |
195 | return errors; | |
196 | } | |
197 | ||
198 | } // namespace Scrub |