]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/hobject.h
import ceph quincy 17.2.4
[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
20effc67
TL
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)
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 141 hobject_t(const sobject_t &soid, const std::string &key, uint32_t hash,
20effc67 142 int64_t pool, const 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
20effc67
TL
149 // used by Crimson
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);
154 }
155
7c673cae
FG
156 /// @return min hobject_t ret s.t. ret.hash == this->hash
157 hobject_t get_boundary() const {
158 if (is_max())
159 return *this;
160 hobject_t ret;
161 ret.set_hash(hash);
162 ret.pool = pool;
163 return ret;
164 }
165
166 hobject_t get_object_boundary() const {
167 if (is_max())
168 return *this;
169 hobject_t ret = *this;
170 ret.snap = 0;
171 return ret;
172 }
173
174 /// @return head version of this hobject_t
175 hobject_t get_head() const {
176 hobject_t ret(*this);
177 ret.snap = CEPH_NOSNAP;
178 return ret;
179 }
180
181 /// @return snapdir version of this hobject_t
182 hobject_t get_snapdir() const {
183 hobject_t ret(*this);
184 ret.snap = CEPH_SNAPDIR;
185 return ret;
186 }
187
188 /// @return true if object is snapdir
189 bool is_snapdir() const {
190 return snap == CEPH_SNAPDIR;
191 }
192
193 /// @return true if object is head
194 bool is_head() const {
195 return snap == CEPH_NOSNAP;
196 }
197
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();
201 }
202
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();
206 }
207
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));
212 }
213
214 bool is_max() const {
11fdf7f2 215 ceph_assert(!max || (*this == hobject_t(hobject_t::get_max())));
7c673cae
FG
216 return max;
217 }
218 bool is_min() const {
219 // this needs to match how it's constructed
220 return snap == 0 &&
221 hash == 0 &&
222 !max &&
223 pool == INT64_MIN;
224 }
225
226 static uint32_t _reverse_bits(uint32_t v) {
31f18b77 227 return reverse_bits(v);
7c673cae
FG
228 }
229 static uint32_t _reverse_nibbles(uint32_t retval) {
31f18b77 230 return reverse_nibbles(retval);
7c673cae
FG
231 }
232
233 /**
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().
9f95a23c 237 * Furthermore, for any s \f$\in\f$ S, s is a prefix of
7c673cae
FG
238 * h.str() implies that h.match(bits, mask).
239 */
9f95a23c 240 static std::set<std::string> get_prefixes(
7c673cae
FG
241 uint32_t bits,
242 uint32_t mask,
243 int64_t pool);
244
245 // filestore nibble-based key
246 uint32_t get_nibblewise_key_u32() const {
11fdf7f2 247 ceph_assert(!max);
7c673cae
FG
248 return nibblewise_key_cache;
249 }
250 uint64_t get_nibblewise_key() const {
251 return max ? 0x100000000ull : nibblewise_key_cache;
252 }
253
254 // newer bit-reversed key
255 uint32_t get_bitwise_key_u32() const {
11fdf7f2 256 ceph_assert(!max);
7c673cae
FG
257 return hash_reverse_bits;
258 }
259 uint64_t get_bitwise_key() const {
260 return max ? 0x100000000ull : hash_reverse_bits;
261 }
262
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);
268 }
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;
275 }
276
9f95a23c 277 const std::string& get_effective_key() const {
7c673cae
FG
278 if (key.length())
279 return key;
280 return oid.name;
281 }
282
9f95a23c 283 hobject_t make_temp_hobject(const std::string& name) const {
7c673cae
FG
284 return hobject_t(object_t(name), "", CEPH_NOSNAP,
285 hash,
f64942e4
AA
286 get_temp_pool(pool),
287 "");
7c673cae
FG
288 }
289
290 void swap(hobject_t &o) {
291 hobject_t temp(o);
292 o = (*this);
293 (*this) = temp;
294 }
295
9f95a23c 296 const std::string &get_namespace() const {
7c673cae
FG
297 return nspace;
298 }
299
9f95a23c 300 bool parse(const std::string& s);
7c673cae 301
9f95a23c
TL
302 void encode(ceph::buffer::list& bl) const;
303 void decode(ceph::bufferlist::const_iterator& bl);
7c673cae 304 void decode(json_spirit::Value& v);
9f95a23c
TL
305 void dump(ceph::Formatter *f) const;
306 static void generate_test_instances(std::list<hobject_t*>& o);
7c673cae
FG
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;
310 }
311 friend bool operator>=(const hobject_t& l, const hobject_t& r) {
312 return cmp(l, r) >= 0;
313 }
314 friend bool operator<(const hobject_t& l, const hobject_t& r) {
315 return cmp(l, r) < 0;
316 }
317 friend bool operator<=(const hobject_t& l, const hobject_t& r) {
318 return cmp(l, r) <= 0;
319 }
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;
323};
324WRITE_CLASS_ENCODER(hobject_t)
325
326namespace std {
9f95a23c
TL
327template<> 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);
331 }
332};
7c673cae
FG
333} // namespace std
334
9f95a23c 335std::ostream& operator<<(std::ostream& out, const hobject_t& o);
7c673cae
FG
336
337WRITE_EQ_OPERATORS_7(hobject_t, hash, oid, get_key(), snap, pool, max, nspace)
338
339template <typename T>
340struct always_false {
341 using value = std::false_type;
342};
343
344template <typename T>
345inline bool operator==(const hobject_t &lhs, const T&) {
346 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
347 return lhs.is_max();
348}
349template <typename T>
350inline bool operator==(const T&, const hobject_t &rhs) {
351 static_assert(always_false<T>::value::value, "Do not compare to get_max()");
352 return rhs.is_max();
353}
354template <typename T>
355inline 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();
358}
359template <typename T>
360inline 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();
363}
364
365extern int cmp(const hobject_t& l, const hobject_t& r);
366template <typename T>
367static 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;
370}
371template <typename T>
372static 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;
375}
376
377
378
379typedef version_t gen_t;
380
381struct ghobject_t {
382 hobject_t hobj;
383 gen_t generation;
384 shard_id_t shard_id;
385 bool max;
386
387public:
388 static const gen_t NO_GEN = UINT64_MAX;
389
390 ghobject_t()
391 : generation(NO_GEN),
392 shard_id(shard_id_t::NO_SHARD),
393 max(false) {}
394
395 explicit ghobject_t(const hobject_t &obj)
396 : hobj(obj),
397 generation(NO_GEN),
398 shard_id(shard_id_t::NO_SHARD),
399 max(false) {}
400
401 ghobject_t(const hobject_t &obj, gen_t gen, shard_id_t shard)
402 : hobj(obj),
403 generation(gen),
404 shard_id(shard),
405 max(false) {}
406
20effc67
TL
407 // used by Crimson
408 ghobject_t(shard_id_t shard, int64_t pool, uint32_t reversed_hash,
f67539c2
TL
409 const std::string& nspace, const std::string& oid,
410 snapid_t snap, gen_t gen)
20effc67 411 : hobj(oid, snap, reversed_hash, pool, nspace),
f67539c2
TL
412 generation(gen),
413 shard_id(shard),
414 max(false) {}
415
7c673cae 416 static ghobject_t make_pgmeta(int64_t pool, uint32_t hash, shard_id_t shard) {
9f95a23c 417 hobject_t h(object_t(), std::string(), CEPH_NOSNAP, hash, pool, std::string());
7c673cae
FG
418 return ghobject_t(h, NO_GEN, shard);
419 }
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();
423 }
424
425 bool match(uint32_t bits, uint32_t match) const {
426 return hobj.match_hash(hobj.hash, bits, match);
427 }
428 /// @return min ghobject_t ret s.t. ret.hash == this->hash
429 ghobject_t get_boundary() const {
430 if (hobj.is_max())
431 return *this;
432 ghobject_t ret;
433 ret.hobj.set_hash(hobj.hash);
434 ret.shard_id = shard_id;
435 ret.hobj.pool = hobj.pool;
436 return ret;
437 }
438 uint32_t get_nibblewise_key_u32() const {
439 return hobj.get_nibblewise_key_u32();
440 }
441 uint32_t get_nibblewise_key() const {
442 return hobj.get_nibblewise_key();
443 }
444
445 bool is_degenerate() const {
446 return generation == NO_GEN && shard_id == shard_id_t::NO_SHARD;
447 }
448
449 bool is_no_gen() const {
450 return generation == NO_GEN;
451 }
452
453 bool is_no_shard() const {
454 return shard_id == shard_id_t::NO_SHARD;
455 }
456
457 void set_shard(shard_id_t s) {
458 shard_id = s;
459 }
460
9f95a23c 461 bool parse(const std::string& s);
7c673cae
FG
462
463 // maximum sorted value.
464 static ghobject_t get_max() {
465 ghobject_t h;
466 h.max = true;
467 h.hobj = hobject_t::get_max(); // so that is_max() => hobj.is_max()
468 return h;
469 }
470 bool is_max() const {
471 return max;
472 }
473 bool is_min() const {
474 return *this == ghobject_t();
475 }
476
477 void swap(ghobject_t &o) {
478 ghobject_t temp(o);
479 o = (*this);
480 (*this) = temp;
481 }
482
9f95a23c
TL
483 void encode(ceph::buffer::list& bl) const;
484 void decode(ceph::buffer::list::const_iterator& bl);
7c673cae
FG
485 void decode(json_spirit::Value& v);
486 size_t encoded_size() const;
9f95a23c
TL
487 void dump(ceph::Formatter *f) const;
488 static void generate_test_instances(std::list<ghobject_t*>& o);
7c673cae
FG
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;
492 }
493 friend bool operator>=(const ghobject_t& l, const ghobject_t& r) {
494 return cmp(l, r) >= 0;
495 }
496 friend bool operator<(const ghobject_t& l, const ghobject_t& r) {
497 return cmp(l, r) < 0;
498 }
499 friend bool operator<=(const ghobject_t& l, const ghobject_t& r) {
500 return cmp(l, r) <= 0;
501 }
502 friend bool operator==(const ghobject_t&, const ghobject_t&);
503 friend bool operator!=(const ghobject_t&, const ghobject_t&);
504
505};
506WRITE_CLASS_ENCODER(ghobject_t)
507
508namespace std {
509 template<> struct hash<ghobject_t> {
510 size_t operator()(const ghobject_t &r) const {
1adf2230
AA
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;
516 return hash;
7c673cae
FG
517 }
518 };
519} // namespace std
520
9f95a23c 521std::ostream& operator<<(std::ostream& out, const ghobject_t& o);
7c673cae
FG
522
523WRITE_EQ_OPERATORS_4(ghobject_t, max, shard_id, hobj, generation)
524
525extern int cmp(const ghobject_t& l, const ghobject_t& r);
526
527
528#endif