]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_obj_types.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rgw / rgw_obj_types.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 /*
5 * Ceph - scalable distributed file system
6 *
7 * Copyright (C) 2019 Red Hat, Inc.
8 *
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
13 *
14 */
15
16 /* N.B., this header defines fundamental serialized types. Do not
17 * include files which can only be compiled in radosgw or OSD
18 * contexts (e.g., rgw_sal.h, rgw_common.h) */
19
20 #pragma once
21
22 #include <fmt/format.h>
23
24 #include "rgw_pool_types.h"
25 #include "rgw_bucket_types.h"
26 #include "rgw_user_types.h"
27
28 #include "common/dout.h"
29 #include "common/Formatter.h"
30
31 struct rgw_obj_index_key { // cls_rgw_obj_key now aliases this type
32 std::string name;
33 std::string instance;
34
35 rgw_obj_index_key() {}
36 rgw_obj_index_key(const std::string &_name) : name(_name) {}
37 rgw_obj_index_key(const std::string& n, const std::string& i) : name(n), instance(i) {}
38
39 std::string to_string() const {
40 return fmt::format("{}({})", name, instance);
41 }
42
43 bool empty() const {
44 return name.empty();
45 }
46
47 void set(const std::string& _name) {
48 name = _name;
49 instance.clear();
50 }
51
52 bool operator==(const rgw_obj_index_key& k) const {
53 return (name.compare(k.name) == 0) &&
54 (instance.compare(k.instance) == 0);
55 }
56
57 bool operator!=(const rgw_obj_index_key& k) const {
58 return (name.compare(k.name) != 0) ||
59 (instance.compare(k.instance) != 0);
60 }
61
62 bool operator<(const rgw_obj_index_key& k) const {
63 int r = name.compare(k.name);
64 if (r == 0) {
65 r = instance.compare(k.instance);
66 }
67 return (r < 0);
68 }
69
70 bool operator<=(const rgw_obj_index_key& k) const {
71 return !(k < *this);
72 }
73
74 void encode(ceph::buffer::list &bl) const {
75 ENCODE_START(1, 1, bl);
76 encode(name, bl);
77 encode(instance, bl);
78 ENCODE_FINISH(bl);
79 }
80 void decode(ceph::buffer::list::const_iterator &bl) {
81 DECODE_START(1, bl);
82 decode(name, bl);
83 decode(instance, bl);
84 DECODE_FINISH(bl);
85 }
86 void dump(ceph::Formatter *f) const {
87 f->dump_string("name", name);
88 f->dump_string("instance", instance);
89 }
90 void decode_json(JSONObj *obj);
91 static void generate_test_instances(std::list<rgw_obj_index_key*>& ls) {
92 ls.push_back(new rgw_obj_index_key);
93 ls.push_back(new rgw_obj_index_key);
94 ls.back()->name = "name";
95 ls.back()->instance = "instance";
96 }
97
98 size_t estimate_encoded_size() const {
99 constexpr size_t start_overhead = sizeof(__u8) + sizeof(__u8) + sizeof(ceph_le32); // version and length prefix
100 constexpr size_t string_overhead = sizeof(__u32); // strings are encoded with 32-bit length prefix
101 return start_overhead +
102 string_overhead + name.size() +
103 string_overhead + instance.size();
104 }
105 };
106 WRITE_CLASS_ENCODER(rgw_obj_index_key)
107
108 struct rgw_obj_key {
109 std::string name;
110 std::string instance;
111 std::string ns;
112
113 rgw_obj_key() {}
114
115 // cppcheck-suppress noExplicitConstructor
116 rgw_obj_key(const std::string& n) : name(n) {}
117 rgw_obj_key(const std::string& n, const std::string& i) : name(n), instance(i) {}
118 rgw_obj_key(const std::string& n, const std::string& i, const std::string& _ns) : name(n), instance(i), ns(_ns) {}
119
120 rgw_obj_key(const rgw_obj_index_key& k) {
121 parse_index_key(k.name, &name, &ns);
122 instance = k.instance;
123 }
124
125 static void parse_index_key(const std::string& key, std::string *name, std::string *ns) {
126 if (key[0] != '_') {
127 *name = key;
128 ns->clear();
129 return;
130 }
131 if (key[1] == '_') {
132 *name = key.substr(1);
133 ns->clear();
134 return;
135 }
136 ssize_t pos = key.find('_', 1);
137 if (pos < 0) {
138 /* shouldn't happen, just use key */
139 *name = key;
140 ns->clear();
141 return;
142 }
143
144 *name = key.substr(pos + 1);
145 *ns = key.substr(1, pos -1);
146 }
147
148 void set(const std::string& n) {
149 name = n;
150 instance.clear();
151 ns.clear();
152 }
153
154 void set(const std::string& n, const std::string& i) {
155 name = n;
156 instance = i;
157 ns.clear();
158 }
159
160 void set(const std::string& n, const std::string& i, const std::string& _ns) {
161 name = n;
162 instance = i;
163 ns = _ns;
164 }
165
166 bool set(const rgw_obj_index_key& index_key) {
167 if (!parse_raw_oid(index_key.name, this)) {
168 return false;
169 }
170 instance = index_key.instance;
171 return true;
172 }
173
174 void set_instance(const std::string& i) {
175 instance = i;
176 }
177
178 const std::string& get_instance() const {
179 return instance;
180 }
181
182 void set_ns(const std::string& _ns) {
183 ns = _ns;
184 }
185
186 const std::string& get_ns() const {
187 return ns;
188 }
189
190 std::string get_index_key_name() const {
191 if (ns.empty()) {
192 if (name.size() < 1 || name[0] != '_') {
193 return name;
194 }
195 return std::string("_") + name;
196 };
197
198 char buf[ns.size() + 16];
199 snprintf(buf, sizeof(buf), "_%s_", ns.c_str());
200 return std::string(buf) + name;
201 };
202
203 void get_index_key(rgw_obj_index_key* key) const {
204 key->name = get_index_key_name();
205 key->instance = instance;
206 }
207
208 std::string get_loc() const {
209 /*
210 * For backward compatibility. Older versions used to have object locator on all objects,
211 * however, the name was the effective object locator. This had the same effect as not
212 * having object locator at all for most objects but the ones that started with underscore as
213 * these were escaped.
214 */
215 if (name[0] == '_' && ns.empty()) {
216 return name;
217 }
218
219 return {};
220 }
221
222 bool empty() const {
223 return name.empty();
224 }
225
226 bool have_null_instance() const {
227 return instance == "null";
228 }
229
230 bool have_instance() const {
231 return !instance.empty();
232 }
233
234 bool need_to_encode_instance() const {
235 return have_instance() && !have_null_instance();
236 }
237
238 std::string get_oid() const {
239 if (ns.empty() && !need_to_encode_instance()) {
240 if (name.size() < 1 || name[0] != '_') {
241 return name;
242 }
243 return std::string("_") + name;
244 }
245
246 std::string oid = "_";
247 oid.append(ns);
248 if (need_to_encode_instance()) {
249 oid.append(std::string(":") + instance);
250 }
251 oid.append("_");
252 oid.append(name);
253 return oid;
254 }
255
256 bool operator==(const rgw_obj_key& k) const {
257 return (name.compare(k.name) == 0) &&
258 (instance.compare(k.instance) == 0);
259 }
260
261 bool operator<(const rgw_obj_key& k) const {
262 int r = name.compare(k.name);
263 if (r == 0) {
264 r = instance.compare(k.instance);
265 }
266 return (r < 0);
267 }
268
269 bool operator<=(const rgw_obj_key& k) const {
270 return !(k < *this);
271 }
272
273 static void parse_ns_field(std::string& ns, std::string& instance) {
274 int pos = ns.find(':');
275 if (pos >= 0) {
276 instance = ns.substr(pos + 1);
277 ns = ns.substr(0, pos);
278 } else {
279 instance.clear();
280 }
281 }
282
283 // takes an oid and parses out the namespace (ns), name, and
284 // instance
285 static bool parse_raw_oid(const std::string& oid, rgw_obj_key *key) {
286 key->instance.clear();
287 key->ns.clear();
288 if (oid[0] != '_') {
289 key->name = oid;
290 return true;
291 }
292
293 if (oid.size() >= 2 && oid[1] == '_') {
294 key->name = oid.substr(1);
295 return true;
296 }
297
298 if (oid.size() < 3) // for namespace, min size would be 3: _x_
299 return false;
300
301 size_t pos = oid.find('_', 2); // oid must match ^_[^_].+$
302 if (pos == std::string::npos)
303 return false;
304
305 key->ns = oid.substr(1, pos - 1);
306 parse_ns_field(key->ns, key->instance);
307
308 key->name = oid.substr(pos + 1);
309 return true;
310 }
311
312 /**
313 * Translate a namespace-mangled object name to the user-facing name
314 * existing in the given namespace.
315 *
316 * If the object is part of the given namespace, it returns true
317 * and cuts down the name to the unmangled version. If it is not
318 * part of the given namespace, it returns false.
319 */
320 static bool oid_to_key_in_ns(const std::string& oid, rgw_obj_key *key, const std::string& ns) {
321 bool ret = parse_raw_oid(oid, key);
322 if (!ret) {
323 return ret;
324 }
325
326 return (ns == key->ns);
327 }
328
329 /**
330 * Given a mangled object name and an empty namespace std::string, this
331 * function extracts the namespace into the std::string and sets the object
332 * name to be the unmangled version.
333 *
334 * It returns true after successfully doing so, or
335 * false if it fails.
336 */
337 static bool strip_namespace_from_name(std::string& name, std::string& ns, std::string& instance) {
338 ns.clear();
339 instance.clear();
340 if (name[0] != '_') {
341 return true;
342 }
343
344 size_t pos = name.find('_', 1);
345 if (pos == std::string::npos) {
346 return false;
347 }
348
349 if (name[1] == '_') {
350 name = name.substr(1);
351 return true;
352 }
353
354 size_t period_pos = name.find('.');
355 if (period_pos < pos) {
356 return false;
357 }
358
359 ns = name.substr(1, pos-1);
360 name = name.substr(pos+1, std::string::npos);
361
362 parse_ns_field(ns, instance);
363 return true;
364 }
365
366 void encode(bufferlist& bl) const {
367 ENCODE_START(2, 1, bl);
368 encode(name, bl);
369 encode(instance, bl);
370 encode(ns, bl);
371 ENCODE_FINISH(bl);
372 }
373 void decode(bufferlist::const_iterator& bl) {
374 DECODE_START(2, bl);
375 decode(name, bl);
376 decode(instance, bl);
377 if (struct_v >= 2) {
378 decode(ns, bl);
379 }
380 DECODE_FINISH(bl);
381 }
382 void dump(Formatter *f) const;
383 void decode_json(JSONObj *obj);
384 };
385 WRITE_CLASS_ENCODER(rgw_obj_key)
386
387 #if FMT_VERSION >= 90000
388 template<> struct fmt::formatter<rgw_obj_key> : fmt::formatter<std::string_view> {
389 template <typename FormatContext>
390 auto format(const rgw_obj_key& key, FormatContext& ctx) const {
391 if (key.instance.empty()) {
392 return formatter<std::string_view>::format(key.name, ctx);
393 } else {
394 return fmt::format_to(ctx.out(), "{}[{}]", key.name, key.instance);
395 }
396 }
397 };
398 #endif
399
400 inline std::ostream& operator<<(std::ostream& out, const rgw_obj_key &key) {
401 #if FMT_VERSION >= 90000
402 return out << fmt::format("{}", key);
403 #else
404 if (key.instance.empty()) {
405 return out << fmt::format("{}", key.name);
406 } else {
407 return out << fmt::format("{}[{}]", key.name, key.instance);
408 }
409 #endif
410 }
411
412 struct rgw_raw_obj {
413 rgw_pool pool;
414 std::string oid;
415 std::string loc;
416
417 rgw_raw_obj() {}
418 rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid) {
419 init(_pool, _oid);
420 }
421 rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid, const std::string& _loc) : loc(_loc) {
422 init(_pool, _oid);
423 }
424
425 void init(const rgw_pool& _pool, const std::string& _oid) {
426 pool = _pool;
427 oid = _oid;
428 }
429
430 bool empty() const {
431 return oid.empty();
432 }
433
434 void encode(bufferlist& bl) const {
435 ENCODE_START(6, 6, bl);
436 encode(pool, bl);
437 encode(oid, bl);
438 encode(loc, bl);
439 ENCODE_FINISH(bl);
440 }
441
442 void decode_from_rgw_obj(bufferlist::const_iterator& bl);
443
444 void decode(bufferlist::const_iterator& bl) {
445 unsigned ofs = bl.get_off();
446 DECODE_START(6, bl);
447 if (struct_v < 6) {
448 /*
449 * this object was encoded as rgw_obj, prior to rgw_raw_obj been split out of it,
450 * let's decode it as rgw_obj and convert it
451 */
452 bl.seek(ofs);
453 decode_from_rgw_obj(bl);
454 return;
455 }
456 decode(pool, bl);
457 decode(oid, bl);
458 decode(loc, bl);
459 DECODE_FINISH(bl);
460 }
461
462 bool operator<(const rgw_raw_obj& o) const {
463 int r = pool.compare(o.pool);
464 if (r == 0) {
465 r = oid.compare(o.oid);
466 if (r == 0) {
467 r = loc.compare(o.loc);
468 }
469 }
470 return (r < 0);
471 }
472
473 bool operator==(const rgw_raw_obj& o) const {
474 return (pool == o.pool && oid == o.oid && loc == o.loc);
475 }
476
477 void dump(Formatter *f) const;
478 void decode_json(JSONObj *obj);
479 };
480 WRITE_CLASS_ENCODER(rgw_raw_obj)
481
482 inline std::ostream& operator<<(std::ostream& out, const rgw_raw_obj& o) {
483 out << o.pool << ":" << o.oid;
484 return out;
485 }
486
487 struct rgw_obj {
488 rgw_bucket bucket;
489 rgw_obj_key key;
490
491 bool in_extra_data{false}; /* in-memory only member, does not serialize */
492
493 // Represents the hash index source for this object once it is set (non-empty)
494 std::string index_hash_source;
495
496 rgw_obj() {}
497 rgw_obj(const rgw_bucket& b, const std::string& name) : bucket(b), key(name) {}
498 rgw_obj(const rgw_bucket& b, const rgw_obj_key& k) : bucket(b), key(k) {}
499 rgw_obj(const rgw_bucket& b, const rgw_obj_index_key& k) : bucket(b), key(k) {}
500
501 void init(const rgw_bucket& b, const rgw_obj_key& k) {
502 bucket = b;
503 key = k;
504 }
505
506 void init(const rgw_bucket& b, const std::string& name) {
507 bucket = b;
508 key.set(name);
509 }
510
511 void init(const rgw_bucket& b, const std::string& name, const std::string& i, const std::string& n) {
512 bucket = b;
513 key.set(name, i, n);
514 }
515
516 void init_ns(const rgw_bucket& b, const std::string& name, const std::string& n) {
517 bucket = b;
518 key.name = name;
519 key.instance.clear();
520 key.ns = n;
521 }
522
523 bool empty() const {
524 return key.empty();
525 }
526
527 void set_key(const rgw_obj_key& k) {
528 key = k;
529 }
530
531 std::string get_oid() const {
532 return key.get_oid();
533 }
534
535 const std::string& get_hash_object() const {
536 return index_hash_source.empty() ? key.name : index_hash_source;
537 }
538
539 void set_in_extra_data(bool val) {
540 in_extra_data = val;
541 }
542
543 bool is_in_extra_data() const {
544 return in_extra_data;
545 }
546
547 void encode(bufferlist& bl) const {
548 ENCODE_START(6, 6, bl);
549 encode(bucket, bl);
550 encode(key.ns, bl);
551 encode(key.name, bl);
552 encode(key.instance, bl);
553 // encode(placement_id, bl);
554 ENCODE_FINISH(bl);
555 }
556
557 void decode(bufferlist::const_iterator& bl) {
558 DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl);
559 if (struct_v < 6) {
560 std::string s;
561 decode(bucket.name, bl); /* bucket.name */
562 decode(s, bl); /* loc */
563 decode(key.ns, bl);
564 decode(key.name, bl);
565 if (struct_v >= 2)
566 decode(bucket, bl);
567 if (struct_v >= 4)
568 decode(key.instance, bl);
569 if (key.ns.empty() && key.instance.empty()) {
570 if (key.name[0] == '_') {
571 key.name = key.name.substr(1);
572 }
573 } else {
574 if (struct_v >= 5) {
575 decode(key.name, bl);
576 } else {
577 ssize_t pos = key.name.find('_', 1);
578 if (pos < 0) {
579 throw buffer::malformed_input();
580 }
581 key.name = key.name.substr(pos + 1);
582 }
583 }
584 } else {
585 decode(bucket, bl);
586 decode(key.ns, bl);
587 decode(key.name, bl);
588 decode(key.instance, bl);
589 // decode(placement_id, bl);
590 }
591 DECODE_FINISH(bl);
592 }
593 void dump(Formatter *f) const;
594 static void generate_test_instances(std::list<rgw_obj*>& o);
595
596 bool operator==(const rgw_obj& o) const {
597 return (key == o.key) &&
598 (bucket == o.bucket);
599 }
600 bool operator<(const rgw_obj& o) const {
601 int r = key.name.compare(o.key.name);
602 if (r == 0) {
603 r = bucket.bucket_id.compare(o.bucket.bucket_id); /* not comparing bucket.name, if bucket_id is equal so will be bucket.name */
604 if (r == 0) {
605 r = key.ns.compare(o.key.ns);
606 if (r == 0) {
607 r = key.instance.compare(o.key.instance);
608 }
609 }
610 }
611
612 return (r < 0);
613 }
614
615 const rgw_pool& get_explicit_data_pool() {
616 if (!in_extra_data || bucket.explicit_placement.data_extra_pool.empty()) {
617 return bucket.explicit_placement.data_pool;
618 }
619 return bucket.explicit_placement.data_extra_pool;
620 }
621 };
622 WRITE_CLASS_ENCODER(rgw_obj)