]>
git.proxmox.com Git - ceph.git/blob - 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
5 * Ceph - scalable distributed file system
7 * Copyright (C) 2019 Red Hat, Inc.
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.
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) */
22 #include <fmt/format.h>
24 #include "rgw_pool_types.h"
25 #include "rgw_bucket_types.h"
26 #include "rgw_user_types.h"
28 #include "common/dout.h"
29 #include "common/Formatter.h"
31 struct rgw_obj_index_key
{ // cls_rgw_obj_key now aliases this type
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
) {}
39 std::string
to_string() const {
40 return fmt::format("{}({})", name
, instance
);
47 void set(const std::string
& _name
) {
52 bool operator==(const rgw_obj_index_key
& k
) const {
53 return (name
.compare(k
.name
) == 0) &&
54 (instance
.compare(k
.instance
) == 0);
57 bool operator!=(const rgw_obj_index_key
& k
) const {
58 return (name
.compare(k
.name
) != 0) ||
59 (instance
.compare(k
.instance
) != 0);
62 bool operator<(const rgw_obj_index_key
& k
) const {
63 int r
= name
.compare(k
.name
);
65 r
= instance
.compare(k
.instance
);
70 bool operator<=(const rgw_obj_index_key
& k
) const {
74 void encode(ceph::buffer::list
&bl
) const {
75 ENCODE_START(1, 1, bl
);
80 void decode(ceph::buffer::list::const_iterator
&bl
) {
86 void dump(ceph::Formatter
*f
) const {
87 f
->dump_string("name", name
);
88 f
->dump_string("instance", instance
);
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";
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();
106 WRITE_CLASS_ENCODER(rgw_obj_index_key
)
110 std::string instance
;
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
) {}
120 rgw_obj_key(const rgw_obj_index_key
& k
) {
121 parse_index_key(k
.name
, &name
, &ns
);
122 instance
= k
.instance
;
125 static void parse_index_key(const std::string
& key
, std::string
*name
, std::string
*ns
) {
132 *name
= key
.substr(1);
136 ssize_t pos
= key
.find('_', 1);
138 /* shouldn't happen, just use key */
144 *name
= key
.substr(pos
+ 1);
145 *ns
= key
.substr(1, pos
-1);
148 void set(const std::string
& n
) {
154 void set(const std::string
& n
, const std::string
& i
) {
160 void set(const std::string
& n
, const std::string
& i
, const std::string
& _ns
) {
166 bool set(const rgw_obj_index_key
& index_key
) {
167 if (!parse_raw_oid(index_key
.name
, this)) {
170 instance
= index_key
.instance
;
174 void set_instance(const std::string
& i
) {
178 const std::string
& get_instance() const {
182 void set_ns(const std::string
& _ns
) {
186 const std::string
& get_ns() const {
190 std::string
get_index_key_name() const {
192 if (name
.size() < 1 || name
[0] != '_') {
195 return std::string("_") + name
;
198 char buf
[ns
.size() + 16];
199 snprintf(buf
, sizeof(buf
), "_%s_", ns
.c_str());
200 return std::string(buf
) + name
;
203 void get_index_key(rgw_obj_index_key
* key
) const {
204 key
->name
= get_index_key_name();
205 key
->instance
= instance
;
208 std::string
get_loc() const {
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.
215 if (name
[0] == '_' && ns
.empty()) {
226 bool have_null_instance() const {
227 return instance
== "null";
230 bool have_instance() const {
231 return !instance
.empty();
234 bool need_to_encode_instance() const {
235 return have_instance() && !have_null_instance();
238 std::string
get_oid() const {
239 if (ns
.empty() && !need_to_encode_instance()) {
240 if (name
.size() < 1 || name
[0] != '_') {
243 return std::string("_") + name
;
246 std::string oid
= "_";
248 if (need_to_encode_instance()) {
249 oid
.append(std::string(":") + instance
);
256 bool operator==(const rgw_obj_key
& k
) const {
257 return (name
.compare(k
.name
) == 0) &&
258 (instance
.compare(k
.instance
) == 0);
261 bool operator<(const rgw_obj_key
& k
) const {
262 int r
= name
.compare(k
.name
);
264 r
= instance
.compare(k
.instance
);
269 bool operator<=(const rgw_obj_key
& k
) const {
273 static void parse_ns_field(std::string
& ns
, std::string
& instance
) {
274 int pos
= ns
.find(':');
276 instance
= ns
.substr(pos
+ 1);
277 ns
= ns
.substr(0, pos
);
283 // takes an oid and parses out the namespace (ns), name, and
285 static bool parse_raw_oid(const std::string
& oid
, rgw_obj_key
*key
) {
286 key
->instance
.clear();
293 if (oid
.size() >= 2 && oid
[1] == '_') {
294 key
->name
= oid
.substr(1);
298 if (oid
.size() < 3) // for namespace, min size would be 3: _x_
301 size_t pos
= oid
.find('_', 2); // oid must match ^_[^_].+$
302 if (pos
== std::string::npos
)
305 key
->ns
= oid
.substr(1, pos
- 1);
306 parse_ns_field(key
->ns
, key
->instance
);
308 key
->name
= oid
.substr(pos
+ 1);
313 * Translate a namespace-mangled object name to the user-facing name
314 * existing in the given namespace.
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.
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
);
326 return (ns
== key
->ns
);
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.
334 * It returns true after successfully doing so, or
337 static bool strip_namespace_from_name(std::string
& name
, std::string
& ns
, std::string
& instance
) {
340 if (name
[0] != '_') {
344 size_t pos
= name
.find('_', 1);
345 if (pos
== std::string::npos
) {
349 if (name
[1] == '_') {
350 name
= name
.substr(1);
354 size_t period_pos
= name
.find('.');
355 if (period_pos
< pos
) {
359 ns
= name
.substr(1, pos
-1);
360 name
= name
.substr(pos
+1, std::string::npos
);
362 parse_ns_field(ns
, instance
);
366 void encode(bufferlist
& bl
) const {
367 ENCODE_START(2, 1, bl
);
369 encode(instance
, bl
);
373 void decode(bufferlist::const_iterator
& bl
) {
376 decode(instance
, bl
);
382 void dump(Formatter
*f
) const;
383 void decode_json(JSONObj
*obj
);
385 WRITE_CLASS_ENCODER(rgw_obj_key
)
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
);
394 return fmt::format_to(ctx
.out(), "{}[{}]", key
.name
, key
.instance
);
400 inline std::ostream
& operator<<(std::ostream
& out
, const rgw_obj_key
&key
) {
401 #if FMT_VERSION >= 90000
402 return out
<< fmt::format("{}", key
);
404 if (key
.instance
.empty()) {
405 return out
<< fmt::format("{}", key
.name
);
407 return out
<< fmt::format("{}[{}]", key
.name
, key
.instance
);
418 rgw_raw_obj(const rgw_pool
& _pool
, const std::string
& _oid
) {
421 rgw_raw_obj(const rgw_pool
& _pool
, const std::string
& _oid
, const std::string
& _loc
) : loc(_loc
) {
425 void init(const rgw_pool
& _pool
, const std::string
& _oid
) {
434 void encode(bufferlist
& bl
) const {
435 ENCODE_START(6, 6, bl
);
442 void decode_from_rgw_obj(bufferlist::const_iterator
& bl
);
444 void decode(bufferlist::const_iterator
& bl
) {
445 unsigned ofs
= bl
.get_off();
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
453 decode_from_rgw_obj(bl
);
462 bool operator<(const rgw_raw_obj
& o
) const {
463 int r
= pool
.compare(o
.pool
);
465 r
= oid
.compare(o
.oid
);
467 r
= loc
.compare(o
.loc
);
473 bool operator==(const rgw_raw_obj
& o
) const {
474 return (pool
== o
.pool
&& oid
== o
.oid
&& loc
== o
.loc
);
477 void dump(Formatter
*f
) const;
478 void decode_json(JSONObj
*obj
);
480 WRITE_CLASS_ENCODER(rgw_raw_obj
)
482 inline std::ostream
& operator<<(std::ostream
& out
, const rgw_raw_obj
& o
) {
483 out
<< o
.pool
<< ":" << o
.oid
;
491 bool in_extra_data
{false}; /* in-memory only member, does not serialize */
493 // Represents the hash index source for this object once it is set (non-empty)
494 std::string index_hash_source
;
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
) {}
501 void init(const rgw_bucket
& b
, const rgw_obj_key
& k
) {
506 void init(const rgw_bucket
& b
, const std::string
& name
) {
511 void init(const rgw_bucket
& b
, const std::string
& name
, const std::string
& i
, const std::string
& n
) {
516 void init_ns(const rgw_bucket
& b
, const std::string
& name
, const std::string
& n
) {
519 key
.instance
.clear();
527 void set_key(const rgw_obj_key
& k
) {
531 std::string
get_oid() const {
532 return key
.get_oid();
535 const std::string
& get_hash_object() const {
536 return index_hash_source
.empty() ? key
.name
: index_hash_source
;
539 void set_in_extra_data(bool val
) {
543 bool is_in_extra_data() const {
544 return in_extra_data
;
547 void encode(bufferlist
& bl
) const {
548 ENCODE_START(6, 6, bl
);
551 encode(key
.name
, bl
);
552 encode(key
.instance
, bl
);
553 // encode(placement_id, bl);
557 void decode(bufferlist::const_iterator
& bl
) {
558 DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl
);
561 decode(bucket
.name
, bl
); /* bucket.name */
562 decode(s
, bl
); /* loc */
564 decode(key
.name
, bl
);
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);
575 decode(key
.name
, bl
);
577 ssize_t pos
= key
.name
.find('_', 1);
579 throw buffer::malformed_input();
581 key
.name
= key
.name
.substr(pos
+ 1);
587 decode(key
.name
, bl
);
588 decode(key
.instance
, bl
);
589 // decode(placement_id, bl);
593 void dump(Formatter
*f
) const;
594 static void generate_test_instances(std::list
<rgw_obj
*>& o
);
596 bool operator==(const rgw_obj
& o
) const {
597 return (key
== o
.key
) &&
598 (bucket
== o
.bucket
);
600 bool operator<(const rgw_obj
& o
) const {
601 int r
= key
.name
.compare(o
.key
.name
);
603 r
= bucket
.bucket_id
.compare(o
.bucket
.bucket_id
); /* not comparing bucket.name, if bucket_id is equal so will be bucket.name */
605 r
= key
.ns
.compare(o
.key
.ns
);
607 r
= key
.instance
.compare(o
.key
.instance
);
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
;
619 return bucket
.explicit_placement
.data_extra_pool
;
622 WRITE_CLASS_ENCODER(rgw_obj
)