]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/hobject.h
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) 2004-2006 Sage Weil <sage@newdream.net>
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.
15 #ifndef __CEPH_OS_HOBJECT_H
16 #define __CEPH_OS_HOBJECT_H
18 #include "include/types.h"
19 #include "include/cmp.h"
21 #include "json_spirit/json_spirit_value.h"
22 #include "include/ceph_assert.h" // spirit clobbers it!
31 #define UINT64_MAX (18446744073709551615ULL)
34 #define INT64_MIN ((int64_t)0x8000000000000000ll)
39 static const int64_t POOL_META
= -1;
40 static const int64_t POOL_TEMP_START
= -2; // and then negative
42 static bool is_temp_pool(int64_t pool
) {
43 return pool
<= POOL_TEMP_START
;
45 static int64_t get_temp_pool(int64_t pool
) {
46 return POOL_TEMP_START
- pool
;
48 static bool is_meta_pool(int64_t pool
) {
49 return pool
== POOL_META
;
58 uint32_t nibblewise_key_cache
;
59 uint32_t hash_reverse_bits
;
67 class hobject_t_max
{};
70 const std::string
& get_key() const {
74 void set_key(const std::string
& key_
) {
81 std::string
to_str() const;
83 uint32_t get_hash() const {
86 void set_hash(uint32_t value
) {
91 static bool match_hash(uint32_t to_check
, uint32_t bits
, uint32_t match
) {
92 return (match
& ~((~0)<<bits
)) == (to_check
& ~((~0)<<bits
));
94 bool match(uint32_t bits
, uint32_t match
) const {
95 return match_hash(hash
, bits
, match
);
98 bool is_temp() const {
99 return is_temp_pool(pool
) && pool
!= INT64_MIN
;
101 bool is_meta() const {
102 return is_meta_pool(pool
);
104 int64_t get_logical_pool() const {
105 if (is_temp_pool(pool
))
106 return get_temp_pool(pool
); // it's reversible
111 hobject_t() : snap(0), hash(0), max(false), pool(INT64_MIN
) {
115 hobject_t(const hobject_t
&rhs
) = default;
116 hobject_t(hobject_t
&&rhs
) = default;
117 hobject_t(hobject_t_max
&&singleton
) : hobject_t() {
120 hobject_t
&operator=(const hobject_t
&rhs
) = default;
121 hobject_t
&operator=(hobject_t
&&rhs
) = default;
122 hobject_t
&operator=(hobject_t_max
&&singleton
) {
128 // maximum sorted value.
129 static hobject_t_max
get_max() {
130 return hobject_t_max();
133 hobject_t(const object_t
& oid
, const std::string
& key
, snapid_t snap
,
134 uint32_t hash
, int64_t pool
, const std::string
& nspace
)
135 : oid(oid
), snap(snap
), hash(hash
), max(false),
136 pool(pool
), nspace(nspace
),
137 key(oid
.name
== key
? std::string() : key
) {
141 hobject_t(const sobject_t
&soid
, const std::string
&key
, uint32_t hash
,
142 int64_t pool
, const std::string
& nspace
)
143 : oid(soid
.oid
), snap(soid
.snap
), hash(hash
), max(false),
144 pool(pool
), nspace(nspace
),
145 key(soid
.oid
.name
== key
? std::string() : key
) {
150 hobject_t(const std::string
&key
, snapid_t snap
, uint32_t reversed_hash
,
151 int64_t pool
, const std::string
& nspace
)
152 : oid(key
), snap(snap
), max(false), pool(pool
), nspace(nspace
) {
153 set_bitwise_key_u32(reversed_hash
);
156 /// @return min hobject_t ret s.t. ret.hash == this->hash
157 hobject_t
get_boundary() const {
166 hobject_t
get_object_boundary() const {
169 hobject_t ret
= *this;
174 /// @return head version of this hobject_t
175 hobject_t
get_head() const {
176 hobject_t
ret(*this);
177 ret
.snap
= CEPH_NOSNAP
;
181 /// @return snapdir version of this hobject_t
182 hobject_t
get_snapdir() const {
183 hobject_t
ret(*this);
184 ret
.snap
= CEPH_SNAPDIR
;
188 /// @return true if object is snapdir
189 bool is_snapdir() const {
190 return snap
== CEPH_SNAPDIR
;
193 /// @return true if object is head
194 bool is_head() const {
195 return snap
== CEPH_NOSNAP
;
198 /// @return true if object is neither head nor snapdir nor max
199 bool is_snap() const {
200 return !is_max() && !is_head() && !is_snapdir();
203 /// @return true iff the object should have a snapset in it's attrs
204 bool has_snapset() const {
205 return is_head() || is_snapdir();
208 /* Do not use when a particular hash function is needed */
209 explicit hobject_t(const sobject_t
&o
) :
210 oid(o
.oid
), snap(o
.snap
), max(false), pool(POOL_META
) {
211 set_hash(std::hash
<sobject_t
>()(o
));
214 bool is_max() const {
215 ceph_assert(!max
|| (*this == hobject_t(hobject_t::get_max())));
218 bool is_min() const {
219 // this needs to match how it's constructed
226 static uint32_t _reverse_bits(uint32_t v
) {
227 return reverse_bits(v
);
229 static uint32_t _reverse_nibbles(uint32_t retval
) {
230 return reverse_nibbles(retval
);
234 * Returns set S of strings such that for any object
235 * h where h.match(bits, mask), there is some string
236 * s \f$\in\f$ S such that s is a prefix of h.to_str().
237 * Furthermore, for any s \f$\in\f$ S, s is a prefix of
238 * h.str() implies that h.match(bits, mask).
240 static std::set
<std::string
> get_prefixes(
245 // filestore nibble-based key
246 uint32_t get_nibblewise_key_u32() const {
248 return nibblewise_key_cache
;
250 uint64_t get_nibblewise_key() const {
251 return max
? 0x100000000ull
: nibblewise_key_cache
;
254 // newer bit-reversed key
255 uint32_t get_bitwise_key_u32() const {
257 return hash_reverse_bits
;
259 uint64_t get_bitwise_key() const {
260 return max
? 0x100000000ull
: hash_reverse_bits
;
263 // please remember to update set_bitwise_key_u32() also
264 // once you change build_hash_cache()
265 void build_hash_cache() {
266 nibblewise_key_cache
= _reverse_nibbles(hash
);
267 hash_reverse_bits
= _reverse_bits(hash
);
269 void set_bitwise_key_u32(uint32_t value
) {
270 hash
= _reverse_bits(value
);
271 // below is identical to build_hash_cache() and shall be
272 // updated correspondingly if you change build_hash_cache()
273 nibblewise_key_cache
= _reverse_nibbles(hash
);
274 hash_reverse_bits
= value
;
277 const std::string
& get_effective_key() const {
283 hobject_t
make_temp_hobject(const std::string
& name
) const {
284 return hobject_t(object_t(name
), "", CEPH_NOSNAP
,
290 void swap(hobject_t
&o
) {
296 const std::string
&get_namespace() const {
300 bool parse(const std::string
& s
);
302 void encode(ceph::buffer::list
& bl
) const;
303 void decode(ceph::bufferlist::const_iterator
& bl
);
304 void decode(json_spirit::Value
& v
);
305 void dump(ceph::Formatter
*f
) const;
306 static void generate_test_instances(std::list
<hobject_t
*>& o
);
307 friend int cmp(const hobject_t
& l
, const hobject_t
& r
);
308 friend bool operator>(const hobject_t
& l
, const hobject_t
& r
) {
309 return cmp(l
, r
) > 0;
311 friend bool operator>=(const hobject_t
& l
, const hobject_t
& r
) {
312 return cmp(l
, r
) >= 0;
314 friend bool operator<(const hobject_t
& l
, const hobject_t
& r
) {
315 return cmp(l
, r
) < 0;
317 friend bool operator<=(const hobject_t
& l
, const hobject_t
& r
) {
318 return cmp(l
, r
) <= 0;
320 friend bool operator==(const hobject_t
&, const hobject_t
&);
321 friend bool operator!=(const hobject_t
&, const hobject_t
&);
322 friend struct ghobject_t
;
324 WRITE_CLASS_ENCODER(hobject_t
)
327 template<> struct hash
<hobject_t
> {
328 size_t operator()(const hobject_t
&r
) const {
329 static rjhash
<uint64_t> RJ
;
330 return RJ(r
.get_hash() ^ r
.snap
);
335 std::ostream
& operator<<(std::ostream
& out
, const hobject_t
& o
);
337 WRITE_EQ_OPERATORS_7(hobject_t
, hash
, oid
, get_key(), snap
, pool
, max
, nspace
)
339 template <typename T
>
340 struct always_false
{
341 using value
= std::false_type
;
344 template <typename T
>
345 inline bool operator==(const hobject_t
&lhs
, const T
&) {
346 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
349 template <typename T
>
350 inline bool operator==(const T
&, const hobject_t
&rhs
) {
351 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
354 template <typename T
>
355 inline bool operator!=(const hobject_t
&lhs
, const T
&) {
356 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
357 return !lhs
.is_max();
359 template <typename T
>
360 inline bool operator!=(const T
&, const hobject_t
&rhs
) {
361 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
362 return !rhs
.is_max();
365 extern int cmp(const hobject_t
& l
, const hobject_t
& r
);
366 template <typename T
>
367 static inline int cmp(const hobject_t
&l
, const T
&) {
368 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
369 return l
.is_max() ? 0 : -1;
371 template <typename T
>
372 static inline int cmp(const T
&, const hobject_t
&r
) {
373 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
374 return r
.is_max() ? 0 : 1;
379 typedef version_t gen_t
;
388 static const gen_t NO_GEN
= UINT64_MAX
;
391 : generation(NO_GEN
),
392 shard_id(shard_id_t::NO_SHARD
),
395 explicit ghobject_t(const hobject_t
&obj
)
398 shard_id(shard_id_t::NO_SHARD
),
401 ghobject_t(const hobject_t
&obj
, gen_t gen
, shard_id_t shard
)
408 ghobject_t(shard_id_t shard
, int64_t pool
, uint32_t reversed_hash
,
409 const std::string
& nspace
, const std::string
& oid
,
410 snapid_t snap
, gen_t gen
)
411 : hobj(oid
, snap
, reversed_hash
, pool
, nspace
),
416 static ghobject_t
make_pgmeta(int64_t pool
, uint32_t hash
, shard_id_t shard
) {
417 hobject_t
h(object_t(), std::string(), CEPH_NOSNAP
, hash
, pool
, std::string());
418 return ghobject_t(h
, NO_GEN
, shard
);
420 bool is_pgmeta() const {
421 // make sure we are distinct from hobject_t(), which has pool INT64_MIN
422 return hobj
.pool
>= 0 && hobj
.oid
.name
.empty();
425 bool match(uint32_t bits
, uint32_t match
) const {
426 return hobj
.match_hash(hobj
.hash
, bits
, match
);
428 /// @return min ghobject_t ret s.t. ret.hash == this->hash
429 ghobject_t
get_boundary() const {
433 ret
.hobj
.set_hash(hobj
.hash
);
434 ret
.shard_id
= shard_id
;
435 ret
.hobj
.pool
= hobj
.pool
;
438 uint32_t get_nibblewise_key_u32() const {
439 return hobj
.get_nibblewise_key_u32();
441 uint32_t get_nibblewise_key() const {
442 return hobj
.get_nibblewise_key();
445 bool is_degenerate() const {
446 return generation
== NO_GEN
&& shard_id
== shard_id_t::NO_SHARD
;
449 bool is_no_gen() const {
450 return generation
== NO_GEN
;
453 bool is_no_shard() const {
454 return shard_id
== shard_id_t::NO_SHARD
;
457 void set_shard(shard_id_t s
) {
461 bool parse(const std::string
& s
);
463 // maximum sorted value.
464 static ghobject_t
get_max() {
467 h
.hobj
= hobject_t::get_max(); // so that is_max() => hobj.is_max()
470 bool is_max() const {
473 bool is_min() const {
474 return *this == ghobject_t();
477 void swap(ghobject_t
&o
) {
483 void encode(ceph::buffer::list
& bl
) const;
484 void decode(ceph::buffer::list::const_iterator
& bl
);
485 void decode(json_spirit::Value
& v
);
486 size_t encoded_size() const;
487 void dump(ceph::Formatter
*f
) const;
488 static void generate_test_instances(std::list
<ghobject_t
*>& o
);
489 friend int cmp(const ghobject_t
& l
, const ghobject_t
& r
);
490 friend bool operator>(const ghobject_t
& l
, const ghobject_t
& r
) {
491 return cmp(l
, r
) > 0;
493 friend bool operator>=(const ghobject_t
& l
, const ghobject_t
& r
) {
494 return cmp(l
, r
) >= 0;
496 friend bool operator<(const ghobject_t
& l
, const ghobject_t
& r
) {
497 return cmp(l
, r
) < 0;
499 friend bool operator<=(const ghobject_t
& l
, const ghobject_t
& r
) {
500 return cmp(l
, r
) <= 0;
502 friend bool operator==(const ghobject_t
&, const ghobject_t
&);
503 friend bool operator!=(const ghobject_t
&, const ghobject_t
&);
506 WRITE_CLASS_ENCODER(ghobject_t
)
509 template<> struct hash
<ghobject_t
> {
510 size_t operator()(const ghobject_t
&r
) const {
511 static rjhash
<uint64_t> RJ
;
512 static hash
<hobject_t
> HO
;
513 size_t hash
= HO(r
.hobj
);
514 hash
= RJ(hash
^ r
.generation
);
515 hash
= hash
^ r
.shard_id
.id
;
521 std::ostream
& operator<<(std::ostream
& out
, const ghobject_t
& o
);
523 WRITE_EQ_OPERATORS_4(ghobject_t
, max
, shard_id
, hobj
, generation
)
525 extern int cmp(const ghobject_t
& l
, const ghobject_t
& r
);