]> git.proxmox.com Git - ceph.git/blob - ceph/src/osd/SnapMapper.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / osd / SnapMapper.h
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 Inktank Storage, Inc.
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #ifndef SNAPMAPPER_H
16 #define SNAPMAPPER_H
17
18 #include <string>
19 #include <set>
20 #include <utility>
21 #include <cstring>
22
23 #include "common/map_cacher.hpp"
24 #include "common/hobject.h"
25 #include "include/buffer.h"
26 #include "include/encoding.h"
27 #include "include/object.h"
28 #include "os/ObjectStore.h"
29 #include "osd/OSDMap.h"
30
31 class OSDriver : public MapCacher::StoreDriver<std::string, ceph::buffer::list> {
32 ObjectStore *os;
33 ObjectStore::CollectionHandle ch;
34 ghobject_t hoid;
35
36 public:
37 class OSTransaction : public MapCacher::Transaction<std::string, ceph::buffer::list> {
38 friend class OSDriver;
39 coll_t cid;
40 ghobject_t hoid;
41 ObjectStore::Transaction *t;
42 OSTransaction(
43 const coll_t &cid,
44 const ghobject_t &hoid,
45 ObjectStore::Transaction *t)
46 : cid(cid), hoid(hoid), t(t) {}
47 public:
48 void set_keys(
49 const std::map<std::string, ceph::buffer::list> &to_set) override {
50 t->omap_setkeys(cid, hoid, to_set);
51 }
52 void remove_keys(
53 const std::set<std::string> &to_remove) override {
54 t->omap_rmkeys(cid, hoid, to_remove);
55 }
56 void add_callback(
57 Context *c) override {
58 t->register_on_applied(c);
59 }
60 };
61
62 OSTransaction get_transaction(
63 ObjectStore::Transaction *t) {
64 return OSTransaction(ch->cid, hoid, t);
65 }
66
67 OSDriver(ObjectStore *os, const coll_t& cid, const ghobject_t &hoid) :
68 os(os),
69 hoid(hoid) {
70 ch = os->open_collection(cid);
71 }
72 int get_keys(
73 const std::set<std::string> &keys,
74 std::map<std::string, ceph::buffer::list> *out) override;
75 int get_next(
76 const std::string &key,
77 std::pair<std::string, ceph::buffer::list> *next) override;
78 };
79
80 /**
81 * SnapMapper
82 *
83 * Manages two mappings:
84 * 1) hobject_t -> {snapid}
85 * 2) snapid -> {hobject_t}
86 *
87 * We accomplish this using two sets of keys:
88 * 1) OBJECT_PREFIX + obj.str() -> encoding of object_snaps
89 * 2) MAPPING_PREFIX + poolid + snapid_t + obj.str() -> encoding of std::pair<snapid_t, obj>
90 *
91 * The on disk strings and encodings are implemented in to_raw, to_raw_key,
92 * from_raw, to_object_key.
93 *
94 * The object -> {snapid} mapping is primarily included so that the
95 * SnapMapper state can be verified against the external PG state during
96 * scrub etc.
97 *
98 * The 2) mapping is arranged such that all objects in a particular
99 * snap will sort together, and so that all objects in a pg for a
100 * particular snap will group under up to 8 prefixes.
101 */
102 class SnapMapper {
103 public:
104 CephContext* cct;
105 struct object_snaps {
106 hobject_t oid;
107 std::set<snapid_t> snaps;
108 object_snaps(hobject_t oid, const std::set<snapid_t> &snaps)
109 : oid(oid), snaps(snaps) {}
110 object_snaps() {}
111 void encode(ceph::buffer::list &bl) const;
112 void decode(ceph::buffer::list::const_iterator &bp);
113 };
114
115 struct Mapping {
116 snapid_t snap;
117 hobject_t hoid;
118 explicit Mapping(const std::pair<snapid_t, hobject_t> &in)
119 : snap(in.first), hoid(in.second) {}
120 Mapping() : snap(0) {}
121 void encode(ceph::buffer::list &bl) const {
122 ENCODE_START(1, 1, bl);
123 encode(snap, bl);
124 encode(hoid, bl);
125 ENCODE_FINISH(bl);
126 }
127 void decode(ceph::buffer::list::const_iterator &bl) {
128 DECODE_START(1, bl);
129 decode(snap, bl);
130 decode(hoid, bl);
131 DECODE_FINISH(bl);
132 }
133 };
134
135 static const std::string LEGACY_MAPPING_PREFIX;
136 static const std::string MAPPING_PREFIX;
137 static const std::string OBJECT_PREFIX;
138 static const char *PURGED_SNAP_EPOCH_PREFIX;
139 static const char *PURGED_SNAP_PREFIX;
140
141 struct Scrubber {
142 CephContext *cct;
143 ObjectStore *store;
144 ObjectStore::CollectionHandle ch;
145 ghobject_t mapping_hoid;
146 ghobject_t purged_snaps_hoid;
147
148 ObjectMap::ObjectMapIterator psit;
149 int64_t pool;
150 snapid_t begin, end;
151
152 bool _parse_p(); ///< advance the purged_snaps pointer
153
154 ObjectMap::ObjectMapIterator mapit;
155 Mapping mapping;
156 shard_id_t shard;
157
158 bool _parse_m(); ///< advance the (object) mapper pointer
159
160 std::vector<std::tuple<int64_t, snapid_t, uint32_t, shard_id_t>> stray;
161
162 Scrubber(
163 CephContext *cct,
164 ObjectStore *store,
165 ObjectStore::CollectionHandle& ch,
166 ghobject_t mapping_hoid,
167 ghobject_t purged_snaps_hoid)
168 : cct(cct),
169 store(store),
170 ch(ch),
171 mapping_hoid(mapping_hoid),
172 purged_snaps_hoid(purged_snaps_hoid) {}
173
174 void run();
175 };
176
177 static int convert_legacy(
178 CephContext *cct,
179 ObjectStore *store,
180 ObjectStore::CollectionHandle& ch,
181 ghobject_t hoid,
182 unsigned max);
183
184 static void record_purged_snaps(
185 CephContext *cct,
186 ObjectStore *store,
187 ObjectStore::CollectionHandle& ch,
188 ghobject_t hoid,
189 ObjectStore::Transaction *t,
190 std::map<epoch_t,mempool::osdmap::map<int64_t,snap_interval_set_t>> purged_snaps);
191 static void scrub_purged_snaps(
192 CephContext *cct,
193 ObjectStore *store,
194 ObjectStore::CollectionHandle& ch,
195 ghobject_t mapper_hoid,
196 ghobject_t purged_snaps_hoid);
197
198 private:
199 static int _lookup_purged_snap(
200 CephContext *cct,
201 ObjectStore *store,
202 ObjectStore::CollectionHandle& ch,
203 const ghobject_t& hoid,
204 int64_t pool, snapid_t snap,
205 snapid_t *begin, snapid_t *end);
206 static void make_purged_snap_key_value(
207 int64_t pool, snapid_t begin,
208 snapid_t end, std::map<std::string,ceph::buffer::list> *m);
209 static std::string make_purged_snap_key(int64_t pool, snapid_t last);
210
211
212 MapCacher::MapCacher<std::string, ceph::buffer::list> backend;
213
214 static std::string get_legacy_prefix(snapid_t snap);
215 std::string to_legacy_raw_key(
216 const std::pair<snapid_t, hobject_t> &to_map);
217 static bool is_legacy_mapping(const std::string &to_test);
218
219 static std::string get_prefix(int64_t pool, snapid_t snap);
220 std::string to_raw_key(
221 const std::pair<snapid_t, hobject_t> &to_map);
222
223 std::pair<std::string, ceph::buffer::list> to_raw(
224 const std::pair<snapid_t, hobject_t> &to_map);
225
226 static bool is_mapping(const std::string &to_test);
227
228 static std::pair<snapid_t, hobject_t> from_raw(
229 const std::pair<std::string, ceph::buffer::list> &image);
230
231 std::string to_object_key(const hobject_t &hoid);
232
233 int get_snaps(const hobject_t &oid, object_snaps *out);
234
235 void set_snaps(
236 const hobject_t &oid,
237 const object_snaps &out,
238 MapCacher::Transaction<std::string, ceph::buffer::list> *t);
239
240 void clear_snaps(
241 const hobject_t &oid,
242 MapCacher::Transaction<std::string, ceph::buffer::list> *t);
243
244 // True if hoid belongs in this mapping based on mask_bits and match
245 bool check(const hobject_t &hoid) const;
246
247 int _remove_oid(
248 const hobject_t &oid, ///< [in] oid to remove
249 MapCacher::Transaction<std::string, ceph::buffer::list> *t ///< [out] transaction
250 );
251
252 public:
253 static std::string make_shard_prefix(shard_id_t shard) {
254 if (shard == shard_id_t::NO_SHARD)
255 return std::string();
256 char buf[20];
257 int r = snprintf(buf, sizeof(buf), ".%x", (int)shard);
258 ceph_assert(r < (int)sizeof(buf));
259 return std::string(buf, r) + '_';
260 }
261 uint32_t mask_bits;
262 const uint32_t match;
263 std::string last_key_checked;
264 const int64_t pool;
265 const shard_id_t shard;
266 const std::string shard_prefix;
267 SnapMapper(
268 CephContext* cct,
269 MapCacher::StoreDriver<std::string, ceph::buffer::list> *driver,
270 uint32_t match, ///< [in] pgid
271 uint32_t bits, ///< [in] current split bits
272 int64_t pool, ///< [in] pool
273 shard_id_t shard ///< [in] shard
274 )
275 : cct(cct), backend(driver), mask_bits(bits), match(match), pool(pool),
276 shard(shard), shard_prefix(make_shard_prefix(shard)) {
277 update_bits(mask_bits);
278 }
279
280 std::set<std::string> prefixes;
281 /// Update bits in case of pg split or merge
282 void update_bits(
283 uint32_t new_bits ///< [in] new split bits
284 ) {
285 mask_bits = new_bits;
286 std::set<std::string> _prefixes = hobject_t::get_prefixes(
287 mask_bits,
288 match,
289 pool);
290 prefixes.clear();
291 for (auto i = _prefixes.begin(); i != _prefixes.end(); ++i) {
292 prefixes.insert(shard_prefix + *i);
293 }
294 }
295
296 /// Update snaps for oid, empty new_snaps removes the mapping
297 int update_snaps(
298 const hobject_t &oid, ///< [in] oid to update
299 const std::set<snapid_t> &new_snaps, ///< [in] new snap std::set
300 const std::set<snapid_t> *old_snaps, ///< [in] old snaps (for debugging)
301 MapCacher::Transaction<std::string, ceph::buffer::list> *t ///< [out] transaction
302 ); ///@ return error, 0 on success
303
304 /// Add mapping for oid, must not already be mapped
305 void add_oid(
306 const hobject_t &oid, ///< [in] oid to add
307 const std::set<snapid_t>& new_snaps, ///< [in] snaps
308 MapCacher::Transaction<std::string, ceph::buffer::list> *t ///< [out] transaction
309 );
310
311 /// Returns first object with snap as a snap
312 int get_next_objects_to_trim(
313 snapid_t snap, ///< [in] snap to check
314 unsigned max, ///< [in] max to get
315 std::vector<hobject_t> *out ///< [out] next objects to trim (must be empty)
316 ); ///< @return error, -ENOENT if no more objects
317
318 /// Remove mapping for oid
319 int remove_oid(
320 const hobject_t &oid, ///< [in] oid to remove
321 MapCacher::Transaction<std::string, ceph::buffer::list> *t ///< [out] transaction
322 ); ///< @return error, -ENOENT if the object is not mapped
323
324 /// Get snaps for oid
325 int get_snaps(
326 const hobject_t &oid, ///< [in] oid to get snaps for
327 std::set<snapid_t> *snaps ///< [out] snaps
328 ); ///< @return error, -ENOENT if oid is not recorded
329 };
330 WRITE_CLASS_ENCODER(SnapMapper::object_snaps)
331 WRITE_CLASS_ENCODER(SnapMapper::Mapping)
332
333 #endif