]>
Commit | Line | Data |
---|---|---|
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 | #include "include/types.h" | |
5 | #include "cls/rgw/cls_rgw_client.h" | |
6 | #include "cls/rgw/cls_rgw_ops.h" | |
7 | ||
8 | #include "gtest/gtest.h" | |
9 | #include "test/librados/test.h" | |
10 | ||
11 | #include <errno.h> | |
12 | #include <string> | |
13 | #include <vector> | |
14 | #include <map> | |
31f18b77 | 15 | #include <set> |
7c673cae FG |
16 | |
17 | using namespace librados; | |
18 | ||
19 | librados::Rados rados; | |
20 | librados::IoCtx ioctx; | |
21 | string pool_name; | |
22 | ||
23 | ||
24 | /* must be the first test! */ | |
25 | TEST(cls_rgw, init) | |
26 | { | |
27 | pool_name = get_temp_pool_name(); | |
28 | /* create pool */ | |
29 | ASSERT_EQ("", create_one_pool_pp(pool_name, rados)); | |
30 | ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); | |
31 | } | |
32 | ||
33 | ||
34 | string str_int(string s, int i) | |
35 | { | |
36 | char buf[32]; | |
37 | snprintf(buf, sizeof(buf), "-%d", i); | |
38 | s.append(buf); | |
39 | ||
40 | return s; | |
41 | } | |
42 | ||
43 | ||
44 | class OpMgr { | |
45 | vector<ObjectOperation *> ops; | |
46 | ||
47 | public: | |
48 | OpMgr() {} | |
49 | ~OpMgr() { | |
50 | vector<ObjectOperation *>::iterator iter; | |
51 | for (iter = ops.begin(); iter != ops.end(); ++iter) { | |
52 | ObjectOperation *op = *iter; | |
53 | delete op; | |
54 | } | |
55 | } | |
56 | ||
57 | ObjectReadOperation *read_op() { | |
58 | ObjectReadOperation *op = new ObjectReadOperation; | |
59 | ops.push_back(op); | |
60 | return op; | |
61 | } | |
62 | ||
63 | ObjectWriteOperation *write_op() { | |
64 | ObjectWriteOperation *op = new ObjectWriteOperation; | |
65 | ops.push_back(op); | |
66 | return op; | |
67 | } | |
68 | }; | |
69 | ||
70 | void test_stats(librados::IoCtx& ioctx, string& oid, int category, uint64_t num_entries, uint64_t total_size) | |
71 | { | |
72 | map<int, struct rgw_cls_list_ret> results; | |
73 | map<int, string> oids; | |
74 | oids[0] = oid; | |
75 | ASSERT_EQ(0, CLSRGWIssueGetDirHeader(ioctx, oids, results, 8)()); | |
76 | ||
77 | uint64_t entries = 0; | |
78 | uint64_t size = 0; | |
79 | map<int, struct rgw_cls_list_ret>::iterator iter = results.begin(); | |
80 | for (; iter != results.end(); ++iter) { | |
81 | entries += (iter->second).dir.header.stats[category].num_entries; | |
82 | size += (iter->second).dir.header.stats[category].total_size; | |
83 | } | |
84 | ASSERT_EQ(total_size, size); | |
85 | ASSERT_EQ(num_entries, entries); | |
86 | } | |
87 | ||
88 | void index_prepare(OpMgr& mgr, librados::IoCtx& ioctx, string& oid, RGWModifyOp index_op, string& tag, string& obj, string& loc) | |
89 | { | |
90 | ObjectWriteOperation *op = mgr.write_op(); | |
91 | cls_rgw_obj_key key(obj, string()); | |
31f18b77 FG |
92 | rgw_zone_set zones_trace; |
93 | cls_rgw_bucket_prepare_op(*op, index_op, tag, key, loc, true, 0, zones_trace); | |
7c673cae FG |
94 | ASSERT_EQ(0, ioctx.operate(oid, op)); |
95 | } | |
96 | ||
97 | void index_complete(OpMgr& mgr, librados::IoCtx& ioctx, string& oid, RGWModifyOp index_op, string& tag, int epoch, string& obj, rgw_bucket_dir_entry_meta& meta) | |
98 | { | |
99 | ObjectWriteOperation *op = mgr.write_op(); | |
100 | cls_rgw_obj_key key(obj, string()); | |
101 | rgw_bucket_entry_ver ver; | |
102 | ver.pool = ioctx.get_id(); | |
103 | ver.epoch = epoch; | |
104 | meta.accounted_size = meta.size; | |
31f18b77 | 105 | cls_rgw_bucket_complete_op(*op, index_op, tag, ver, key, meta, nullptr, true, 0, nullptr); |
7c673cae FG |
106 | ASSERT_EQ(0, ioctx.operate(oid, op)); |
107 | } | |
108 | ||
109 | TEST(cls_rgw, index_basic) | |
110 | { | |
111 | string bucket_oid = str_int("bucket", 0); | |
112 | ||
113 | OpMgr mgr; | |
114 | ||
115 | ObjectWriteOperation *op = mgr.write_op(); | |
116 | cls_rgw_bucket_init(*op); | |
117 | ASSERT_EQ(0, ioctx.operate(bucket_oid, op)); | |
118 | ||
119 | uint64_t epoch = 1; | |
120 | ||
121 | uint64_t obj_size = 1024; | |
122 | ||
123 | #define NUM_OBJS 10 | |
124 | for (int i = 0; i < NUM_OBJS; i++) { | |
125 | string obj = str_int("obj", i); | |
126 | string tag = str_int("tag", i); | |
127 | string loc = str_int("loc", i); | |
128 | ||
129 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, obj, loc); | |
130 | ||
131 | test_stats(ioctx, bucket_oid, 0, i, obj_size * i); | |
132 | ||
133 | op = mgr.write_op(); | |
134 | rgw_bucket_dir_entry_meta meta; | |
135 | meta.category = 0; | |
136 | meta.size = obj_size; | |
137 | index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, epoch, obj, meta); | |
138 | } | |
139 | ||
140 | test_stats(ioctx, bucket_oid, 0, NUM_OBJS, obj_size * NUM_OBJS); | |
141 | } | |
142 | ||
143 | TEST(cls_rgw, index_multiple_obj_writers) | |
144 | { | |
145 | string bucket_oid = str_int("bucket", 1); | |
146 | ||
147 | OpMgr mgr; | |
148 | ||
149 | ObjectWriteOperation *op = mgr.write_op(); | |
150 | cls_rgw_bucket_init(*op); | |
151 | ASSERT_EQ(0, ioctx.operate(bucket_oid, op)); | |
152 | ||
153 | uint64_t obj_size = 1024; | |
154 | ||
155 | string obj = str_int("obj", 0); | |
156 | string loc = str_int("loc", 0); | |
157 | /* multi prepare on a single object */ | |
158 | for (int i = 0; i < NUM_OBJS; i++) { | |
159 | string tag = str_int("tag", i); | |
160 | ||
161 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, obj, loc); | |
162 | ||
163 | test_stats(ioctx, bucket_oid, 0, 0, 0); | |
164 | } | |
165 | ||
166 | for (int i = NUM_OBJS; i > 0; i--) { | |
167 | string tag = str_int("tag", i - 1); | |
168 | ||
169 | rgw_bucket_dir_entry_meta meta; | |
170 | meta.category = 0; | |
171 | meta.size = obj_size * i; | |
172 | ||
173 | index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, i, obj, meta); | |
174 | ||
175 | /* verify that object size doesn't change, as we went back with epoch */ | |
176 | test_stats(ioctx, bucket_oid, 0, 1, obj_size * NUM_OBJS); | |
177 | } | |
178 | } | |
179 | ||
180 | TEST(cls_rgw, index_remove_object) | |
181 | { | |
182 | string bucket_oid = str_int("bucket", 2); | |
183 | ||
184 | OpMgr mgr; | |
185 | ||
186 | ObjectWriteOperation *op = mgr.write_op(); | |
187 | cls_rgw_bucket_init(*op); | |
188 | ASSERT_EQ(0, ioctx.operate(bucket_oid, op)); | |
189 | ||
190 | uint64_t obj_size = 1024; | |
191 | uint64_t total_size = 0; | |
192 | ||
193 | int epoch = 0; | |
194 | ||
195 | /* prepare multiple objects */ | |
196 | for (int i = 0; i < NUM_OBJS; i++) { | |
197 | string obj = str_int("obj", i); | |
198 | string tag = str_int("tag", i); | |
199 | string loc = str_int("loc", i); | |
200 | ||
201 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, obj, loc); | |
202 | ||
203 | test_stats(ioctx, bucket_oid, 0, i, total_size); | |
204 | ||
205 | rgw_bucket_dir_entry_meta meta; | |
206 | meta.category = 0; | |
207 | meta.size = i * obj_size; | |
208 | total_size += i * obj_size; | |
209 | ||
210 | index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, ++epoch, obj, meta); | |
211 | ||
212 | test_stats(ioctx, bucket_oid, 0, i + 1, total_size); | |
213 | } | |
214 | ||
215 | int i = NUM_OBJS / 2; | |
216 | string tag_remove = "tag-rm"; | |
217 | string tag_modify = "tag-mod"; | |
218 | string obj = str_int("obj", i); | |
219 | string loc = str_int("loc", i); | |
220 | ||
221 | /* prepare both removal and modification on the same object */ | |
222 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_DEL, tag_remove, obj, loc); | |
223 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag_modify, obj, loc); | |
224 | ||
225 | test_stats(ioctx, bucket_oid, 0, NUM_OBJS, total_size); | |
226 | ||
227 | rgw_bucket_dir_entry_meta meta; | |
228 | ||
229 | /* complete object removal */ | |
230 | index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_DEL, tag_remove, ++epoch, obj, meta); | |
231 | ||
232 | /* verify stats correct */ | |
233 | total_size -= i * obj_size; | |
234 | test_stats(ioctx, bucket_oid, 0, NUM_OBJS - 1, total_size); | |
235 | ||
236 | meta.size = 512; | |
237 | meta.category = 0; | |
238 | ||
239 | /* complete object modification */ | |
240 | index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag_modify, ++epoch, obj, meta); | |
241 | ||
242 | /* verify stats correct */ | |
243 | total_size += meta.size; | |
244 | test_stats(ioctx, bucket_oid, 0, NUM_OBJS, total_size); | |
245 | ||
246 | ||
247 | /* prepare both removal and modification on the same object, this time we'll | |
248 | * first complete modification then remove*/ | |
249 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_DEL, tag_remove, obj, loc); | |
250 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_DEL, tag_modify, obj, loc); | |
251 | ||
252 | /* complete modification */ | |
253 | total_size -= meta.size; | |
254 | meta.size = i * obj_size * 2; | |
255 | meta.category = 0; | |
256 | ||
257 | /* complete object modification */ | |
258 | index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag_modify, ++epoch, obj, meta); | |
259 | ||
260 | /* verify stats correct */ | |
261 | total_size += meta.size; | |
262 | test_stats(ioctx, bucket_oid, 0, NUM_OBJS, total_size); | |
263 | ||
264 | /* complete object removal */ | |
265 | index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_DEL, tag_remove, ++epoch, obj, meta); | |
266 | ||
267 | /* verify stats correct */ | |
268 | total_size -= meta.size; | |
269 | test_stats(ioctx, bucket_oid, 0, NUM_OBJS - 1, total_size); | |
270 | } | |
271 | ||
272 | TEST(cls_rgw, index_suggest) | |
273 | { | |
274 | string bucket_oid = str_int("bucket", 3); | |
275 | ||
276 | OpMgr mgr; | |
277 | ||
278 | ObjectWriteOperation *op = mgr.write_op(); | |
279 | cls_rgw_bucket_init(*op); | |
280 | ASSERT_EQ(0, ioctx.operate(bucket_oid, op)); | |
281 | ||
282 | uint64_t total_size = 0; | |
283 | ||
284 | int epoch = 0; | |
285 | ||
286 | int num_objs = 100; | |
287 | ||
288 | uint64_t obj_size = 1024; | |
289 | ||
290 | /* create multiple objects */ | |
291 | for (int i = 0; i < num_objs; i++) { | |
292 | string obj = str_int("obj", i); | |
293 | string tag = str_int("tag", i); | |
294 | string loc = str_int("loc", i); | |
295 | ||
296 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, obj, loc); | |
297 | ||
298 | test_stats(ioctx, bucket_oid, 0, i, total_size); | |
299 | ||
300 | rgw_bucket_dir_entry_meta meta; | |
301 | meta.category = 0; | |
302 | meta.size = obj_size; | |
303 | total_size += meta.size; | |
304 | ||
305 | index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, ++epoch, obj, meta); | |
306 | ||
307 | test_stats(ioctx, bucket_oid, 0, i + 1, total_size); | |
308 | } | |
309 | ||
310 | /* prepare (without completion) some of the objects */ | |
311 | for (int i = 0; i < num_objs; i += 2) { | |
312 | string obj = str_int("obj", i); | |
313 | string tag = str_int("tag-prepare", i); | |
314 | string loc = str_int("loc", i); | |
315 | ||
316 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, obj, loc); | |
317 | ||
318 | test_stats(ioctx, bucket_oid, 0, num_objs, total_size); | |
319 | } | |
320 | ||
321 | int actual_num_objs = num_objs; | |
322 | /* remove half of the objects */ | |
323 | for (int i = num_objs / 2; i < num_objs; i++) { | |
324 | string obj = str_int("obj", i); | |
325 | string tag = str_int("tag-rm", i); | |
326 | string loc = str_int("loc", i); | |
327 | ||
328 | index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, obj, loc); | |
329 | ||
330 | test_stats(ioctx, bucket_oid, 0, actual_num_objs, total_size); | |
331 | ||
332 | rgw_bucket_dir_entry_meta meta; | |
333 | index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_DEL, tag, ++epoch, obj, meta); | |
334 | ||
335 | total_size -= obj_size; | |
336 | actual_num_objs--; | |
337 | test_stats(ioctx, bucket_oid, 0, actual_num_objs, total_size); | |
338 | } | |
339 | ||
340 | bufferlist updates; | |
341 | ||
342 | for (int i = 0; i < num_objs; i += 2) { | |
343 | string obj = str_int("obj", i); | |
344 | string tag = str_int("tag-rm", i); | |
345 | string loc = str_int("loc", i); | |
346 | ||
347 | rgw_bucket_dir_entry dirent; | |
348 | dirent.key.name = obj; | |
349 | dirent.locator = loc; | |
350 | dirent.exists = (i < num_objs / 2); // we removed half the objects | |
351 | dirent.meta.size = 1024; | |
352 | dirent.meta.accounted_size = 1024; | |
353 | ||
354 | char suggest_op = (i < num_objs / 2 ? CEPH_RGW_UPDATE : CEPH_RGW_REMOVE); | |
355 | cls_rgw_encode_suggestion(suggest_op, dirent, updates); | |
356 | } | |
357 | ||
358 | map<int, string> bucket_objs; | |
359 | bucket_objs[0] = bucket_oid; | |
360 | int r = CLSRGWIssueSetTagTimeout(ioctx, bucket_objs, 8 /* max aio */, 1)(); | |
361 | ASSERT_EQ(0, r); | |
362 | ||
363 | sleep(1); | |
364 | ||
365 | /* suggest changes! */ | |
366 | op = mgr.write_op(); | |
367 | cls_rgw_suggest_changes(*op, updates); | |
368 | ASSERT_EQ(0, ioctx.operate(bucket_oid, op)); | |
369 | ||
370 | /* suggest changes twice! */ | |
371 | op = mgr.write_op(); | |
372 | cls_rgw_suggest_changes(*op, updates); | |
373 | ASSERT_EQ(0, ioctx.operate(bucket_oid, op)); | |
374 | ||
375 | test_stats(ioctx, bucket_oid, 0, num_objs / 2, total_size); | |
376 | } | |
377 | ||
378 | /* test garbage collection */ | |
379 | static void create_obj(cls_rgw_obj& obj, int i, int j) | |
380 | { | |
381 | char buf[32]; | |
382 | snprintf(buf, sizeof(buf), "-%d.%d", i, j); | |
383 | obj.pool = "pool"; | |
384 | obj.pool.append(buf); | |
385 | obj.key.name = "oid"; | |
386 | obj.key.name.append(buf); | |
387 | obj.loc = "loc"; | |
388 | obj.loc.append(buf); | |
389 | } | |
390 | ||
391 | static bool cmp_objs(cls_rgw_obj& obj1, cls_rgw_obj& obj2) | |
392 | { | |
393 | return (obj1.pool == obj2.pool) && | |
394 | (obj1.key == obj2.key) && | |
395 | (obj1.loc == obj2.loc); | |
396 | } | |
397 | ||
398 | ||
399 | TEST(cls_rgw, gc_set) | |
400 | { | |
401 | /* add chains */ | |
402 | string oid = "obj"; | |
403 | for (int i = 0; i < 10; i++) { | |
404 | char buf[32]; | |
405 | snprintf(buf, sizeof(buf), "chain-%d", i); | |
406 | string tag = buf; | |
407 | librados::ObjectWriteOperation op; | |
408 | cls_rgw_gc_obj_info info; | |
409 | ||
410 | cls_rgw_obj obj1, obj2; | |
411 | create_obj(obj1, i, 1); | |
412 | create_obj(obj2, i, 2); | |
413 | info.chain.objs.push_back(obj1); | |
414 | info.chain.objs.push_back(obj2); | |
415 | ||
416 | op.create(false); // create object | |
417 | ||
418 | info.tag = tag; | |
419 | cls_rgw_gc_set_entry(op, 0, info); | |
420 | ||
421 | ASSERT_EQ(0, ioctx.operate(oid, &op)); | |
422 | } | |
423 | ||
424 | bool truncated; | |
425 | list<cls_rgw_gc_obj_info> entries; | |
426 | string marker; | |
31f18b77 | 427 | string next_marker; |
7c673cae FG |
428 | |
429 | /* list chains, verify truncated */ | |
31f18b77 | 430 | ASSERT_EQ(0, cls_rgw_gc_list(ioctx, oid, marker, 8, true, entries, &truncated, next_marker)); |
7c673cae FG |
431 | ASSERT_EQ(8, (int)entries.size()); |
432 | ASSERT_EQ(1, truncated); | |
433 | ||
434 | entries.clear(); | |
31f18b77 | 435 | next_marker.clear(); |
7c673cae FG |
436 | |
437 | /* list all chains, verify not truncated */ | |
31f18b77 | 438 | ASSERT_EQ(0, cls_rgw_gc_list(ioctx, oid, marker, 10, true, entries, &truncated, next_marker)); |
7c673cae FG |
439 | ASSERT_EQ(10, (int)entries.size()); |
440 | ASSERT_EQ(0, truncated); | |
441 | ||
442 | /* verify all chains are valid */ | |
443 | list<cls_rgw_gc_obj_info>::iterator iter = entries.begin(); | |
444 | for (int i = 0; i < 10; i++, ++iter) { | |
445 | cls_rgw_gc_obj_info& entry = *iter; | |
446 | ||
447 | /* create expected chain name */ | |
448 | char buf[32]; | |
449 | snprintf(buf, sizeof(buf), "chain-%d", i); | |
450 | string tag = buf; | |
451 | ||
452 | /* verify chain name as expected */ | |
453 | ASSERT_EQ(entry.tag, tag); | |
454 | ||
455 | /* verify expected num of objects in chain */ | |
456 | ASSERT_EQ(2, (int)entry.chain.objs.size()); | |
457 | ||
458 | list<cls_rgw_obj>::iterator oiter = entry.chain.objs.begin(); | |
459 | cls_rgw_obj obj1, obj2; | |
460 | ||
461 | /* create expected objects */ | |
462 | create_obj(obj1, i, 1); | |
463 | create_obj(obj2, i, 2); | |
464 | ||
465 | /* assign returned object names */ | |
466 | cls_rgw_obj& ret_obj1 = *oiter++; | |
467 | cls_rgw_obj& ret_obj2 = *oiter; | |
468 | ||
469 | /* verify objects are as expected */ | |
470 | ASSERT_EQ(1, (int)cmp_objs(obj1, ret_obj1)); | |
471 | ASSERT_EQ(1, (int)cmp_objs(obj2, ret_obj2)); | |
472 | } | |
473 | } | |
474 | ||
31f18b77 FG |
475 | TEST(cls_rgw, gc_list) |
476 | { | |
477 | /* add chains */ | |
478 | string oid = "obj"; | |
479 | for (int i = 0; i < 10; i++) { | |
480 | char buf[32]; | |
481 | snprintf(buf, sizeof(buf), "chain-%d", i); | |
482 | string tag = buf; | |
483 | librados::ObjectWriteOperation op; | |
484 | cls_rgw_gc_obj_info info; | |
485 | ||
486 | cls_rgw_obj obj1, obj2; | |
487 | create_obj(obj1, i, 1); | |
488 | create_obj(obj2, i, 2); | |
489 | info.chain.objs.push_back(obj1); | |
490 | info.chain.objs.push_back(obj2); | |
491 | ||
492 | op.create(false); // create object | |
493 | ||
494 | info.tag = tag; | |
495 | cls_rgw_gc_set_entry(op, 0, info); | |
496 | ||
497 | ASSERT_EQ(0, ioctx.operate(oid, &op)); | |
498 | } | |
499 | ||
500 | bool truncated; | |
501 | list<cls_rgw_gc_obj_info> entries; | |
502 | list<cls_rgw_gc_obj_info> entries2; | |
503 | string marker; | |
504 | string next_marker; | |
505 | ||
506 | /* list chains, verify truncated */ | |
507 | ASSERT_EQ(0, cls_rgw_gc_list(ioctx, oid, marker, 8, true, entries, &truncated, next_marker)); | |
508 | ASSERT_EQ(8, (int)entries.size()); | |
509 | ASSERT_EQ(1, truncated); | |
510 | ||
511 | marker = next_marker; | |
512 | next_marker.clear(); | |
513 | ||
514 | ASSERT_EQ(0, cls_rgw_gc_list(ioctx, oid, marker, 8, true, entries2, &truncated, next_marker)); | |
515 | ASSERT_EQ(2, (int)entries2.size()); | |
516 | ASSERT_EQ(0, truncated); | |
517 | ||
518 | entries.splice(entries.end(), entries2); | |
519 | ||
520 | /* verify all chains are valid */ | |
521 | list<cls_rgw_gc_obj_info>::iterator iter = entries.begin(); | |
522 | for (int i = 0; i < 10; i++, ++iter) { | |
523 | cls_rgw_gc_obj_info& entry = *iter; | |
524 | ||
525 | /* create expected chain name */ | |
526 | char buf[32]; | |
527 | snprintf(buf, sizeof(buf), "chain-%d", i); | |
528 | string tag = buf; | |
529 | ||
530 | /* verify chain name as expected */ | |
531 | ASSERT_EQ(entry.tag, tag); | |
532 | ||
533 | /* verify expected num of objects in chain */ | |
534 | ASSERT_EQ(2, (int)entry.chain.objs.size()); | |
535 | ||
536 | list<cls_rgw_obj>::iterator oiter = entry.chain.objs.begin(); | |
537 | cls_rgw_obj obj1, obj2; | |
538 | ||
539 | /* create expected objects */ | |
540 | create_obj(obj1, i, 1); | |
541 | create_obj(obj2, i, 2); | |
542 | ||
543 | /* assign returned object names */ | |
544 | cls_rgw_obj& ret_obj1 = *oiter++; | |
545 | cls_rgw_obj& ret_obj2 = *oiter; | |
546 | ||
547 | /* verify objects are as expected */ | |
548 | ASSERT_EQ(1, (int)cmp_objs(obj1, ret_obj1)); | |
549 | ASSERT_EQ(1, (int)cmp_objs(obj2, ret_obj2)); | |
550 | } | |
551 | } | |
552 | ||
7c673cae FG |
553 | TEST(cls_rgw, gc_defer) |
554 | { | |
555 | librados::IoCtx ioctx; | |
556 | librados::Rados rados; | |
557 | ||
558 | string gc_pool_name = get_temp_pool_name(); | |
559 | /* create pool */ | |
560 | ASSERT_EQ("", create_one_pool_pp(gc_pool_name, rados)); | |
561 | ASSERT_EQ(0, rados.ioctx_create(gc_pool_name.c_str(), ioctx)); | |
562 | ||
563 | string oid = "obj"; | |
564 | string tag = "mychain"; | |
565 | ||
566 | librados::ObjectWriteOperation op; | |
567 | cls_rgw_gc_obj_info info; | |
568 | ||
569 | op.create(false); | |
570 | ||
571 | info.tag = tag; | |
572 | ||
573 | /* create chain */ | |
574 | cls_rgw_gc_set_entry(op, 0, info); | |
575 | ||
576 | ASSERT_EQ(0, ioctx.operate(oid, &op)); | |
577 | ||
578 | bool truncated; | |
579 | list<cls_rgw_gc_obj_info> entries; | |
580 | string marker; | |
31f18b77 | 581 | string next_marker; |
7c673cae FG |
582 | |
583 | /* list chains, verify num entries as expected */ | |
31f18b77 | 584 | ASSERT_EQ(0, cls_rgw_gc_list(ioctx, oid, marker, 1, true, entries, &truncated, next_marker)); |
7c673cae FG |
585 | ASSERT_EQ(1, (int)entries.size()); |
586 | ASSERT_EQ(0, truncated); | |
587 | ||
588 | librados::ObjectWriteOperation op2; | |
589 | ||
590 | /* defer chain */ | |
591 | cls_rgw_gc_defer_entry(op2, 5, tag); | |
592 | ASSERT_EQ(0, ioctx.operate(oid, &op2)); | |
593 | ||
594 | entries.clear(); | |
31f18b77 | 595 | next_marker.clear(); |
7c673cae FG |
596 | |
597 | /* verify list doesn't show deferred entry (this may fail if cluster is thrashing) */ | |
31f18b77 | 598 | ASSERT_EQ(0, cls_rgw_gc_list(ioctx, oid, marker, 1, true, entries, &truncated, next_marker)); |
7c673cae FG |
599 | ASSERT_EQ(0, (int)entries.size()); |
600 | ASSERT_EQ(0, truncated); | |
601 | ||
602 | /* wait enough */ | |
603 | sleep(5); | |
31f18b77 | 604 | next_marker.clear(); |
7c673cae FG |
605 | |
606 | /* verify list shows deferred entry */ | |
31f18b77 | 607 | ASSERT_EQ(0, cls_rgw_gc_list(ioctx, oid, marker, 1, true, entries, &truncated, next_marker)); |
7c673cae FG |
608 | ASSERT_EQ(1, (int)entries.size()); |
609 | ASSERT_EQ(0, truncated); | |
610 | ||
611 | librados::ObjectWriteOperation op3; | |
612 | list<string> tags; | |
613 | tags.push_back(tag); | |
614 | ||
615 | /* remove chain */ | |
616 | cls_rgw_gc_remove(op3, tags); | |
617 | ASSERT_EQ(0, ioctx.operate(oid, &op3)); | |
618 | ||
619 | entries.clear(); | |
31f18b77 | 620 | next_marker.clear(); |
7c673cae FG |
621 | |
622 | /* verify entry was removed */ | |
31f18b77 | 623 | ASSERT_EQ(0, cls_rgw_gc_list(ioctx, oid, marker, 1, true, entries, &truncated, next_marker)); |
7c673cae FG |
624 | ASSERT_EQ(0, (int)entries.size()); |
625 | ASSERT_EQ(0, truncated); | |
626 | ||
627 | /* remove pool */ | |
628 | ioctx.close(); | |
629 | ASSERT_EQ(0, destroy_one_pool_pp(gc_pool_name, rados)); | |
630 | } | |
631 | ||
632 | ||
633 | /* must be last test! */ | |
634 | ||
635 | TEST(cls_rgw, finalize) | |
636 | { | |
637 | /* remove pool */ | |
638 | ioctx.close(); | |
639 | ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados)); | |
640 | } |