]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/hobject.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / common / hobject.h
CommitLineData
7c673cae
FG
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) 2004-2006 Sage Weil <sage@newdream.net>
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 __CEPH_OS_HOBJECT_H
16#define __CEPH_OS_HOBJECT_H
17
7c673cae 18#include "include/types.h"
7c673cae
FG
19#include "include/cmp.h"
20
21#include "json_spirit/json_spirit_value.h"
11fdf7f2 22#include "include/ceph_assert.h" // spirit clobbers it!
7c673cae 23
31f18b77
FG
24#include "reverse.h"
25
7c673cae
FG
26namespace ceph {
27 class Formatter;
28}
29
30#ifndef UINT64_MAX
31#define UINT64_MAX (18446744073709551615ULL)
32#endif
33#ifndef INT64_MIN
34#define INT64_MIN ((int64_t)0x8000000000000000ll)
35#endif
36
37struct hobject_t {
f64942e4
AA
38public:
39 static const int64_t POOL_META = -1;
40 static const int64_t POOL_TEMP_START = -2; // and then negative
41
42 static bool is_temp_pool(int64_t pool) {
43 return pool <= POOL_TEMP_START;
44 }
45 static int64_t get_temp_pool(int64_t pool) {
46 return POOL_TEMP_START - pool;
47 }
48 static bool is_meta_pool(int64_t pool) {
49 return pool == POOL_META;
50 }
51
52public:
7c673cae
FG
53 object_t oid;
54 snapid_t snap;
55private:
56 uint32_t hash;
57 bool max;
58 uint32_t nibblewise_key_cache;
59 uint32_t hash_reverse_bits;
7c673cae
FG
60public:
61 int64_t pool;
9f95a23c 62 std::string nspace;
7c673cae
FG
63
64private:
9f95a23c 65 std::string key;
7c673cae
FG
66
67 class hobject_t_max {};
68
69public:
9f95a23c 70 const std::string& get_key() const {
7c673cae
FG
71 return key;
72 }
73
9f95a23c 74 void set_key(const std::string& key_) {
7c673cae
FG
75 if (key_ == oid.name)
76 key.clear();
77 else
78 key = key_;
79 }
80
9f95a23c 81 std::string to_str() const;
7c673cae
FG
82
83 uint32_t get_hash() const {
84 return hash;
85 }
86 void set_hash(uint32_t value) {
87 hash = value;
88 build_hash_cache();
89 }
90
91 static bool match_hash(uint32_t to_check, uint32_t bits, uint32_t match) {
92 return (match & ~((~0)<<bits)) == (to_check & ~((~0)<<bits));
93 }
94 bool match(uint32_t bits, uint32_t match) const {
95 return match_hash(hash, bits, match);
96 }
97
98 bool is_temp() const {
f64942e4 99 return is_temp_pool(pool) && pool != INT64_MIN;
7c673cae
FG
100 }
101 bool is_meta() const {
f64942e4
AA
102 return is_meta_pool(pool);
103 }
104 int64_t get_logical_pool() const {
105 if (is_temp_pool(pool))
106 return get_temp_pool(pool); // it's reversible
107 else
108 return pool;
7c673cae
FG
109 }
110
111 hobject_t() : snap(0), hash(0), max(false), pool(INT64_MIN) {
112 build_hash_cache();
113 }
114
115 hobject_t(const hobject_t &rhs) = default;
116 hobject_t(hobject_t &&rhs) = default;
117 hobject_t(hobject_t_max &&singleton) : hobject_t() {
118 max = true;
119 }
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) {
123 *this = hobject_t();
124 max = true;
125 return *this;
126 }
127
128 // maximum sorted value.
129 static hobject_t_max get_max() {
130 return hobject_t_max();
131 }
132
9f95a23c
TL
133 hobject_t(object_t oid, const std::string& key, snapid_t snap, uint32_t hash,
134 int64_t pool, std::string nspace)
7c673cae
FG
135 : oid(oid), snap(snap), hash(hash), max(false),
136 pool(pool), nspace(nspace),
9f95a23c 137 key(oid.name == key ? std::string() : key) {
7c673cae
FG
138 build_hash_cache();
139 }
140
9f95a23c
TL
141 hobject_t(const sobject_t &soid, const std::string &key, uint32_t hash,
142 int64_t pool, std::string nspace)
7c673cae
FG
143 : oid(soid.oid), snap(soid.snap), hash(hash), max(false),
144 pool(pool), nspace(nspace),
9f95a23c 145 key(soid.oid.name == key ? std::string() : key) {
7c673cae
FG
146 build_hash_cache();
147 }
148
149 /// @return min hobject_t ret s.t. ret.hash == this->hash
150 hobject_t get_boundary() const {
151 if (is_max())
152 return *this;
153 hobject_t ret;
154 ret.set_hash(hash);
155 ret.pool = pool;
156 return ret;
157 }
158
159 hobject_t get_object_boundary() const {
160 if (is_max())
161 return *this;
162 hobject_t ret = *this;
163 ret.snap = 0;
164 return ret;
165 }
166
167 /// @return head version of this hobject_t
168 hobject_t get_head() const {
169 hobject_t ret(*this);
170 ret.snap = CEPH_NOSNAP;
171 return ret;
172 }
173
174 /// @return snapdir version of this hobject_t
175 hobject_t get_snapdir() const {
176 hobject_t ret(*this);
177 ret.snap = CEPH_SNAPDIR;
178 return ret;
179 }
180
181 /// @return true if object is snapdir
182 bool is_snapdir() const {
183 return snap == CEPH_SNAPDIR;
184 }
185
186 /// @return true if object is head
187 bool is_head() const {
188 return snap == CEPH_NOSNAP;
189 }
190
191 /// @return true if object is neither head nor snapdir nor max
192 bool is_snap() const {
193 return !is_max() && !is_head() && !is_snapdir();
194 }
195
196 /// @return true iff the object should have a snapset in it's attrs
197 bool has_snapset() const {
198 return is_head() || is_snapdir();
199 }
200
201 /* Do not use when a particular hash function is needed */
202 explicit hobject_t(const sobject_t &o) :
203 oid(o.oid), snap(o.snap), max(false), pool(POOL_META) {
204 set_hash(std::hash<sobject_t>()(o));
205 }
206
207 bool is_max() const {
11fdf7f2 208 ceph_assert(!max || (*this == hobject_t(hobject_t::get_max())));
7c673cae
FG
209 return max;
210 }
211 bool is_min() const {
212 // this needs to match how it's constructed
213 return snap == 0 &&
214 hash == 0 &&
215 !max &&
216 pool == INT64_MIN;
217 }
218
219 static uint32_t _reverse_bits(uint32_t v) {
31f18b77 220 return reverse_bits(v);
7c673cae
FG
221 }
222 static uint32_t _reverse_nibbles(uint32_t retval) {
31f18b77 223 return reverse_nibbles(retval);
7c673cae
FG
224 }
225
226 /**
227 * Returns set S of strings such that for any object
228 * h where h.match(bits, mask), there is some string
229 * s \f$\in\f$ S such that s is a prefix of h.to_str().
9f95a23c 230 * Furthermore, for any s \f$\in\f$ S, s is a prefix of
7c673cae
FG
231 * h.str() implies that h.match(bits, mask).
232 */
9f95a23c 233 static std::set<std::string> get_prefixes(
7c673cae
FG
234 uint32_t bits,
235 uint32_t mask,
236 int64_t pool);
237
238 // filestore nibble-based key
239 uint32_t get_nibblewise_key_u32() const {
11fdf7f2 240 ceph_assert(!max);
7c673cae
FG
241 return nibblewise_key_cache;
242 }
243 uint64_t get_nibblewise_key() const {
244 return max ? 0x100000000ull : nibblewise_key_cache;
245 }
246
247 // newer bit-reversed key
248 uint32_t get_bitwise_key_u32() const {
11fdf7f2 249 ceph_assert(!max);
7c673cae
FG
250 return hash_reverse_bits;
251 }
252 uint64_t get_bitwise_key() const {
253 return max ? 0x100000000ull : hash_reverse_bits;
254 }
255
256 // please remember to update set_bitwise_key_u32() also
257 // once you change build_hash_cache()
258 void build_hash_cache() {
259 nibblewise_key_cache = _reverse_nibbles(hash);
260 hash_reverse_bits = _reverse_bits(hash);
261 }
262 void set_bitwise_key_u32(uint32_t value) {
263 hash = _reverse_bits(value);
264 // below is identical to build_hash_cache() and shall be
265 // updated correspondingly if you change build_hash_cache()
266 nibblewise_key_cache = _reverse_nibbles(hash);
267 hash_reverse_bits = value;
268 }
269
9f95a23c 270 const std::string& get_effective_key() const {
7c673cae
FG
271 if (key.length())
272 return key;
273 return oid.name;
274 }
275
9f95a23c 276 hobject_t make_temp_hobject(const std::string& name) const {
7c673cae
FG
277 return hobject_t(object_t(name), "", CEPH_NOSNAP,
278 hash,
f64942e4
AA
279 get_temp_pool(pool),
280 "");
7c673cae
FG
281 }
282
283 void swap(hobject_t &o) {
284 hobject_t temp(o);
285 o = (*this);
286 (*this) = temp;
287 }
288
9f95a23c 289 const std::string &get_namespace() const {
7c673cae
FG
290 return nspace;
291 }
292
9f95a23c 293 bool parse(const std::string& s);
7c673cae 294
9f95a23c
TL
295 void encode(ceph::buffer::list& bl) const;
296 void decode(ceph::bufferlist::const_iterator& bl);
7c673cae 297 void decode(json_spirit::Value& v);
9f95a23c
TL
298 void dump(ceph::Formatter *f) const;
299 static void generate_test_instances(std::list<hobject_t*>& o);
7c673cae
FG
300 friend int cmp(const hobject_t& l, const hobject_t& r);
301 friend bool operator>(const hobject_t& l, const hobject_t& r) {
302 return cmp(l, r) > 0;
303 }
304 friend bool operator>=(const hobject_t& l, const hobject_t& r) {
305 return cmp(l, r) >= 0;
306 }
307 friend bool operator<(const hobject_t& l, const hobject_t& r) {
308 return cmp(l, r) < 0;
309 }
310 friend bool operator<=(const hobject_t& l, const hobject_t& r) {
311 return cmp(l, r) <= 0;
312 }
313 friend bool operator==(const hobject_t&, const hobject_t&);
314 friend bool operator!=(const hobject_t&, const hobject_t&);
315 friend struct ghobject_t;
316};
317WRITE_CLASS_ENCODER(hobject_t)
318
319namespace std {
9f95a23c
TL
320template<> struct hash<hobject_t> {
321 size_t operator()(const hobject_t &r) const {
322 static rjhash<uint64_t> RJ;
323 return RJ(r.get_hash() ^ r.snap);
324 }
325};
7c673cae
FG
326} // namespace std
327
9f95a23c 328std::ostream& operator<<(std::ostream& out, const hobject_t& o);
7c673cae
FG
329
330WRITE_EQ_OPERATORS_7(hobject_t, hash, oid, get_key(), snap, pool, max, nspace)
331
332template <typename T>
333struct always_false {
334 using value = std::false_type;
335};
336
337template <typename T>
338inline bool operator==(const hobject_t &lhs, const T&) {
339 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
340 return lhs.is_max();
341}
342template <typename T>
343inline bool operator==(const T&, const hobject_t &rhs) {
344 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
345 return rhs.is_max();
346}
347template <typename T>
348inline bool operator!=(const hobject_t &lhs, const T&) {
349 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
350 return !lhs.is_max();
351}
352template <typename T>
353inline bool operator!=(const T&, const hobject_t &rhs) {
354 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
355 return !rhs.is_max();
356}
357
358extern int cmp(const hobject_t& l, const hobject_t& r);
359template <typename T>
360static inline int cmp(const hobject_t &l, const T&) {
361 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
362 return l.is_max() ? 0 : -1;
363}
364template <typename T>
365static inline int cmp(const T&, const hobject_t&r) {
366 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
367 return r.is_max() ? 0 : 1;
368}
369
370
371
372typedef version_t gen_t;
373
374struct ghobject_t {
375 hobject_t hobj;
376 gen_t generation;
377 shard_id_t shard_id;
378 bool max;
379
380public:
381 static const gen_t NO_GEN = UINT64_MAX;
382
383 ghobject_t()
384 : generation(NO_GEN),
385 shard_id(shard_id_t::NO_SHARD),
386 max(false) {}
387
388 explicit ghobject_t(const hobject_t &obj)
389 : hobj(obj),
390 generation(NO_GEN),
391 shard_id(shard_id_t::NO_SHARD),
392 max(false) {}
393
394 ghobject_t(const hobject_t &obj, gen_t gen, shard_id_t shard)
395 : hobj(obj),
396 generation(gen),
397 shard_id(shard),
398 max(false) {}
399
f67539c2
TL
400 ghobject_t(shard_id_t shard, int64_t pool, uint32_t hash,
401 const std::string& nspace, const std::string& oid,
402 snapid_t snap, gen_t gen)
403 : hobj(object_t(oid), "", snap, hash, pool, nspace),
404 generation(gen),
405 shard_id(shard),
406 max(false) {}
407
7c673cae 408 static ghobject_t make_pgmeta(int64_t pool, uint32_t hash, shard_id_t shard) {
9f95a23c 409 hobject_t h(object_t(), std::string(), CEPH_NOSNAP, hash, pool, std::string());
7c673cae
FG
410 return ghobject_t(h, NO_GEN, shard);
411 }
412 bool is_pgmeta() const {
413 // make sure we are distinct from hobject_t(), which has pool INT64_MIN
414 return hobj.pool >= 0 && hobj.oid.name.empty();
415 }
416
417 bool match(uint32_t bits, uint32_t match) const {
418 return hobj.match_hash(hobj.hash, bits, match);
419 }
420 /// @return min ghobject_t ret s.t. ret.hash == this->hash
421 ghobject_t get_boundary() const {
422 if (hobj.is_max())
423 return *this;
424 ghobject_t ret;
425 ret.hobj.set_hash(hobj.hash);
426 ret.shard_id = shard_id;
427 ret.hobj.pool = hobj.pool;
428 return ret;
429 }
430 uint32_t get_nibblewise_key_u32() const {
431 return hobj.get_nibblewise_key_u32();
432 }
433 uint32_t get_nibblewise_key() const {
434 return hobj.get_nibblewise_key();
435 }
436
437 bool is_degenerate() const {
438 return generation == NO_GEN && shard_id == shard_id_t::NO_SHARD;
439 }
440
441 bool is_no_gen() const {
442 return generation == NO_GEN;
443 }
444
445 bool is_no_shard() const {
446 return shard_id == shard_id_t::NO_SHARD;
447 }
448
449 void set_shard(shard_id_t s) {
450 shard_id = s;
451 }
452
9f95a23c 453 bool parse(const std::string& s);
7c673cae
FG
454
455 // maximum sorted value.
456 static ghobject_t get_max() {
457 ghobject_t h;
458 h.max = true;
459 h.hobj = hobject_t::get_max(); // so that is_max() => hobj.is_max()
460 return h;
461 }
462 bool is_max() const {
463 return max;
464 }
465 bool is_min() const {
466 return *this == ghobject_t();
467 }
468
469 void swap(ghobject_t &o) {
470 ghobject_t temp(o);
471 o = (*this);
472 (*this) = temp;
473 }
474
9f95a23c
TL
475 void encode(ceph::buffer::list& bl) const;
476 void decode(ceph::buffer::list::const_iterator& bl);
7c673cae
FG
477 void decode(json_spirit::Value& v);
478 size_t encoded_size() const;
9f95a23c
TL
479 void dump(ceph::Formatter *f) const;
480 static void generate_test_instances(std::list<ghobject_t*>& o);
7c673cae
FG
481 friend int cmp(const ghobject_t& l, const ghobject_t& r);
482 friend bool operator>(const ghobject_t& l, const ghobject_t& r) {
483 return cmp(l, r) > 0;
484 }
485 friend bool operator>=(const ghobject_t& l, const ghobject_t& r) {
486 return cmp(l, r) >= 0;
487 }
488 friend bool operator<(const ghobject_t& l, const ghobject_t& r) {
489 return cmp(l, r) < 0;
490 }
491 friend bool operator<=(const ghobject_t& l, const ghobject_t& r) {
492 return cmp(l, r) <= 0;
493 }
494 friend bool operator==(const ghobject_t&, const ghobject_t&);
495 friend bool operator!=(const ghobject_t&, const ghobject_t&);
496
497};
498WRITE_CLASS_ENCODER(ghobject_t)
499
500namespace std {
501 template<> struct hash<ghobject_t> {
502 size_t operator()(const ghobject_t &r) const {
1adf2230
AA
503 static rjhash<uint64_t> RJ;
504 static hash<hobject_t> HO;
505 size_t hash = HO(r.hobj);
506 hash = RJ(hash ^ r.generation);
507 hash = hash ^ r.shard_id.id;
508 return hash;
7c673cae
FG
509 }
510 };
511} // namespace std
512
9f95a23c 513std::ostream& operator<<(std::ostream& out, const ghobject_t& o);
7c673cae
FG
514
515WRITE_EQ_OPERATORS_4(ghobject_t, max, shard_id, hobj, generation)
516
517extern int cmp(const ghobject_t& l, const ghobject_t& r);
518
519
520#endif