1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "common/ceph_json.h"
16 #include "common/Formatter.h"
17 #include "rgw/rgw_common.h"
18 #include "rgw/rgw_rados.h"
20 #ifndef CEPH_TEST_RGW_COMMON_H
21 #define CEPH_TEST_RGW_COMMON_H
23 struct old_rgw_bucket {
26 std::string data_pool;
27 std::string data_extra_pool; /* if not set, then we should use data_pool instead */
28 std::string index_pool;
30 std::string bucket_id;
33 * runtime in-memory only info. If not empty, points to the bucket instance object
37 // cppcheck-suppress noExplicitConstructor
38 old_rgw_bucket(const std::string& s) : name(s) {
39 data_pool = index_pool = s;
42 old_rgw_bucket(const char *n) : name(n) {
43 data_pool = index_pool = n;
46 old_rgw_bucket(const char *t, const char *n, const char *dp, const char *ip, const char *m, const char *id, const char *h) :
47 tenant(t), name(n), data_pool(dp), index_pool(ip), marker(m), bucket_id(id) {}
49 void encode(bufferlist& bl) const {
50 ENCODE_START(8, 3, bl);
52 ::encode(data_pool, bl);
54 ::encode(bucket_id, bl);
55 ::encode(index_pool, bl);
56 ::encode(data_extra_pool, bl);
60 void decode(bufferlist::iterator& bl) {
61 DECODE_START_LEGACY_COMPAT_LEN(8, 3, 3, bl);
63 ::decode(data_pool, bl);
70 snprintf(buf, sizeof(buf), "%llu", (long long)id);
73 ::decode(bucket_id, bl);
77 ::decode(index_pool, bl);
79 index_pool = data_pool;
82 ::decode(data_extra_pool, bl);
90 // format a key for the bucket/instance. pass delim=0 to skip a field
91 std::string get_key(char tenant_delim = '/',
92 char id_delim = ':') const;
94 const std::string& get_data_extra_pool() {
95 if (data_extra_pool.empty()) {
98 return data_extra_pool;
101 void dump(Formatter *f) const;
102 void decode_json(JSONObj *obj);
103 static void generate_test_instances(list<old_rgw_bucket*>& o);
105 bool operator<(const old_rgw_bucket& b) const {
106 return name.compare(b.name) < 0;
109 WRITE_CLASS_ENCODER(old_rgw_bucket)
112 std::string orig_obj;
115 std::string instance;
117 const std::string& get_object() const { return object; }
118 const std::string& get_orig_obj() const { return orig_obj; }
119 const std::string& get_loc() const { return loc; }
120 const std::string& get_instance() const { return instance; }
121 old_rgw_bucket bucket;
124 bool in_extra_data; /* in-memory only member, does not serialize */
126 // Represents the hash index source for this object once it is set (non-empty)
127 std::string index_hash_source;
129 old_rgw_obj() : in_extra_data(false) {}
130 old_rgw_obj(old_rgw_bucket& b, const std::string& o) : in_extra_data(false) {
133 old_rgw_obj(old_rgw_bucket& b, const rgw_obj_key& k) : in_extra_data(false) {
134 from_index_key(b, k);
136 void init(old_rgw_bucket& b, const std::string& o) {
141 void init_ns(old_rgw_bucket& b, const std::string& o, const std::string& n) {
147 int set_ns(const char *n) {
150 std::string ns_str(n);
151 return set_ns(ns_str);
153 int set_ns(const std::string& n) {
160 int set_instance(const std::string& i) {
168 int clear_instance() {
169 return set_instance(string());
172 void set_loc(const std::string& k) {
179 * For backward compatibility. Older versions used to have object locator on all objects,
180 * however, the orig_obj was the effective object locator. This had the same effect as not
181 * having object locator at all for most objects but the ones that started with underscore as
182 * these were escaped.
184 if (orig_obj[0] == '_' && ns.empty()) {
189 bool have_null_instance() {
190 return instance == "null";
193 bool have_instance() {
194 return !instance.empty();
197 bool need_to_encode_instance() {
198 return have_instance() && !have_null_instance();
201 void set_obj(const std::string& o) {
205 if (ns.empty() && !need_to_encode_instance()) {
209 if (o.size() < 1 || o[0] != '_') {
218 if (need_to_encode_instance()) {
219 object.append(string(":") + instance);
228 * get the object's key name as being referred to by the bucket index.
230 std::string get_index_key_name() const {
232 if (orig_obj.size() < 1 || orig_obj[0] != '_') {
235 return std::string("_") + orig_obj;
238 char buf[ns.size() + 16];
239 snprintf(buf, sizeof(buf), "_%s_", ns.c_str());
240 return std::string(buf) + orig_obj;
243 void from_index_key(old_rgw_bucket& b, const rgw_obj_key& key) {
244 if (key.name[0] != '_') {
246 set_instance(key.instance);
249 if (key.name[1] == '_') {
250 init(b, key.name.substr(1));
251 set_instance(key.instance);
254 ssize_t pos = key.name.find('_', 1);
256 /* shouldn't happen, just use key */
258 set_instance(key.instance);
262 init_ns(b, key.name.substr(pos + 1), key.name.substr(1, pos -1));
263 set_instance(key.instance);
266 void get_index_key(rgw_obj_key *key) const {
267 key->name = get_index_key_name();
268 key->instance = instance;
271 static void parse_ns_field(string& ns, std::string& instance) {
272 int pos = ns.find(':');
274 instance = ns.substr(pos + 1);
275 ns = ns.substr(0, pos);
281 std::string& get_hash_object() {
282 return index_hash_source.empty() ? orig_obj : index_hash_source;
285 * Translate a namespace-mangled object name to the user-facing name
286 * existing in the given namespace.
288 * If the object is part of the given namespace, it returns true
289 * and cuts down the name to the unmangled version. If it is not
290 * part of the given namespace, it returns false.
292 static bool translate_raw_obj_to_obj_in_ns(string& obj, std::string& instance, std::string& ns) {
301 bool ret = parse_raw_oid(obj, &obj, &instance, &obj_ns);
306 return (ns == obj_ns);
309 static bool parse_raw_oid(const std::string& oid, std::string *obj_name, std::string *obj_instance, std::string *obj_ns) {
310 obj_instance->clear();
317 if (oid.size() >= 2 && oid[1] == '_') {
318 *obj_name = oid.substr(1);
322 if (oid[0] != '_' || oid.size() < 3) // for namespace, min size would be 3: _x_
325 int pos = oid.find('_', 1);
326 if (pos <= 1) // if it starts with __, it's not in our namespace
329 *obj_ns = oid.substr(1, pos - 1);
330 parse_ns_field(*obj_ns, *obj_instance);
332 *obj_name = oid.substr(pos + 1);
337 * Given a mangled object name and an empty namespace string, this
338 * function extracts the namespace into the string and sets the object
339 * name to be the unmangled version.
341 * It returns true after successfully doing so, or
344 static bool strip_namespace_from_object(string& obj, std::string& ns, std::string& instance) {
351 size_t pos = obj.find('_', 1);
352 if (pos == std::string::npos) {
361 size_t period_pos = obj.find('.');
362 if (period_pos < pos) {
366 ns = obj.substr(1, pos-1);
367 obj = obj.substr(pos+1, std::string::npos);
369 parse_ns_field(ns, instance);
373 void set_in_extra_data(bool val) {
377 bool is_in_extra_data() const {
378 return in_extra_data;
381 void encode(bufferlist& bl) const {
382 ENCODE_START(5, 3, bl);
383 ::encode(bucket.name, bl);
386 ::encode(object, bl);
387 ::encode(bucket, bl);
388 ::encode(instance, bl);
389 if (!ns.empty() || !instance.empty()) {
390 ::encode(orig_obj, bl);
394 void decode(bufferlist::iterator& bl) {
395 DECODE_START_LEGACY_COMPAT_LEN(5, 3, 3, bl);
396 ::decode(bucket.name, bl);
399 ::decode(object, bl);
401 ::decode(bucket, bl);
403 ::decode(instance, bl);
404 if (ns.empty() && instance.empty()) {
405 if (object[0] != '_') {
408 orig_obj = object.substr(1);
412 ::decode(orig_obj, bl);
414 ssize_t pos = object.find('_', 1);
416 throw buffer::error();
418 orig_obj = object.substr(pos);
424 bool operator==(const old_rgw_obj& o) const {
425 return (object.compare(o.object) == 0) &&
426 (bucket.name.compare(o.bucket.name) == 0) &&
427 (ns.compare(o.ns) == 0) &&
428 (instance.compare(o.instance) == 0);
430 bool operator<(const old_rgw_obj& o) const {
431 int r = bucket.name.compare(o.bucket.name);
433 r = bucket.bucket_id.compare(o.bucket.bucket_id);
435 r = object.compare(o.object);
437 r = ns.compare(o.ns);
439 r = instance.compare(o.instance);
448 WRITE_CLASS_ENCODER(old_rgw_obj)
450 static inline void prepend_old_bucket_marker(const old_rgw_bucket& bucket, const string& orig_oid, string& oid)
452 if (bucket.marker.empty() || orig_oid.empty()) {
457 oid.append(orig_oid);
461 void test_rgw_init_env(RGWZoneGroup *zonegroup, RGWZoneParams *zone_params);
463 struct test_rgw_env {
464 RGWZoneGroup zonegroup;
465 RGWZoneParams zone_params;
466 rgw_data_placement_target default_placement;
469 test_rgw_init_env(&zonegroup, &zone_params);
470 default_placement.data_pool = rgw_pool(zone_params.placement_pools[zonegroup.default_placement].data_pool);
471 default_placement.data_extra_pool = rgw_pool(zone_params.placement_pools[zonegroup.default_placement].data_extra_pool);
474 rgw_data_placement_target get_placement(const std::string& placement_id) {
475 const RGWZonePlacementInfo& pi = zone_params.placement_pools[placement_id];
476 rgw_data_placement_target pt;
477 pt.index_pool = pi.index_pool;
478 pt.data_pool = pi.data_pool;
479 pt.data_extra_pool = pi.data_extra_pool;
483 rgw_raw_obj get_raw(const rgw_obj& obj) {
484 rgw_obj_select s(obj);
485 return s.get_raw_obj(zonegroup, zone_params);
488 rgw_raw_obj get_raw(const rgw_obj_select& os) {
489 return os.get_raw_obj(zonegroup, zone_params);
493 void test_rgw_add_placement(RGWZoneGroup *zonegroup, RGWZoneParams *zone_params, const std::string& name, bool is_default);
494 void test_rgw_populate_explicit_placement_bucket(rgw_bucket *b, const char *t, const char *n, const char *dp, const char *ip, const char *m, const char *id);
495 void test_rgw_populate_old_bucket(old_rgw_bucket *b, const char *t, const char *n, const char *dp, const char *ip, const char *m, const char *id);
497 std::string test_rgw_get_obj_oid(const rgw_obj& obj);
498 void test_rgw_init_explicit_placement_bucket(rgw_bucket *bucket, const char *name);
499 void test_rgw_init_old_bucket(old_rgw_bucket *bucket, const char *name);
500 void test_rgw_populate_bucket(rgw_bucket *b, const char *t, const char *n, const char *m, const char *id);
501 void test_rgw_init_bucket(rgw_bucket *bucket, const char *name);
502 rgw_obj test_rgw_create_obj(const rgw_bucket& bucket, const std::string& name, const std::string& instance, const std::string& ns);