]>
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
19 #include "include/types.h"
20 #include "include/object.h"
21 #include "include/cmp.h"
23 #include "json_spirit/json_spirit_value.h"
24 #include "include/assert.h" // spirit clobbers it!
31 #define UINT64_MAX (18446744073709551615ULL)
34 #define INT64_MIN ((int64_t)0x8000000000000000ll)
43 uint32_t nibblewise_key_cache
;
44 uint32_t hash_reverse_bits
;
45 static const int64_t POOL_META
= -1;
46 static const int64_t POOL_TEMP_START
= -2; // and then negative
47 friend class spg_t
; // for POOL_TEMP_START
55 class hobject_t_max
{};
58 const string
&get_key() const {
62 void set_key(const std::string
&key_
) {
69 string
to_str() const;
71 uint32_t get_hash() const {
74 void set_hash(uint32_t value
) {
79 static bool match_hash(uint32_t to_check
, uint32_t bits
, uint32_t match
) {
80 return (match
& ~((~0)<<bits
)) == (to_check
& ~((~0)<<bits
));
82 bool match(uint32_t bits
, uint32_t match
) const {
83 return match_hash(hash
, bits
, match
);
86 bool is_temp() const {
87 return pool
<= POOL_TEMP_START
&& pool
!= INT64_MIN
;
89 bool is_meta() const {
90 return pool
== POOL_META
;
93 hobject_t() : snap(0), hash(0), max(false), pool(INT64_MIN
) {
97 hobject_t(const hobject_t
&rhs
) = default;
98 hobject_t(hobject_t
&&rhs
) = default;
99 hobject_t(hobject_t_max
&&singleton
) : hobject_t() {
102 hobject_t
&operator=(const hobject_t
&rhs
) = default;
103 hobject_t
&operator=(hobject_t
&&rhs
) = default;
104 hobject_t
&operator=(hobject_t_max
&&singleton
) {
110 // maximum sorted value.
111 static hobject_t_max
get_max() {
112 return hobject_t_max();
115 hobject_t(object_t oid
, const string
& key
, snapid_t snap
, uint32_t hash
,
116 int64_t pool
, string nspace
)
117 : oid(oid
), snap(snap
), hash(hash
), max(false),
118 pool(pool
), nspace(nspace
),
119 key(oid
.name
== key
? string() : key
) {
123 hobject_t(const sobject_t
&soid
, const string
&key
, uint32_t hash
,
124 int64_t pool
, string nspace
)
125 : oid(soid
.oid
), snap(soid
.snap
), hash(hash
), max(false),
126 pool(pool
), nspace(nspace
),
127 key(soid
.oid
.name
== key
? string() : key
) {
131 /// @return min hobject_t ret s.t. ret.hash == this->hash
132 hobject_t
get_boundary() const {
141 hobject_t
get_object_boundary() const {
144 hobject_t ret
= *this;
149 /// @return head version of this hobject_t
150 hobject_t
get_head() const {
151 hobject_t
ret(*this);
152 ret
.snap
= CEPH_NOSNAP
;
156 /// @return snapdir version of this hobject_t
157 hobject_t
get_snapdir() const {
158 hobject_t
ret(*this);
159 ret
.snap
= CEPH_SNAPDIR
;
163 /// @return true if object is snapdir
164 bool is_snapdir() const {
165 return snap
== CEPH_SNAPDIR
;
168 /// @return true if object is head
169 bool is_head() const {
170 return snap
== CEPH_NOSNAP
;
173 /// @return true if object is neither head nor snapdir nor max
174 bool is_snap() const {
175 return !is_max() && !is_head() && !is_snapdir();
178 /// @return true iff the object should have a snapset in it's attrs
179 bool has_snapset() const {
180 return is_head() || is_snapdir();
183 /* Do not use when a particular hash function is needed */
184 explicit hobject_t(const sobject_t
&o
) :
185 oid(o
.oid
), snap(o
.snap
), max(false), pool(POOL_META
) {
186 set_hash(std::hash
<sobject_t
>()(o
));
189 bool is_max() const {
190 assert(!max
|| (*this == hobject_t(hobject_t::get_max())));
193 bool is_min() const {
194 // this needs to match how it's constructed
201 static uint32_t _reverse_bits(uint32_t v
) {
205 // swap odd and even bits
206 v
= ((v
>> 1) & 0x55555555) | ((v
& 0x55555555) << 1);
207 // swap consecutive pairs
208 v
= ((v
>> 2) & 0x33333333) | ((v
& 0x33333333) << 2);
210 v
= ((v
>> 4) & 0x0F0F0F0F) | ((v
& 0x0F0F0F0F) << 4);
212 v
= ((v
>> 8) & 0x00FF00FF) | ((v
& 0x00FF00FF) << 8);
213 // swap 2-byte long pairs
214 v
= ( v
>> 16 ) | ( v
<< 16);
217 static uint32_t _reverse_nibbles(uint32_t retval
) {
219 retval
= ((retval
& 0x0f0f0f0f) << 4) | ((retval
& 0xf0f0f0f0) >> 4);
220 retval
= ((retval
& 0x00ff00ff) << 8) | ((retval
& 0xff00ff00) >> 8);
221 retval
= ((retval
& 0x0000ffff) << 16) | ((retval
& 0xffff0000) >> 16);
226 * Returns set S of strings such that for any object
227 * h where h.match(bits, mask), there is some string
228 * s \f$\in\f$ S such that s is a prefix of h.to_str().
229 * Furthermore, for any s $f\in\f$ S, s is a prefix of
230 * h.str() implies that h.match(bits, mask).
232 static set
<string
> get_prefixes(
237 // filestore nibble-based key
238 uint32_t get_nibblewise_key_u32() const {
240 return nibblewise_key_cache
;
242 uint64_t get_nibblewise_key() const {
243 return max
? 0x100000000ull
: nibblewise_key_cache
;
246 // newer bit-reversed key
247 uint32_t get_bitwise_key_u32() const {
249 return hash_reverse_bits
;
251 uint64_t get_bitwise_key() const {
252 return max
? 0x100000000ull
: hash_reverse_bits
;
255 // please remember to update set_bitwise_key_u32() also
256 // once you change build_hash_cache()
257 void build_hash_cache() {
258 nibblewise_key_cache
= _reverse_nibbles(hash
);
259 hash_reverse_bits
= _reverse_bits(hash
);
261 void set_bitwise_key_u32(uint32_t value
) {
262 hash
= _reverse_bits(value
);
263 // below is identical to build_hash_cache() and shall be
264 // updated correspondingly if you change build_hash_cache()
265 nibblewise_key_cache
= _reverse_nibbles(hash
);
266 hash_reverse_bits
= value
;
269 const string
& get_effective_key() const {
275 hobject_t
make_temp_hobject(const string
& name
) const {
276 return hobject_t(object_t(name
), "", CEPH_NOSNAP
,
278 hobject_t::POOL_TEMP_START
- pool
, "");
281 void swap(hobject_t
&o
) {
287 const string
&get_namespace() const {
291 bool parse(const string
& s
);
293 void encode(bufferlist
& bl
) const;
294 void decode(bufferlist::iterator
& bl
);
295 void decode(json_spirit::Value
& v
);
296 void dump(Formatter
*f
) const;
297 static void generate_test_instances(list
<hobject_t
*>& o
);
298 friend int cmp(const hobject_t
& l
, const hobject_t
& r
);
299 friend bool operator>(const hobject_t
& l
, const hobject_t
& r
) {
300 return cmp(l
, r
) > 0;
302 friend bool operator>=(const hobject_t
& l
, const hobject_t
& r
) {
303 return cmp(l
, r
) >= 0;
305 friend bool operator<(const hobject_t
& l
, const hobject_t
& r
) {
306 return cmp(l
, r
) < 0;
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
&, const hobject_t
&);
312 friend bool operator!=(const hobject_t
&, const hobject_t
&);
313 friend struct ghobject_t
;
315 WRITE_CLASS_ENCODER(hobject_t
)
318 template<> struct hash
<hobject_t
> {
319 size_t operator()(const hobject_t
&r
) const {
320 static rjhash
<uint64_t> I
;
321 return r
.get_hash() ^ I(r
.snap
);
326 ostream
& operator<<(ostream
& out
, const hobject_t
& o
);
328 WRITE_EQ_OPERATORS_7(hobject_t
, hash
, oid
, get_key(), snap
, pool
, max
, nspace
)
330 template <typename T
>
331 struct always_false
{
332 using value
= std::false_type
;
335 template <typename T
>
336 inline bool operator==(const hobject_t
&lhs
, const T
&) {
337 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
340 template <typename T
>
341 inline bool operator==(const T
&, const hobject_t
&rhs
) {
342 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
345 template <typename T
>
346 inline bool operator!=(const hobject_t
&lhs
, const T
&) {
347 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
348 return !lhs
.is_max();
350 template <typename T
>
351 inline bool operator!=(const T
&, const hobject_t
&rhs
) {
352 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
353 return !rhs
.is_max();
356 extern int cmp(const hobject_t
& l
, const hobject_t
& r
);
357 template <typename T
>
358 static inline int cmp(const hobject_t
&l
, const T
&) {
359 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
360 return l
.is_max() ? 0 : -1;
362 template <typename T
>
363 static inline int cmp(const T
&, const hobject_t
&r
) {
364 static_assert(always_false
<T
>::value::value
, "Do not compare to get_max()");
365 return r
.is_max() ? 0 : 1;
370 typedef version_t gen_t
;
379 static const gen_t NO_GEN
= UINT64_MAX
;
382 : generation(NO_GEN
),
383 shard_id(shard_id_t::NO_SHARD
),
386 explicit ghobject_t(const hobject_t
&obj
)
389 shard_id(shard_id_t::NO_SHARD
),
392 ghobject_t(const hobject_t
&obj
, gen_t gen
, shard_id_t shard
)
398 static ghobject_t
make_pgmeta(int64_t pool
, uint32_t hash
, shard_id_t shard
) {
399 hobject_t
h(object_t(), string(), CEPH_NOSNAP
, hash
, pool
, string());
400 return ghobject_t(h
, NO_GEN
, shard
);
402 bool is_pgmeta() const {
403 // make sure we are distinct from hobject_t(), which has pool INT64_MIN
404 return hobj
.pool
>= 0 && hobj
.oid
.name
.empty();
407 bool match(uint32_t bits
, uint32_t match
) const {
408 return hobj
.match_hash(hobj
.hash
, bits
, match
);
410 /// @return min ghobject_t ret s.t. ret.hash == this->hash
411 ghobject_t
get_boundary() const {
415 ret
.hobj
.set_hash(hobj
.hash
);
416 ret
.shard_id
= shard_id
;
417 ret
.hobj
.pool
= hobj
.pool
;
420 uint32_t get_nibblewise_key_u32() const {
421 return hobj
.get_nibblewise_key_u32();
423 uint32_t get_nibblewise_key() const {
424 return hobj
.get_nibblewise_key();
427 bool is_degenerate() const {
428 return generation
== NO_GEN
&& shard_id
== shard_id_t::NO_SHARD
;
431 bool is_no_gen() const {
432 return generation
== NO_GEN
;
435 bool is_no_shard() const {
436 return shard_id
== shard_id_t::NO_SHARD
;
439 void set_shard(shard_id_t s
) {
443 bool parse(const string
& s
);
445 // maximum sorted value.
446 static ghobject_t
get_max() {
449 h
.hobj
= hobject_t::get_max(); // so that is_max() => hobj.is_max()
452 bool is_max() const {
455 bool is_min() const {
456 return *this == ghobject_t();
459 void swap(ghobject_t
&o
) {
465 void encode(bufferlist
& bl
) const;
466 void decode(bufferlist::iterator
& bl
);
467 void decode(json_spirit::Value
& v
);
468 size_t encoded_size() const;
469 void dump(Formatter
*f
) const;
470 static void generate_test_instances(list
<ghobject_t
*>& o
);
471 friend int cmp(const ghobject_t
& l
, const ghobject_t
& r
);
472 friend bool operator>(const ghobject_t
& l
, const ghobject_t
& r
) {
473 return cmp(l
, r
) > 0;
475 friend bool operator>=(const ghobject_t
& l
, const ghobject_t
& r
) {
476 return cmp(l
, r
) >= 0;
478 friend bool operator<(const ghobject_t
& l
, const ghobject_t
& r
) {
479 return cmp(l
, r
) < 0;
481 friend bool operator<=(const ghobject_t
& l
, const ghobject_t
& r
) {
482 return cmp(l
, r
) <= 0;
484 friend bool operator==(const ghobject_t
&, const ghobject_t
&);
485 friend bool operator!=(const ghobject_t
&, const ghobject_t
&);
488 WRITE_CLASS_ENCODER(ghobject_t
)
491 template<> struct hash
<ghobject_t
> {
492 size_t operator()(const ghobject_t
&r
) const {
493 static rjhash
<uint64_t> I
;
494 return r
.hobj
.get_hash() ^ I(r
.hobj
.snap
);
499 ostream
& operator<<(ostream
& out
, const ghobject_t
& o
);
501 WRITE_EQ_OPERATORS_4(ghobject_t
, max
, shard_id
, hobj
, generation
)
503 extern int cmp(const ghobject_t
& l
, const ghobject_t
& r
);