]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/rgw/test_rgw_common.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / rgw / test_rgw_common.h
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14#include <iostream>
15#include "common/ceph_json.h"
16#include "common/Formatter.h"
17#include "rgw/rgw_common.h"
18#include "rgw/rgw_rados.h"
11fdf7f2 19#include "rgw/rgw_zone.h"
7c673cae
FG
20
21#ifndef CEPH_TEST_RGW_COMMON_H
22#define CEPH_TEST_RGW_COMMON_H
23
24struct old_rgw_bucket {
25 std::string tenant;
26 std::string name;
27 std::string data_pool;
28 std::string data_extra_pool; /* if not set, then we should use data_pool instead */
29 std::string index_pool;
30 std::string marker;
31 std::string bucket_id;
32
33 std::string oid; /*
34 * runtime in-memory only info. If not empty, points to the bucket instance object
35 */
36
37 old_rgw_bucket() { }
38 // cppcheck-suppress noExplicitConstructor
39 old_rgw_bucket(const std::string& s) : name(s) {
40 data_pool = index_pool = s;
41 marker = "";
42 }
11fdf7f2 43 explicit old_rgw_bucket(const char *n) : name(n) {
7c673cae
FG
44 data_pool = index_pool = n;
45 marker = "";
46 }
47 old_rgw_bucket(const char *t, const char *n, const char *dp, const char *ip, const char *m, const char *id, const char *h) :
48 tenant(t), name(n), data_pool(dp), index_pool(ip), marker(m), bucket_id(id) {}
49
50 void encode(bufferlist& bl) const {
51 ENCODE_START(8, 3, bl);
11fdf7f2
TL
52 encode(name, bl);
53 encode(data_pool, bl);
54 encode(marker, bl);
55 encode(bucket_id, bl);
56 encode(index_pool, bl);
57 encode(data_extra_pool, bl);
58 encode(tenant, bl);
7c673cae
FG
59 ENCODE_FINISH(bl);
60 }
11fdf7f2 61 void decode(bufferlist::const_iterator& bl) {
7c673cae 62 DECODE_START_LEGACY_COMPAT_LEN(8, 3, 3, bl);
11fdf7f2
TL
63 decode(name, bl);
64 decode(data_pool, bl);
7c673cae 65 if (struct_v >= 2) {
11fdf7f2 66 decode(marker, bl);
7c673cae
FG
67 if (struct_v <= 3) {
68 uint64_t id;
11fdf7f2 69 decode(id, bl);
7c673cae
FG
70 char buf[16];
71 snprintf(buf, sizeof(buf), "%llu", (long long)id);
72 bucket_id = buf;
73 } else {
11fdf7f2 74 decode(bucket_id, bl);
7c673cae
FG
75 }
76 }
77 if (struct_v >= 5) {
11fdf7f2 78 decode(index_pool, bl);
7c673cae
FG
79 } else {
80 index_pool = data_pool;
81 }
82 if (struct_v >= 7) {
11fdf7f2 83 decode(data_extra_pool, bl);
7c673cae
FG
84 }
85 if (struct_v >= 8) {
11fdf7f2 86 decode(tenant, bl);
7c673cae
FG
87 }
88 DECODE_FINISH(bl);
89 }
90
91 // format a key for the bucket/instance. pass delim=0 to skip a field
92 std::string get_key(char tenant_delim = '/',
93 char id_delim = ':') const;
94
95 const std::string& get_data_extra_pool() {
96 if (data_extra_pool.empty()) {
97 return data_pool;
98 }
99 return data_extra_pool;
100 }
101
102 void dump(Formatter *f) const;
103 void decode_json(JSONObj *obj);
20effc67 104 static void generate_test_instances(std::list<old_rgw_bucket*>& o);
7c673cae
FG
105
106 bool operator<(const old_rgw_bucket& b) const {
107 return name.compare(b.name) < 0;
108 }
109};
110WRITE_CLASS_ENCODER(old_rgw_bucket)
111
112class old_rgw_obj {
113 std::string orig_obj;
114 std::string loc;
115 std::string object;
116 std::string instance;
117public:
118 const std::string& get_object() const { return object; }
119 const std::string& get_orig_obj() const { return orig_obj; }
120 const std::string& get_loc() const { return loc; }
121 const std::string& get_instance() const { return instance; }
122 old_rgw_bucket bucket;
123 std::string ns;
124
125 bool in_extra_data; /* in-memory only member, does not serialize */
126
127 // Represents the hash index source for this object once it is set (non-empty)
128 std::string index_hash_source;
129
130 old_rgw_obj() : in_extra_data(false) {}
131 old_rgw_obj(old_rgw_bucket& b, const std::string& o) : in_extra_data(false) {
132 init(b, o);
133 }
134 old_rgw_obj(old_rgw_bucket& b, const rgw_obj_key& k) : in_extra_data(false) {
135 from_index_key(b, k);
136 }
137 void init(old_rgw_bucket& b, const std::string& o) {
138 bucket = b;
139 set_obj(o);
140 reset_loc();
141 }
142 void init_ns(old_rgw_bucket& b, const std::string& o, const std::string& n) {
143 bucket = b;
144 set_ns(n);
145 set_obj(o);
146 reset_loc();
147 }
148 int set_ns(const char *n) {
149 if (!n)
150 return -EINVAL;
151 std::string ns_str(n);
152 return set_ns(ns_str);
153 }
154 int set_ns(const std::string& n) {
155 if (n[0] == '_')
156 return -EINVAL;
157 ns = n;
158 set_obj(orig_obj);
159 return 0;
160 }
161 int set_instance(const std::string& i) {
162 if (i[0] == '_')
163 return -EINVAL;
164 instance = i;
165 set_obj(orig_obj);
166 return 0;
167 }
168
169 int clear_instance() {
20effc67 170 return set_instance(std::string());
7c673cae
FG
171 }
172
173 void set_loc(const std::string& k) {
174 loc = k;
175 }
176
177 void reset_loc() {
178 loc.clear();
179 /*
180 * For backward compatibility. Older versions used to have object locator on all objects,
181 * however, the orig_obj was the effective object locator. This had the same effect as not
182 * having object locator at all for most objects but the ones that started with underscore as
183 * these were escaped.
184 */
185 if (orig_obj[0] == '_' && ns.empty()) {
186 loc = orig_obj;
187 }
188 }
189
190 bool have_null_instance() {
191 return instance == "null";
192 }
193
194 bool have_instance() {
195 return !instance.empty();
196 }
197
198 bool need_to_encode_instance() {
199 return have_instance() && !have_null_instance();
200 }
201
202 void set_obj(const std::string& o) {
203 object.reserve(128);
204
205 orig_obj = o;
206 if (ns.empty() && !need_to_encode_instance()) {
207 if (o.empty()) {
208 return;
209 }
210 if (o.size() < 1 || o[0] != '_') {
211 object = o;
212 return;
213 }
214 object = "_";
215 object.append(o);
216 } else {
217 object = "_";
218 object.append(ns);
219 if (need_to_encode_instance()) {
20effc67 220 object.append(std::string(":") + instance);
7c673cae
FG
221 }
222 object.append("_");
223 object.append(o);
224 }
225 reset_loc();
226 }
227
228 /*
229 * get the object's key name as being referred to by the bucket index.
230 */
231 std::string get_index_key_name() const {
232 if (ns.empty()) {
233 if (orig_obj.size() < 1 || orig_obj[0] != '_') {
234 return orig_obj;
235 }
236 return std::string("_") + orig_obj;
237 };
238
239 char buf[ns.size() + 16];
240 snprintf(buf, sizeof(buf), "_%s_", ns.c_str());
241 return std::string(buf) + orig_obj;
242 };
243
244 void from_index_key(old_rgw_bucket& b, const rgw_obj_key& key) {
245 if (key.name[0] != '_') {
246 init(b, key.name);
247 set_instance(key.instance);
248 return;
249 }
250 if (key.name[1] == '_') {
251 init(b, key.name.substr(1));
252 set_instance(key.instance);
253 return;
254 }
255 ssize_t pos = key.name.find('_', 1);
256 if (pos < 0) {
257 /* shouldn't happen, just use key */
258 init(b, key.name);
259 set_instance(key.instance);
260 return;
261 }
262
263 init_ns(b, key.name.substr(pos + 1), key.name.substr(1, pos -1));
264 set_instance(key.instance);
265 }
266
267 void get_index_key(rgw_obj_key *key) const {
268 key->name = get_index_key_name();
269 key->instance = instance;
270 }
271
20effc67 272 static void parse_ns_field(std::string& ns, std::string& instance) {
7c673cae
FG
273 int pos = ns.find(':');
274 if (pos >= 0) {
275 instance = ns.substr(pos + 1);
276 ns = ns.substr(0, pos);
277 } else {
278 instance.clear();
279 }
280 }
281
282 std::string& get_hash_object() {
283 return index_hash_source.empty() ? orig_obj : index_hash_source;
284 }
285 /**
286 * Translate a namespace-mangled object name to the user-facing name
287 * existing in the given namespace.
288 *
289 * If the object is part of the given namespace, it returns true
290 * and cuts down the name to the unmangled version. If it is not
291 * part of the given namespace, it returns false.
292 */
20effc67 293 static bool translate_raw_obj_to_obj_in_ns(std::string& obj, std::string& instance, std::string& ns) {
7c673cae
FG
294 if (obj[0] != '_') {
295 if (ns.empty()) {
296 return true;
297 }
298 return false;
299 }
300
301 std::string obj_ns;
302 bool ret = parse_raw_oid(obj, &obj, &instance, &obj_ns);
303 if (!ret) {
304 return ret;
305 }
306
307 return (ns == obj_ns);
308 }
309
310 static bool parse_raw_oid(const std::string& oid, std::string *obj_name, std::string *obj_instance, std::string *obj_ns) {
311 obj_instance->clear();
312 obj_ns->clear();
313 if (oid[0] != '_') {
314 *obj_name = oid;
315 return true;
316 }
317
318 if (oid.size() >= 2 && oid[1] == '_') {
319 *obj_name = oid.substr(1);
320 return true;
321 }
322
323 if (oid[0] != '_' || oid.size() < 3) // for namespace, min size would be 3: _x_
324 return false;
325
326 int pos = oid.find('_', 1);
327 if (pos <= 1) // if it starts with __, it's not in our namespace
328 return false;
329
330 *obj_ns = oid.substr(1, pos - 1);
331 parse_ns_field(*obj_ns, *obj_instance);
332
333 *obj_name = oid.substr(pos + 1);
334 return true;
335 }
336
337 /**
338 * Given a mangled object name and an empty namespace string, this
339 * function extracts the namespace into the string and sets the object
340 * name to be the unmangled version.
341 *
342 * It returns true after successfully doing so, or
343 * false if it fails.
344 */
20effc67 345 static bool strip_namespace_from_object(std::string& obj, std::string& ns, std::string& instance) {
7c673cae
FG
346 ns.clear();
347 instance.clear();
348 if (obj[0] != '_') {
349 return true;
350 }
351
352 size_t pos = obj.find('_', 1);
353 if (pos == std::string::npos) {
354 return false;
355 }
356
357 if (obj[1] == '_') {
358 obj = obj.substr(1);
359 return true;
360 }
361
362 size_t period_pos = obj.find('.');
363 if (period_pos < pos) {
364 return false;
365 }
366
367 ns = obj.substr(1, pos-1);
368 obj = obj.substr(pos+1, std::string::npos);
369
370 parse_ns_field(ns, instance);
371 return true;
372 }
373
374 void set_in_extra_data(bool val) {
375 in_extra_data = val;
376 }
377
378 bool is_in_extra_data() const {
379 return in_extra_data;
380 }
381
382 void encode(bufferlist& bl) const {
383 ENCODE_START(5, 3, bl);
11fdf7f2
TL
384 encode(bucket.name, bl);
385 encode(loc, bl);
386 encode(ns, bl);
387 encode(object, bl);
388 encode(bucket, bl);
389 encode(instance, bl);
7c673cae 390 if (!ns.empty() || !instance.empty()) {
11fdf7f2 391 encode(orig_obj, bl);
7c673cae
FG
392 }
393 ENCODE_FINISH(bl);
394 }
11fdf7f2 395 void decode(bufferlist::const_iterator& bl) {
7c673cae 396 DECODE_START_LEGACY_COMPAT_LEN(5, 3, 3, bl);
11fdf7f2
TL
397 decode(bucket.name, bl);
398 decode(loc, bl);
399 decode(ns, bl);
400 decode(object, bl);
7c673cae 401 if (struct_v >= 2)
11fdf7f2 402 decode(bucket, bl);
7c673cae 403 if (struct_v >= 4)
11fdf7f2 404 decode(instance, bl);
7c673cae
FG
405 if (ns.empty() && instance.empty()) {
406 if (object[0] != '_') {
407 orig_obj = object;
408 } else {
409 orig_obj = object.substr(1);
410 }
411 } else {
412 if (struct_v >= 5) {
11fdf7f2 413 decode(orig_obj, bl);
7c673cae
FG
414 } else {
415 ssize_t pos = object.find('_', 1);
416 if (pos < 0) {
f67539c2 417 throw buffer::malformed_input();
7c673cae
FG
418 }
419 orig_obj = object.substr(pos);
420 }
421 }
422 DECODE_FINISH(bl);
423 }
424
425 bool operator==(const old_rgw_obj& o) const {
426 return (object.compare(o.object) == 0) &&
427 (bucket.name.compare(o.bucket.name) == 0) &&
428 (ns.compare(o.ns) == 0) &&
429 (instance.compare(o.instance) == 0);
430 }
431 bool operator<(const old_rgw_obj& o) const {
432 int r = bucket.name.compare(o.bucket.name);
433 if (r == 0) {
434 r = bucket.bucket_id.compare(o.bucket.bucket_id);
435 if (r == 0) {
436 r = object.compare(o.object);
437 if (r == 0) {
438 r = ns.compare(o.ns);
439 if (r == 0) {
440 r = instance.compare(o.instance);
441 }
442 }
443 }
444 }
445
446 return (r < 0);
447 }
448};
449WRITE_CLASS_ENCODER(old_rgw_obj)
450
20effc67 451static inline void prepend_old_bucket_marker(const old_rgw_bucket& bucket, const std::string& orig_oid, std::string& oid)
7c673cae
FG
452{
453 if (bucket.marker.empty() || orig_oid.empty()) {
454 oid = orig_oid;
455 } else {
456 oid = bucket.marker;
457 oid.append("_");
458 oid.append(orig_oid);
459 }
460}
461
462void test_rgw_init_env(RGWZoneGroup *zonegroup, RGWZoneParams *zone_params);
463
464struct test_rgw_env {
465 RGWZoneGroup zonegroup;
466 RGWZoneParams zone_params;
467 rgw_data_placement_target default_placement;
468
469 test_rgw_env() {
470 test_rgw_init_env(&zonegroup, &zone_params);
11fdf7f2
TL
471 default_placement.data_pool = rgw_pool(zone_params.placement_pools[zonegroup.default_placement.name].get_standard_data_pool());
472 default_placement.data_extra_pool = rgw_pool(zone_params.placement_pools[zonegroup.default_placement.name].data_extra_pool);
7c673cae
FG
473 }
474
475 rgw_data_placement_target get_placement(const std::string& placement_id) {
476 const RGWZonePlacementInfo& pi = zone_params.placement_pools[placement_id];
477 rgw_data_placement_target pt;
478 pt.index_pool = pi.index_pool;
11fdf7f2 479 pt.data_pool = pi.get_standard_data_pool();
7c673cae
FG
480 pt.data_extra_pool = pi.data_extra_pool;
481 return pt;
482 }
483
484 rgw_raw_obj get_raw(const rgw_obj& obj) {
485 rgw_obj_select s(obj);
486 return s.get_raw_obj(zonegroup, zone_params);
487 }
488
489 rgw_raw_obj get_raw(const rgw_obj_select& os) {
490 return os.get_raw_obj(zonegroup, zone_params);
491 }
492};
493
494void test_rgw_add_placement(RGWZoneGroup *zonegroup, RGWZoneParams *zone_params, const std::string& name, bool is_default);
495void 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);
496void 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
498std::string test_rgw_get_obj_oid(const rgw_obj& obj);
499void test_rgw_init_explicit_placement_bucket(rgw_bucket *bucket, const char *name);
500void test_rgw_init_old_bucket(old_rgw_bucket *bucket, const char *name);
501void test_rgw_populate_bucket(rgw_bucket *b, const char *t, const char *n, const char *m, const char *id);
502void test_rgw_init_bucket(rgw_bucket *bucket, const char *name);
503rgw_obj test_rgw_create_obj(const rgw_bucket& bucket, const std::string& name, const std::string& instance, const std::string& ns);
504
505#endif
506