From c30449b35b5151f0da54cf0cfa59b9d7b8050314 Mon Sep 17 00:00:00 2001 From: Matt Benjamin Date: Fri, 18 Sep 2020 20:59:31 -0400 Subject: [PATCH] rgw: define a hierarchy of basic type headers Defines a hierarchy of "simple" data types ensured to be safe to include in any context above the zipper line, and also from CLS. The following headers are currently defined to contain basic types only: rewrite src/rgw/rgw_basic_types.h (70%) // includes the whole hierarchy create mode 100644 src/rgw/rgw_acl_types.h create mode 100644 src/rgw/rgw_bucket_types.h create mode 100644 src/rgw/rgw_obj_types.h create mode 100644 src/rgw/rgw_placement_types.h create mode 100644 src/rgw/rgw_pool_types.h create mode 100644 src/rgw/rgw_quota_types.h create mode 100644 src/rgw/rgw_user_types.h create mode 100644 src/rgw/rgw_zone_types.h This commit consolidates the following original commits: * rgw: move RGWUploadPartInfo to rgw_basic_types.{h,cc} * rgw: move rgw_obj_key to rgw_basic_types.{h,cc} * rgw: move rgw_placement_rule to rgw_basic_types.{h,cc} * rgw: move rgw_obj to rgw_basic_types.{h,cc} * rgw: include rgw_compression_types.h in rgw_basic_types.{h,cc} * rgw: move rgw_raw_obj to rgw_basic_types.{h,cc} * rgw: rgw_multi.h: remove unused RGWMPObj forward decl and the following cleanups from review: * rgw: remove stray comments * rgw: move rgw_obj_manifest.h inclusion to top of rgw_basic_types.h * rgw: nit: indentation * rgw: remove this line * rgw: move rgw_bucket_shard to rgw_bucket_types.h, cleanup * rgw: fix rgw_quota.h Signed-off-by: Matt Benjamin Signed-off-by: Daniel Gryniewicz --- src/cls/CMakeLists.txt | 20 + src/cls/rgw/cls_rgw_types.h | 78 +-- src/rgw/driver/rados/rgw_obj_manifest.h | 17 +- src/rgw/driver/rados/rgw_user.cc | 1 + src/rgw/driver/rados/rgw_zone.h | 585 +------------------ src/rgw/rgw_acl.h | 97 +--- src/rgw/rgw_acl_types.h | 213 +++++++ src/rgw/rgw_basic_types.h | 538 +++-------------- src/rgw/rgw_bucket_layout.h | 5 + src/rgw/rgw_bucket_types.h | 233 ++++++++ src/rgw/rgw_common.h | 735 +----------------------- src/rgw/rgw_compression_types.h | 2 - src/rgw/rgw_multi.h | 46 +- src/rgw/rgw_obj_types.h | 610 ++++++++++++++++++++ src/rgw/rgw_placement_types.h | 118 ++++ src/rgw/rgw_pool_types.h | 157 +++++ src/rgw/rgw_quota.h | 71 +-- src/rgw/rgw_quota_types.h | 87 +++ src/rgw/rgw_rados.h | 1 + src/rgw/rgw_user_types.h | 158 +++++ src/rgw/rgw_zone_features.h | 4 + src/rgw/rgw_zone_types.h | 620 ++++++++++++++++++++ src/test/librados/CMakeLists.txt | 3 + 23 files changed, 2337 insertions(+), 2062 deletions(-) create mode 100644 src/rgw/rgw_acl_types.h create mode 100644 src/rgw/rgw_bucket_types.h create mode 100644 src/rgw/rgw_obj_types.h create mode 100644 src/rgw/rgw_placement_types.h create mode 100644 src/rgw/rgw_pool_types.h create mode 100644 src/rgw/rgw_quota_types.h create mode 100644 src/rgw/rgw_user_types.h create mode 100644 src/rgw/rgw_zone_types.h diff --git a/src/cls/CMakeLists.txt b/src/cls/CMakeLists.txt index 88a4deded4d22..2be0b3665fc04 100644 --- a/src/cls/CMakeLists.txt +++ b/src/cls/CMakeLists.txt @@ -74,6 +74,10 @@ if (WITH_RADOSGW) set(cls_otp_srcs otp/cls_otp.cc) add_library(cls_otp SHARED ${cls_otp_srcs}) target_link_libraries(cls_otp OATH::OATH) + target_include_directories(cls_otp + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw/driver/rados" + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw" + PUBLIC "${CMAKE_SOURCE_DIR}/src/spawn/include") set_target_properties(cls_otp PROPERTIES VERSION "1.0.0" SOVERSION "1" @@ -198,6 +202,10 @@ if (WITH_RADOSGW) ${CMAKE_SOURCE_DIR}/src/common/ceph_json.cc) add_library(cls_rgw SHARED ${cls_rgw_srcs}) target_link_libraries(cls_rgw json_spirit) + target_include_directories(cls_rgw + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw/driver/rados" + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw" + PUBLIC "${CMAKE_SOURCE_DIR}/src/spawn/include") set_target_properties(cls_rgw PROPERTIES VERSION "1.0.0" SOVERSION "1" @@ -210,6 +218,10 @@ if (WITH_RADOSGW) rgw/cls_rgw_types.cc rgw/cls_rgw_ops.cc) add_library(cls_rgw_client STATIC ${cls_rgw_client_srcs}) + target_include_directories(cls_rgw_client + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw/driver/rados" + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw" + PUBLIC "${CMAKE_SOURCE_DIR}/src/spawn/include") endif (WITH_RADOSGW) @@ -299,6 +311,10 @@ if (WITH_RADOSGW) queue/cls_queue_src.cc ${CMAKE_SOURCE_DIR}/src/common/ceph_json.cc) add_library(cls_rgw_gc SHARED ${cls_rgw_gc_srcs}) + target_include_directories(cls_rgw_gc + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw/driver/rados" + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw" + PUBLIC "${CMAKE_SOURCE_DIR}/src/spawn/include") set_target_properties(cls_rgw_gc PROPERTIES VERSION "1.0.0" SOVERSION "1" @@ -309,6 +325,10 @@ if (WITH_RADOSGW) set(cls_rgw_gc_client_srcs rgw_gc/cls_rgw_gc_client.cc) add_library(cls_rgw_gc_client STATIC ${cls_rgw_gc_client_srcs}) + target_include_directories(cls_rgw_gc_client + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw/driver/rados" + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw" + PUBLIC "${CMAKE_SOURCE_DIR}/src/spawn/include") endif (WITH_RADOSGW) diff --git a/src/cls/rgw/cls_rgw_types.h b/src/cls/rgw/cls_rgw_types.h index ae1d6c3752ef0..c65526c06c59d 100644 --- a/src/cls/rgw/cls_rgw_types.h +++ b/src/cls/rgw/cls_rgw_types.h @@ -352,83 +352,7 @@ struct rgw_bucket_entry_ver { }; WRITE_CLASS_ENCODER(rgw_bucket_entry_ver) - -struct cls_rgw_obj_key { - std::string name; - std::string instance; - - cls_rgw_obj_key() {} - cls_rgw_obj_key(const std::string &_name) : name(_name) {} - cls_rgw_obj_key(const std::string& n, const std::string& i) : name(n), instance(i) {} - - std::string to_string() const { - return fmt::format("{}({})", name, instance); - } - - bool empty() const { - return name.empty(); - } - - void set(const std::string& _name) { - name = _name; - instance.clear(); - } - - bool operator==(const cls_rgw_obj_key& k) const { - return (name.compare(k.name) == 0) && - (instance.compare(k.instance) == 0); - } - - bool operator!=(const cls_rgw_obj_key& k) const { - return (name.compare(k.name) != 0) || - (instance.compare(k.instance) != 0); - } - - bool operator<(const cls_rgw_obj_key& k) const { - int r = name.compare(k.name); - if (r == 0) { - r = instance.compare(k.instance); - } - return (r < 0); - } - - bool operator<=(const cls_rgw_obj_key& k) const { - return !(k < *this); - } - - void encode(ceph::buffer::list &bl) const { - ENCODE_START(1, 1, bl); - encode(name, bl); - encode(instance, bl); - ENCODE_FINISH(bl); - } - void decode(ceph::buffer::list::const_iterator &bl) { - DECODE_START(1, bl); - decode(name, bl); - decode(instance, bl); - DECODE_FINISH(bl); - } - void dump(ceph::Formatter *f) const { - f->dump_string("name", name); - f->dump_string("instance", instance); - } - void decode_json(JSONObj *obj); - static void generate_test_instances(std::list& ls) { - ls.push_back(new cls_rgw_obj_key); - ls.push_back(new cls_rgw_obj_key); - ls.back()->name = "name"; - ls.back()->instance = "instance"; - } - - size_t estimate_encoded_size() const { - constexpr size_t start_overhead = sizeof(__u8) + sizeof(__u8) + sizeof(ceph_le32); // version and length prefix - constexpr size_t string_overhead = sizeof(__u32); // strings are encoded with 32-bit length prefix - return start_overhead + - string_overhead + name.size() + - string_overhead + instance.size(); - } -}; -WRITE_CLASS_ENCODER(cls_rgw_obj_key) +typedef rgw_obj_index_key cls_rgw_obj_key; inline std::ostream& operator<<(std::ostream& out, const cls_rgw_obj_key& o) { out << o.name; diff --git a/src/rgw/driver/rados/rgw_obj_manifest.h b/src/rgw/driver/rados/rgw_obj_manifest.h index ac73359305e6d..99c5eeee35ac2 100644 --- a/src/rgw/driver/rados/rgw_obj_manifest.h +++ b/src/rgw/driver/rados/rgw_obj_manifest.h @@ -13,17 +13,26 @@ * */ +/* N.B., this header defines fundamental serialized types. Do not + * introduce changes or include files which can only be compiled in + * radosgw or OSD contexts (e.g., rgw_sal.h, rgw_common.h) + */ + #pragma once -#include "rgw_common.h" -#include "rgw_compression_types.h" -#include "rgw_sal.h" -#include "rgw_zone.h" +#include "rgw_zone_types.h" +#include "rgw_bucket_types.h" +#include "rgw_obj_types.h" +#include "rgw_placement_types.h" + +#include "common/dout.h" +#include "common/Formatter.h" class RGWSI_Zone; struct RGWZoneGroup; struct RGWZoneParams; class RGWRados; + namespace rgw { namespace sal { class RadosStore; } }; diff --git a/src/rgw/driver/rados/rgw_user.cc b/src/rgw/driver/rados/rgw_user.cc index 7c36a52e31d55..628ff0c3c95a4 100644 --- a/src/rgw/driver/rados/rgw_user.cc +++ b/src/rgw/driver/rados/rgw_user.cc @@ -6,6 +6,7 @@ #include "rgw_user.h" #include "rgw_bucket.h" +#include "rgw_quota.h" #include "services/svc_user.h" #include "services/svc_meta.h" diff --git a/src/rgw/driver/rados/rgw_zone.h b/src/rgw/driver/rados/rgw_zone.h index e1792a40ccef1..bede6c7a44812 100644 --- a/src/rgw/driver/rados/rgw_zone.h +++ b/src/rgw/driver/rados/rgw_zone.h @@ -5,77 +5,13 @@ #define CEPH_RGW_ZONE_H #include +#include "rgw_zone_types.h" #include "rgw_common.h" #include "rgw_sal_fwd.h" #include "rgw_sync_policy.h" -#include "rgw_zone_features.h" - -namespace rgw_zone_defaults { - -extern std::string zone_names_oid_prefix; -extern std::string region_info_oid_prefix; -extern std::string realm_names_oid_prefix; -extern std::string zone_group_info_oid_prefix; -extern std::string realm_info_oid_prefix; -extern std::string default_region_info_oid; -extern std::string default_zone_group_info_oid; -extern std::string region_map_oid; -extern std::string default_realm_info_oid; -extern std::string default_zonegroup_name; -extern std::string default_zone_name; -extern std::string zonegroup_names_oid_prefix; -extern std::string RGW_DEFAULT_ZONE_ROOT_POOL; -extern std::string RGW_DEFAULT_ZONEGROUP_ROOT_POOL; -extern std::string RGW_DEFAULT_REALM_ROOT_POOL; -extern std::string RGW_DEFAULT_PERIOD_ROOT_POOL; -extern std::string avail_pools; -extern std::string default_storage_pool_suffix; - -} - -class JSONObj; -class RGWSyncModulesManager; - - -struct RGWNameToId { - std::string obj_id; - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(obj_id, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(obj_id, bl); - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWNameToId) -struct RGWDefaultSystemMetaObjInfo { - std::string default_id; - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(default_id, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(default_id, bl); - DECODE_FINISH(bl); - } - - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWDefaultSystemMetaObjInfo) +class RGWSyncModulesManager; class RGWSI_SysObj; class RGWSI_Zone; @@ -162,209 +98,6 @@ public: }; WRITE_CLASS_ENCODER(RGWSystemMetaObj) -struct RGWZoneStorageClass { - boost::optional data_pool; - boost::optional compression_type; - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(data_pool, bl); - encode(compression_type, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(data_pool, bl); - decode(compression_type, bl); - DECODE_FINISH(bl); - } - - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWZoneStorageClass) - - -class RGWZoneStorageClasses { - std::map m; - - /* in memory only */ - RGWZoneStorageClass *standard_class; - -public: - RGWZoneStorageClasses() { - standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; - } - RGWZoneStorageClasses(const RGWZoneStorageClasses& rhs) { - m = rhs.m; - standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; - } - RGWZoneStorageClasses& operator=(const RGWZoneStorageClasses& rhs) { - m = rhs.m; - standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; - return *this; - } - - const RGWZoneStorageClass& get_standard() const { - return *standard_class; - } - - bool find(const std::string& sc, const RGWZoneStorageClass **pstorage_class) const { - auto iter = m.find(sc); - if (iter == m.end()) { - return false; - } - *pstorage_class = &iter->second; - return true; - } - - bool exists(const std::string& sc) const { - if (sc.empty()) { - return true; - } - auto iter = m.find(sc); - return (iter != m.end()); - } - - const std::map& get_all() const { - return m; - } - - std::map& get_all() { - return m; - } - - void set_storage_class(const std::string& sc, const rgw_pool *data_pool, const std::string *compression_type) { - const std::string *psc = ≻ - if (sc.empty()) { - psc = &RGW_STORAGE_CLASS_STANDARD; - } - RGWZoneStorageClass& storage_class = m[*psc]; - if (data_pool) { - storage_class.data_pool = *data_pool; - } - if (compression_type) { - storage_class.compression_type = *compression_type; - } - } - - void remove_storage_class(const std::string& sc) { - if (!sc.empty()) { - m.erase(sc); - } - } - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(m, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(m, bl); - standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; - DECODE_FINISH(bl); - } - - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWZoneStorageClasses) - -struct RGWZonePlacementInfo { - rgw_pool index_pool; - rgw_pool data_extra_pool; /* if not set we should use data_pool */ - RGWZoneStorageClasses storage_classes; - rgw::BucketIndexType index_type; - - RGWZonePlacementInfo() : index_type(rgw::BucketIndexType::Normal) {} - - void encode(bufferlist& bl) const { - ENCODE_START(7, 1, bl); - encode(index_pool.to_str(), bl); - rgw_pool standard_data_pool = get_data_pool(RGW_STORAGE_CLASS_STANDARD); - encode(standard_data_pool.to_str(), bl); - encode(data_extra_pool.to_str(), bl); - encode((uint32_t)index_type, bl); - std::string standard_compression_type = get_compression_type(RGW_STORAGE_CLASS_STANDARD); - encode(standard_compression_type, bl); - encode(storage_classes, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(7, bl); - std::string index_pool_str; - std::string data_pool_str; - decode(index_pool_str, bl); - index_pool = rgw_pool(index_pool_str); - decode(data_pool_str, bl); - rgw_pool standard_data_pool(data_pool_str); - if (struct_v >= 4) { - std::string data_extra_pool_str; - decode(data_extra_pool_str, bl); - data_extra_pool = rgw_pool(data_extra_pool_str); - } - if (struct_v >= 5) { - uint32_t it; - decode(it, bl); - index_type = (rgw::BucketIndexType)it; - } - std::string standard_compression_type; - if (struct_v >= 6) { - decode(standard_compression_type, bl); - } - if (struct_v >= 7) { - decode(storage_classes, bl); - } else { - storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, &standard_data_pool, - (!standard_compression_type.empty() ? &standard_compression_type : nullptr)); - } - DECODE_FINISH(bl); - } - const rgw_pool& get_data_extra_pool() const { - static rgw_pool no_pool; - if (data_extra_pool.empty()) { - return storage_classes.get_standard().data_pool.get_value_or(no_pool); - } - return data_extra_pool; - } - const rgw_pool& get_data_pool(const std::string& sc) const { - const RGWZoneStorageClass *storage_class; - static rgw_pool no_pool; - - if (!storage_classes.find(sc, &storage_class)) { - return storage_classes.get_standard().data_pool.get_value_or(no_pool); - } - - return storage_class->data_pool.get_value_or(no_pool); - } - const rgw_pool& get_standard_data_pool() const { - return get_data_pool(RGW_STORAGE_CLASS_STANDARD); - } - - const std::string& get_compression_type(const std::string& sc) const { - const RGWZoneStorageClass *storage_class; - static std::string no_compression; - - if (!storage_classes.find(sc, &storage_class)) { - return no_compression; - } - return storage_class->compression_type.get_value_or(no_compression); - } - - bool storage_class_exists(const std::string& sc) const { - return storage_classes.exists(sc); - } - - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); - -}; -WRITE_CLASS_ENCODER(RGWZonePlacementInfo) - struct RGWZoneParams : RGWSystemMetaObj { rgw_pool domain_root; rgw_pool control_pool; @@ -535,7 +268,7 @@ struct RGWZoneParams : RGWSystemMetaObj { /* * return data pool of the head object */ - bool get_head_data_pool(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_pool *pool) const { + bool get_head_data_pool(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_pool* pool) const { const rgw_data_placement_target& explicit_placement = obj.bucket.explicit_placement; if (!explicit_placement.data_pool.empty()) { if (!obj.in_extra_data) { @@ -570,318 +303,6 @@ struct RGWZoneParams : RGWSystemMetaObj { }; WRITE_CLASS_ENCODER(RGWZoneParams) - -struct RGWZone { - std::string id; - std::string name; - std::list endpoints; - bool log_meta; - bool log_data; - bool read_only; - std::string tier_type; - - std::string redirect_zone; - -/** - * Represents the number of shards for the bucket index object, a value of zero - * indicates there is no sharding. By default (no sharding, the name of the object - * is '.dir.{marker}', with sharding, the name is '.dir.{marker}.{sharding_id}', - * sharding_id is zero-based value. It is not recommended to set a too large value - * (e.g. thousand) as it increases the cost for bucket listing. - */ - uint32_t bucket_index_max_shards; - - // pre-shard buckets on creation to enable some write-parallism by default, - // delay the need to reshard as the bucket grows, and (in multisite) get some - // bucket index sharding where dynamic resharding is not supported - static constexpr uint32_t default_bucket_index_max_shards = 11; - - bool sync_from_all; - std::set sync_from; /* list of zones to sync from */ - - rgw::zone_features::set supported_features; - - RGWZone() - : log_meta(false), log_data(false), read_only(false), - bucket_index_max_shards(default_bucket_index_max_shards), - sync_from_all(true) {} - - void encode(bufferlist& bl) const { - ENCODE_START(8, 1, bl); - encode(name, bl); - encode(endpoints, bl); - encode(log_meta, bl); - encode(log_data, bl); - encode(bucket_index_max_shards, bl); - encode(id, bl); - encode(read_only, bl); - encode(tier_type, bl); - encode(sync_from_all, bl); - encode(sync_from, bl); - encode(redirect_zone, bl); - encode(supported_features, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(8, bl); - decode(name, bl); - if (struct_v < 4) { - id = name; - } - decode(endpoints, bl); - if (struct_v >= 2) { - decode(log_meta, bl); - decode(log_data, bl); - } - if (struct_v >= 3) { - decode(bucket_index_max_shards, bl); - } - if (struct_v >= 4) { - decode(id, bl); - decode(read_only, bl); - } - if (struct_v >= 5) { - decode(tier_type, bl); - } - if (struct_v >= 6) { - decode(sync_from_all, bl); - decode(sync_from, bl); - } - if (struct_v >= 7) { - decode(redirect_zone, bl); - } - if (struct_v >= 8) { - decode(supported_features, bl); - } - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); - static void generate_test_instances(std::list& o); - - bool is_read_only() const { return read_only; } - - bool syncs_from(const std::string& zone_name) const { - return (sync_from_all || sync_from.find(zone_name) != sync_from.end()); - } - - bool supports(std::string_view feature) const { - return supported_features.contains(feature); - } -}; -WRITE_CLASS_ENCODER(RGWZone) - -struct RGWDefaultZoneGroupInfo { - std::string default_zonegroup; - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(default_zonegroup, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(default_zonegroup, bl); - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); - //todo: implement ceph-dencoder -}; -WRITE_CLASS_ENCODER(RGWDefaultZoneGroupInfo) - -struct RGWTierACLMapping { - ACLGranteeTypeEnum type{ACL_TYPE_CANON_USER}; - std::string source_id; - std::string dest_id; - - RGWTierACLMapping() = default; - - RGWTierACLMapping(ACLGranteeTypeEnum t, - const std::string& s, - const std::string& d) : type(t), - source_id(s), - dest_id(d) {} - - void init(const JSONFormattable& config) { - const std::string& t = config["type"]; - - if (t == "email") { - type = ACL_TYPE_EMAIL_USER; - } else if (t == "uri") { - type = ACL_TYPE_GROUP; - } else { - type = ACL_TYPE_CANON_USER; - } - - source_id = config["source_id"]; - dest_id = config["dest_id"]; - } - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode((uint32_t)type, bl); - encode(source_id, bl); - encode(dest_id, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - uint32_t it; - decode(it, bl); - type = (ACLGranteeTypeEnum)it; - decode(source_id, bl); - decode(dest_id, bl); - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWTierACLMapping) - -struct RGWZoneGroupPlacementTierS3 { -#define DEFAULT_MULTIPART_SYNC_PART_SIZE (32 * 1024 * 1024) - std::string endpoint; - RGWAccessKey key; - std::string region; - HostStyle host_style{PathStyle}; - std::string target_storage_class; - - /* Should below be bucket/zone specific?? */ - std::string target_path; - std::map acl_mappings; - - uint64_t multipart_sync_threshold{DEFAULT_MULTIPART_SYNC_PART_SIZE}; - uint64_t multipart_min_part_size{DEFAULT_MULTIPART_SYNC_PART_SIZE}; - - int update_params(const JSONFormattable& config); - int clear_params(const JSONFormattable& config); - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(endpoint, bl); - encode(key, bl); - encode(region, bl); - encode((uint32_t)host_style, bl); - encode(target_storage_class, bl); - encode(target_path, bl); - encode(acl_mappings, bl); - encode(multipart_sync_threshold, bl); - encode(multipart_min_part_size, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(endpoint, bl); - decode(key, bl); - decode(region, bl); - - uint32_t it; - decode(it, bl); - host_style = (HostStyle)it; - - decode(target_storage_class, bl); - decode(target_path, bl); - decode(acl_mappings, bl); - decode(multipart_sync_threshold, bl); - decode(multipart_min_part_size, bl); - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTierS3) - -struct RGWZoneGroupPlacementTier { - std::string tier_type; - std::string storage_class; - bool retain_head_object = false; - - struct _tier { - RGWZoneGroupPlacementTierS3 s3; - } t; - - int update_params(const JSONFormattable& config); - int clear_params(const JSONFormattable& config); - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(tier_type, bl); - encode(storage_class, bl); - encode(retain_head_object, bl); - if (tier_type == "cloud-s3") { - encode(t.s3, bl); - } - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(tier_type, bl); - decode(storage_class, bl); - decode(retain_head_object, bl); - if (tier_type == "cloud-s3") { - decode(t.s3, bl); - } - DECODE_FINISH(bl); - } - - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTier) - -struct RGWZoneGroupPlacementTarget { - std::string name; - std::set tags; - std::set storage_classes; - std::map tier_targets; - - bool user_permitted(const std::list& user_tags) const { - if (tags.empty()) { - return true; - } - for (auto& rule : user_tags) { - if (tags.find(rule) != tags.end()) { - return true; - } - } - return false; - } - - void encode(bufferlist& bl) const { - ENCODE_START(3, 1, bl); - encode(name, bl); - encode(tags, bl); - encode(storage_classes, bl); - encode(tier_targets, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(3, bl); - decode(name, bl); - decode(tags, bl); - if (struct_v >= 2) { - decode(storage_classes, bl); - } - if (storage_classes.empty()) { - storage_classes.insert(RGW_STORAGE_CLASS_STANDARD); - } - if (struct_v >= 3) { - decode(tier_targets, bl); - } - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTarget) - struct RGWZoneGroup : public RGWSystemMetaObj { std::string api_name; std::list endpoints; diff --git a/src/rgw/rgw_acl.h b/src/rgw/rgw_acl.h index 6fc16c7800326..aa346a63f13f6 100644 --- a/src/rgw/rgw_acl.h +++ b/src/rgw/rgw_acl.h @@ -14,102 +14,7 @@ #include "common/debug.h" -#include "rgw_basic_types.h" - -#define RGW_PERM_NONE 0x00 -#define RGW_PERM_READ 0x01 -#define RGW_PERM_WRITE 0x02 -#define RGW_PERM_READ_ACP 0x04 -#define RGW_PERM_WRITE_ACP 0x08 -#define RGW_PERM_READ_OBJS 0x10 -#define RGW_PERM_WRITE_OBJS 0x20 -#define RGW_PERM_FULL_CONTROL ( RGW_PERM_READ | RGW_PERM_WRITE | \ - RGW_PERM_READ_ACP | RGW_PERM_WRITE_ACP ) -#define RGW_PERM_ALL_S3 RGW_PERM_FULL_CONTROL -#define RGW_PERM_INVALID 0xFF00 - -static constexpr char RGW_REFERER_WILDCARD[] = "*"; - -enum ACLGranteeTypeEnum { -/* numbers are encoded, should not change */ - ACL_TYPE_CANON_USER = 0, - ACL_TYPE_EMAIL_USER = 1, - ACL_TYPE_GROUP = 2, - ACL_TYPE_UNKNOWN = 3, - ACL_TYPE_REFERER = 4, -}; - -enum ACLGroupTypeEnum { -/* numbers are encoded should not change */ - ACL_GROUP_NONE = 0, - ACL_GROUP_ALL_USERS = 1, - ACL_GROUP_AUTHENTICATED_USERS = 2, -}; - -class ACLPermission -{ -protected: - int flags; -public: - ACLPermission() : flags(0) {} - ~ACLPermission() {} - uint32_t get_permissions() const { return flags; } - void set_permissions(uint32_t perm) { flags = perm; } - - void encode(bufferlist& bl) const { - ENCODE_START(2, 2, bl); - encode(flags, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl); - decode(flags, bl); - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - static void generate_test_instances(std::list& o); - - friend bool operator==(const ACLPermission& lhs, const ACLPermission& rhs); - friend bool operator!=(const ACLPermission& lhs, const ACLPermission& rhs); -}; -WRITE_CLASS_ENCODER(ACLPermission) - -class ACLGranteeType -{ -protected: - __u32 type; -public: - ACLGranteeType() : type(ACL_TYPE_UNKNOWN) {} - virtual ~ACLGranteeType() {} -// virtual const char *to_string() = 0; - ACLGranteeTypeEnum get_type() const { return (ACLGranteeTypeEnum)type; } - void set(ACLGranteeTypeEnum t) { type = t; } -// virtual void set(const char *s) = 0; - void encode(bufferlist& bl) const { - ENCODE_START(2, 2, bl); - encode(type, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl); - decode(type, bl); - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - static void generate_test_instances(std::list& o); - - friend bool operator==(const ACLGranteeType& lhs, const ACLGranteeType& rhs); - friend bool operator!=(const ACLGranteeType& lhs, const ACLGranteeType& rhs); -}; -WRITE_CLASS_ENCODER(ACLGranteeType) - -class ACLGrantee -{ -public: - ACLGrantee() {} - ~ACLGrantee() {} -}; - +#include "rgw_basic_types.h" //includes rgw_acl_types.h class ACLGrant { diff --git a/src/rgw/rgw_acl_types.h b/src/rgw/rgw_acl_types.h new file mode 100644 index 0000000000000..af256b1b5a678 --- /dev/null +++ b/src/rgw/rgw_acl_types.h @@ -0,0 +1,213 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2019 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* N.B., this header defines fundamental serialized types. Do not + * introduce changes or include files which can only be compiled in + * radosgw or OSD contexts (e.g., rgw_sal.h, rgw_common.h) + */ + +#pragma once + +#include +#include +#include + +#include "include/types.h" +#include "common/Formatter.h" + +#define RGW_PERM_NONE 0x00 +#define RGW_PERM_READ 0x01 +#define RGW_PERM_WRITE 0x02 +#define RGW_PERM_READ_ACP 0x04 +#define RGW_PERM_WRITE_ACP 0x08 +#define RGW_PERM_READ_OBJS 0x10 +#define RGW_PERM_WRITE_OBJS 0x20 +#define RGW_PERM_FULL_CONTROL ( RGW_PERM_READ | RGW_PERM_WRITE | \ + RGW_PERM_READ_ACP | RGW_PERM_WRITE_ACP ) +#define RGW_PERM_ALL_S3 RGW_PERM_FULL_CONTROL +#define RGW_PERM_INVALID 0xFF00 + +static constexpr char RGW_REFERER_WILDCARD[] = "*"; + +struct RGWAccessKey { + std::string id; // AccessKey + std::string key; // SecretKey + std::string subuser; + + RGWAccessKey() {} + RGWAccessKey(std::string _id, std::string _key) + : id(std::move(_id)), key(std::move(_key)) {} + + void encode(bufferlist& bl) const { + ENCODE_START(2, 2, bl); + encode(id, bl); + encode(key, bl); + encode(subuser, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START_LEGACY_COMPAT_LEN_32(2, 2, 2, bl); + decode(id, bl); + decode(key, bl); + decode(subuser, bl); + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + void dump_plain(Formatter *f) const; + void dump(Formatter *f, const std::string& user, bool swift) const; + static void generate_test_instances(std::list& o); + + void decode_json(JSONObj *obj); + void decode_json(JSONObj *obj, bool swift); +}; +WRITE_CLASS_ENCODER(RGWAccessKey) + +struct RGWSubUser { + std::string name; + uint32_t perm_mask; + + RGWSubUser() : perm_mask(0) {} + void encode(bufferlist& bl) const { + ENCODE_START(2, 2, bl); + encode(name, bl); + encode(perm_mask, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START_LEGACY_COMPAT_LEN_32(2, 2, 2, bl); + decode(name, bl); + decode(perm_mask, bl); + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + void dump(Formatter *f, const std::string& user) const; + static void generate_test_instances(std::list& o); + + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWSubUser) + +class RGWUserCaps +{ + std::map caps; + + int get_cap(const std::string& cap, std::string& type, uint32_t *perm); + int add_cap(const std::string& cap); + int remove_cap(const std::string& cap); +public: + static int parse_cap_perm(const std::string& str, uint32_t *perm); + int add_from_string(const std::string& str); + int remove_from_string(const std::string& str); + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(caps, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(caps, bl); + DECODE_FINISH(bl); + } + int check_cap(const std::string& cap, uint32_t perm) const; + bool is_valid_cap_type(const std::string& tp); + void dump(Formatter *f) const; + void dump(Formatter *f, const char *name) const; + + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWUserCaps) + +enum ACLGranteeTypeEnum { +/* numbers are encoded, should not change */ + ACL_TYPE_CANON_USER = 0, + ACL_TYPE_EMAIL_USER = 1, + ACL_TYPE_GROUP = 2, + ACL_TYPE_UNKNOWN = 3, + ACL_TYPE_REFERER = 4, +}; + +enum ACLGroupTypeEnum { +/* numbers are encoded should not change */ + ACL_GROUP_NONE = 0, + ACL_GROUP_ALL_USERS = 1, + ACL_GROUP_AUTHENTICATED_USERS = 2, +}; + +class ACLPermission +{ +protected: + int flags; +public: + ACLPermission() : flags(0) {} + ~ACLPermission() {} + uint32_t get_permissions() const { return flags; } + void set_permissions(uint32_t perm) { flags = perm; } + + void encode(bufferlist& bl) const { + ENCODE_START(2, 2, bl); + encode(flags, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator& bl) { + DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl); + decode(flags, bl); + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + static void generate_test_instances(std::list& o); + + friend bool operator==(const ACLPermission& lhs, const ACLPermission& rhs); + friend bool operator!=(const ACLPermission& lhs, const ACLPermission& rhs); +}; +WRITE_CLASS_ENCODER(ACLPermission) + +class ACLGranteeType +{ +protected: + __u32 type; +public: + ACLGranteeType() : type(ACL_TYPE_UNKNOWN) {} + virtual ~ACLGranteeType() {} +// virtual const char *to_string() = 0; + ACLGranteeTypeEnum get_type() const { return (ACLGranteeTypeEnum)type; } + void set(ACLGranteeTypeEnum t) { type = t; } +// virtual void set(const char *s) = 0; + void encode(bufferlist& bl) const { + ENCODE_START(2, 2, bl); + encode(type, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator& bl) { + DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl); + decode(type, bl); + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + static void generate_test_instances(std::list& o); + + friend bool operator==(const ACLGranteeType& lhs, const ACLGranteeType& rhs); + friend bool operator!=(const ACLGranteeType& lhs, const ACLGranteeType& rhs); +}; +WRITE_CLASS_ENCODER(ACLGranteeType) + +class ACLGrantee +{ +public: + ACLGrantee() {} + ~ACLGrantee() {} +}; diff --git a/src/rgw/rgw_basic_types.h b/src/rgw/rgw_basic_types.h index afbcf17c82803..168e8bc63b816 100644 --- a/src/rgw/rgw_basic_types.h +++ b/src/rgw/rgw_basic_types.h @@ -1,470 +1,62 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab ft=cpp +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2019 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* N.B., this header defines fundamental serialized types. Do not + * introduce changes or include files which can only be compiled in + * radosgw or OSD contexts (e.g., rgw_sal.h, rgw_common.h) + */ + #ifndef CEPH_RGW_BASIC_TYPES_H #define CEPH_RGW_BASIC_TYPES_H #include +#include #include "include/types.h" +#include "rgw_compression_types.h" +#include "rgw_pool_types.h" +#include "rgw_acl_types.h" +#include "rgw_zone_types.h" +#include "rgw_user_types.h" +#include "rgw_bucket_types.h" +#include "rgw_obj_types.h" +#include "rgw_obj_manifest.h" + +#include "common/Formatter.h" class JSONObj; class cls_user_bucket; -struct rgw_user { - std::string tenant; - std::string id; - std::string ns; - - rgw_user() {} - explicit rgw_user(const std::string& s) { - from_str(s); - } - rgw_user(const std::string& tenant, const std::string& id, const std::string& ns="") - : tenant(tenant), - id(id), - ns(ns) { - } - rgw_user(std::string&& tenant, std::string&& id, std::string&& ns="") - : tenant(std::move(tenant)), - id(std::move(id)), - ns(std::move(ns)) { - } - - void encode(ceph::buffer::list& bl) const { - ENCODE_START(2, 1, bl); - encode(tenant, bl); - encode(id, bl); - encode(ns, bl); - ENCODE_FINISH(bl); - } - void decode(ceph::buffer::list::const_iterator& bl) { - DECODE_START(2, bl); - decode(tenant, bl); - decode(id, bl); - if (struct_v >= 2) { - decode(ns, bl); - } - DECODE_FINISH(bl); - } - - void to_str(std::string& str) const { - if (!tenant.empty()) { - if (!ns.empty()) { - str = tenant + '$' + ns + '$' + id; - } else { - str = tenant + '$' + id; - } - } else if (!ns.empty()) { - str = '$' + ns + '$' + id; - } else { - str = id; - } - } - - void clear() { - tenant.clear(); - id.clear(); - ns.clear(); - } - - bool empty() const { - return id.empty(); - } - - std::string to_str() const { - std::string s; - to_str(s); - return s; - } - - void from_str(const std::string& str) { - size_t pos = str.find('$'); - if (pos != std::string::npos) { - tenant = str.substr(0, pos); - std::string_view sv = str; - std::string_view ns_id = sv.substr(pos + 1); - size_t ns_pos = ns_id.find('$'); - if (ns_pos != std::string::npos) { - ns = std::string(ns_id.substr(0, ns_pos)); - id = std::string(ns_id.substr(ns_pos + 1)); - } else { - ns.clear(); - id = std::string(ns_id); - } - } else { - tenant.clear(); - ns.clear(); - id = str; - } - } - - rgw_user& operator=(const std::string& str) { - from_str(str); - return *this; - } - - int compare(const rgw_user& u) const { - int r = tenant.compare(u.tenant); - if (r != 0) - return r; - r = ns.compare(u.ns); - if (r != 0) { - return r; - } - return id.compare(u.id); - } - int compare(const std::string& str) const { - rgw_user u(str); - return compare(u); - } - - bool operator!=(const rgw_user& rhs) const { - return (compare(rhs) != 0); - } - bool operator==(const rgw_user& rhs) const { - return (compare(rhs) == 0); - } - bool operator<(const rgw_user& rhs) const { - if (tenant < rhs.tenant) { - return true; - } else if (tenant > rhs.tenant) { - return false; - } - if (ns < rhs.ns) { - return true; - } else if (ns > rhs.ns) { - return false; - } - return (id < rhs.id); - } - void dump(ceph::Formatter *f) const; - static void generate_test_instances(std::list& o); +enum RGWIntentEvent { + DEL_OBJ = 0, + DEL_DIR = 1, }; -WRITE_CLASS_ENCODER(rgw_user) -struct rgw_pool { - std::string name; - std::string ns; - - rgw_pool() = default; - rgw_pool(const rgw_pool& _p) : name(_p.name), ns(_p.ns) {} - rgw_pool(rgw_pool&&) = default; - rgw_pool(const std::string& _s) { - from_str(_s); - } - rgw_pool(const std::string& _name, const std::string& _ns) : name(_name), ns(_ns) {} - - std::string to_str() const; - void from_str(const std::string& s); - - void init(const std::string& _s) { - from_str(_s); - } - - bool empty() const { - return name.empty(); - } - - int compare(const rgw_pool& p) const { - int r = name.compare(p.name); - if (r != 0) { - return r; - } - return ns.compare(p.ns); - } - - void encode(ceph::buffer::list& bl) const { - ENCODE_START(10, 10, bl); - encode(name, bl); - encode(ns, bl); - ENCODE_FINISH(bl); - } - - void decode_from_bucket(ceph::buffer::list::const_iterator& bl); - - void decode(ceph::buffer::list::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(10, 3, 3, bl); - - decode(name, bl); - - if (struct_v < 10) { - - /* - * note that rgw_pool can be used where rgw_bucket was used before - * therefore we inherit rgw_bucket's old versions. However, we only - * need the first field from rgw_bucket. unless we add more fields - * in which case we'll need to look at struct_v, and check the actual - * version. Anything older than 10 needs to be treated as old rgw_bucket - */ - - } else { - decode(ns, bl); - } - - DECODE_FINISH(bl); - } - - rgw_pool& operator=(const rgw_pool&) = default; - - bool operator==(const rgw_pool& p) const { - return (compare(p) == 0); - } - bool operator!=(const rgw_pool& p) const { - return !(*this == p); - } - bool operator<(const rgw_pool& p) const { - int r = name.compare(p.name); - if (r == 0) { - return (ns.compare(p.ns) < 0); - } - return (r < 0); - } -}; -WRITE_CLASS_ENCODER(rgw_pool) - -inline std::ostream& operator<<(std::ostream& out, const rgw_pool& p) { - out << p.to_str(); - return out; -} - -struct rgw_data_placement_target { - rgw_pool data_pool; - rgw_pool data_extra_pool; - rgw_pool index_pool; - - rgw_data_placement_target() = default; - rgw_data_placement_target(const rgw_data_placement_target&) = default; - rgw_data_placement_target(rgw_data_placement_target&&) = default; - - rgw_data_placement_target(const rgw_pool& data_pool, - const rgw_pool& data_extra_pool, - const rgw_pool& index_pool) - : data_pool(data_pool), - data_extra_pool(data_extra_pool), - index_pool(index_pool) { - } - - rgw_data_placement_target& - operator=(const rgw_data_placement_target&) = default; - - const rgw_pool& get_data_extra_pool() const { - if (data_extra_pool.empty()) { - return data_pool; - } - return data_extra_pool; - } - - int compare(const rgw_data_placement_target& t) { - int c = data_pool.compare(t.data_pool); - if (c != 0) { - return c; - } - c = data_extra_pool.compare(t.data_extra_pool); - if (c != 0) { - return c; - } - return index_pool.compare(t.index_pool); - }; - - void dump(ceph::Formatter *f) const; - void decode_json(JSONObj *obj); -}; - -struct rgw_bucket_key { - std::string tenant; - std::string name; - std::string bucket_id; - - rgw_bucket_key(const std::string& _tenant, - const std::string& _name, - const std::string& _bucket_id) : tenant(_tenant), - name(_name), - bucket_id(_bucket_id) {} - rgw_bucket_key(const std::string& _tenant, - const std::string& _name) : tenant(_tenant), - name(_name) {} -}; - -struct rgw_bucket { - std::string tenant; - std::string name; - std::string marker; - std::string bucket_id; - rgw_data_placement_target explicit_placement; - - rgw_bucket() { } - // cppcheck-suppress noExplicitConstructor - explicit rgw_bucket(const rgw_user& u, const cls_user_bucket& b); - - rgw_bucket(const std::string& _tenant, - const std::string& _name, - const std::string& _bucket_id) : tenant(_tenant), - name(_name), - bucket_id(_bucket_id) {} - rgw_bucket(const rgw_bucket_key& bk) : tenant(bk.tenant), - name(bk.name), - bucket_id(bk.bucket_id) {} - rgw_bucket(const rgw_bucket&) = default; - rgw_bucket(rgw_bucket&&) = default; - - bool match(const rgw_bucket& b) const { - return (tenant == b.tenant && - name == b.name && - (bucket_id == b.bucket_id || - bucket_id.empty() || - b.bucket_id.empty())); - } - - void convert(cls_user_bucket *b) const; - - void encode(ceph::buffer::list& bl) const { - ENCODE_START(10, 10, bl); - encode(name, bl); - encode(marker, bl); - encode(bucket_id, bl); - encode(tenant, bl); - bool encode_explicit = !explicit_placement.data_pool.empty(); - encode(encode_explicit, bl); - if (encode_explicit) { - encode(explicit_placement.data_pool, bl); - encode(explicit_placement.data_extra_pool, bl); - encode(explicit_placement.index_pool, bl); - } - ENCODE_FINISH(bl); - } - void decode(ceph::buffer::list::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(10, 3, 3, bl); - decode(name, bl); - if (struct_v < 10) { - decode(explicit_placement.data_pool.name, bl); - } - if (struct_v >= 2) { - decode(marker, bl); - if (struct_v <= 3) { - uint64_t id; - decode(id, bl); - char buf[16]; - snprintf(buf, sizeof(buf), "%" PRIu64, id); - bucket_id = buf; - } else { - decode(bucket_id, bl); - } - } - if (struct_v < 10) { - if (struct_v >= 5) { - decode(explicit_placement.index_pool.name, bl); - } else { - explicit_placement.index_pool = explicit_placement.data_pool; - } - if (struct_v >= 7) { - decode(explicit_placement.data_extra_pool.name, bl); - } - } - if (struct_v >= 8) { - decode(tenant, bl); - } - if (struct_v >= 10) { - bool decode_explicit = !explicit_placement.data_pool.empty(); - decode(decode_explicit, bl); - if (decode_explicit) { - decode(explicit_placement.data_pool, bl); - decode(explicit_placement.data_extra_pool, bl); - decode(explicit_placement.index_pool, bl); - } - } - DECODE_FINISH(bl); - } - - void update_bucket_id(const std::string& new_bucket_id) { - bucket_id = new_bucket_id; - } - - // format a key for the bucket/instance. pass delim=0 to skip a field - std::string get_key(char tenant_delim = '/', - char id_delim = ':', - size_t reserve = 0) const; - - const rgw_pool& get_data_extra_pool() const { - return explicit_placement.get_data_extra_pool(); - } - - void dump(ceph::Formatter *f) const; - void decode_json(JSONObj *obj); - static void generate_test_instances(std::list& o); - - rgw_bucket& operator=(const rgw_bucket&) = default; - - bool operator<(const rgw_bucket& b) const { - if (tenant < b.tenant) { - return true; - } else if (tenant > b.tenant) { - return false; - } - - if (name < b.name) { - return true; - } else if (name > b.name) { - return false; - } - - return (bucket_id < b.bucket_id); - } - - bool operator==(const rgw_bucket& b) const { - return (tenant == b.tenant) && (name == b.name) && \ - (bucket_id == b.bucket_id); - } - bool operator!=(const rgw_bucket& b) const { - return (tenant != b.tenant) || (name != b.name) || - (bucket_id != b.bucket_id); - } -}; -WRITE_CLASS_ENCODER(rgw_bucket) - -inline std::ostream& operator<<(std::ostream& out, const rgw_bucket &b) { - out << b.tenant << ":" << b.name << "[" << b.bucket_id << "])"; - return out; -} - -struct rgw_bucket_shard { - rgw_bucket bucket; - int shard_id; - - rgw_bucket_shard() : shard_id(-1) {} - rgw_bucket_shard(const rgw_bucket& _b, int _sid) : bucket(_b), shard_id(_sid) {} - - std::string get_key(char tenant_delim = '/', char id_delim = ':', - char shard_delim = ':', - size_t reserve = 0) const; - - bool operator<(const rgw_bucket_shard& b) const { - if (bucket < b.bucket) { - return true; - } - if (b.bucket < bucket) { - return false; - } - return shard_id < b.shard_id; - } - - bool operator==(const rgw_bucket_shard& b) const { - return (bucket == b.bucket && - shard_id == b.shard_id); - } -}; - -void encode(const rgw_bucket_shard& b, bufferlist& bl, uint64_t f=0); -void decode(rgw_bucket_shard& b, bufferlist::const_iterator& bl); - -inline std::ostream& operator<<(std::ostream& out, const rgw_bucket_shard& bs) { - if (bs.shard_id <= 0) { - return out << bs.bucket; - } - - return out << bs.bucket << ":" << bs.shard_id; -} +/** Store error returns for output at a different point in the program */ +struct rgw_err { + rgw_err(); + void clear(); + bool is_clear() const; + bool is_err() const; + friend std::ostream& operator<<(std::ostream& oss, const rgw_err &err); + int http_ret; + int ret; + std::string err_code; + std::string message; +}; /* rgw_err */ struct rgw_zone_id { std::string id; @@ -649,5 +241,47 @@ inline std::ostream& operator<<(std::ostream& out, const rgw_user &u) { return out << s; } +struct RGWUploadPartInfo { + uint32_t num; + uint64_t size; + uint64_t accounted_size{0}; + std::string etag; + ceph::real_time modified; + RGWObjManifest manifest; + RGWCompressionInfo cs_info; + + RGWUploadPartInfo() : num(0), size(0) {} + + void encode(bufferlist& bl) const { + ENCODE_START(4, 2, bl); + encode(num, bl); + encode(size, bl); + encode(etag, bl); + encode(modified, bl); + encode(manifest, bl); + encode(cs_info, bl); + encode(accounted_size, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator& bl) { + DECODE_START_LEGACY_COMPAT_LEN(4, 2, 2, bl); + decode(num, bl); + decode(size, bl); + decode(etag, bl); + decode(modified, bl); + if (struct_v >= 3) + decode(manifest, bl); + if (struct_v >= 4) { + decode(cs_info, bl); + decode(accounted_size, bl); + } else { + accounted_size = size; + } + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + static void generate_test_instances(std::list& o); +}; +WRITE_CLASS_ENCODER(RGWUploadPartInfo) -#endif +#endif /* CEPH_RGW_BASIC_TYPES_H */ diff --git a/src/rgw/rgw_bucket_layout.h b/src/rgw/rgw_bucket_layout.h index f1fe3fcf86643..80607e70aed41 100644 --- a/src/rgw/rgw_bucket_layout.h +++ b/src/rgw/rgw_bucket_layout.h @@ -13,6 +13,11 @@ * */ +/* N.B., this header defines fundamental serialized types. Do not + * introduce changes or include files which can only be compiled in + * radosgw or OSD contexts (e.g., rgw_sal.h, rgw_common.h) + */ + #pragma once #include diff --git a/src/rgw/rgw_bucket_types.h b/src/rgw/rgw_bucket_types.h new file mode 100644 index 0000000000000..61acc58bbeb1a --- /dev/null +++ b/src/rgw/rgw_bucket_types.h @@ -0,0 +1,233 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2019 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* N.B., this header defines fundamental serialized types. Do not + * include files which can only be compiled in radosgw or OSD + * contexts (e.g., rgw_sal.h, rgw_common.h) */ + +#pragma once + +#include + +#include "rgw_pool_types.h" +#include "rgw_user_types.h" +#include "rgw_placement_types.h" + +#include "common/dout.h" +#include "common/Formatter.h" + +struct cls_user_bucket; + +struct rgw_bucket_key { + std::string tenant; + std::string name; + std::string bucket_id; + + rgw_bucket_key(const std::string& _tenant, + const std::string& _name, + const std::string& _bucket_id) : tenant(_tenant), + name(_name), + bucket_id(_bucket_id) {} + rgw_bucket_key(const std::string& _tenant, + const std::string& _name) : tenant(_tenant), + name(_name) {} +}; + +struct rgw_bucket { + std::string tenant; + std::string name; + std::string marker; + std::string bucket_id; + rgw_data_placement_target explicit_placement; + + rgw_bucket() { } + // cppcheck-suppress noExplicitConstructor + explicit rgw_bucket(const rgw_user& u, const cls_user_bucket& b); + + rgw_bucket(const std::string& _tenant, + const std::string& _name, + const std::string& _bucket_id) : tenant(_tenant), + name(_name), + bucket_id(_bucket_id) {} + rgw_bucket(const rgw_bucket_key& bk) : tenant(bk.tenant), + name(bk.name), + bucket_id(bk.bucket_id) {} + rgw_bucket(const rgw_bucket&) = default; + rgw_bucket(rgw_bucket&&) = default; + + bool match(const rgw_bucket& b) const { + return (tenant == b.tenant && + name == b.name && + (bucket_id == b.bucket_id || + bucket_id.empty() || + b.bucket_id.empty())); + } + + void convert(cls_user_bucket *b) const; + + void encode(ceph::buffer::list& bl) const { + ENCODE_START(10, 10, bl); + encode(name, bl); + encode(marker, bl); + encode(bucket_id, bl); + encode(tenant, bl); + bool encode_explicit = !explicit_placement.data_pool.empty(); + encode(encode_explicit, bl); + if (encode_explicit) { + encode(explicit_placement.data_pool, bl); + encode(explicit_placement.data_extra_pool, bl); + encode(explicit_placement.index_pool, bl); + } + ENCODE_FINISH(bl); + } + + void decode(ceph::buffer::list::const_iterator& bl) { + DECODE_START_LEGACY_COMPAT_LEN(10, 3, 3, bl); + decode(name, bl); + if (struct_v < 10) { + decode(explicit_placement.data_pool.name, bl); + } + if (struct_v >= 2) { + decode(marker, bl); + if (struct_v <= 3) { + uint64_t id; + decode(id, bl); + char buf[16]; + snprintf(buf, sizeof(buf), "%" PRIu64, id); + bucket_id = buf; + } else { + decode(bucket_id, bl); + } + } + if (struct_v < 10) { + if (struct_v >= 5) { + decode(explicit_placement.index_pool.name, bl); + } else { + explicit_placement.index_pool = explicit_placement.data_pool; + } + if (struct_v >= 7) { + decode(explicit_placement.data_extra_pool.name, bl); + } + } + if (struct_v >= 8) { + decode(tenant, bl); + } + if (struct_v >= 10) { + bool decode_explicit = !explicit_placement.data_pool.empty(); + decode(decode_explicit, bl); + if (decode_explicit) { + decode(explicit_placement.data_pool, bl); + decode(explicit_placement.data_extra_pool, bl); + decode(explicit_placement.index_pool, bl); + } + } + DECODE_FINISH(bl); + } + + void update_bucket_id(const std::string& new_bucket_id) { + bucket_id = new_bucket_id; + } + + // format a key for the bucket/instance. pass delim=0 to skip a field + std::string get_key(char tenant_delim = '/', + char id_delim = ':', + size_t reserve = 0) const; + + const rgw_pool& get_data_extra_pool() const { + return explicit_placement.get_data_extra_pool(); + } + + void dump(ceph::Formatter *f) const; + void decode_json(JSONObj *obj); + static void generate_test_instances(std::list& o); + + rgw_bucket& operator=(const rgw_bucket&) = default; + + bool operator<(const rgw_bucket& b) const { + if (tenant < b.tenant) { + return true; + } else if (tenant > b.tenant) { + return false; + } + + if (name < b.name) { + return true; + } else if (name > b.name) { + return false; + } + + return (bucket_id < b.bucket_id); + } + + bool operator==(const rgw_bucket& b) const { + return (tenant == b.tenant) && (name == b.name) && \ + (bucket_id == b.bucket_id); + } + bool operator!=(const rgw_bucket& b) const { + return (tenant != b.tenant) || (name != b.name) || + (bucket_id != b.bucket_id); + } +}; +WRITE_CLASS_ENCODER(rgw_bucket) + +inline std::ostream& operator<<(std::ostream& out, const rgw_bucket &b) { + out << b.tenant << ":" << b.name << "[" << b.bucket_id << "])"; + return out; +} + +struct rgw_bucket_placement { + rgw_placement_rule placement_rule; + rgw_bucket bucket; + + void dump(Formatter *f) const; +}; /* rgw_bucket_placement */ + +struct rgw_bucket_shard { + rgw_bucket bucket; + int shard_id; + + rgw_bucket_shard() : shard_id(-1) {} + rgw_bucket_shard(const rgw_bucket& _b, int _sid) : bucket(_b), shard_id(_sid) {} + + std::string get_key(char tenant_delim = '/', char id_delim = ':', + char shard_delim = ':', + size_t reserve = 0) const; + + bool operator<(const rgw_bucket_shard& b) const { + if (bucket < b.bucket) { + return true; + } + if (b.bucket < bucket) { + return false; + } + return shard_id < b.shard_id; + } + + bool operator==(const rgw_bucket_shard& b) const { + return (bucket == b.bucket && + shard_id == b.shard_id); + } +}; /* rgw_bucket_shard */ + +void encode(const rgw_bucket_shard& b, bufferlist& bl, uint64_t f=0); +void decode(rgw_bucket_shard& b, bufferlist::const_iterator& bl); + +inline std::ostream& operator<<(std::ostream& out, const rgw_bucket_shard& bs) { + if (bs.shard_id <= 0) { + return out << bs.bucket; + } + + return out << bs.bucket << ":" << bs.shard_id; +} diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index da1f654d0fde3..6784f6248280a 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -28,7 +28,7 @@ #include "rgw_cors.h" #include "rgw_basic_types.h" #include "rgw_iam_policy.h" -#include "rgw_quota.h" +#include "rgw_quota_types.h" #include "rgw_string.h" #include "common/async/yield_context.h" #include "rgw_website.h" @@ -307,31 +307,6 @@ static inline const char* to_mime_type(const RGWFormat f) typedef void *RGWAccessHandle; -enum RGWIntentEvent { - DEL_OBJ = 0, - DEL_DIR = 1, -}; - -enum HostStyle { - PathStyle = 0, - VirtualStyle = 1, -}; - -/** Store error returns for output at a different point in the program */ -struct rgw_err { - rgw_err(); - void clear(); - bool is_clear() const; - bool is_err() const; - friend std::ostream& operator<<(std::ostream& oss, const rgw_err &err); - - int http_ret; - int ret; - std::string err_code; - std::string message; -}; - - /* Helper class used for RGWHTTPArgs parsing */ class NameVal { @@ -499,104 +474,11 @@ enum http_op { class RGWAccessControlPolicy; class JSONObj; -struct RGWAccessKey { - std::string id; // AccessKey - std::string key; // SecretKey - std::string subuser; - - RGWAccessKey() {} - RGWAccessKey(std::string _id, std::string _key) - : id(std::move(_id)), key(std::move(_key)) {} - - void encode(bufferlist& bl) const { - ENCODE_START(2, 2, bl); - encode(id, bl); - encode(key, bl); - encode(subuser, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN_32(2, 2, 2, bl); - decode(id, bl); - decode(key, bl); - decode(subuser, bl); - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - void dump_plain(Formatter *f) const; - void dump(Formatter *f, const std::string& user, bool swift) const; - static void generate_test_instances(std::list& o); - - void decode_json(JSONObj *obj); - void decode_json(JSONObj *obj, bool swift); -}; -WRITE_CLASS_ENCODER(RGWAccessKey) - -struct RGWSubUser { - std::string name; - uint32_t perm_mask; - - RGWSubUser() : perm_mask(0) {} - void encode(bufferlist& bl) const { - ENCODE_START(2, 2, bl); - encode(name, bl); - encode(perm_mask, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN_32(2, 2, 2, bl); - decode(name, bl); - decode(perm_mask, bl); - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - void dump(Formatter *f, const std::string& user) const; - static void generate_test_instances(std::list& o); - - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWSubUser) - -class RGWUserCaps -{ - std::map caps; - - int get_cap(const std::string& cap, std::string& type, uint32_t *perm); - int add_cap(const std::string& cap); - int remove_cap(const std::string& cap); -public: - static int parse_cap_perm(const std::string& str, uint32_t *perm); - int add_from_string(const std::string& str); - int remove_from_string(const std::string& str); - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(caps, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(caps, bl); - DECODE_FINISH(bl); - } - int check_cap(const std::string& cap, uint32_t perm) const; - bool is_valid_cap_type(const std::string& tp); - void dump(Formatter *f) const; - void dump(Formatter *f, const char *name) const; - - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(RGWUserCaps) - void encode_json(const char *name, const obj_version& v, Formatter *f); void encode_json(const char *name, const RGWUserCaps& val, Formatter *f); void decode_json_obj(obj_version& v, JSONObj *obj); - - enum RGWIdentityType { TYPE_NONE=0, @@ -607,113 +489,6 @@ enum RGWIdentityType TYPE_WEB=5, }; -static std::string RGW_STORAGE_CLASS_STANDARD = "STANDARD"; - -struct rgw_placement_rule { - std::string name; - std::string storage_class; - - rgw_placement_rule() {} - rgw_placement_rule(const std::string& _n, const std::string& _sc) : name(_n), storage_class(_sc) {} - rgw_placement_rule(const rgw_placement_rule& _r, const std::string& _sc) : name(_r.name) { - if (!_sc.empty()) { - storage_class = _sc; - } else { - storage_class = _r.storage_class; - } - } - - bool empty() const { - return name.empty() && storage_class.empty(); - } - - void inherit_from(const rgw_placement_rule& r) { - if (name.empty()) { - name = r.name; - } - if (storage_class.empty()) { - storage_class = r.storage_class; - } - } - - void clear() { - name.clear(); - storage_class.clear(); - } - - void init(const std::string& n, const std::string& c) { - name = n; - storage_class = c; - } - - static const std::string& get_canonical_storage_class(const std::string& storage_class) { - if (storage_class.empty()) { - return RGW_STORAGE_CLASS_STANDARD; - } - return storage_class; - } - - const std::string& get_storage_class() const { - return get_canonical_storage_class(storage_class); - } - - int compare(const rgw_placement_rule& r) const { - int c = name.compare(r.name); - if (c != 0) { - return c; - } - return get_storage_class().compare(r.get_storage_class()); - } - - bool operator==(const rgw_placement_rule& r) const { - return (name == r.name && - get_storage_class() == r.get_storage_class()); - } - - bool operator!=(const rgw_placement_rule& r) const { - return !(*this == r); - } - - void encode(bufferlist& bl) const { - /* no ENCODE_START/END due to backward compatibility */ - std::string s = to_str(); - ceph::encode(s, bl); - } - - void decode(bufferlist::const_iterator& bl) { - std::string s; - ceph::decode(s, bl); - from_str(s); - } - - std::string to_str() const { - if (standard_storage_class()) { - return name; - } - return to_str_explicit(); - } - - std::string to_str_explicit() const { - return name + "/" + storage_class; - } - - void from_str(const std::string& s) { - size_t pos = s.find("/"); - if (pos == std::string::npos) { - name = s; - storage_class.clear(); - return; - } - name = s.substr(0, pos); - storage_class = s.substr(pos + 1); - } - - bool standard_storage_class() const { - return storage_class.empty() || storage_class == RGW_STORAGE_CLASS_STANDARD; - } -}; -WRITE_CLASS_ENCODER(rgw_placement_rule) - void encode_json(const char *name, const rgw_placement_rule& val, ceph::Formatter *f); void decode_json_obj(rgw_placement_rule& v, JSONObj *obj); @@ -942,88 +717,6 @@ struct RGWUserInfo }; WRITE_CLASS_ENCODER(RGWUserInfo) -struct rgw_raw_obj { - rgw_pool pool; - std::string oid; - std::string loc; - - rgw_raw_obj() {} - rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid) { - init(_pool, _oid); - } - rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid, const std::string& _loc) : loc(_loc) { - init(_pool, _oid); - } - - void init(const rgw_pool& _pool, const std::string& _oid) { - pool = _pool; - oid = _oid; - } - - bool empty() const { - return oid.empty(); - } - - void encode(bufferlist& bl) const { - ENCODE_START(6, 6, bl); - encode(pool, bl); - encode(oid, bl); - encode(loc, bl); - ENCODE_FINISH(bl); - } - - void decode_from_rgw_obj(bufferlist::const_iterator& bl); - - void decode(bufferlist::const_iterator& bl) { - unsigned ofs = bl.get_off(); - DECODE_START(6, bl); - if (struct_v < 6) { - /* - * this object was encoded as rgw_obj, prior to rgw_raw_obj been split out of it, - * let's decode it as rgw_obj and convert it - */ - bl.seek(ofs); - decode_from_rgw_obj(bl); - return; - } - decode(pool, bl); - decode(oid, bl); - decode(loc, bl); - DECODE_FINISH(bl); - } - - bool operator<(const rgw_raw_obj& o) const { - int r = pool.compare(o.pool); - if (r == 0) { - r = oid.compare(o.oid); - if (r == 0) { - r = loc.compare(o.loc); - } - } - return (r < 0); - } - - bool operator==(const rgw_raw_obj& o) const { - return (pool == o.pool && oid == o.oid && loc == o.loc); - } - - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); -}; -WRITE_CLASS_ENCODER(rgw_raw_obj) - -inline std::ostream& operator<<(std::ostream& out, const rgw_raw_obj& o) { - out << o.pool << ":" << o.oid; - return out; -} - -struct rgw_bucket_placement { - rgw_placement_rule placement_rule; - rgw_bucket bucket; - - void dump(Formatter *f) const; -}; - /// `RGWObjVersionTracker` /// ====================== /// @@ -1362,299 +1055,6 @@ struct req_info { void init_meta_info(const DoutPrefixProvider *dpp, bool *found_bad_meta); }; -typedef cls_rgw_obj_key rgw_obj_index_key; - -struct rgw_obj_key { - std::string name; - std::string instance; - std::string ns; - - rgw_obj_key() {} - // cppcheck-suppress noExplicitConstructor - rgw_obj_key(const std::string& n) : name(n) {} - rgw_obj_key(const std::string& n, const std::string& i) : name(n), instance(i) {} - rgw_obj_key(const std::string& n, const std::string& i, const std::string& _ns) : name(n), instance(i), ns(_ns) {} - - rgw_obj_key(const rgw_obj_index_key& k) { - parse_index_key(k.name, &name, &ns); - instance = k.instance; - } - - static void parse_index_key(const std::string& key, std::string *name, std::string *ns) { - if (key[0] != '_') { - *name = key; - ns->clear(); - return; - } - if (key[1] == '_') { - *name = key.substr(1); - ns->clear(); - return; - } - ssize_t pos = key.find('_', 1); - if (pos < 0) { - /* shouldn't happen, just use key */ - *name = key; - ns->clear(); - return; - } - - *name = key.substr(pos + 1); - *ns = key.substr(1, pos -1); - } - - void set(const std::string& n) { - name = n; - instance.clear(); - ns.clear(); - } - - void set(const std::string& n, const std::string& i) { - name = n; - instance = i; - ns.clear(); - } - - void set(const std::string& n, const std::string& i, const std::string& _ns) { - name = n; - instance = i; - ns = _ns; - } - - bool set(const rgw_obj_index_key& index_key) { - if (!parse_raw_oid(index_key.name, this)) { - return false; - } - instance = index_key.instance; - return true; - } - - void set_instance(const std::string& i) { - instance = i; - } - - const std::string& get_instance() const { - return instance; - } - - void set_ns(const std::string& _ns) { - ns = _ns; - } - - const std::string& get_ns() const { - return ns; - } - - std::string get_index_key_name() const { - if (ns.empty()) { - if (name.size() < 1 || name[0] != '_') { - return name; - } - return std::string("_") + name; - }; - - char buf[ns.size() + 16]; - snprintf(buf, sizeof(buf), "_%s_", ns.c_str()); - return std::string(buf) + name; - }; - - void get_index_key(rgw_obj_index_key *key) const { - key->name = get_index_key_name(); - key->instance = instance; - } - - std::string get_loc() const { - /* - * For backward compatibility. Older versions used to have object locator on all objects, - * however, the name was the effective object locator. This had the same effect as not - * having object locator at all for most objects but the ones that started with underscore as - * these were escaped. - */ - if (name[0] == '_' && ns.empty()) { - return name; - } - - return {}; - } - - bool empty() const { - return name.empty(); - } - - bool have_null_instance() const { - return instance == "null"; - } - - bool have_instance() const { - return !instance.empty(); - } - - bool need_to_encode_instance() const { - return have_instance() && !have_null_instance(); - } - - std::string get_oid() const { - if (ns.empty() && !need_to_encode_instance()) { - if (name.size() < 1 || name[0] != '_') { - return name; - } - return std::string("_") + name; - } - - std::string oid = "_"; - oid.append(ns); - if (need_to_encode_instance()) { - oid.append(std::string(":") + instance); - } - oid.append("_"); - oid.append(name); - return oid; - } - - bool operator==(const rgw_obj_key& k) const { - return (name.compare(k.name) == 0) && - (instance.compare(k.instance) == 0); - } - - bool operator<(const rgw_obj_key& k) const { - int r = name.compare(k.name); - if (r == 0) { - r = instance.compare(k.instance); - } - return (r < 0); - } - - bool operator<=(const rgw_obj_key& k) const { - return !(k < *this); - } - - static void parse_ns_field(std::string& ns, std::string& instance) { - int pos = ns.find(':'); - if (pos >= 0) { - instance = ns.substr(pos + 1); - ns = ns.substr(0, pos); - } else { - instance.clear(); - } - } - - // takes an oid and parses out the namespace (ns), name, and - // instance - static bool parse_raw_oid(const std::string& oid, rgw_obj_key *key) { - key->instance.clear(); - key->ns.clear(); - if (oid[0] != '_') { - key->name = oid; - return true; - } - - if (oid.size() >= 2 && oid[1] == '_') { - key->name = oid.substr(1); - return true; - } - - if (oid.size() < 3) // for namespace, min size would be 3: _x_ - return false; - - size_t pos = oid.find('_', 2); // oid must match ^_[^_].+$ - if (pos == std::string::npos) - return false; - - key->ns = oid.substr(1, pos - 1); - parse_ns_field(key->ns, key->instance); - - key->name = oid.substr(pos + 1); - return true; - } - - /** - * Translate a namespace-mangled object name to the user-facing name - * existing in the given namespace. - * - * If the object is part of the given namespace, it returns true - * and cuts down the name to the unmangled version. If it is not - * part of the given namespace, it returns false. - */ - static bool oid_to_key_in_ns(const std::string& oid, rgw_obj_key *key, const std::string& ns) { - bool ret = parse_raw_oid(oid, key); - if (!ret) { - return ret; - } - - return (ns == key->ns); - } - - /** - * Given a mangled object name and an empty namespace std::string, this - * function extracts the namespace into the std::string and sets the object - * name to be the unmangled version. - * - * It returns true after successfully doing so, or - * false if it fails. - */ - static bool strip_namespace_from_name(std::string& name, std::string& ns, std::string& instance) { - ns.clear(); - instance.clear(); - if (name[0] != '_') { - return true; - } - - size_t pos = name.find('_', 1); - if (pos == std::string::npos) { - return false; - } - - if (name[1] == '_') { - name = name.substr(1); - return true; - } - - size_t period_pos = name.find('.'); - if (period_pos < pos) { - return false; - } - - ns = name.substr(1, pos-1); - name = name.substr(pos+1, std::string::npos); - - parse_ns_field(ns, instance); - return true; - } - - void encode(bufferlist& bl) const { - ENCODE_START(2, 1, bl); - encode(name, bl); - encode(instance, bl); - encode(ns, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& bl) { - DECODE_START(2, bl); - decode(name, bl); - decode(instance, bl); - if (struct_v >= 2) { - decode(ns, bl); - } - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - void decode_json(JSONObj *obj); - - std::string to_str() const { - if (instance.empty()) { - return name; - } - char buf[name.size() + instance.size() + 16]; - snprintf(buf, sizeof(buf), "%s[%s]", name.c_str(), instance.c_str()); - return buf; - } -}; -WRITE_CLASS_ENCODER(rgw_obj_key) - -inline std::ostream& operator<<(std::ostream& out, const rgw_obj_key &o) { - return out << o.to_str(); -} - struct req_init_state { /* Keeps [[tenant]:]bucket until we parse the token. */ std::string url_bucket; @@ -1920,139 +1320,6 @@ struct RGWBucketEnt { }; WRITE_CLASS_ENCODER(RGWBucketEnt) -struct rgw_obj { - rgw_bucket bucket; - rgw_obj_key key; - - bool in_extra_data{false}; /* in-memory only member, does not serialize */ - - // Represents the hash index source for this object once it is set (non-empty) - std::string index_hash_source; - - rgw_obj() {} - rgw_obj(const rgw_bucket& b, const std::string& name) : bucket(b), key(name) {} - rgw_obj(const rgw_bucket& b, const rgw_obj_key& k) : bucket(b), key(k) {} - rgw_obj(const rgw_bucket& b, const rgw_obj_index_key& k) : bucket(b), key(k) {} - - void init(const rgw_bucket& b, const rgw_obj_key& k) { - bucket = b; - key = k; - } - void init(const rgw_bucket& b, const std::string& name) { - bucket = b; - key.set(name); - } - void init(const rgw_bucket& b, const std::string& name, const std::string& i, const std::string& n) { - bucket = b; - key.set(name, i, n); - } - void init_ns(const rgw_bucket& b, const std::string& name, const std::string& n) { - bucket = b; - key.name = name; - key.instance.clear(); - key.ns = n; - } - - bool empty() const { - return key.empty(); - } - - void set_key(const rgw_obj_key& k) { - key = k; - } - - std::string get_oid() const { - return key.get_oid(); - } - - const std::string& get_hash_object() const { - return index_hash_source.empty() ? key.name : index_hash_source; - } - - void set_in_extra_data(bool val) { - in_extra_data = val; - } - - bool is_in_extra_data() const { - return in_extra_data; - } - - void encode(bufferlist& bl) const { - ENCODE_START(6, 6, bl); - encode(bucket, bl); - encode(key.ns, bl); - encode(key.name, bl); - encode(key.instance, bl); -// encode(placement_id, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl); - if (struct_v < 6) { - std::string s; - decode(bucket.name, bl); /* bucket.name */ - decode(s, bl); /* loc */ - decode(key.ns, bl); - decode(key.name, bl); - if (struct_v >= 2) - decode(bucket, bl); - if (struct_v >= 4) - decode(key.instance, bl); - if (key.ns.empty() && key.instance.empty()) { - if (key.name[0] == '_') { - key.name = key.name.substr(1); - } - } else { - if (struct_v >= 5) { - decode(key.name, bl); - } else { - ssize_t pos = key.name.find('_', 1); - if (pos < 0) { - throw buffer::malformed_input(); - } - key.name = key.name.substr(pos + 1); - } - } - } else { - decode(bucket, bl); - decode(key.ns, bl); - decode(key.name, bl); - decode(key.instance, bl); -// decode(placement_id, bl); - } - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - static void generate_test_instances(std::list& o); - - bool operator==(const rgw_obj& o) const { - return (key == o.key) && - (bucket == o.bucket); - } - bool operator<(const rgw_obj& o) const { - int r = key.name.compare(o.key.name); - if (r == 0) { - r = bucket.bucket_id.compare(o.bucket.bucket_id); /* not comparing bucket.name, if bucket_id is equal so will be bucket.name */ - if (r == 0) { - r = key.ns.compare(o.key.ns); - if (r == 0) { - r = key.instance.compare(o.key.instance); - } - } - } - - return (r < 0); - } - - const rgw_pool& get_explicit_data_pool() { - if (!in_extra_data || bucket.explicit_placement.data_extra_pool.empty()) { - return bucket.explicit_placement.data_pool; - } - return bucket.explicit_placement.data_extra_pool; - } -}; -WRITE_CLASS_ENCODER(rgw_obj) - struct rgw_cache_entry_info { std::string cache_locator; uint64_t gen; diff --git a/src/rgw/rgw_compression_types.h b/src/rgw/rgw_compression_types.h index 82c45d4e8f9a2..efc002efbece5 100644 --- a/src/rgw/rgw_compression_types.h +++ b/src/rgw/rgw_compression_types.h @@ -15,8 +15,6 @@ #pragma once -#include "rgw_common.h" - struct compression_block { uint64_t old_ofs; uint64_t new_ofs; diff --git a/src/rgw/rgw_multi.h b/src/rgw/rgw_multi.h index 8070455f835f5..bb371e71c5e5a 100644 --- a/src/rgw/rgw_multi.h +++ b/src/rgw/rgw_multi.h @@ -6,6 +6,7 @@ #include #include "rgw_xml.h" +#include "rgw_obj_types.h" #include "rgw_obj_manifest.h" #include "rgw_compression_types.h" #include "common/dout.h" @@ -14,51 +15,6 @@ #define MULTIPART_UPLOAD_ID_PREFIX_LEGACY "2/" #define MULTIPART_UPLOAD_ID_PREFIX "2~" // must contain a unique char that may not come up in gen_rand_alpha() -class RGWMPObj; - -struct RGWUploadPartInfo { - uint32_t num; - uint64_t size; - uint64_t accounted_size{0}; - std::string etag; - ceph::real_time modified; - RGWObjManifest manifest; - RGWCompressionInfo cs_info; - - RGWUploadPartInfo() : num(0), size(0) {} - - void encode(bufferlist& bl) const { - ENCODE_START(4, 2, bl); - encode(num, bl); - encode(size, bl); - encode(etag, bl); - encode(modified, bl); - encode(manifest, bl); - encode(cs_info, bl); - encode(accounted_size, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(4, 2, 2, bl); - decode(num, bl); - decode(size, bl); - decode(etag, bl); - decode(modified, bl); - if (struct_v >= 3) - decode(manifest, bl); - if (struct_v >= 4) { - decode(cs_info, bl); - decode(accounted_size, bl); - } else { - accounted_size = size; - } - DECODE_FINISH(bl); - } - void dump(Formatter *f) const; - static void generate_test_instances(std::list& o); -}; -WRITE_CLASS_ENCODER(RGWUploadPartInfo) - class RGWMultiCompleteUpload : public XMLObj { public: diff --git a/src/rgw/rgw_obj_types.h b/src/rgw/rgw_obj_types.h new file mode 100644 index 0000000000000..781150b8becda --- /dev/null +++ b/src/rgw/rgw_obj_types.h @@ -0,0 +1,610 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2019 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* N.B., this header defines fundamental serialized types. Do not + * include files which can only be compiled in radosgw or OSD + * contexts (e.g., rgw_sal.h, rgw_common.h) */ + +#pragma once + +#include + +#include "rgw_pool_types.h" +#include "rgw_bucket_types.h" +#include "rgw_user_types.h" + +#include "common/dout.h" +#include "common/Formatter.h" + +struct rgw_obj_index_key { // cls_rgw_obj_key now aliases this type + std::string name; + std::string instance; + + rgw_obj_index_key() {} + rgw_obj_index_key(const std::string &_name) : name(_name) {} + rgw_obj_index_key(const std::string& n, const std::string& i) : name(n), instance(i) {} + + std::string to_string() const { + return fmt::format("{}({})", name, instance); + } + + bool empty() const { + return name.empty(); + } + + void set(const std::string& _name) { + name = _name; + instance.clear(); + } + + bool operator==(const rgw_obj_index_key& k) const { + return (name.compare(k.name) == 0) && + (instance.compare(k.instance) == 0); + } + + bool operator!=(const rgw_obj_index_key& k) const { + return (name.compare(k.name) != 0) || + (instance.compare(k.instance) != 0); + } + + bool operator<(const rgw_obj_index_key& k) const { + int r = name.compare(k.name); + if (r == 0) { + r = instance.compare(k.instance); + } + return (r < 0); + } + + bool operator<=(const rgw_obj_index_key& k) const { + return !(k < *this); + } + + void encode(ceph::buffer::list &bl) const { + ENCODE_START(1, 1, bl); + encode(name, bl); + encode(instance, bl); + ENCODE_FINISH(bl); + } + void decode(ceph::buffer::list::const_iterator &bl) { + DECODE_START(1, bl); + decode(name, bl); + decode(instance, bl); + DECODE_FINISH(bl); + } + void dump(ceph::Formatter *f) const { + f->dump_string("name", name); + f->dump_string("instance", instance); + } + void decode_json(JSONObj *obj); + static void generate_test_instances(std::list& ls) { + ls.push_back(new rgw_obj_index_key); + ls.push_back(new rgw_obj_index_key); + ls.back()->name = "name"; + ls.back()->instance = "instance"; + } + + size_t estimate_encoded_size() const { + constexpr size_t start_overhead = sizeof(__u8) + sizeof(__u8) + sizeof(ceph_le32); // version and length prefix + constexpr size_t string_overhead = sizeof(__u32); // strings are encoded with 32-bit length prefix + return start_overhead + + string_overhead + name.size() + + string_overhead + instance.size(); + } +}; +WRITE_CLASS_ENCODER(rgw_obj_index_key) + +struct rgw_obj_key { + std::string name; + std::string instance; + std::string ns; + + rgw_obj_key() {} + + // cppcheck-suppress noExplicitConstructor + rgw_obj_key(const std::string& n) : name(n) {} + rgw_obj_key(const std::string& n, const std::string& i) : name(n), instance(i) {} + rgw_obj_key(const std::string& n, const std::string& i, const std::string& _ns) : name(n), instance(i), ns(_ns) {} + + rgw_obj_key(const rgw_obj_index_key& k) { + parse_index_key(k.name, &name, &ns); + instance = k.instance; + } + + static void parse_index_key(const std::string& key, std::string *name, std::string *ns) { + if (key[0] != '_') { + *name = key; + ns->clear(); + return; + } + if (key[1] == '_') { + *name = key.substr(1); + ns->clear(); + return; + } + ssize_t pos = key.find('_', 1); + if (pos < 0) { + /* shouldn't happen, just use key */ + *name = key; + ns->clear(); + return; + } + + *name = key.substr(pos + 1); + *ns = key.substr(1, pos -1); + } + + void set(const std::string& n) { + name = n; + instance.clear(); + ns.clear(); + } + + void set(const std::string& n, const std::string& i) { + name = n; + instance = i; + ns.clear(); + } + + void set(const std::string& n, const std::string& i, const std::string& _ns) { + name = n; + instance = i; + ns = _ns; + } + + bool set(const rgw_obj_index_key& index_key) { + if (!parse_raw_oid(index_key.name, this)) { + return false; + } + instance = index_key.instance; + return true; + } + + void set_instance(const std::string& i) { + instance = i; + } + + const std::string& get_instance() const { + return instance; + } + + void set_ns(const std::string& _ns) { + ns = _ns; + } + + const std::string& get_ns() const { + return ns; + } + + std::string get_index_key_name() const { + if (ns.empty()) { + if (name.size() < 1 || name[0] != '_') { + return name; + } + return std::string("_") + name; + }; + + char buf[ns.size() + 16]; + snprintf(buf, sizeof(buf), "_%s_", ns.c_str()); + return std::string(buf) + name; + }; + + void get_index_key(rgw_obj_index_key* key) const { + key->name = get_index_key_name(); + key->instance = instance; + } + + std::string get_loc() const { + /* + * For backward compatibility. Older versions used to have object locator on all objects, + * however, the name was the effective object locator. This had the same effect as not + * having object locator at all for most objects but the ones that started with underscore as + * these were escaped. + */ + if (name[0] == '_' && ns.empty()) { + return name; + } + + return {}; + } + + bool empty() const { + return name.empty(); + } + + bool have_null_instance() const { + return instance == "null"; + } + + bool have_instance() const { + return !instance.empty(); + } + + bool need_to_encode_instance() const { + return have_instance() && !have_null_instance(); + } + + std::string get_oid() const { + if (ns.empty() && !need_to_encode_instance()) { + if (name.size() < 1 || name[0] != '_') { + return name; + } + return std::string("_") + name; + } + + std::string oid = "_"; + oid.append(ns); + if (need_to_encode_instance()) { + oid.append(std::string(":") + instance); + } + oid.append("_"); + oid.append(name); + return oid; + } + + bool operator==(const rgw_obj_key& k) const { + return (name.compare(k.name) == 0) && + (instance.compare(k.instance) == 0); + } + + bool operator<(const rgw_obj_key& k) const { + int r = name.compare(k.name); + if (r == 0) { + r = instance.compare(k.instance); + } + return (r < 0); + } + + bool operator<=(const rgw_obj_key& k) const { + return !(k < *this); + } + + static void parse_ns_field(std::string& ns, std::string& instance) { + int pos = ns.find(':'); + if (pos >= 0) { + instance = ns.substr(pos + 1); + ns = ns.substr(0, pos); + } else { + instance.clear(); + } + } + + // takes an oid and parses out the namespace (ns), name, and + // instance + static bool parse_raw_oid(const std::string& oid, rgw_obj_key *key) { + key->instance.clear(); + key->ns.clear(); + if (oid[0] != '_') { + key->name = oid; + return true; + } + + if (oid.size() >= 2 && oid[1] == '_') { + key->name = oid.substr(1); + return true; + } + + if (oid.size() < 3) // for namespace, min size would be 3: _x_ + return false; + + size_t pos = oid.find('_', 2); // oid must match ^_[^_].+$ + if (pos == std::string::npos) + return false; + + key->ns = oid.substr(1, pos - 1); + parse_ns_field(key->ns, key->instance); + + key->name = oid.substr(pos + 1); + return true; + } + + /** + * Translate a namespace-mangled object name to the user-facing name + * existing in the given namespace. + * + * If the object is part of the given namespace, it returns true + * and cuts down the name to the unmangled version. If it is not + * part of the given namespace, it returns false. + */ + static bool oid_to_key_in_ns(const std::string& oid, rgw_obj_key *key, const std::string& ns) { + bool ret = parse_raw_oid(oid, key); + if (!ret) { + return ret; + } + + return (ns == key->ns); + } + + /** + * Given a mangled object name and an empty namespace std::string, this + * function extracts the namespace into the std::string and sets the object + * name to be the unmangled version. + * + * It returns true after successfully doing so, or + * false if it fails. + */ + static bool strip_namespace_from_name(std::string& name, std::string& ns, std::string& instance) { + ns.clear(); + instance.clear(); + if (name[0] != '_') { + return true; + } + + size_t pos = name.find('_', 1); + if (pos == std::string::npos) { + return false; + } + + if (name[1] == '_') { + name = name.substr(1); + return true; + } + + size_t period_pos = name.find('.'); + if (period_pos < pos) { + return false; + } + + ns = name.substr(1, pos-1); + name = name.substr(pos+1, std::string::npos); + + parse_ns_field(ns, instance); + return true; + } + + void encode(bufferlist& bl) const { + ENCODE_START(2, 1, bl); + encode(name, bl); + encode(instance, bl); + encode(ns, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator& bl) { + DECODE_START(2, bl); + decode(name, bl); + decode(instance, bl); + if (struct_v >= 2) { + decode(ns, bl); + } + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); + + std::string to_str() const { + if (instance.empty()) { + return name; + } + char buf[name.size() + instance.size() + 16]; + snprintf(buf, sizeof(buf), "%s[%s]", name.c_str(), instance.c_str()); + return buf; + } +}; +WRITE_CLASS_ENCODER(rgw_obj_key) + +inline std::ostream& operator<<(std::ostream& out, const rgw_obj_key &o) { + return out << o.to_str(); +} + +struct rgw_raw_obj { + rgw_pool pool; + std::string oid; + std::string loc; + + rgw_raw_obj() {} + rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid) { + init(_pool, _oid); + } + rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid, const std::string& _loc) : loc(_loc) { + init(_pool, _oid); + } + + void init(const rgw_pool& _pool, const std::string& _oid) { + pool = _pool; + oid = _oid; + } + + bool empty() const { + return oid.empty(); + } + + void encode(bufferlist& bl) const { + ENCODE_START(6, 6, bl); + encode(pool, bl); + encode(oid, bl); + encode(loc, bl); + ENCODE_FINISH(bl); + } + + void decode_from_rgw_obj(bufferlist::const_iterator& bl); + + void decode(bufferlist::const_iterator& bl) { + unsigned ofs = bl.get_off(); + DECODE_START(6, bl); + if (struct_v < 6) { + /* + * this object was encoded as rgw_obj, prior to rgw_raw_obj been split out of it, + * let's decode it as rgw_obj and convert it + */ + bl.seek(ofs); + decode_from_rgw_obj(bl); + return; + } + decode(pool, bl); + decode(oid, bl); + decode(loc, bl); + DECODE_FINISH(bl); + } + + bool operator<(const rgw_raw_obj& o) const { + int r = pool.compare(o.pool); + if (r == 0) { + r = oid.compare(o.oid); + if (r == 0) { + r = loc.compare(o.loc); + } + } + return (r < 0); + } + + bool operator==(const rgw_raw_obj& o) const { + return (pool == o.pool && oid == o.oid && loc == o.loc); + } + + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(rgw_raw_obj) + +inline std::ostream& operator<<(std::ostream& out, const rgw_raw_obj& o) { + out << o.pool << ":" << o.oid; + return out; +} + +struct rgw_obj { + rgw_bucket bucket; + rgw_obj_key key; + + bool in_extra_data{false}; /* in-memory only member, does not serialize */ + + // Represents the hash index source for this object once it is set (non-empty) + std::string index_hash_source; + + rgw_obj() {} + rgw_obj(const rgw_bucket& b, const std::string& name) : bucket(b), key(name) {} + rgw_obj(const rgw_bucket& b, const rgw_obj_key& k) : bucket(b), key(k) {} + rgw_obj(const rgw_bucket& b, const rgw_obj_index_key& k) : bucket(b), key(k) {} + + void init(const rgw_bucket& b, const rgw_obj_key& k) { + bucket = b; + key = k; + } + + void init(const rgw_bucket& b, const std::string& name) { + bucket = b; + key.set(name); + } + + void init(const rgw_bucket& b, const std::string& name, const std::string& i, const std::string& n) { + bucket = b; + key.set(name, i, n); + } + + void init_ns(const rgw_bucket& b, const std::string& name, const std::string& n) { + bucket = b; + key.name = name; + key.instance.clear(); + key.ns = n; + } + + bool empty() const { + return key.empty(); + } + + void set_key(const rgw_obj_key& k) { + key = k; + } + + std::string get_oid() const { + return key.get_oid(); + } + + const std::string& get_hash_object() const { + return index_hash_source.empty() ? key.name : index_hash_source; + } + + void set_in_extra_data(bool val) { + in_extra_data = val; + } + + bool is_in_extra_data() const { + return in_extra_data; + } + + void encode(bufferlist& bl) const { + ENCODE_START(6, 6, bl); + encode(bucket, bl); + encode(key.ns, bl); + encode(key.name, bl); + encode(key.instance, bl); +// encode(placement_id, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl); + if (struct_v < 6) { + std::string s; + decode(bucket.name, bl); /* bucket.name */ + decode(s, bl); /* loc */ + decode(key.ns, bl); + decode(key.name, bl); + if (struct_v >= 2) + decode(bucket, bl); + if (struct_v >= 4) + decode(key.instance, bl); + if (key.ns.empty() && key.instance.empty()) { + if (key.name[0] == '_') { + key.name = key.name.substr(1); + } + } else { + if (struct_v >= 5) { + decode(key.name, bl); + } else { + ssize_t pos = key.name.find('_', 1); + if (pos < 0) { + throw buffer::malformed_input(); + } + key.name = key.name.substr(pos + 1); + } + } + } else { + decode(bucket, bl); + decode(key.ns, bl); + decode(key.name, bl); + decode(key.instance, bl); +// decode(placement_id, bl); + } + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + static void generate_test_instances(std::list& o); + + bool operator==(const rgw_obj& o) const { + return (key == o.key) && + (bucket == o.bucket); + } + bool operator<(const rgw_obj& o) const { + int r = key.name.compare(o.key.name); + if (r == 0) { + r = bucket.bucket_id.compare(o.bucket.bucket_id); /* not comparing bucket.name, if bucket_id is equal so will be bucket.name */ + if (r == 0) { + r = key.ns.compare(o.key.ns); + if (r == 0) { + r = key.instance.compare(o.key.instance); + } + } + } + + return (r < 0); + } + + const rgw_pool& get_explicit_data_pool() { + if (!in_extra_data || bucket.explicit_placement.data_extra_pool.empty()) { + return bucket.explicit_placement.data_pool; + } + return bucket.explicit_placement.data_extra_pool; + } +}; +WRITE_CLASS_ENCODER(rgw_obj) diff --git a/src/rgw/rgw_placement_types.h b/src/rgw/rgw_placement_types.h new file mode 100644 index 0000000000000..bcf7a4af735b1 --- /dev/null +++ b/src/rgw/rgw_placement_types.h @@ -0,0 +1,118 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +#pragma once + +#include + +#include "include/types.h" + +#include "common/Formatter.h" + + +static std::string RGW_STORAGE_CLASS_STANDARD = "STANDARD"; + +struct rgw_placement_rule { + std::string name; + std::string storage_class; + + rgw_placement_rule() {} + rgw_placement_rule(const std::string& _n, const std::string& _sc) : name(_n), storage_class(_sc) {} + rgw_placement_rule(const rgw_placement_rule& _r, const std::string& _sc) : name(_r.name) { + if (!_sc.empty()) { + storage_class = _sc; + } else { + storage_class = _r.storage_class; + } + } + + bool empty() const { + return name.empty() && storage_class.empty(); + } + + void inherit_from(const rgw_placement_rule& r) { + if (name.empty()) { + name = r.name; + } + if (storage_class.empty()) { + storage_class = r.storage_class; + } + } + + void clear() { + name.clear(); + storage_class.clear(); + } + + void init(const std::string& n, const std::string& c) { + name = n; + storage_class = c; + } + + static const std::string& get_canonical_storage_class(const std::string& storage_class) { + if (storage_class.empty()) { + return RGW_STORAGE_CLASS_STANDARD; + } + return storage_class; + } + + const std::string& get_storage_class() const { + return get_canonical_storage_class(storage_class); + } + + int compare(const rgw_placement_rule& r) const { + int c = name.compare(r.name); + if (c != 0) { + return c; + } + return get_storage_class().compare(r.get_storage_class()); + } + + bool operator==(const rgw_placement_rule& r) const { + return (name == r.name && + get_storage_class() == r.get_storage_class()); + } + + bool operator!=(const rgw_placement_rule& r) const { + return !(*this == r); + } + + void encode(bufferlist& bl) const { + /* no ENCODE_START/END due to backward compatibility */ + std::string s = to_str(); + ceph::encode(s, bl); + } + + void decode(bufferlist::const_iterator& bl) { + std::string s; + ceph::decode(s, bl); + from_str(s); + } + + std::string to_str() const { + if (standard_storage_class()) { + return name; + } + return to_str_explicit(); + } + + std::string to_str_explicit() const { + return name + "/" + storage_class; + } + + void from_str(const std::string& s) { + size_t pos = s.find("/"); + if (pos == std::string::npos) { + name = s; + storage_class.clear(); + return; + } + name = s.substr(0, pos); + storage_class = s.substr(pos + 1); + } + + bool standard_storage_class() const { + return storage_class.empty() || storage_class == RGW_STORAGE_CLASS_STANDARD; + } +}; +WRITE_CLASS_ENCODER(rgw_placement_rule) diff --git a/src/rgw/rgw_pool_types.h b/src/rgw/rgw_pool_types.h new file mode 100644 index 0000000000000..b23e7d005dbe6 --- /dev/null +++ b/src/rgw/rgw_pool_types.h @@ -0,0 +1,157 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2019 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* N.B., this header defines fundamental serialized types. Do not + * introduce changes or include files which can only be compiled in + * radosgw or OSD contexts (e.g., rgw_sal.h, rgw_common.h) + */ + +#pragma once + +#include +#include + +#include "include/types.h" +#include "common/Formatter.h" + +class JSONObj; + +struct rgw_pool { + std::string name; + std::string ns; + + rgw_pool() = default; + rgw_pool(const rgw_pool& _p) : name(_p.name), ns(_p.ns) {} + rgw_pool(rgw_pool&&) = default; + rgw_pool(const std::string& _s) { + from_str(_s); + } + rgw_pool(const std::string& _name, const std::string& _ns) : name(_name), ns(_ns) {} + + std::string to_str() const; + void from_str(const std::string& s); + + void init(const std::string& _s) { + from_str(_s); + } + + bool empty() const { + return name.empty(); + } + + int compare(const rgw_pool& p) const { + int r = name.compare(p.name); + if (r != 0) { + return r; + } + return ns.compare(p.ns); + } + + void encode(ceph::buffer::list& bl) const { + ENCODE_START(10, 10, bl); + encode(name, bl); + encode(ns, bl); + ENCODE_FINISH(bl); + } + + void decode_from_bucket(ceph::buffer::list::const_iterator& bl); + + void decode(ceph::buffer::list::const_iterator& bl) { + DECODE_START_LEGACY_COMPAT_LEN(10, 3, 3, bl); + + decode(name, bl); + + if (struct_v < 10) { + + /* + * note that rgw_pool can be used where rgw_bucket was used before + * therefore we inherit rgw_bucket's old versions. However, we only + * need the first field from rgw_bucket. unless we add more fields + * in which case we'll need to look at struct_v, and check the actual + * version. Anything older than 10 needs to be treated as old rgw_bucket + */ + + } else { + decode(ns, bl); + } + + DECODE_FINISH(bl); + } + + rgw_pool& operator=(const rgw_pool&) = default; + + bool operator==(const rgw_pool& p) const { + return (compare(p) == 0); + } + bool operator!=(const rgw_pool& p) const { + return !(*this == p); + } + bool operator<(const rgw_pool& p) const { + int r = name.compare(p.name); + if (r == 0) { + return (ns.compare(p.ns) < 0); + } + return (r < 0); + } +}; +WRITE_CLASS_ENCODER(rgw_pool) + +inline std::ostream& operator<<(std::ostream& out, const rgw_pool& p) { + out << p.to_str(); + return out; +} + +struct rgw_data_placement_target { + rgw_pool data_pool; + rgw_pool data_extra_pool; + rgw_pool index_pool; + + rgw_data_placement_target() = default; + rgw_data_placement_target(const rgw_data_placement_target&) = default; + rgw_data_placement_target(rgw_data_placement_target&&) = default; + + rgw_data_placement_target(const rgw_pool& data_pool, + const rgw_pool& data_extra_pool, + const rgw_pool& index_pool) + : data_pool(data_pool), + data_extra_pool(data_extra_pool), + index_pool(index_pool) { + } + + rgw_data_placement_target& + operator=(const rgw_data_placement_target&) = default; + + const rgw_pool& get_data_extra_pool() const { + if (data_extra_pool.empty()) { + return data_pool; + } + return data_extra_pool; + } + + int compare(const rgw_data_placement_target& t) { + int c = data_pool.compare(t.data_pool); + if (c != 0) { + return c; + } + c = data_extra_pool.compare(t.data_extra_pool); + if (c != 0) { + return c; + } + return index_pool.compare(t.index_pool); + }; + + void dump(ceph::Formatter *f) const; + void decode_json(JSONObj *obj); +}; diff --git a/src/rgw/rgw_quota.h b/src/rgw/rgw_quota.h index 48cddb85b0ac3..b97e83a69b13c 100644 --- a/src/rgw/rgw_quota.h +++ b/src/rgw/rgw_quota.h @@ -20,79 +20,10 @@ #include "common/config_fwd.h" #include "common/lru_map.h" -#include - -#include "rgw/rgw_basic_types.h" +#include "rgw/rgw_quota_types.h" #include "common/async/yield_context.h" #include "rgw_sal_fwd.h" -static inline int64_t rgw_rounded_kb(int64_t bytes) -{ - return (bytes + 1023) / 1024; -} - -class JSONObj; - -struct RGWQuotaInfo { - template friend class RGWQuotaCache; -public: - int64_t max_size; - int64_t max_objects; - bool enabled; - /* Do we want to compare with raw, not rounded RGWStorageStats::size (true) - * or maybe rounded-to-4KiB RGWStorageStats::size_rounded (false)? */ - bool check_on_raw; - - RGWQuotaInfo() - : max_size(-1), - max_objects(-1), - enabled(false), - check_on_raw(false) { - } - - void encode(bufferlist& bl) const { - ENCODE_START(3, 1, bl); - if (max_size < 0) { - encode(-rgw_rounded_kb(abs(max_size)), bl); - } else { - encode(rgw_rounded_kb(max_size), bl); - } - encode(max_objects, bl); - encode(enabled, bl); - encode(max_size, bl); - encode(check_on_raw, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(3, 1, 1, bl); - int64_t max_size_kb; - decode(max_size_kb, bl); - decode(max_objects, bl); - decode(enabled, bl); - if (struct_v < 2) { - max_size = max_size_kb * 1024; - } else { - decode(max_size, bl); - } - if (struct_v >= 3) { - decode(check_on_raw, bl); - } - DECODE_FINISH(bl); - } - - void dump(Formatter *f) const; - - void decode_json(JSONObj *obj); - -}; -WRITE_CLASS_ENCODER(RGWQuotaInfo) - -struct RGWQuota { - RGWQuotaInfo user_quota; - RGWQuotaInfo bucket_quota; -}; - - struct rgw_bucket; class RGWQuotaHandler { diff --git a/src/rgw/rgw_quota_types.h b/src/rgw/rgw_quota_types.h new file mode 100644 index 0000000000000..8306968155533 --- /dev/null +++ b/src/rgw/rgw_quota_types.h @@ -0,0 +1,87 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2013 Inktank, Inc + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* N.B., this header defines fundamental serialized types. Do not + * introduce changes or include files which can only be compiled in + * radosgw or OSD contexts (e.g., rgw_sal.h, rgw_common.h) + */ + +#pragma once + +static inline int64_t rgw_rounded_kb(int64_t bytes) +{ + return (bytes + 1023) / 1024; +} + +class JSONObj; + +struct RGWQuotaInfo { + template friend class RGWQuotaCache; +public: + int64_t max_size; + int64_t max_objects; + bool enabled; + /* Do we want to compare with raw, not rounded RGWStorageStats::size (true) + * or maybe rounded-to-4KiB RGWStorageStats::size_rounded (false)? */ + bool check_on_raw; + + RGWQuotaInfo() + : max_size(-1), + max_objects(-1), + enabled(false), + check_on_raw(false) { + } + + void encode(bufferlist& bl) const { + ENCODE_START(3, 1, bl); + if (max_size < 0) { + encode(-rgw_rounded_kb(abs(max_size)), bl); + } else { + encode(rgw_rounded_kb(max_size), bl); + } + encode(max_objects, bl); + encode(enabled, bl); + encode(max_size, bl); + encode(check_on_raw, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator& bl) { + DECODE_START_LEGACY_COMPAT_LEN(3, 1, 1, bl); + int64_t max_size_kb; + decode(max_size_kb, bl); + decode(max_objects, bl); + decode(enabled, bl); + if (struct_v < 2) { + max_size = max_size_kb * 1024; + } else { + decode(max_size, bl); + } + if (struct_v >= 3) { + decode(check_on_raw, bl); + } + DECODE_FINISH(bl); + } + + void dump(Formatter *f) const; + + void decode_json(JSONObj *obj); + +}; +WRITE_CLASS_ENCODER(RGWQuotaInfo) + +struct RGWQuota { + RGWQuotaInfo user_quota; + RGWQuotaInfo bucket_quota; +}; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 432b0a8034386..1b52951787272 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -21,6 +21,7 @@ #include "cls/log/cls_log_types.h" #include "cls/timeindex/cls_timeindex_types.h" #include "cls/otp/cls_otp_types.h" +#include "rgw_quota.h" #include "rgw_log.h" #include "rgw_metadata.h" #include "rgw_meta_sync_status.h" diff --git a/src/rgw/rgw_user_types.h b/src/rgw/rgw_user_types.h new file mode 100644 index 0000000000000..c9a1a46ade1e9 --- /dev/null +++ b/src/rgw/rgw_user_types.h @@ -0,0 +1,158 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2019 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* N.B., this header defines fundamental serialized types. Do not + * include files which can only be compiled in radosgw or OSD + * contexts (e.g., rgw_sal.h, rgw_common.h) */ + +#pragma once + +#include +#include + +#include "common/dout.h" +#include "common/Formatter.h" + +struct rgw_user { + std::string tenant; + std::string id; + std::string ns; + + rgw_user() {} + explicit rgw_user(const std::string& s) { + from_str(s); + } + rgw_user(const std::string& tenant, const std::string& id, const std::string& ns="") + : tenant(tenant), + id(id), + ns(ns) { + } + rgw_user(std::string&& tenant, std::string&& id, std::string&& ns="") + : tenant(std::move(tenant)), + id(std::move(id)), + ns(std::move(ns)) { + } + + void encode(ceph::buffer::list& bl) const { + ENCODE_START(2, 1, bl); + encode(tenant, bl); + encode(id, bl); + encode(ns, bl); + ENCODE_FINISH(bl); + } + void decode(ceph::buffer::list::const_iterator& bl) { + DECODE_START(2, bl); + decode(tenant, bl); + decode(id, bl); + if (struct_v >= 2) { + decode(ns, bl); + } + DECODE_FINISH(bl); + } + + void to_str(std::string& str) const { + if (!tenant.empty()) { + if (!ns.empty()) { + str = tenant + '$' + ns + '$' + id; + } else { + str = tenant + '$' + id; + } + } else if (!ns.empty()) { + str = '$' + ns + '$' + id; + } else { + str = id; + } + } + + void clear() { + tenant.clear(); + id.clear(); + ns.clear(); + } + + bool empty() const { + return id.empty(); + } + + std::string to_str() const { + std::string s; + to_str(s); + return s; + } + + void from_str(const std::string& str) { + size_t pos = str.find('$'); + if (pos != std::string::npos) { + tenant = str.substr(0, pos); + std::string_view sv = str; + std::string_view ns_id = sv.substr(pos + 1); + size_t ns_pos = ns_id.find('$'); + if (ns_pos != std::string::npos) { + ns = std::string(ns_id.substr(0, ns_pos)); + id = std::string(ns_id.substr(ns_pos + 1)); + } else { + ns.clear(); + id = std::string(ns_id); + } + } else { + tenant.clear(); + ns.clear(); + id = str; + } + } + + rgw_user& operator=(const std::string& str) { + from_str(str); + return *this; + } + + int compare(const rgw_user& u) const { + int r = tenant.compare(u.tenant); + if (r != 0) + return r; + r = ns.compare(u.ns); + if (r != 0) { + return r; + } + return id.compare(u.id); + } + int compare(const std::string& str) const { + rgw_user u(str); + return compare(u); + } + + bool operator!=(const rgw_user& rhs) const { + return (compare(rhs) != 0); + } + bool operator==(const rgw_user& rhs) const { + return (compare(rhs) == 0); + } + bool operator<(const rgw_user& rhs) const { + if (tenant < rhs.tenant) { + return true; + } else if (tenant > rhs.tenant) { + return false; + } + if (ns < rhs.ns) { + return true; + } else if (ns > rhs.ns) { + return false; + } + return (id < rhs.id); + } + void dump(ceph::Formatter *f) const; + static void generate_test_instances(std::list& o); +}; +WRITE_CLASS_ENCODER(rgw_user) diff --git a/src/rgw/rgw_zone_features.h b/src/rgw/rgw_zone_features.h index 3b553046d098b..b787ffc5a6bfa 100644 --- a/src/rgw/rgw_zone_features.h +++ b/src/rgw/rgw_zone_features.h @@ -1,6 +1,10 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab ft=cpp +/* N.B., this header defines fundamental serialized types. Do not + * include files which can only be compiled in radosgw or OSD + * contexts (e.g., rgw_sal.h, rgw_common.h) */ + #pragma once #include diff --git a/src/rgw/rgw_zone_types.h b/src/rgw/rgw_zone_types.h new file mode 100644 index 0000000000000..abb699f236ebc --- /dev/null +++ b/src/rgw/rgw_zone_types.h @@ -0,0 +1,620 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2019 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/* N.B., this header defines fundamental serialized types. Do not + * introduce changes or include files which can only be compiled in + * radosgw or OSD contexts (e.g., rgw_sal.h, rgw_common.h) + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include "include/types.h" +#include "rgw_bucket_layout.h" +#include "rgw_zone_features.h" +#include "rgw_pool_types.h" +#include "rgw_acl_types.h" +#include "rgw_placement_types.h" + +#include "common/Formatter.h" + +class JSONObj; + +namespace rgw_zone_defaults { + +extern std::string zone_names_oid_prefix; +extern std::string region_info_oid_prefix; +extern std::string realm_names_oid_prefix; +extern std::string zone_group_info_oid_prefix; +extern std::string realm_info_oid_prefix; +extern std::string default_region_info_oid; +extern std::string default_zone_group_info_oid; +extern std::string region_map_oid; +extern std::string default_realm_info_oid; +extern std::string default_zonegroup_name; +extern std::string default_zone_name; +extern std::string zonegroup_names_oid_prefix; +extern std::string RGW_DEFAULT_ZONE_ROOT_POOL; +extern std::string RGW_DEFAULT_ZONEGROUP_ROOT_POOL; +extern std::string RGW_DEFAULT_REALM_ROOT_POOL; +extern std::string RGW_DEFAULT_PERIOD_ROOT_POOL; +extern std::string avail_pools; +extern std::string default_storage_pool_suffix; + +} /* namespace rgw_zone_defaults */ + +struct RGWNameToId { + std::string obj_id; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(obj_id, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(obj_id, bl); + DECODE_FINISH(bl); + } + + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWNameToId) + +struct RGWDefaultSystemMetaObjInfo { + std::string default_id; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(default_id, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(default_id, bl); + DECODE_FINISH(bl); + } + + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWDefaultSystemMetaObjInfo) + +struct RGWZoneStorageClass { + boost::optional data_pool; + boost::optional compression_type; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(data_pool, bl); + encode(compression_type, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(data_pool, bl); + decode(compression_type, bl); + DECODE_FINISH(bl); + } + + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWZoneStorageClass) + +class RGWZoneStorageClasses { + std::map m; + + /* in memory only */ + RGWZoneStorageClass *standard_class; + +public: + RGWZoneStorageClasses() { + standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; + } + RGWZoneStorageClasses(const RGWZoneStorageClasses& rhs) { + m = rhs.m; + standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; + } + RGWZoneStorageClasses& operator=(const RGWZoneStorageClasses& rhs) { + m = rhs.m; + standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; + return *this; + } + + const RGWZoneStorageClass& get_standard() const { + return *standard_class; + } + + bool find(const std::string& sc, const RGWZoneStorageClass** pstorage_class) const { + auto iter = m.find(sc); + if (iter == m.end()) { + return false; + } + *pstorage_class = &iter->second; + return true; + } + + bool exists(const std::string& sc) const { + if (sc.empty()) { + return true; + } + auto iter = m.find(sc); + return (iter != m.end()); + } + + const std::map& get_all() const { + return m; + } + + std::map& get_all() { + return m; + } + + void set_storage_class(const std::string& sc, const rgw_pool* data_pool, const std::string* compression_type) { + const std::string *psc = ≻ + if (sc.empty()) { + psc = &RGW_STORAGE_CLASS_STANDARD; + } + RGWZoneStorageClass& storage_class = m[*psc]; + if (data_pool) { + storage_class.data_pool = *data_pool; + } + if (compression_type) { + storage_class.compression_type = *compression_type; + } + } + + void remove_storage_class(const std::string& sc) { + if (!sc.empty()) { + m.erase(sc); + } + } + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(m, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(m, bl); + standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; + DECODE_FINISH(bl); + } + + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWZoneStorageClasses) + +struct RGWZonePlacementInfo { + rgw_pool index_pool; + rgw_pool data_extra_pool; /* if not set we should use data_pool */ + RGWZoneStorageClasses storage_classes; + rgw::BucketIndexType index_type; + + RGWZonePlacementInfo() : index_type(rgw::BucketIndexType::Normal) {} + + void encode(bufferlist& bl) const { + ENCODE_START(7, 1, bl); + encode(index_pool.to_str(), bl); + rgw_pool standard_data_pool = get_data_pool(RGW_STORAGE_CLASS_STANDARD); + encode(standard_data_pool.to_str(), bl); + encode(data_extra_pool.to_str(), bl); + encode((uint32_t)index_type, bl); + std::string standard_compression_type = get_compression_type(RGW_STORAGE_CLASS_STANDARD); + encode(standard_compression_type, bl); + encode(storage_classes, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(7, bl); + std::string index_pool_str; + std::string data_pool_str; + decode(index_pool_str, bl); + index_pool = rgw_pool(index_pool_str); + decode(data_pool_str, bl); + rgw_pool standard_data_pool(data_pool_str); + if (struct_v >= 4) { + std::string data_extra_pool_str; + decode(data_extra_pool_str, bl); + data_extra_pool = rgw_pool(data_extra_pool_str); + } + if (struct_v >= 5) { + uint32_t it; + decode(it, bl); + index_type = (rgw::BucketIndexType)it; + } + std::string standard_compression_type; + if (struct_v >= 6) { + decode(standard_compression_type, bl); + } + if (struct_v >= 7) { + decode(storage_classes, bl); + } else { + storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, &standard_data_pool, + (!standard_compression_type.empty() ? &standard_compression_type : nullptr)); + } + DECODE_FINISH(bl); + } + const rgw_pool& get_data_extra_pool() const { + static rgw_pool no_pool; + if (data_extra_pool.empty()) { + return storage_classes.get_standard().data_pool.get_value_or(no_pool); + } + return data_extra_pool; + } + const rgw_pool& get_data_pool(const std::string& sc) const { + const RGWZoneStorageClass *storage_class; + static rgw_pool no_pool; + + if (!storage_classes.find(sc, &storage_class)) { + return storage_classes.get_standard().data_pool.get_value_or(no_pool); + } + + return storage_class->data_pool.get_value_or(no_pool); + } + const rgw_pool& get_standard_data_pool() const { + return get_data_pool(RGW_STORAGE_CLASS_STANDARD); + } + + const std::string& get_compression_type(const std::string& sc) const { + const RGWZoneStorageClass *storage_class; + static std::string no_compression; + + if (!storage_classes.find(sc, &storage_class)) { + return no_compression; + } + return storage_class->compression_type.get_value_or(no_compression); + } + + bool storage_class_exists(const std::string& sc) const { + return storage_classes.exists(sc); + } + + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); + +}; +WRITE_CLASS_ENCODER(RGWZonePlacementInfo) + +struct RGWZone { + std::string id; + std::string name; + std::list endpoints; // std::vector? + bool log_meta; + bool log_data; + bool read_only; + std::string tier_type; + std::string redirect_zone; + +/** + * Represents the number of shards for the bucket index object, a value of zero + * indicates there is no sharding. By default (no sharding, the name of the object + * is '.dir.{marker}', with sharding, the name is '.dir.{marker}.{sharding_id}', + * sharding_id is zero-based value. It is not recommended to set a too large value + * (e.g. thousand) as it increases the cost for bucket listing. + */ + uint32_t bucket_index_max_shards; + + // pre-shard buckets on creation to enable some write-parallism by default, + // delay the need to reshard as the bucket grows, and (in multisite) get some + // bucket index sharding where dynamic resharding is not supported + static constexpr uint32_t default_bucket_index_max_shards = 11; + + bool sync_from_all; + std::set sync_from; /* list of zones to sync from */ + + rgw::zone_features::set supported_features; + + RGWZone() + : log_meta(false), log_data(false), read_only(false), + bucket_index_max_shards(default_bucket_index_max_shards), + sync_from_all(true) {} + + void encode(bufferlist& bl) const { + ENCODE_START(8, 1, bl); + encode(name, bl); + encode(endpoints, bl); + encode(log_meta, bl); + encode(log_data, bl); + encode(bucket_index_max_shards, bl); + encode(id, bl); + encode(read_only, bl); + encode(tier_type, bl); + encode(sync_from_all, bl); + encode(sync_from, bl); + encode(redirect_zone, bl); + encode(supported_features, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(8, bl); + decode(name, bl); + if (struct_v < 4) { + id = name; + } + decode(endpoints, bl); + if (struct_v >= 2) { + decode(log_meta, bl); + decode(log_data, bl); + } + if (struct_v >= 3) { + decode(bucket_index_max_shards, bl); + } + if (struct_v >= 4) { + decode(id, bl); + decode(read_only, bl); + } + if (struct_v >= 5) { + decode(tier_type, bl); + } + if (struct_v >= 6) { + decode(sync_from_all, bl); + decode(sync_from, bl); + } + if (struct_v >= 7) { + decode(redirect_zone, bl); + } + if (struct_v >= 8) { + decode(supported_features, bl); + } + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); + static void generate_test_instances(std::list& o); + + bool is_read_only() const { return read_only; } + + bool syncs_from(const std::string& zone_name) const { + return (sync_from_all || sync_from.find(zone_name) != sync_from.end()); + } + + bool supports(std::string_view feature) const { + return supported_features.contains(feature); + } +}; +WRITE_CLASS_ENCODER(RGWZone) + +struct RGWDefaultZoneGroupInfo { + std::string default_zonegroup; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(default_zonegroup, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(default_zonegroup, bl); + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); + //todo: implement ceph-dencoder +}; +WRITE_CLASS_ENCODER(RGWDefaultZoneGroupInfo) + +struct RGWTierACLMapping { + ACLGranteeTypeEnum type{ACL_TYPE_CANON_USER}; + std::string source_id; + std::string dest_id; + + RGWTierACLMapping() = default; + + RGWTierACLMapping(ACLGranteeTypeEnum t, + const std::string& s, + const std::string& d) : type(t), + source_id(s), + dest_id(d) {} + + void init(const JSONFormattable& config) { + const std::string& t = config["type"]; + + if (t == "email") { + type = ACL_TYPE_EMAIL_USER; + } else if (t == "uri") { + type = ACL_TYPE_GROUP; + } else { + type = ACL_TYPE_CANON_USER; + } + + source_id = config["source_id"]; + dest_id = config["dest_id"]; + } + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode((uint32_t)type, bl); + encode(source_id, bl); + encode(dest_id, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + uint32_t it; + decode(it, bl); + type = (ACLGranteeTypeEnum)it; + decode(source_id, bl); + decode(dest_id, bl); + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWTierACLMapping) + +enum HostStyle { + PathStyle = 0, + VirtualStyle = 1, +}; + +struct RGWZoneGroupPlacementTierS3 { +#define DEFAULT_MULTIPART_SYNC_PART_SIZE (32 * 1024 * 1024) + std::string endpoint; + RGWAccessKey key; + std::string region; + HostStyle host_style{PathStyle}; + std::string target_storage_class; + + /* Should below be bucket/zone specific?? */ + std::string target_path; + std::map acl_mappings; + + uint64_t multipart_sync_threshold{DEFAULT_MULTIPART_SYNC_PART_SIZE}; + uint64_t multipart_min_part_size{DEFAULT_MULTIPART_SYNC_PART_SIZE}; + + int update_params(const JSONFormattable& config); + int clear_params(const JSONFormattable& config); + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(endpoint, bl); + encode(key, bl); + encode(region, bl); + encode((uint32_t)host_style, bl); // XXX kill C-style casts + encode(target_storage_class, bl); + encode(target_path, bl); + encode(acl_mappings, bl); + encode(multipart_sync_threshold, bl); + encode(multipart_min_part_size, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(endpoint, bl); + decode(key, bl); + decode(region, bl); + + uint32_t it; + decode(it, bl); + host_style = (HostStyle)it; // XXX can't this be HostStyle(it)? + + decode(target_storage_class, bl); + decode(target_path, bl); + decode(acl_mappings, bl); + decode(multipart_sync_threshold, bl); + decode(multipart_min_part_size, bl); + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTierS3) + +struct RGWZoneGroupPlacementTier { + std::string tier_type; + std::string storage_class; + bool retain_head_object = false; + + struct _tier { + RGWZoneGroupPlacementTierS3 s3; + } t; + + int update_params(const JSONFormattable& config); + int clear_params(const JSONFormattable& config); + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(tier_type, bl); + encode(storage_class, bl); + encode(retain_head_object, bl); + if (tier_type == "cloud-s3") { + encode(t.s3, bl); + } + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(tier_type, bl); + decode(storage_class, bl); + decode(retain_head_object, bl); + if (tier_type == "cloud-s3") { + decode(t.s3, bl); + } + DECODE_FINISH(bl); + } + + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTier) + +struct RGWZoneGroupPlacementTarget { + std::string name; + std::set tags; + std::set storage_classes; + std::map tier_targets; + + bool user_permitted(const std::list& user_tags) const { + if (tags.empty()) { + return true; + } + for (auto& rule : user_tags) { + if (tags.find(rule) != tags.end()) { + return true; + } + } + return false; + } + + void encode(bufferlist& bl) const { + ENCODE_START(3, 1, bl); + encode(name, bl); + encode(tags, bl); + encode(storage_classes, bl); + encode(tier_targets, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(3, bl); + decode(name, bl); + decode(tags, bl); + if (struct_v >= 2) { + decode(storage_classes, bl); + } + if (storage_classes.empty()) { + storage_classes.insert(RGW_STORAGE_CLASS_STANDARD); + } + if (struct_v >= 3) { + decode(tier_targets, bl); + } + DECODE_FINISH(bl); + } + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); +}; +WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTarget) diff --git a/src/test/librados/CMakeLists.txt b/src/test/librados/CMakeLists.txt index b20cd8da4d1c3..5d5623f06c829 100644 --- a/src/test/librados/CMakeLists.txt +++ b/src/test/librados/CMakeLists.txt @@ -128,6 +128,9 @@ target_link_libraries(ceph_test_rados_api_service_pp add_executable(ceph_test_rados_api_tier_pp tier_cxx.cc $) +target_include_directories(ceph_test_rados_api_tier_pp + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw/driver/rados" + PUBLIC "${CMAKE_SOURCE_DIR}/src/rgw") target_link_libraries(ceph_test_rados_api_tier_pp librados global ${UNITTEST_LIBS} Boost::system radostest-cxx cls_cas_internal cls_cas_client spawn) -- 2.39.5