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/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) {
202 return reverse_bits(v);
204 static uint32_t _reverse_nibbles(uint32_t retval) {
205 return reverse_nibbles(retval);
209 * Returns set S of strings such that for any object
210 * h where h.match(bits, mask), there is some string
211 * s \f$\in\f$ S such that s is a prefix of h.to_str().
212 * Furthermore, for any s $f\in\f$ S, s is a prefix of
213 * h.str() implies that h.match(bits, mask).
215 static set<string> get_prefixes(
220 // filestore nibble-based key
221 uint32_t get_nibblewise_key_u32() const {
223 return nibblewise_key_cache;
225 uint64_t get_nibblewise_key() const {
226 return max ? 0x100000000ull : nibblewise_key_cache;
229 // newer bit-reversed key
230 uint32_t get_bitwise_key_u32() const {
232 return hash_reverse_bits;
234 uint64_t get_bitwise_key() const {
235 return max ? 0x100000000ull : hash_reverse_bits;
238 // please remember to update set_bitwise_key_u32() also
239 // once you change build_hash_cache()
240 void build_hash_cache() {
241 nibblewise_key_cache = _reverse_nibbles(hash);
242 hash_reverse_bits = _reverse_bits(hash);
244 void set_bitwise_key_u32(uint32_t value) {
245 hash = _reverse_bits(value);
246 // below is identical to build_hash_cache() and shall be
247 // updated correspondingly if you change build_hash_cache()
248 nibblewise_key_cache = _reverse_nibbles(hash);
249 hash_reverse_bits = value;
252 const string& get_effective_key() const {
258 hobject_t make_temp_hobject(const string& name) const {
259 return hobject_t(object_t(name), "", CEPH_NOSNAP,
261 hobject_t::POOL_TEMP_START - pool, "");
264 void swap(hobject_t &o) {
270 const string &get_namespace() const {
274 bool parse(const string& s);
276 void encode(bufferlist& bl) const;
277 void decode(bufferlist::iterator& bl);
278 void decode(json_spirit::Value& v);
279 void dump(Formatter *f) const;
280 static void generate_test_instances(list<hobject_t*>& o);
281 friend int cmp(const hobject_t& l, const hobject_t& r);
282 friend bool operator>(const hobject_t& l, const hobject_t& r) {
283 return cmp(l, r) > 0;
285 friend bool operator>=(const hobject_t& l, const hobject_t& r) {
286 return cmp(l, r) >= 0;
288 friend bool operator<(const hobject_t& l, const hobject_t& r) {
289 return cmp(l, r) < 0;
291 friend bool operator<=(const hobject_t& l, const hobject_t& r) {
292 return cmp(l, r) <= 0;
294 friend bool operator==(const hobject_t&, const hobject_t&);
295 friend bool operator!=(const hobject_t&, const hobject_t&);
296 friend struct ghobject_t;
298 WRITE_CLASS_ENCODER(hobject_t)
301 template<> struct hash<hobject_t> {
302 size_t operator()(const hobject_t &r) const {
303 static rjhash<uint64_t> I;
304 return r.get_hash() ^ I(r.snap);
309 ostream& operator<<(ostream& out, const hobject_t& o);
311 WRITE_EQ_OPERATORS_7(hobject_t, hash, oid, get_key(), snap, pool, max, nspace)
313 template <typename T>
314 struct always_false {
315 using value = std::false_type;
318 template <typename T>
319 inline bool operator==(const hobject_t &lhs, const T&) {
320 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
323 template <typename T>
324 inline bool operator==(const T&, const hobject_t &rhs) {
325 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
328 template <typename T>
329 inline bool operator!=(const hobject_t &lhs, const T&) {
330 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
331 return !lhs.is_max();
333 template <typename T>
334 inline bool operator!=(const T&, const hobject_t &rhs) {
335 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
336 return !rhs.is_max();
339 extern int cmp(const hobject_t& l, const hobject_t& r);
340 template <typename T>
341 static inline int cmp(const hobject_t &l, const T&) {
342 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
343 return l.is_max() ? 0 : -1;
345 template <typename T>
346 static inline int cmp(const T&, const hobject_t&r) {
347 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
348 return r.is_max() ? 0 : 1;
353 typedef version_t gen_t;
362 static const gen_t NO_GEN = UINT64_MAX;
365 : generation(NO_GEN),
366 shard_id(shard_id_t::NO_SHARD),
369 explicit ghobject_t(const hobject_t &obj)
372 shard_id(shard_id_t::NO_SHARD),
375 ghobject_t(const hobject_t &obj, gen_t gen, shard_id_t shard)
381 static ghobject_t make_pgmeta(int64_t pool, uint32_t hash, shard_id_t shard) {
382 hobject_t h(object_t(), string(), CEPH_NOSNAP, hash, pool, string());
383 return ghobject_t(h, NO_GEN, shard);
385 bool is_pgmeta() const {
386 // make sure we are distinct from hobject_t(), which has pool INT64_MIN
387 return hobj.pool >= 0 && hobj.oid.name.empty();
390 bool match(uint32_t bits, uint32_t match) const {
391 return hobj.match_hash(hobj.hash, bits, match);
393 /// @return min ghobject_t ret s.t. ret.hash == this->hash
394 ghobject_t get_boundary() const {
398 ret.hobj.set_hash(hobj.hash);
399 ret.shard_id = shard_id;
400 ret.hobj.pool = hobj.pool;
403 uint32_t get_nibblewise_key_u32() const {
404 return hobj.get_nibblewise_key_u32();
406 uint32_t get_nibblewise_key() const {
407 return hobj.get_nibblewise_key();
410 bool is_degenerate() const {
411 return generation == NO_GEN && shard_id == shard_id_t::NO_SHARD;
414 bool is_no_gen() const {
415 return generation == NO_GEN;
418 bool is_no_shard() const {
419 return shard_id == shard_id_t::NO_SHARD;
422 void set_shard(shard_id_t s) {
426 bool parse(const string& s);
428 // maximum sorted value.
429 static ghobject_t get_max() {
432 h.hobj = hobject_t::get_max(); // so that is_max() => hobj.is_max()
435 bool is_max() const {
438 bool is_min() const {
439 return *this == ghobject_t();
442 void swap(ghobject_t &o) {
448 void encode(bufferlist& bl) const;
449 void decode(bufferlist::iterator& bl);
450 void decode(json_spirit::Value& v);
451 size_t encoded_size() const;
452 void dump(Formatter *f) const;
453 static void generate_test_instances(list<ghobject_t*>& o);
454 friend int cmp(const ghobject_t& l, const ghobject_t& r);
455 friend bool operator>(const ghobject_t& l, const ghobject_t& r) {
456 return cmp(l, r) > 0;
458 friend bool operator>=(const ghobject_t& l, const ghobject_t& r) {
459 return cmp(l, r) >= 0;
461 friend bool operator<(const ghobject_t& l, const ghobject_t& r) {
462 return cmp(l, r) < 0;
464 friend bool operator<=(const ghobject_t& l, const ghobject_t& r) {
465 return cmp(l, r) <= 0;
467 friend bool operator==(const ghobject_t&, const ghobject_t&);
468 friend bool operator!=(const ghobject_t&, const ghobject_t&);
471 WRITE_CLASS_ENCODER(ghobject_t)
474 template<> struct hash<ghobject_t> {
475 size_t operator()(const ghobject_t &r) const {
476 static rjhash<uint64_t> I;
477 return r.hobj.get_hash() ^ I(r.hobj.snap);
482 ostream& operator<<(ostream& out, const ghobject_t& o);
484 WRITE_EQ_OPERATORS_4(ghobject_t, max, shard_id, hobj, generation)
486 extern int cmp(const ghobject_t& l, const ghobject_t& r);