1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2013 Inktank Storage, Inc.
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.
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"
31 class OSDriver
: public MapCacher::StoreDriver
<std::string
, ceph::buffer::list
> {
33 ObjectStore::CollectionHandle ch
;
37 class OSTransaction
: public MapCacher::Transaction
<std::string
, ceph::buffer::list
> {
38 friend class OSDriver
;
41 ObjectStore::Transaction
*t
;
44 const ghobject_t
&hoid
,
45 ObjectStore::Transaction
*t
)
46 : cid(cid
), hoid(hoid
), t(t
) {}
49 const std::map
<std::string
, ceph::buffer::list
> &to_set
) override
{
50 t
->omap_setkeys(cid
, hoid
, to_set
);
53 const std::set
<std::string
> &to_remove
) override
{
54 t
->omap_rmkeys(cid
, hoid
, to_remove
);
57 Context
*c
) override
{
58 t
->register_on_applied(c
);
62 OSTransaction
get_transaction(
63 ObjectStore::Transaction
*t
) {
64 return OSTransaction(ch
->cid
, hoid
, t
);
67 OSDriver(ObjectStore
*os
, const coll_t
& cid
, const ghobject_t
&hoid
) :
70 ch
= os
->open_collection(cid
);
73 const std::set
<std::string
> &keys
,
74 std::map
<std::string
, ceph::buffer::list
> *out
) override
;
76 const std::string
&key
,
77 std::pair
<std::string
, ceph::buffer::list
> *next
) override
;
83 * Manages two mappings:
84 * 1) hobject_t -> {snapid}
85 * 2) snapid -> {hobject_t}
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>
91 * The on disk strings and encodings are implemented in to_raw, to_raw_key,
92 * from_raw, to_object_key.
94 * The object -> {snapid} mapping is primarily included so that the
95 * SnapMapper state can be verified against the external PG state during
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.
105 struct object_snaps
{
107 std::set
<snapid_t
> snaps
;
108 object_snaps(hobject_t oid
, const std::set
<snapid_t
> &snaps
)
109 : oid(oid
), snaps(snaps
) {}
111 void encode(ceph::buffer::list
&bl
) const;
112 void decode(ceph::buffer::list::const_iterator
&bp
);
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
);
127 void decode(ceph::buffer::list::const_iterator
&bl
) {
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
;
144 ObjectStore::CollectionHandle ch
;
145 ghobject_t mapping_hoid
;
146 ghobject_t purged_snaps_hoid
;
148 ObjectMap::ObjectMapIterator psit
;
152 bool _parse_p(); ///< advance the purged_snaps pointer
154 ObjectMap::ObjectMapIterator mapit
;
158 bool _parse_m(); ///< advance the (object) mapper pointer
160 std::vector
<std::tuple
<int64_t, snapid_t
, uint32_t, shard_id_t
>> stray
;
165 ObjectStore::CollectionHandle
& ch
,
166 ghobject_t mapping_hoid
,
167 ghobject_t purged_snaps_hoid
)
171 mapping_hoid(mapping_hoid
),
172 purged_snaps_hoid(purged_snaps_hoid
) {}
177 static int convert_legacy(
180 ObjectStore::CollectionHandle
& ch
,
184 static void record_purged_snaps(
187 ObjectStore::CollectionHandle
& ch
,
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(
194 ObjectStore::CollectionHandle
& ch
,
195 ghobject_t mapper_hoid
,
196 ghobject_t purged_snaps_hoid
);
199 static int _lookup_purged_snap(
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
);
212 MapCacher::MapCacher
<std::string
, ceph::buffer::list
> backend
;
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
);
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
);
223 std::pair
<std::string
, ceph::buffer::list
> to_raw(
224 const std::pair
<snapid_t
, hobject_t
> &to_map
);
226 static bool is_mapping(const std::string
&to_test
);
228 static std::pair
<snapid_t
, hobject_t
> from_raw(
229 const std::pair
<std::string
, ceph::buffer::list
> &image
);
231 std::string
to_object_key(const hobject_t
&hoid
);
233 int get_snaps(const hobject_t
&oid
, object_snaps
*out
);
236 const hobject_t
&oid
,
237 const object_snaps
&out
,
238 MapCacher::Transaction
<std::string
, ceph::buffer::list
> *t
);
241 const hobject_t
&oid
,
242 MapCacher::Transaction
<std::string
, ceph::buffer::list
> *t
);
244 // True if hoid belongs in this mapping based on mask_bits and match
245 bool check(const hobject_t
&hoid
) const;
248 const hobject_t
&oid
, ///< [in] oid to remove
249 MapCacher::Transaction
<std::string
, ceph::buffer::list
> *t
///< [out] transaction
253 static std::string
make_shard_prefix(shard_id_t shard
) {
254 if (shard
== shard_id_t::NO_SHARD
)
255 return std::string();
257 int r
= snprintf(buf
, sizeof(buf
), ".%x", (int)shard
);
258 ceph_assert(r
< (int)sizeof(buf
));
259 return std::string(buf
, r
) + '_';
262 const uint32_t match
;
263 std::string last_key_checked
;
265 const shard_id_t shard
;
266 const std::string shard_prefix
;
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
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
);
280 std::set
<std::string
> prefixes
;
281 /// Update bits in case of pg split or merge
283 uint32_t new_bits
///< [in] new split bits
285 mask_bits
= new_bits
;
286 std::set
<std::string
> _prefixes
= hobject_t::get_prefixes(
291 for (auto i
= _prefixes
.begin(); i
!= _prefixes
.end(); ++i
) {
292 prefixes
.insert(shard_prefix
+ *i
);
296 /// Update snaps for oid, empty new_snaps removes the mapping
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
304 /// Add mapping for oid, must not already be mapped
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
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
318 /// Remove mapping for 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
324 /// Get snaps for oid
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
330 WRITE_CLASS_ENCODER(SnapMapper::object_snaps
)
331 WRITE_CLASS_ENCODER(SnapMapper::Mapping
)