]>
Commit | Line | Data |
---|---|---|
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 |
26 | namespace 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 | ||
37 | struct hobject_t { | |
f64942e4 AA |
38 | public: |
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 | ||
52 | public: | |
7c673cae FG |
53 | object_t oid; |
54 | snapid_t snap; | |
55 | private: | |
56 | uint32_t hash; | |
57 | bool max; | |
58 | uint32_t nibblewise_key_cache; | |
59 | uint32_t hash_reverse_bits; | |
7c673cae FG |
60 | public: |
61 | int64_t pool; | |
9f95a23c | 62 | std::string nspace; |
7c673cae FG |
63 | |
64 | private: | |
9f95a23c | 65 | std::string key; |
7c673cae FG |
66 | |
67 | class hobject_t_max {}; | |
68 | ||
69 | public: | |
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 | }; | |
324 | WRITE_CLASS_ENCODER(hobject_t) | |
325 | ||
326 | namespace std { | |
9f95a23c TL |
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); | |
331 | } | |
332 | }; | |
7c673cae FG |
333 | } // namespace std |
334 | ||
9f95a23c | 335 | std::ostream& operator<<(std::ostream& out, const hobject_t& o); |
7c673cae FG |
336 | |
337 | WRITE_EQ_OPERATORS_7(hobject_t, hash, oid, get_key(), snap, pool, max, nspace) | |
338 | ||
339 | template <typename T> | |
340 | struct always_false { | |
341 | using value = std::false_type; | |
342 | }; | |
343 | ||
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()"); | |
347 | return lhs.is_max(); | |
348 | } | |
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()"); | |
352 | return rhs.is_max(); | |
353 | } | |
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(); | |
358 | } | |
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(); | |
363 | } | |
364 | ||
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; | |
370 | } | |
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; | |
375 | } | |
376 | ||
377 | ||
378 | ||
379 | typedef version_t gen_t; | |
380 | ||
381 | struct ghobject_t { | |
382 | hobject_t hobj; | |
383 | gen_t generation; | |
384 | shard_id_t shard_id; | |
385 | bool max; | |
386 | ||
387 | public: | |
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 | }; | |
506 | WRITE_CLASS_ENCODER(ghobject_t) | |
507 | ||
508 | namespace 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 | 521 | std::ostream& operator<<(std::ostream& out, const ghobject_t& o); |
7c673cae FG |
522 | |
523 | WRITE_EQ_OPERATORS_4(ghobject_t, max, shard_id, hobj, generation) | |
524 | ||
525 | extern int cmp(const ghobject_t& l, const ghobject_t& r); | |
526 | ||
527 | ||
528 | #endif |