From: Pritha Srivastava Date: Mon, 22 Jul 2019 07:28:34 +0000 (+0530) Subject: Re-arranged files to move gc related code under a new cls module. X-Git-Tag: v15.1.0~1185^2~11 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e3b82990981df684e650905047bc1d0b90918512;p=ceph.git Re-arranged files to move gc related code under a new cls module. Moved gc related cls code to cls_rgw_gc module and Renaming the test folder and files from cls_queue to cls_rgw_gc Signed-off-by: Pritha Srivastava --- diff --git a/src/cls/CMakeLists.txt b/src/cls/CMakeLists.txt index add5ec0f7bb..00f077ce0ec 100644 --- a/src/cls/CMakeLists.txt +++ b/src/cls/CMakeLists.txt @@ -269,8 +269,6 @@ add_library(cls_cas_client STATIC ${cls_cas_client_srcs}) set(cls_queue_srcs queue/cls_queue.cc queue/cls_queue_src.cc - queue/cls_queue_ops.cc - queue/cls_queue_types.cc ${CMAKE_SOURCE_DIR}/src/common/ceph_json.cc) add_library(cls_queue SHARED ${cls_queue_srcs}) set_target_properties(cls_queue PROPERTIES @@ -280,25 +278,25 @@ set_target_properties(cls_queue PROPERTIES CXX_VISIBILITY_PRESET hidden) install(TARGETS cls_queue DESTINATION ${cls_dir}) -# cls_rgw_queue +set(cls_queue_client_srcs + queue/cls_queue_client.cc) +add_library(cls_queue_client STATIC ${cls_queue_client_srcs}) + +# cls_rgw_gc if (WITH_RADOSGW) - set(cls_rgw_queue_srcs - queue/cls_rgw_queue.cc + set(cls_rgw_gc_srcs + rgw_gc/cls_rgw_gc.cc queue/cls_queue_src.cc - queue/cls_queue_ops.cc - queue/cls_queue_types.cc ${CMAKE_SOURCE_DIR}/src/common/ceph_json.cc) - add_library(cls_rgw_queue SHARED ${cls_rgw_queue_srcs}) - set_target_properties(cls_rgw_queue PROPERTIES + add_library(cls_rgw_gc SHARED ${cls_rgw_gc_srcs}) + set_target_properties(cls_rgw_gc PROPERTIES VERSION "1.0.0" SOVERSION "1" INSTALL_RPATH "" CXX_VISIBILITY_PRESET hidden) - install(TARGETS cls_rgw_queue DESTINATION ${cls_dir}) + install(TARGETS cls_rgw_gc DESTINATION ${cls_dir}) - set(cls_queue_client_srcs - queue/cls_queue_client.cc - queue/cls_queue_types.cc - queue/cls_queue_ops.cc) - add_library(cls_queue_client STATIC ${cls_queue_client_srcs}) + 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}) endif (WITH_RADOSGW) diff --git a/src/cls/queue/cls_queue.cc b/src/cls/queue/cls_queue.cc index f2ba7d754ad..c939b847b7f 100644 --- a/src/cls/queue/cls_queue.cc +++ b/src/cls/queue/cls_queue.cc @@ -14,7 +14,7 @@ CLS_VER(1,0) CLS_NAME(queue) -static int cls_init_queue(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +static int cls_queue_init(cls_method_context_t hctx, bufferlist *in, bufferlist *out) { auto in_iter = in->cbegin(); cls_queue_init_op op; @@ -26,13 +26,13 @@ static int cls_init_queue(cls_method_context_t hctx, bufferlist *in, bufferlist return -EINVAL; } - return init_queue(hctx, op); + return queue_init(hctx, op); } -static int cls_get_queue_size(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +static int cls_queue_get_capacity(cls_method_context_t hctx, bufferlist *in, bufferlist *out) { - cls_queue_get_size_ret op_ret; - auto ret = get_queue_size(hctx, op_ret); + cls_queue_get_capacity_ret op_ret; + auto ret = queue_get_capacity(hctx, op_ret); if (ret < 0) { return ret; } @@ -41,30 +41,30 @@ static int cls_get_queue_size(cls_method_context_t hctx, bufferlist *in, bufferl return 0; } -static int cls_enqueue(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +static int cls_queue_enqueue(cls_method_context_t hctx, bufferlist *in, bufferlist *out) { auto iter = in->cbegin(); cls_queue_enqueue_op op; try { decode(op, iter); } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_enqueue: failed to decode input data \n"); + CLS_LOG(1, "ERROR: cls_queue_enqueue: failed to decode input data \n"); return -EINVAL; } cls_queue_head head; - auto ret = get_queue_head(hctx, head); + auto ret = queue_read_head(hctx, head); if (ret < 0) { return ret; } - ret = enqueue(hctx, op, head); + ret = queue_enqueue(hctx, op, head); if (ret < 0) { return ret; } //Write back head - return write_queue_head(hctx, head); + return queue_write_head(hctx, head); } static int cls_queue_list_entries(cls_method_context_t hctx, bufferlist *in, bufferlist *out) @@ -74,12 +74,12 @@ static int cls_queue_list_entries(cls_method_context_t hctx, bufferlist *in, buf try { decode(op, in_iter); } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_queue_list_entries(): failed to decode input data\n"); + CLS_LOG(5, "ERROR: cls_queue_list_entries(): failed to decode input data\n"); return -EINVAL; } cls_queue_head head; - auto ret = get_queue_head(hctx, head); + auto ret = queue_read_head(hctx, head); if (ret < 0) { return ret; } @@ -101,12 +101,12 @@ static int cls_queue_remove_entries(cls_method_context_t hctx, bufferlist *in, b try { decode(op, in_iter); } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_queue_remove_entries: failed to decode input data\n"); + CLS_LOG(5, "ERROR: cls_queue_remove_entries: failed to decode input data\n"); return -EINVAL; } cls_queue_head head; - auto ret = get_queue_head(hctx, head); + auto ret = queue_read_head(hctx, head); if (ret < 0) { return ret; } @@ -114,7 +114,7 @@ static int cls_queue_remove_entries(cls_method_context_t hctx, bufferlist *in, b if (ret < 0) { return ret; } - return write_queue_head(hctx, head); + return queue_write_head(hctx, head); } CLS_INIT(queue) @@ -122,18 +122,18 @@ CLS_INIT(queue) CLS_LOG(1, "Loaded queue class!"); cls_handle_t h_class; - cls_method_handle_t h_init_queue; - cls_method_handle_t h_get_queue_size; - cls_method_handle_t h_enqueue; + cls_method_handle_t h_queue_init; + cls_method_handle_t h_queue_get_capacity; + cls_method_handle_t h_queue_enqueue; cls_method_handle_t h_queue_list_entries; cls_method_handle_t h_queue_remove_entries; cls_register(QUEUE_CLASS, &h_class); /* queue*/ - cls_register_cxx_method(h_class, INIT_QUEUE, CLS_METHOD_WR, cls_init_queue, &h_init_queue); - cls_register_cxx_method(h_class, GET_QUEUE_SIZE, CLS_METHOD_RD, cls_get_queue_size, &h_get_queue_size); - cls_register_cxx_method(h_class, ENQUEUE, CLS_METHOD_RD | CLS_METHOD_WR, cls_enqueue, &h_enqueue); + cls_register_cxx_method(h_class, QUEUE_INIT, CLS_METHOD_WR, cls_queue_init, &h_queue_init); + cls_register_cxx_method(h_class, QUEUE_GET_CAPACITY, CLS_METHOD_RD, cls_queue_get_capacity, &h_queue_get_capacity); + cls_register_cxx_method(h_class, QUEUE_ENQUEUE, CLS_METHOD_RD | CLS_METHOD_WR, cls_queue_enqueue, &h_queue_enqueue); cls_register_cxx_method(h_class, QUEUE_LIST_ENTRIES, CLS_METHOD_RD, cls_queue_list_entries, &h_queue_list_entries); cls_register_cxx_method(h_class, QUEUE_REMOVE_ENTRIES, CLS_METHOD_RD | CLS_METHOD_WR, cls_queue_remove_entries, &h_queue_remove_entries); diff --git a/src/cls/queue/cls_queue_client.cc b/src/cls/queue/cls_queue_client.cc index ea6116030fd..bfa6e0a252b 100644 --- a/src/cls/queue/cls_queue_client.cc +++ b/src/cls/queue/cls_queue_client.cc @@ -2,35 +2,30 @@ // vim: ts=8 sw=2 smarttab #include -#include "cls/rgw/cls_rgw_ops.h" -#include "cls/queue/cls_rgw_queue_ops.h" #include "cls/queue/cls_queue_ops.h" #include "cls/queue/cls_queue_const.h" #include "cls/queue/cls_queue_client.h" -#include "common/debug.h" - using namespace librados; -void cls_rgw_gc_init_queue(ObjectWriteOperation& op, string& queue_name, uint64_t& size, uint64_t& num_urgent_data_entries) +void cls_queue_init(ObjectWriteOperation& op, const string& queue_name, uint64_t size) { bufferlist in; - cls_gc_init_queue_op call; - call.name = queue_name; - call.size = size; - call.num_urgent_data_entries = num_urgent_data_entries; + cls_queue_init_op call; + call.has_urgent_data = false; + call.head.queue_size = size; encode(call, in); - op.exec(RGW_QUEUE_CLASS, GC_INIT_QUEUE, in); + op.exec(QUEUE_CLASS, QUEUE_INIT, in); } -int cls_rgw_gc_get_queue_size(IoCtx& io_ctx, string& oid, uint64_t& size) +int cls_queue_get_capacity(IoCtx& io_ctx, const string& oid, uint64_t& size) { bufferlist in, out; - int r = io_ctx.exec(oid, QUEUE_CLASS, GET_QUEUE_SIZE, in, out); + int r = io_ctx.exec(oid, QUEUE_CLASS, QUEUE_GET_CAPACITY, in, out); if (r < 0) return r; - cls_queue_get_size_ret op_ret; + cls_queue_get_capacity_ret op_ret; auto iter = out.cbegin(); try { decode(op_ret, iter); @@ -38,36 +33,35 @@ int cls_rgw_gc_get_queue_size(IoCtx& io_ctx, string& oid, uint64_t& size) return -EIO; } - size = op_ret.queue_size; + size = op_ret.queue_capacity; return 0; } -void cls_rgw_gc_enqueue(ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info) +void cls_queue_enqueue(ObjectWriteOperation& op, uint32_t expiration_secs, vector bl_data_vec) { bufferlist in; - cls_rgw_gc_set_entry_op call; - call.expiration_secs = expiration_secs; - call.info = info; + cls_queue_enqueue_op call; + call.bl_data_vec = std::move(bl_data_vec); encode(call, in); - op.exec(RGW_QUEUE_CLASS, GC_ENQUEUE, in); + op.exec(QUEUE_CLASS, QUEUE_ENQUEUE, in); } -int cls_rgw_gc_list_queue(IoCtx& io_ctx, string& oid, string& marker, uint32_t max, bool expired_only, - list& entries, bool *truncated, string& next_marker) +int cls_queue_list_entries(IoCtx& io_ctx, const string& oid, const string& marker, uint32_t max, + vector& entries, + bool *truncated, string& next_marker) { bufferlist in, out; - cls_rgw_gc_list_op op; - op.marker = marker; + cls_queue_list_op op; + op.start_marker = marker; op.max = max; - op.expired_only = expired_only; encode(op, in); - int r = io_ctx.exec(oid, RGW_QUEUE_CLASS, GC_QUEUE_LIST_ENTRIES, in, out); + int r = io_ctx.exec(oid, QUEUE_CLASS, QUEUE_LIST_ENTRIES, in, out); if (r < 0) return r; - cls_rgw_gc_list_ret ret; + cls_queue_list_ret ret; auto iter = out.cbegin(); try { decode(ret, iter); @@ -75,30 +69,19 @@ int cls_rgw_gc_list_queue(IoCtx& io_ctx, string& oid, string& marker, uint32_t m return -EIO; } - entries.swap(ret.entries); - - *truncated = ret.truncated; + entries = std::move(ret.entries); + *truncated = ret.is_truncated; next_marker = std::move(ret.next_marker); return 0; } -void cls_rgw_gc_remove_entries_queue(ObjectWriteOperation& op, uint32_t num_entries) +void cls_queue_remove_entries(ObjectWriteOperation& op, const string& end_marker) { bufferlist in, out; - cls_rgw_gc_queue_remove_op rem_op; - rem_op.num_entries = num_entries; + cls_queue_remove_op rem_op; + rem_op.end_marker = end_marker; encode(rem_op, in); - op.exec(RGW_QUEUE_CLASS, GC_QUEUE_REMOVE_ENTRIES, in); -} - -void cls_rgw_gc_defer_entry_queue(ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info) -{ - bufferlist in; - cls_gc_defer_entry_op defer_op; - defer_op.expiration_secs = expiration_secs; - defer_op.info = info; - encode(defer_op, in); - op.exec(RGW_QUEUE_CLASS, GC_QUEUE_UPDATE_ENTRY, in); + op.exec(QUEUE_CLASS, QUEUE_REMOVE_ENTRIES, in); } diff --git a/src/cls/queue/cls_queue_client.h b/src/cls/queue/cls_queue_client.h index 2650a0ad5c3..59d32bfa1a7 100644 --- a/src/cls/queue/cls_queue_client.h +++ b/src/cls/queue/cls_queue_client.h @@ -1,21 +1,16 @@ #ifndef CEPH_CLS_QUEUE_CLIENT_H #define CEPH_CLS_QUEUE_CLIENT_H -#include "include/str_list.h" #include "include/rados/librados.hpp" #include "cls/queue/cls_queue_types.h" #include "cls_queue_ops.h" -#include "common/RefCountedObj.h" -#include "include/compat.h" #include "common/ceph_time.h" -#include "common/Cond.h" -void cls_rgw_gc_init_queue(librados::ObjectWriteOperation& op, string& queue_name, uint64_t& size, uint64_t& num_urgent_data_entries); -int cls_rgw_gc_get_queue_size(librados::IoCtx& io_ctx, string& oid, uint64_t& size); -void cls_rgw_gc_enqueue(librados::ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info); -int cls_rgw_gc_list_queue(librados::IoCtx& io_ctx, string& oid, string& marker, uint32_t max, bool expired_only, - list& entries, bool *truncated, string& next_marker); -void cls_rgw_gc_remove_entries_queue(librados::ObjectWriteOperation& op, uint32_t num_entries); -void cls_rgw_gc_defer_entry_queue(librados::ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info); +void cls_queue_init(librados::ObjectWriteOperation& op, const string& queue_name, uint64_t size); +int cls_queue_get_capacity(librados::IoCtx& io_ctx, const string& oid, uint64_t& size); +void cls_queue_enqueue(librados::ObjectWriteOperation& op, uint32_t expiration_secs, vector bl_data_vec); +int cls_queue_list_entries(librados::IoCtx& io_ctx, const string& oid, const string& marker, uint32_t max, + vector& entries, bool *truncated, string& next_marker); +void cls_queue_remove_entries(librados::ObjectWriteOperation& op, const string& end_marker); #endif \ No newline at end of file diff --git a/src/cls/queue/cls_queue_const.h b/src/cls/queue/cls_queue_const.h index 3b61f00e0ba..3f289abb073 100644 --- a/src/cls/queue/cls_queue_const.h +++ b/src/cls/queue/cls_queue_const.h @@ -2,22 +2,11 @@ #define CEPH_CLS_QUEUE_CONSTS_H #define QUEUE_CLASS "queue" -#define RGW_QUEUE_CLASS "rgw_queue" -#define INIT_QUEUE "init_queue" -#define GET_QUEUE_SIZE "get_queue_size" -#define ENQUEUE "enqueue" +#define QUEUE_INIT "queue_init" +#define QUEUE_GET_CAPACITY "queue_get_capacity" +#define QUEUE_ENQUEUE "queue_enqueue" #define QUEUE_LIST_ENTRIES "queue_list_entries" #define QUEUE_REMOVE_ENTRIES "queue_remove_entries" -#define QUEUE_READ_URGENT_DATA "queue_read_urgent_data" -#define QUEUE_WRITE_URGENT_DATA "queue_write_urgent_data" -#define QUEUE_CAN_URGENT_DATA_FIT "queue_can_urgent_data_fit" - -#define GC_INIT_QUEUE "gc_init_queue" -#define GC_ENQUEUE "gc_enqueue" -#define GC_DEQUEUE "gc_dequeue" -#define GC_QUEUE_LIST_ENTRIES "gc_queue_list_entries" -#define GC_QUEUE_REMOVE_ENTRIES "gc_queue_remove_entries" -#define GC_QUEUE_UPDATE_ENTRY "gc_queue_update_entry" #endif \ No newline at end of file diff --git a/src/cls/queue/cls_queue_ops.cc b/src/cls/queue/cls_queue_ops.cc deleted file mode 100644 index 4e35090f6e9..00000000000 --- a/src/cls/queue/cls_queue_ops.cc +++ /dev/null @@ -1,7 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -#include "cls/queue/cls_queue_ops.h" - -#include "common/Formatter.h" -#include "common/ceph_json.h" -#include "include/utime.h" diff --git a/src/cls/queue/cls_queue_ops.h b/src/cls/queue/cls_queue_ops.h index c7a8e709699..9c5a78ea2fb 100644 --- a/src/cls/queue/cls_queue_ops.h +++ b/src/cls/queue/cls_queue_ops.h @@ -73,8 +73,7 @@ WRITE_CLASS_ENCODER(cls_queue_list_op) struct cls_queue_list_ret { bool is_truncated; string next_marker; - vector data; - vector markers; + vector entries; cls_queue_list_ret() {} @@ -82,8 +81,7 @@ struct cls_queue_list_ret { ENCODE_START(1, 1, bl); encode(is_truncated, bl); encode(next_marker, bl); - encode(data, bl); - encode(markers, bl); + encode(entries, bl); ENCODE_FINISH(bl); } @@ -91,8 +89,7 @@ struct cls_queue_list_ret { DECODE_START(1, bl); decode(is_truncated, bl); decode(next_marker, bl); - decode(data, bl); - decode(markers, bl); + decode(entries, bl); DECODE_FINISH(bl); } }; @@ -117,23 +114,23 @@ struct cls_queue_remove_op { }; WRITE_CLASS_ENCODER(cls_queue_remove_op) -struct cls_queue_get_size_ret { - uint64_t queue_size; +struct cls_queue_get_capacity_ret { + uint64_t queue_capacity; - cls_queue_get_size_ret() {} + cls_queue_get_capacity_ret() {} void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); - encode(queue_size, bl); + encode(queue_capacity, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); - decode(queue_size, bl); + decode(queue_capacity, bl); DECODE_FINISH(bl); } }; -WRITE_CLASS_ENCODER(cls_queue_get_size_ret) +WRITE_CLASS_ENCODER(cls_queue_get_capacity_ret) #endif /* CEPH_CLS_QUEUE_OPS_H */ \ No newline at end of file diff --git a/src/cls/queue/cls_queue_src.cc b/src/cls/queue/cls_queue_src.cc index 52aae9b57f5..22a88a07eb3 100644 --- a/src/cls/queue/cls_queue_src.cc +++ b/src/cls/queue/cls_queue_src.cc @@ -11,7 +11,7 @@ #include "cls/queue/cls_queue_const.h" #include "cls/queue/cls_queue_src.h" -int write_queue_head(cls_method_context_t hctx, cls_queue_head& head) +int queue_write_head(cls_method_context_t hctx, cls_queue_head& head) { bufferlist bl; uint16_t entry_start = QUEUE_HEAD_START; @@ -27,20 +27,20 @@ int write_queue_head(cls_method_context_t hctx, cls_queue_head& head) int ret = cls_cxx_write2(hctx, 0, bl.length(), &bl, CEPH_OSD_OP_FLAG_FADVISE_WILLNEED); if (ret < 0) { - CLS_LOG(5, "ERROR: write_queue_head: failed to write head \n"); + CLS_LOG(5, "ERROR: queue_write_head: failed to write head \n"); return ret; } return 0; } -int get_queue_head(cls_method_context_t hctx, cls_queue_head& head) +int queue_read_head(cls_method_context_t hctx, cls_queue_head& head) { uint64_t chunk_size = 1024, start_offset = 0; bufferlist bl_head; int ret = cls_cxx_read(hctx, start_offset, chunk_size, &bl_head); if (ret < 0) { - CLS_LOG(5, "ERROR: get_queue_head: failed to read head \n"); + CLS_LOG(5, "ERROR: queue_read_head: failed to read head \n"); return ret; } @@ -51,11 +51,11 @@ int get_queue_head(cls_method_context_t hctx, cls_queue_head& head) try { decode(queue_head_start, it); } catch (buffer::error& err) { - CLS_LOG(0, "ERROR: get_queue_head: failed to decode queue start \n"); + CLS_LOG(0, "ERROR: queue_read_head: failed to decode queue start \n"); return -EINVAL; } if (queue_head_start != QUEUE_HEAD_START) { - CLS_LOG(0, "ERROR: get_queue_head: invalid queue start \n"); + CLS_LOG(0, "ERROR: queue_read_head: invalid queue start \n"); return -EINVAL; } @@ -63,7 +63,7 @@ int get_queue_head(cls_method_context_t hctx, cls_queue_head& head) try { decode(encoded_len, it); } catch (buffer::error& err) { - CLS_LOG(0, "ERROR: get_queue_head: failed to decode encoded head size \n"); + CLS_LOG(0, "ERROR: queue_read_head: failed to decode encoded head size \n"); return -EINVAL; } @@ -74,7 +74,7 @@ int get_queue_head(cls_method_context_t hctx, cls_queue_head& head) bufferlist bl_remaining_head; int ret = cls_cxx_read2(hctx, start_offset, chunk_size, &bl_remaining_head, CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL); if (ret < 0) { - CLS_LOG(5, "ERROR: get_queue_head: failed to read remaining part of head \n"); + CLS_LOG(5, "ERROR: queue_read_head: failed to read remaining part of head \n"); return ret; } bl_head.claim_append(bl_remaining_head); @@ -83,18 +83,18 @@ int get_queue_head(cls_method_context_t hctx, cls_queue_head& head) try { decode(head, it); } catch (buffer::error& err) { - CLS_LOG(0, "ERROR: get_queue_head: failed to decode head\n"); + CLS_LOG(0, "ERROR: queue_read_head: failed to decode head\n"); return -EINVAL; } return 0; } -int init_queue(cls_method_context_t hctx, const cls_queue_init_op& op) +int queue_init(cls_method_context_t hctx, const cls_queue_init_op& op) { //get head and its size cls_queue_head head; - int ret = get_queue_head(hctx, head); + int ret = queue_read_head(hctx, head); //head is already initialized if (ret == 0) { @@ -135,26 +135,26 @@ int init_queue(cls_method_context_t hctx, const cls_queue_init_op& op) CLS_LOG(20, "INFO: init_queue_op queue front offset %s", head.front.to_str().c_str()); CLS_LOG(20, "INFO: init_queue_op queue max urgent data size %lu", head.max_urgent_data_size); - return write_queue_head(hctx, head); + return queue_write_head(hctx, head); } -int get_queue_size(cls_method_context_t hctx, cls_queue_get_size_ret& op_ret) +int queue_get_capacity(cls_method_context_t hctx, cls_queue_get_capacity_ret& op_ret) { //get head cls_queue_head head; - int ret = get_queue_head(hctx, head); + int ret = queue_read_head(hctx, head); if (ret < 0) { return ret; } - op_ret.queue_size = head.queue_size - head.max_head_size; + op_ret.queue_capacity = head.queue_size - head.max_head_size; - CLS_LOG(20, "INFO: get_queue_size: size of queue is %lu\n", op_ret.queue_size); + CLS_LOG(20, "INFO: queue_get_capacity: size of queue is %lu\n", op_ret.queue_capacity); return 0; } -int enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& head) +int queue_enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& head) { if ((head.front.offset == head.tail.offset) && (head.tail.gen == head.front.gen + 1)) { CLS_LOG(0, "ERROR: No space left in queue\n"); @@ -169,12 +169,12 @@ int enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& encode(data_size, bl); bl.claim_append(bl_data); - CLS_LOG(10, "INFO: enqueue(): Total size to be written is %u and data size is %u\n", bl.length(), bl_data.length()); + CLS_LOG(10, "INFO: queue_enqueue(): Total size to be written is %u and data size is %u\n", bl.length(), bl_data.length()); if (head.tail.offset >= head.front.offset) { // check if data can fit in the remaining space in queue if ((head.tail.offset + bl.length()) <= head.queue_size) { - CLS_LOG(5, "INFO: enqueue: Writing data size and data: offset: %s, size: %u\n", head.tail.to_str().c_str(), bl.length()); + CLS_LOG(5, "INFO: queue_enqueue: Writing data size and data: offset: %s, size: %u\n", head.tail.to_str().c_str(), bl.length()); //write data size and data at tail offset auto ret = cls_cxx_write2(hctx, head.tail.offset, bl.length(), &bl, CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL); if (ret < 0) { @@ -189,7 +189,7 @@ int enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& bufferlist bl_data_before_wrap; bl.splice(0, size_before_wrap, &bl_data_before_wrap); //write spliced (data size and data) at tail offset - CLS_LOG(5, "INFO: enqueue: Writing spliced data at offset: %s and data size: %u\n", head.tail.to_str().c_str(), bl_data_before_wrap.length()); + CLS_LOG(5, "INFO: queue_enqueue: Writing spliced data at offset: %s and data size: %u\n", head.tail.to_str().c_str(), bl_data_before_wrap.length()); auto ret = cls_cxx_write2(hctx, head.tail.offset, bl_data_before_wrap.length(), &bl_data_before_wrap, CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL); if (ret < 0) { return ret; @@ -197,7 +197,7 @@ int enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& head.tail.offset = head.max_head_size; head.tail.gen += 1; //write remaining data at tail offset after wrapping around - CLS_LOG(5, "INFO: enqueue: Writing remaining data at offset: %s and data size: %u\n", head.tail.to_str().c_str(), bl.length()); + CLS_LOG(5, "INFO: queue_enqueue: Writing remaining data at offset: %s and data size: %u\n", head.tail.to_str().c_str(), bl.length()); ret = cls_cxx_write2(hctx, head.tail.offset, bl.length(), &bl, CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL); if (ret < 0) { return ret; @@ -211,7 +211,7 @@ int enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& } } else if (head.front.offset > head.tail.offset) { if ((head.tail.offset + bl.length()) <= head.front.offset) { - CLS_LOG(5, "INFO: enqueue: Writing data size and data: offset: %s, size: %u\n\n", head.tail.to_str().c_str(), bl.length()); + CLS_LOG(5, "INFO: queue_enqueue: Writing data size and data: offset: %s, size: %u\n\n", head.tail.to_str().c_str(), bl.length()); //write data size and data at tail offset auto ret = cls_cxx_write2(hctx, head.tail.offset, bl.length(), &bl, CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL); if (ret < 0) { @@ -229,7 +229,7 @@ int enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& head.tail.offset = head.max_head_size; head.tail.gen += 1; } - CLS_LOG(20, "INFO: enqueue: New tail offset: %s \n", head.tail.to_str().c_str()); + CLS_LOG(20, "INFO: queue_enqueue: New tail offset: %s \n", head.tail.to_str().c_str()); } //end - for return 0; @@ -317,13 +317,13 @@ int queue_list_entries(cls_method_context_t hctx, const cls_queue_list_op& op, c uint64_t size_to_process = bl_chunk.length(); do { CLS_LOG(10, "INFO: queue_list_entries(): index: %u, size_to_process: %lu\n", index, size_to_process); + cls_queue_entry entry; it.seek(index); //Populate offset if not done in previous iteration if (! offset_populated) { cls_queue_marker marker = {start_offset + index, gen}; CLS_LOG(5, "INFO: queue_list_entries(): offset: %s\n", marker.to_str().c_str()); - string opaque_marker = marker.to_str(); - op_ret.markers.emplace_back(opaque_marker); + entry.marker = marker.to_str(); } // Magic number + Data size - process if not done in previous iteration if (! entry_start_processed ) { @@ -361,12 +361,9 @@ int queue_list_entries(cls_method_context_t hctx, const cls_queue_list_op& op, c } // Data if (data_size <= size_to_process) { - bufferlist bl_data; - bl_chunk.copy(index, data_size, bl_data); - //Return data here - op_ret.data.emplace_back(bl_data); - index += bl_data.length(); - size_to_process -= bl_data.length(); + bl_chunk.copy(index, data_size, entry.data); + index += entry.data.length(); + size_to_process -= entry.data.length(); } else { bl_chunk.copy(index, size_to_process, bl); offset_populated = true; @@ -374,6 +371,7 @@ int queue_list_entries(cls_method_context_t hctx, const cls_queue_list_op& op, c CLS_LOG(10, "INFO: queue_list_entries(): not enough data to read data, breaking out!\n"); break; } + op_ret.entries.emplace_back(entry); // Resetting some values offset_populated = false; entry_start_processed = false; diff --git a/src/cls/queue/cls_queue_src.h b/src/cls/queue/cls_queue_src.h index 2b225f60143..9111f1f0409 100644 --- a/src/cls/queue/cls_queue_src.h +++ b/src/cls/queue/cls_queue_src.h @@ -1,11 +1,11 @@ #ifndef CEPH_CLS_QUEUE_SRC_H #define CEPH_CLS_QUEUE_SRC_H -int write_queue_head(cls_method_context_t hctx, cls_queue_head& head); -int get_queue_head(cls_method_context_t hctx, cls_queue_head& head); -int init_queue(cls_method_context_t hctx, const cls_queue_init_op& op); -int get_queue_size(cls_method_context_t hctx, cls_queue_get_size_ret& op_ret); -int enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& head); +int queue_write_head(cls_method_context_t hctx, cls_queue_head& head); +int queue_read_head(cls_method_context_t hctx, cls_queue_head& head); +int queue_init(cls_method_context_t hctx, const cls_queue_init_op& op); +int queue_get_capacity(cls_method_context_t hctx, cls_queue_get_capacity_ret& op_ret); +int queue_enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& head); int queue_list_entries(cls_method_context_t hctx, const cls_queue_list_op& op, cls_queue_list_ret& op_ret, cls_queue_head& head); int queue_remove_entries(cls_method_context_t hctx, const cls_queue_remove_op& op, cls_queue_head& head); diff --git a/src/cls/queue/cls_queue_types.cc b/src/cls/queue/cls_queue_types.cc deleted file mode 100644 index 33319d9a34c..00000000000 --- a/src/cls/queue/cls_queue_types.cc +++ /dev/null @@ -1,7 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "cls/queue/cls_queue_types.h" -#include "common/ceph_json.h" -#include "include/utime.h" - diff --git a/src/cls/queue/cls_queue_types.h b/src/cls/queue/cls_queue_types.h index 0caa269ed25..e00b7c2f5f7 100644 --- a/src/cls/queue/cls_queue_types.h +++ b/src/cls/queue/cls_queue_types.h @@ -3,8 +3,6 @@ #include #include "include/types.h" -#include "common/ceph_time.h" -#include "common/Formatter.h" #define QUEUE_HEAD_SIZE_1K 1024 //Actual start offset of queue data @@ -17,6 +15,27 @@ constexpr unsigned int QUEUE_HEAD_START = 0xDEAD; constexpr unsigned int QUEUE_ENTRY_START = 0xBEEF; +struct cls_queue_entry +{ + bufferlist data; + std::string marker; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(data, bl); + encode(marker, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(data, bl); + decode(marker, bl); + DECODE_FINISH(bl); + } +}; +WRITE_CLASS_ENCODER(cls_queue_entry) + struct cls_queue_marker { uint64_t offset{0}; diff --git a/src/cls/queue/cls_rgw_queue.cc b/src/cls/queue/cls_rgw_queue.cc deleted file mode 100644 index bea69fa6617..00000000000 --- a/src/cls/queue/cls_rgw_queue.cc +++ /dev/null @@ -1,559 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "include/types.h" - -#include - -#include "objclass/objclass.h" -#include "cls/rgw/cls_rgw_ops.h" -#include "cls/rgw/cls_rgw_types.h" -#include "cls/queue/cls_queue_types.h" -#include "cls/queue/cls_rgw_queue_types.h" -#include "cls/queue/cls_queue_ops.h" -#include "cls/queue/cls_rgw_queue_ops.h" -#include "cls/queue/cls_queue_const.h" -#include "cls/queue/cls_queue_src.h" - -#include -#include -#include - -#include "common/ceph_context.h" -#include "global/global_context.h" - -#define dout_context g_ceph_context -#define dout_subsys ceph_subsys_rgw - -#define GC_LIST_DEFAULT_MAX 128 - -CLS_VER(1,0) -CLS_NAME(rgw_queue) - -static int cls_gc_init_queue(cls_method_context_t hctx, bufferlist *in, bufferlist *out) -{ - auto in_iter = in->cbegin(); - - cls_gc_init_queue_op op; - try { - decode(op, in_iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_init_queue: failed to decode entry\n"); - return -EINVAL; - } - - cls_gc_urgent_data urgent_data; - urgent_data.num_urgent_data_entries = op.num_urgent_data_entries; - - cls_queue_init_op init_op; - - CLS_LOG(10, "INFO: cls_gc_init_queue: queue size is %lu\n", op.size); - CLS_LOG(10, "INFO: cls_gc_init_queue: queue name is %s\n", op.name.c_str()); - init_op.head.queue_size = op.size; - init_op.head_size = g_ceph_context->_conf->rgw_gc_queue_head_size; - init_op.has_urgent_data = true; - encode(urgent_data, init_op.head.bl_urgent_data); - - return init_queue(hctx, init_op); -} - -static int cls_gc_enqueue(cls_method_context_t hctx, bufferlist *in, bufferlist *out) -{ - auto in_iter = in->cbegin(); - cls_rgw_gc_set_entry_op op; - try { - decode(op, in_iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_enqueue: failed to decode entry\n"); - return -EINVAL; - } - - op.info.time = ceph::real_clock::now(); - op.info.time += make_timespan(op.expiration_secs); - - //get head - cls_queue_head head; - int ret = get_queue_head(hctx, head); - if (ret < 0) { - return ret; - } - - cls_queue_enqueue_op enqueue_op; - bufferlist bl_data; - encode(op.info, bl_data); - enqueue_op.bl_data_vec.emplace_back(bl_data); - - CLS_LOG(1, "INFO: cls_gc_enqueue: Data size is: %u \n", bl_data.length()); - - ret = enqueue(hctx, enqueue_op, head); - if (ret < 0) { - return ret; - } - - //Write back head - return write_queue_head(hctx, head); -} - -static int cls_gc_queue_list(cls_method_context_t hctx, bufferlist *in, bufferlist *out) -{ - CLS_LOG(1, "INFO: cls_gc_queue_list(): Entered cls_gc_queue_list \n"); - auto in_iter = in->cbegin(); - cls_rgw_gc_list_op op; - try { - decode(op, in_iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_list(): failed to decode input\n"); - return -EINVAL; - } - - cls_queue_head head; - auto ret = get_queue_head(hctx, head); - if (ret < 0) { - return ret; - } - - cls_gc_urgent_data urgent_data; - if (head.bl_urgent_data.length() > 0) { - auto iter_urgent_data = head.bl_urgent_data.cbegin(); - try { - decode(urgent_data, iter_urgent_data); - } catch (buffer::error& err) { - CLS_LOG(5, "ERROR: cls_gc_queue_list(): failed to decode urgent data\n"); - return -EINVAL; - } - } - - cls_queue_list_op list_op; - if (! op.max) { - op.max = GC_LIST_DEFAULT_MAX; - } - - list_op.max = op.max; - list_op.start_marker = op.marker; - - cls_rgw_gc_list_ret list_ret; - uint32_t num_entries = 0; //Entries excluding the deferred ones - bool is_truncated = true; - string next_marker; - do { - CLS_LOG(1, "INFO: cls_gc_queue_list(): Entering queue_list_entries \n"); - cls_queue_list_ret op_ret; - int ret = queue_list_entries(hctx, list_op, op_ret, head); - if (ret < 0) { - CLS_LOG(1, "ERROR: queue_list_entries(): returned error %d\n", ret); - return ret; - } - is_truncated = op_ret.is_truncated; - next_marker = op_ret.next_marker; - - if (op_ret.data.size()) { - for (auto it : op_ret.data) { - cls_rgw_gc_obj_info info; - try { - decode(info, it); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_list(): failed to decode gc info\n"); - return -EINVAL; - } - bool found = false; - //Check for info tag in urgent data map - auto iter = urgent_data.urgent_data_map.find(info.tag); - if (iter != urgent_data.urgent_data_map.end()) { - found = true; - stringstream ss1, ss2; - ss1 << iter->second; - ss2 << info.time; - if (iter->second > info.time) { - CLS_LOG(1, "INFO: cls_gc_queue_list(): tag found in urgent data: %s\n", info.tag.c_str()); - CLS_LOG(1, "INFO: cls_gc_queue_list(): time found in urgent data: %s\n", ss1.str().c_str()); - CLS_LOG(1, "INFO: cls_gc_queue_list(): time found in queue data: %s\n", ss2.str().c_str()); - continue; - } - } - //Search in xattrs - if (! found && urgent_data.num_xattr_urgent_entries > 0) { - bufferlist bl_xattrs; - int ret = cls_cxx_getxattr(hctx, "cls_queue_urgent_data", &bl_xattrs); - if (ret < 0 && (ret != -ENOENT && ret != -ENODATA)) { - CLS_LOG(0, "ERROR: %s(): cls_cxx_getxattrs() returned %d", __func__, ret); - return ret; - } - if (ret != -ENOENT && ret != -ENODATA) { - std::unordered_map xattr_urgent_data_map; - auto iter = bl_xattrs.cbegin(); - try { - decode(xattr_urgent_data_map, iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_list(): failed to decode xattrs urgent data map\n"); - return -EINVAL; - } //end - catch - auto xattr_iter = xattr_urgent_data_map.find(info.tag); - if (xattr_iter != xattr_urgent_data_map.end()) { - if (xattr_iter->second > info.time) { - CLS_LOG(1, "INFO: cls_gc_queue_list(): tag found in xattrs urgent data map: %s\n", info.tag.c_str()); - continue; - } - } - } // end - ret != ENOENT && ENODATA - } // end - if not found - if (op.expired_only) { - real_time now = ceph::real_clock::now(); - if (info.time <= now) { - list_ret.entries.emplace_back(info); - } - //Can break out here if info.time > now, since all subsequent entries won't have expired - } else { - list_ret.entries.emplace_back(info); - } - num_entries++; - } - CLS_LOG(1, "INFO: cls_gc_queue_list(): num_entries: %u and op.max: %u\n", num_entries, op.max); - if (num_entries < op.max) { - list_op.max = (op.max - num_entries); - list_op.start_marker = op_ret.next_marker; - out->clear(); - } else { - //We've reached the max number of entries needed - break; - } - } else { - //We dont have data to process - break; - } - } while(is_truncated); - - list_ret.truncated = is_truncated; - if (list_ret.truncated) { - list_ret.next_marker = next_marker; - } - out->clear(); - encode(list_ret, *out); - return 0; -} - -static int cls_gc_queue_remove(cls_method_context_t hctx, bufferlist *in, bufferlist *out) -{ - CLS_LOG(1, "INFO: cls_gc_queue_remove(): Entered cls_gc_queue_remove \n"); - - auto in_iter = in->cbegin(); - - cls_rgw_gc_queue_remove_op op; - try { - decode(op, in_iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_remove(): failed to decode input\n"); - return -EINVAL; - } - - cls_queue_head head; - auto ret = get_queue_head(hctx, head); - if (ret < 0) { - return ret; - } - - cls_gc_urgent_data urgent_data; - if (head.bl_urgent_data.length() > 0) { - auto iter_urgent_data = head.bl_urgent_data.cbegin(); - try { - decode(urgent_data, iter_urgent_data); - } catch (buffer::error& err) { - CLS_LOG(5, "ERROR: cls_gc_queue_remove(): failed to decode urgent data\n"); - return -EINVAL; - } - } - - // List entries and calculate total number of entries (including invalid entries) - if (! op.num_entries) { - op.num_entries = GC_LIST_DEFAULT_MAX; - } - cls_queue_list_op list_op; - list_op.max = op.num_entries + 1; // +1 to get the offset of last + 1 entry - bool is_truncated = true; - uint32_t total_num_entries = 0, num_entries = 0; - string end_marker; - do { - CLS_LOG(1, "INFO: cls_gc_queue_remove(): Entering queue_list_entries \n"); - cls_queue_list_ret op_ret; - int ret = queue_list_entries(hctx, list_op, op_ret, head); - if (ret < 0) { - CLS_LOG(1, "ERROR: queue_list_entries(): returned error %d\n", ret); - return ret; - } - - is_truncated = op_ret.is_truncated; - unsigned int index = 0; - // If data is not empty - if (op_ret.data.size()) { - for (auto it : op_ret.data) { - cls_rgw_gc_obj_info info; - try { - decode(info, it); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_remove(): failed to decode gc info\n"); - return -EINVAL; - } - CLS_LOG(1, "INFO: cls_gc_queue_remove(): entry: %s\n", info.tag.c_str()); - total_num_entries++; - index++; - bool found = false; - //Search for tag in urgent data map - auto iter = urgent_data.urgent_data_map.find(info.tag); - if (iter != urgent_data.urgent_data_map.end()) { - found = true; - if (iter->second > info.time) { - CLS_LOG(1, "INFO: cls_gc_queue_remove(): tag found in urgent data: %s\n", info.tag.c_str()); - continue; - } else if (iter->second == info.time) { - CLS_LOG(1, "INFO: cls_gc_queue_remove(): erasing tag from urgent data: %s\n", info.tag.c_str()); - urgent_data.urgent_data_map.erase(info.tag); //erase entry from map, as it will be removed later from queue - urgent_data.num_head_urgent_entries -= 1; - } - }//end-if map end - if (! found && urgent_data.num_xattr_urgent_entries > 0) { - //Search in xattrs - bufferlist bl_xattrs; - int ret = cls_cxx_getxattr(hctx, "cls_queue_urgent_data", &bl_xattrs); - if (ret < 0 && (ret != -ENOENT && ret != -ENODATA)) { - CLS_LOG(0, "ERROR: %s(): cls_cxx_getxattrs() returned %d", __func__, ret); - return ret; - } - if (ret != -ENOENT && ret != -ENODATA) { - std::unordered_map xattr_urgent_data_map; - auto iter = bl_xattrs.cbegin(); - try { - decode(xattr_urgent_data_map, iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_remove(): failed to decode xattrs urgent data map\n"); - return -EINVAL; - } //end - catch - auto xattr_iter = xattr_urgent_data_map.find(info.tag); - if (xattr_iter != xattr_urgent_data_map.end()) { - if (xattr_iter->second > info.time) { - CLS_LOG(1, "INFO: cls_gc_queue_remove(): tag found in xattrs urgent data map: %s\n", info.tag.c_str()); - continue; - } else if (xattr_iter->second == info.time) { - CLS_LOG(1, "INFO: cls_gc_queue_remove(): erasing tag from xattrs urgent data: %s\n", info.tag.c_str()); - xattr_urgent_data_map.erase(info.tag); //erase entry from map, as it will be removed later - urgent_data.num_xattr_urgent_entries -= 1; - } - } - } // end - ret != ENOENT && ENODATA - }// search in xattrs - num_entries++; - }//end-for - - if (! op_ret.is_truncated && num_entries < (op.num_entries + 1)) { - end_marker = op_ret.next_marker; - CLS_LOG(1, "INFO: cls_gc_queue_remove(): truncated and end offset is %s\n", end_marker.c_str()); - break; - } - if (num_entries < (op.num_entries + 1)) { - list_op.max = ((op.num_entries + 1) - num_entries); - list_op.start_marker = op_ret.next_marker; - out->clear(); - } else { - end_marker = op_ret.markers[index - 1]; - CLS_LOG(1, "INFO: cls_gc_queue_remove(): index is %u and end_offset is: %s\n", index, end_marker.c_str()); - break; - } - } //end-if - else { - break; - } - } while(is_truncated); - - CLS_LOG(1, "INFO: cls_gc_queue_remove(): Total number of entries to remove: %d\n", total_num_entries); - CLS_LOG(1, "INFO: cls_gc_queue_remove(): End offset is %s\n", end_marker.c_str()); - - if (! end_marker.empty()) { - cls_queue_remove_op rem_op; - rem_op.end_marker = end_marker; - - CLS_LOG(1, "INFO: cls_gc_queue_remove(): Entering queue_remove_entries \n"); - int ret = queue_remove_entries(hctx, rem_op, head); - if (ret < 0) { - CLS_LOG(1, "ERROR: queue_remove_entries(): returned error %d\n", ret); - return ret; - } - } - - //Update urgent data map - encode(urgent_data, head.bl_urgent_data); - - return write_queue_head(hctx, head); -} - -static int cls_gc_queue_update_entry(cls_method_context_t hctx, bufferlist *in, bufferlist *out) -{ - int ret = 0; - auto in_iter = in->cbegin(); - - cls_gc_defer_entry_op op; - try { - decode(op, in_iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_update_entry(): failed to decode input\n"); - return -EINVAL; - } - - op.info.time = ceph::real_clock::now(); - op.info.time += make_timespan(op.expiration_secs); - - // Read head - cls_queue_head head; - ret = get_queue_head(hctx, head); - if (ret < 0) { - return ret; - } - - auto bl_iter = head.bl_urgent_data.cbegin(); - cls_gc_urgent_data urgent_data; - try { - decode(urgent_data, bl_iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_update_entry(): failed to decode urgent data\n"); - return -EINVAL; - } - - //has_urgent_data signifies whether urgent data in queue has changed - bool has_urgent_data = false, tag_found = false; - //search in unordered map in head - auto it = urgent_data.urgent_data_map.find(op.info.tag); - if (it != urgent_data.urgent_data_map.end()) { - it->second = op.info.time; - tag_found = true; - has_urgent_data = true; - } else { //search in xattrs - bufferlist bl_xattrs; - int ret = cls_cxx_getxattr(hctx, "cls_queue_urgent_data", &bl_xattrs); - if (ret < 0 && (ret != -ENOENT && ret != -ENODATA)) { - CLS_LOG(0, "ERROR: %s(): cls_cxx_getxattrs() returned %d", __func__, ret); - return ret; - } - if (ret != -ENOENT && ret != -ENODATA) { - std::unordered_map xattr_urgent_data_map; - auto iter = bl_xattrs.cbegin(); - try { - decode(xattr_urgent_data_map, iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_update_entry(): failed to decode xattrs urgent data map\n"); - return -EINVAL; - } //end - catch - auto xattr_iter = xattr_urgent_data_map.find(op.info.tag); - if (xattr_iter != xattr_urgent_data_map.end()) { - it->second = op.info.time; - tag_found = true; - //write the updated map back - bufferlist bl_map; - encode(xattr_urgent_data_map, bl_map); - ret = cls_cxx_setxattr(hctx, "cls_queue_urgent_data", &bl_map); - CLS_LOG(20, "%s(): setting attr: %s", __func__, "cls_queue_urgent_data"); - if (ret < 0) { - CLS_LOG(0, "ERROR: %s(): cls_cxx_setxattr (attr=%s) returned %d", __func__, "cls_queue_urgent_data", ret); - return ret; - } - } - }// end ret != ENOENT ... - } - - if (! tag_found) { - stringstream ss1; - ss1 << op.info.time; - CLS_LOG(1, "INFO: cls_gc_queue_update_entry(): time inserted in urgent data: %s\n", ss1.str().c_str()); - //try inserting in queue head - urgent_data.urgent_data_map.insert({op.info.tag, op.info.time}); - urgent_data.num_head_urgent_entries += 1; - has_urgent_data = true; - - bufferlist bl_urgent_data; - encode(urgent_data, bl_urgent_data); - //insert as xattrs - if (bl_urgent_data.length() > head.max_urgent_data_size) { - //remove inserted entry from urgent data - urgent_data.urgent_data_map.erase(op.info.tag); - urgent_data.num_head_urgent_entries -= 1; - has_urgent_data = false; - - bufferlist bl_xattrs; - int ret = cls_cxx_getxattr(hctx, "cls_queue_urgent_data", &bl_xattrs); - if (ret < 0 && (ret != -ENOENT && ret != -ENODATA)) { - CLS_LOG(0, "ERROR: %s(): cls_cxx_getxattrs() returned %d", __func__, ret); - return ret; - } - std::unordered_map xattr_urgent_data_map; - if (ret != -ENOENT && ret != -ENODATA) { - auto iter = bl_xattrs.cbegin(); - try { - decode(xattr_urgent_data_map, iter); - } catch (buffer::error& err) { - CLS_LOG(1, "ERROR: cls_gc_queue_remove(): failed to decode xattrs urgent data map\n"); - return -EINVAL; - } //end - catch - } - xattr_urgent_data_map.insert({op.info.tag, op.info.time}); - urgent_data.num_xattr_urgent_entries += 1; - has_urgent_data = true; - bufferlist bl_map; - encode(xattr_urgent_data_map, bl_map); - ret = cls_cxx_setxattr(hctx, "cls_queue_urgent_data", &bl_map); - CLS_LOG(20, "%s(): setting attr: %s", __func__, "cls_queue_urgent_data"); - if (ret < 0) { - CLS_LOG(0, "ERROR: %s(): cls_cxx_setxattr (attr=%s) returned %d", __func__, "cls_queue_urgent_data", ret); - return ret; - } - } - } - - if ((urgent_data.num_head_urgent_entries + urgent_data.num_xattr_urgent_entries) > urgent_data.num_urgent_data_entries) { - CLS_LOG(0, "Total num entries %u", urgent_data.num_urgent_data_entries); - CLS_LOG(0, "Num xattr entries %u", urgent_data.num_xattr_urgent_entries); - CLS_LOG(0, "Num head entries %u", urgent_data.num_head_urgent_entries); - CLS_LOG(0, "ERROR: Number of urgent data entries exceeded that requested by user, returning no space!"); - return -ENOSPC; - } - - cls_queue_enqueue_op enqueue_op; - bufferlist bl_data; - stringstream ss1; - ss1 << op.info.time; - CLS_LOG(1, "INFO: cls_gc_queue_update_entry(): time inserted in queue: %s\n", ss1.str().c_str()); - encode(op.info, bl_data); - enqueue_op.bl_data_vec.emplace_back(bl_data); - CLS_LOG(1, "INFO: cls_gc_update_entry: Data size is: %u \n", bl_data.length()); - - ret = enqueue(hctx, enqueue_op, head); - if (ret < 0) { - return ret; - } - - if (has_urgent_data) { - head.bl_urgent_data.clear(); - encode(urgent_data, head.bl_urgent_data); - } - - return write_queue_head(hctx, head); -} - -CLS_INIT(rgw_queue) -{ - CLS_LOG(1, "Loaded rgw queue class!"); - - cls_handle_t h_class; - cls_method_handle_t h_gc_init_queue; - cls_method_handle_t h_gc_enqueue; - cls_method_handle_t h_gc_queue_list_entries; - cls_method_handle_t h_gc_queue_remove_entries; - cls_method_handle_t h_gc_queue_update_entry; - - cls_register(RGW_QUEUE_CLASS, &h_class); - - /* gc */ - cls_register_cxx_method(h_class, GC_INIT_QUEUE, CLS_METHOD_RD | CLS_METHOD_WR, cls_gc_init_queue, &h_gc_init_queue); - cls_register_cxx_method(h_class, GC_ENQUEUE, CLS_METHOD_RD | CLS_METHOD_WR, cls_gc_enqueue, &h_gc_enqueue); - cls_register_cxx_method(h_class, GC_QUEUE_LIST_ENTRIES, CLS_METHOD_RD, cls_gc_queue_list, &h_gc_queue_list_entries); - cls_register_cxx_method(h_class, GC_QUEUE_REMOVE_ENTRIES, CLS_METHOD_RD | CLS_METHOD_WR, cls_gc_queue_remove, &h_gc_queue_remove_entries); - cls_register_cxx_method(h_class, GC_QUEUE_UPDATE_ENTRY, CLS_METHOD_RD | CLS_METHOD_WR, cls_gc_queue_update_entry, &h_gc_queue_update_entry); - - return; -} - diff --git a/src/cls/queue/cls_rgw_queue_ops.h b/src/cls/queue/cls_rgw_queue_ops.h deleted file mode 100644 index 78ea1af21b0..00000000000 --- a/src/cls/queue/cls_rgw_queue_ops.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef CEPH_CLS_RGW_QUEUE_OPS_H -#define CEPH_CLS_RGW_QUEUE_OPS_H - -#include "cls/rgw/cls_rgw_types.h" -#include "cls/rgw/cls_rgw_ops.h" - -struct cls_gc_init_queue_op { - uint64_t size; - uint64_t num_urgent_data_entries{0}; - string name; //for debugging, to be removed later - - cls_gc_init_queue_op() {} - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(size, bl); - encode(num_urgent_data_entries, bl); - encode(name, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(size, bl); - decode(num_urgent_data_entries, bl); - decode(name, bl); - DECODE_FINISH(bl); - } - -}; -WRITE_CLASS_ENCODER(cls_gc_init_queue_op) - -struct cls_rgw_gc_queue_remove_op { - uint64_t num_entries; - - cls_rgw_gc_queue_remove_op() {} - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(num_entries, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(num_entries, bl); - DECODE_FINISH(bl); - } -}; -WRITE_CLASS_ENCODER(cls_rgw_gc_queue_remove_op) - -struct cls_gc_defer_entry_op { - uint32_t expiration_secs; - cls_rgw_gc_obj_info info; - cls_gc_defer_entry_op() : expiration_secs(0) {} - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(expiration_secs, bl); - encode(info, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(expiration_secs, bl); - decode(info, bl); - DECODE_FINISH(bl); - } -}; -WRITE_CLASS_ENCODER(cls_gc_defer_entry_op) -#endif /* CEPH_CLS_RGW_QUEUE_OPS_H */ \ No newline at end of file diff --git a/src/cls/queue/cls_rgw_queue_types.h b/src/cls/queue/cls_rgw_queue_types.h deleted file mode 100644 index 95a7f00b134..00000000000 --- a/src/cls/queue/cls_rgw_queue_types.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef CEPH_CLS_RGW_QUEUE_TYPES_H -#define CEPH_CLS_RGW_QUEUE_TYPES_H - -#include "include/types.h" -#include "common/ceph_time.h" -#include "common/Formatter.h" - -#include - -struct cls_gc_urgent_data -{ - std::unordered_map urgent_data_map; - uint32_t num_urgent_data_entries{0}; // requested by user - uint32_t num_head_urgent_entries{0}; // actual number of entries in queue head - uint32_t num_xattr_urgent_entries{0}; // actual number of entries in xattr in case of spill over - - void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); - encode(urgent_data_map, bl); - encode(num_urgent_data_entries, bl); - encode(num_head_urgent_entries, bl); - encode(num_xattr_urgent_entries, bl); - ENCODE_FINISH(bl); - } - - void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); - decode(urgent_data_map, bl); - decode(num_urgent_data_entries, bl); - decode(num_head_urgent_entries, bl); - decode(num_xattr_urgent_entries, bl); - DECODE_FINISH(bl); - } -}; -WRITE_CLASS_ENCODER(cls_gc_urgent_data) - -#endif \ No newline at end of file diff --git a/src/cls/rgw_gc/cls_rgw_gc.cc b/src/cls/rgw_gc/cls_rgw_gc.cc new file mode 100644 index 00000000000..e8ddfd12053 --- /dev/null +++ b/src/cls/rgw_gc/cls_rgw_gc.cc @@ -0,0 +1,536 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "include/types.h" + +#include + +#include "objclass/objclass.h" +#include "cls/rgw/cls_rgw_ops.h" +#include "cls/rgw/cls_rgw_types.h" +#include "cls/rgw_gc/cls_rgw_gc_types.h" +#include "cls/rgw_gc/cls_rgw_gc_ops.h" +#include "cls/queue/cls_queue_ops.h" +#include "cls/rgw_gc/cls_rgw_gc_const.h" +#include "cls/queue/cls_queue_src.h" + +#include "common/ceph_context.h" +#include "global/global_context.h" + +#define dout_context g_ceph_context +#define dout_subsys ceph_subsys_rgw + +#define GC_LIST_DEFAULT_MAX 128 + +CLS_VER(1,0) +CLS_NAME(rgw_gc) + +static int cls_rgw_gc_queue_init(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + auto in_iter = in->cbegin(); + + cls_rgw_gc_queue_init_op op; + try { + decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_init: failed to decode entry\n"); + return -EINVAL; + } + + cls_rgw_gc_urgent_data urgent_data; + urgent_data.num_urgent_data_entries = op.num_urgent_data_entries; + + cls_queue_init_op init_op; + + CLS_LOG(10, "INFO: cls_rgw_gc_queue_init: queue size is %lu\n", op.size); + init_op.head.queue_size = op.size; + init_op.head_size = g_ceph_context->_conf->rgw_gc_queue_head_size; + init_op.has_urgent_data = true; + encode(urgent_data, init_op.head.bl_urgent_data); + + return queue_init(hctx, init_op); +} + +static int cls_rgw_gc_queue_enqueue(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + auto in_iter = in->cbegin(); + cls_rgw_gc_set_entry_op op; + try { + decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: cls_rgw_gc_queue_enqueue: failed to decode entry\n"); + return -EINVAL; + } + + op.info.time = ceph::real_clock::now(); + op.info.time += make_timespan(op.expiration_secs); + + //get head + cls_queue_head head; + int ret = queue_read_head(hctx, head); + if (ret < 0) { + return ret; + } + + cls_queue_enqueue_op enqueue_op; + bufferlist bl_data; + encode(op.info, bl_data); + enqueue_op.bl_data_vec.emplace_back(bl_data); + + CLS_LOG(20, "INFO: cls_rgw_gc_queue_enqueue: Data size is: %u \n", bl_data.length()); + + ret = queue_enqueue(hctx, enqueue_op, head); + if (ret < 0) { + return ret; + } + + //Write back head + return queue_write_head(hctx, head); +} + +static int cls_rgw_gc_queue_list_entries(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + auto in_iter = in->cbegin(); + cls_rgw_gc_list_op op; + try { + decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_list_entries(): failed to decode input\n"); + return -EINVAL; + } + + cls_queue_head head; + auto ret = queue_read_head(hctx, head); + if (ret < 0) { + return ret; + } + + cls_rgw_gc_urgent_data urgent_data; + if (head.bl_urgent_data.length() > 0) { + auto iter_urgent_data = head.bl_urgent_data.cbegin(); + try { + decode(urgent_data, iter_urgent_data); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_list_entries(): failed to decode urgent data\n"); + return -EINVAL; + } + } + + cls_queue_list_op list_op; + if (! op.max) { + op.max = GC_LIST_DEFAULT_MAX; + } + + list_op.max = op.max; + list_op.start_marker = op.marker; + + cls_rgw_gc_list_ret list_ret; + uint32_t num_entries = 0; //Entries excluding the deferred ones + bool is_truncated = true; + string next_marker; + do { + cls_queue_list_ret op_ret; + int ret = queue_list_entries(hctx, list_op, op_ret, head); + if (ret < 0) { + CLS_LOG(5, "ERROR: queue_list_entries(): returned error %d\n", ret); + return ret; + } + is_truncated = op_ret.is_truncated; + next_marker = op_ret.next_marker; + + if (op_ret.entries.size()) { + for (auto it : op_ret.entries) { + cls_rgw_gc_obj_info info; + try { + decode(info, it.data); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_list_entries(): failed to decode gc info\n"); + return -EINVAL; + } + bool found = false; + //Check for info tag in urgent data map + auto iter = urgent_data.urgent_data_map.find(info.tag); + if (iter != urgent_data.urgent_data_map.end()) { + found = true; + if (iter->second > info.time) { + CLS_LOG(10, "INFO: cls_rgw_gc_queue_list_entries(): tag found in urgent data: %s\n", info.tag.c_str()); + continue; + } + } + //Search in xattrs + if (! found && urgent_data.num_xattr_urgent_entries > 0) { + bufferlist bl_xattrs; + int ret = cls_cxx_getxattr(hctx, "cls_queue_urgent_data", &bl_xattrs); + if (ret < 0 && (ret != -ENOENT && ret != -ENODATA)) { + CLS_LOG(0, "ERROR: %s(): cls_cxx_getxattrs() returned %d", __func__, ret); + return ret; + } + if (ret != -ENOENT && ret != -ENODATA) { + std::unordered_map xattr_urgent_data_map; + auto iter = bl_xattrs.cbegin(); + try { + decode(xattr_urgent_data_map, iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: cls_rgw_gc_queue_list_entries(): failed to decode xattrs urgent data map\n"); + return -EINVAL; + } //end - catch + auto xattr_iter = xattr_urgent_data_map.find(info.tag); + if (xattr_iter != xattr_urgent_data_map.end()) { + if (xattr_iter->second > info.time) { + CLS_LOG(1, "INFO: cls_rgw_gc_queue_list_entries(): tag found in xattrs urgent data map: %s\n", info.tag.c_str()); + continue; + } + } + } // end - ret != ENOENT && ENODATA + } // end - if not found + if (op.expired_only) { + real_time now = ceph::real_clock::now(); + if (info.time <= now) { + list_ret.entries.emplace_back(info); + } + //Can break out here if info.time > now, since all subsequent entries won't have expired + } else { + list_ret.entries.emplace_back(info); + } + num_entries++; + } + CLS_LOG(10, "INFO: cls_rgw_gc_queue_list_entries(): num_entries: %u and op.max: %u\n", num_entries, op.max); + if (num_entries < op.max) { + list_op.max = (op.max - num_entries); + list_op.start_marker = op_ret.next_marker; + out->clear(); + } else { + //We've reached the max number of entries needed + break; + } + } else { + //We dont have data to process + break; + } + } while(is_truncated); + + list_ret.truncated = is_truncated; + if (list_ret.truncated) { + list_ret.next_marker = next_marker; + } + out->clear(); + encode(list_ret, *out); + return 0; +} + +static int cls_rgw_gc_queue_remove_entries(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + auto in_iter = in->cbegin(); + + cls_rgw_gc_queue_remove_entries_op op; + try { + decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_remove_entries(): failed to decode input\n"); + return -EINVAL; + } + + cls_queue_head head; + auto ret = queue_read_head(hctx, head); + if (ret < 0) { + return ret; + } + + cls_rgw_gc_urgent_data urgent_data; + if (head.bl_urgent_data.length() > 0) { + auto iter_urgent_data = head.bl_urgent_data.cbegin(); + try { + decode(urgent_data, iter_urgent_data); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_remove_entries(): failed to decode urgent data\n"); + return -EINVAL; + } + } + + // List entries and calculate total number of entries (including invalid entries) + if (! op.num_entries) { + op.num_entries = GC_LIST_DEFAULT_MAX; + } + cls_queue_list_op list_op; + list_op.max = op.num_entries + 1; // +1 to get the offset of last + 1 entry + bool is_truncated = true; + uint32_t total_num_entries = 0, num_entries = 0; + string end_marker; + do { + cls_queue_list_ret op_ret; + int ret = queue_list_entries(hctx, list_op, op_ret, head); + if (ret < 0) { + CLS_LOG(5, "ERROR: queue_list_entries(): returned error %d\n", ret); + return ret; + } + + is_truncated = op_ret.is_truncated; + unsigned int index = 0; + // If data is not empty + if (op_ret.entries.size()) { + for (auto it : op_ret.entries) { + cls_rgw_gc_obj_info info; + try { + decode(info, it.data); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_remove_entries(): failed to decode gc info\n"); + return -EINVAL; + } + CLS_LOG(20, "INFO: cls_rgw_gc_queue_remove_entries(): entry: %s\n", info.tag.c_str()); + total_num_entries++; + index++; + bool found = false; + //Search for tag in urgent data map + auto iter = urgent_data.urgent_data_map.find(info.tag); + if (iter != urgent_data.urgent_data_map.end()) { + found = true; + if (iter->second > info.time) { + CLS_LOG(10, "INFO: cls_rgw_gc_queue_remove_entries(): tag found in urgent data: %s\n", info.tag.c_str()); + continue; + } else if (iter->second == info.time) { + CLS_LOG(10, "INFO: cls_rgw_gc_queue_remove_entries(): erasing tag from urgent data: %s\n", info.tag.c_str()); + urgent_data.urgent_data_map.erase(info.tag); //erase entry from map, as it will be removed later from queue + urgent_data.num_head_urgent_entries -= 1; + } + }//end-if map end + if (! found && urgent_data.num_xattr_urgent_entries > 0) { + //Search in xattrs + bufferlist bl_xattrs; + int ret = cls_cxx_getxattr(hctx, "cls_queue_urgent_data", &bl_xattrs); + if (ret < 0 && (ret != -ENOENT && ret != -ENODATA)) { + CLS_LOG(0, "ERROR: %s(): cls_cxx_getxattrs() returned %d", __func__, ret); + return ret; + } + if (ret != -ENOENT && ret != -ENODATA) { + std::unordered_map xattr_urgent_data_map; + auto iter = bl_xattrs.cbegin(); + try { + decode(xattr_urgent_data_map, iter); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_remove_entries(): failed to decode xattrs urgent data map\n"); + return -EINVAL; + } //end - catch + auto xattr_iter = xattr_urgent_data_map.find(info.tag); + if (xattr_iter != xattr_urgent_data_map.end()) { + if (xattr_iter->second > info.time) { + CLS_LOG(10, "INFO: cls_rgw_gc_queue_remove_entries(): tag found in xattrs urgent data map: %s\n", info.tag.c_str()); + continue; + } else if (xattr_iter->second == info.time) { + CLS_LOG(10, "INFO: cls_rgw_gc_queue_remove_entries(): erasing tag from xattrs urgent data: %s\n", info.tag.c_str()); + xattr_urgent_data_map.erase(info.tag); //erase entry from map, as it will be removed later + urgent_data.num_xattr_urgent_entries -= 1; + } + } + } // end - ret != ENOENT && ENODATA + }// search in xattrs + num_entries++; + }//end-for + + if (num_entries < (op.num_entries + 1)) { + if (! op_ret.is_truncated) { + end_marker = op_ret.next_marker; + CLS_LOG(10, "INFO: cls_rgw_gc_queue_remove_entries(): not truncated and end offset is %s\n", end_marker.c_str()); + break; + } else { + list_op.max = ((op.num_entries + 1) - num_entries); + list_op.start_marker = op_ret.next_marker; + out->clear(); + } + } else { + end_marker = op_ret.entries[index - 1].marker; + CLS_LOG(1, "INFO: cls_rgw_gc_queue_remove_entries(): index is %u and end_offset is: %s\n", index, end_marker.c_str()); + break; + } + } //end-if + else { + break; + } + } while(is_truncated); + + CLS_LOG(10, "INFO: cls_rgw_gc_queue_remove_entries(): Total number of entries to remove: %d\n", total_num_entries); + CLS_LOG(10, "INFO: cls_rgw_gc_queue_remove_entries(): End offset is %s\n", end_marker.c_str()); + + if (! end_marker.empty()) { + cls_queue_remove_op rem_op; + rem_op.end_marker = end_marker; + int ret = queue_remove_entries(hctx, rem_op, head); + if (ret < 0) { + CLS_LOG(5, "ERROR: queue_remove_entries(): returned error %d\n", ret); + return ret; + } + } + + //Update urgent data map + encode(urgent_data, head.bl_urgent_data); + + return queue_write_head(hctx, head); +} + +static int cls_rgw_gc_queue_update_entry(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + int ret = 0; + auto in_iter = in->cbegin(); + + cls_rgw_gc_queue_defer_entry_op op; + try { + decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_update_entry(): failed to decode input\n"); + return -EINVAL; + } + + op.info.time = ceph::real_clock::now(); + op.info.time += make_timespan(op.expiration_secs); + + // Read head + cls_queue_head head; + ret = queue_read_head(hctx, head); + if (ret < 0) { + return ret; + } + + auto bl_iter = head.bl_urgent_data.cbegin(); + cls_rgw_gc_urgent_data urgent_data; + try { + decode(urgent_data, bl_iter); + } catch (buffer::error& err) { + CLS_LOG(5, "ERROR: cls_rgw_gc_queue_update_entry(): failed to decode urgent data\n"); + return -EINVAL; + } + + //has_urgent_data signifies whether urgent data in queue has changed + bool has_urgent_data = false, tag_found = false; + //search in unordered map in head + auto it = urgent_data.urgent_data_map.find(op.info.tag); + if (it != urgent_data.urgent_data_map.end()) { + it->second = op.info.time; + tag_found = true; + has_urgent_data = true; + } else { //search in xattrs + bufferlist bl_xattrs; + int ret = cls_cxx_getxattr(hctx, "cls_queue_urgent_data", &bl_xattrs); + if (ret < 0 && (ret != -ENOENT && ret != -ENODATA)) { + CLS_LOG(0, "ERROR: %s(): cls_cxx_getxattrs() returned %d", __func__, ret); + return ret; + } + if (ret != -ENOENT && ret != -ENODATA) { + std::unordered_map xattr_urgent_data_map; + auto iter = bl_xattrs.cbegin(); + try { + decode(xattr_urgent_data_map, iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: cls_rgw_gc_queue_update_entry(): failed to decode xattrs urgent data map\n"); + return -EINVAL; + } //end - catch + auto xattr_iter = xattr_urgent_data_map.find(op.info.tag); + if (xattr_iter != xattr_urgent_data_map.end()) { + it->second = op.info.time; + tag_found = true; + //write the updated map back + bufferlist bl_map; + encode(xattr_urgent_data_map, bl_map); + ret = cls_cxx_setxattr(hctx, "cls_queue_urgent_data", &bl_map); + CLS_LOG(20, "%s(): setting attr: %s", __func__, "cls_queue_urgent_data"); + if (ret < 0) { + CLS_LOG(0, "ERROR: %s(): cls_cxx_setxattr (attr=%s) returned %d", __func__, "cls_queue_urgent_data", ret); + return ret; + } + } + }// end ret != ENOENT ... + } + + if (! tag_found) { + //try inserting in queue head + urgent_data.urgent_data_map.insert({op.info.tag, op.info.time}); + urgent_data.num_head_urgent_entries += 1; + has_urgent_data = true; + + bufferlist bl_urgent_data; + encode(urgent_data, bl_urgent_data); + //insert as xattrs + if (bl_urgent_data.length() > head.max_urgent_data_size) { + //remove inserted entry from urgent data + urgent_data.urgent_data_map.erase(op.info.tag); + urgent_data.num_head_urgent_entries -= 1; + has_urgent_data = false; + + bufferlist bl_xattrs; + int ret = cls_cxx_getxattr(hctx, "cls_queue_urgent_data", &bl_xattrs); + if (ret < 0 && (ret != -ENOENT && ret != -ENODATA)) { + CLS_LOG(0, "ERROR: %s(): cls_cxx_getxattrs() returned %d", __func__, ret); + return ret; + } + std::unordered_map xattr_urgent_data_map; + if (ret != -ENOENT && ret != -ENODATA) { + auto iter = bl_xattrs.cbegin(); + try { + decode(xattr_urgent_data_map, iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: cls_rgw_gc_queue_remove_entries(): failed to decode xattrs urgent data map\n"); + return -EINVAL; + } //end - catch + } + xattr_urgent_data_map.insert({op.info.tag, op.info.time}); + urgent_data.num_xattr_urgent_entries += 1; + has_urgent_data = true; + bufferlist bl_map; + encode(xattr_urgent_data_map, bl_map); + ret = cls_cxx_setxattr(hctx, "cls_queue_urgent_data", &bl_map); + CLS_LOG(20, "%s(): setting attr: %s", __func__, "cls_queue_urgent_data"); + if (ret < 0) { + CLS_LOG(0, "ERROR: %s(): cls_cxx_setxattr (attr=%s) returned %d", __func__, "cls_queue_urgent_data", ret); + return ret; + } + } + } + + if ((urgent_data.num_head_urgent_entries + urgent_data.num_xattr_urgent_entries) > urgent_data.num_urgent_data_entries) { + CLS_LOG(20, "Total num entries %u", urgent_data.num_urgent_data_entries); + CLS_LOG(20, "Num xattr entries %u", urgent_data.num_xattr_urgent_entries); + CLS_LOG(20, "Num head entries %u", urgent_data.num_head_urgent_entries); + CLS_LOG(0, "ERROR: Number of urgent data entries exceeded that requested by user, returning no space!"); + return -ENOSPC; + } + + cls_queue_enqueue_op enqueue_op; + bufferlist bl_data; + encode(op.info, bl_data); + enqueue_op.bl_data_vec.emplace_back(bl_data); + CLS_LOG(10, "INFO: cls_gc_update_entry: Data size is: %u \n", bl_data.length()); + + ret = queue_enqueue(hctx, enqueue_op, head); + if (ret < 0) { + return ret; + } + + if (has_urgent_data) { + head.bl_urgent_data.clear(); + encode(urgent_data, head.bl_urgent_data); + } + + return queue_write_head(hctx, head); +} + +CLS_INIT(rgw_gc) +{ + CLS_LOG(1, "Loaded rgw gc class!"); + + cls_handle_t h_class; + cls_method_handle_t h_rgw_gc_queue_init; + cls_method_handle_t h_rgw_gc_queue_enqueue; + cls_method_handle_t h_rgw_gc_queue_list_entries; + cls_method_handle_t h_rgw_gc_queue_remove_entries; + cls_method_handle_t h_rgw_gc_queue_update_entry; + + cls_register(RGW_GC_CLASS, &h_class); + + /* gc */ + cls_register_cxx_method(h_class, RGW_GC_QUEUE_INIT, CLS_METHOD_RD | CLS_METHOD_WR, cls_rgw_gc_queue_init, &h_rgw_gc_queue_init); + cls_register_cxx_method(h_class, RGW_GC_QUEUE_ENQUEUE, CLS_METHOD_RD | CLS_METHOD_WR, cls_rgw_gc_queue_enqueue, &h_rgw_gc_queue_enqueue); + cls_register_cxx_method(h_class, RGW_GC_QUEUE_LIST_ENTRIES, CLS_METHOD_RD, cls_rgw_gc_queue_list_entries, &h_rgw_gc_queue_list_entries); + cls_register_cxx_method(h_class, RGW_GC_QUEUE_REMOVE_ENTRIES, CLS_METHOD_RD | CLS_METHOD_WR, cls_rgw_gc_queue_remove_entries, &h_rgw_gc_queue_remove_entries); + cls_register_cxx_method(h_class, RGW_GC_QUEUE_UPDATE_ENTRY, CLS_METHOD_RD | CLS_METHOD_WR, cls_rgw_gc_queue_update_entry, &h_rgw_gc_queue_update_entry); + + return; +} + diff --git a/src/cls/rgw_gc/cls_rgw_gc_client.cc b/src/cls/rgw_gc/cls_rgw_gc_client.cc new file mode 100644 index 00000000000..e7f98c232a7 --- /dev/null +++ b/src/cls/rgw_gc/cls_rgw_gc_client.cc @@ -0,0 +1,102 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +#include + +#include "cls/rgw/cls_rgw_ops.h" +#include "cls/rgw_gc/cls_rgw_gc_ops.h" +#include "cls/queue/cls_queue_ops.h" +#include "cls/rgw_gc/cls_rgw_gc_const.h" +#include "cls/queue/cls_queue_const.h" +#include "cls/rgw_gc/cls_rgw_gc_client.h" + +using namespace librados; + +void cls_rgw_gc_queue_init(ObjectWriteOperation& op, uint64_t size, uint64_t num_urgent_data_entries) +{ + bufferlist in; + cls_rgw_gc_queue_init_op call; + call.size = size; + call.num_urgent_data_entries = num_urgent_data_entries; + encode(call, in); + op.exec(RGW_GC_CLASS, RGW_GC_QUEUE_INIT, in); +} + +int cls_rgw_gc_queue_get_capacity(IoCtx& io_ctx, const string& oid, uint64_t& size) +{ + bufferlist in, out; + int r = io_ctx.exec(oid, QUEUE_CLASS, QUEUE_GET_CAPACITY, in, out); + if (r < 0) + return r; + + cls_queue_get_capacity_ret op_ret; + auto iter = out.cbegin(); + try { + decode(op_ret, iter); + } catch (buffer::error& err) { + return -EIO; + } + + size = op_ret.queue_capacity; + + return 0; +} + +void cls_rgw_gc_queue_enqueue(ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info) +{ + bufferlist in; + cls_rgw_gc_set_entry_op call; + call.expiration_secs = expiration_secs; + call.info = info; + encode(call, in); + op.exec(RGW_GC_CLASS, RGW_GC_QUEUE_ENQUEUE, in); +} + +int cls_rgw_gc_queue_list_entries(IoCtx& io_ctx, const string& oid, const string& marker, uint32_t max, bool expired_only, + list& entries, bool *truncated, string& next_marker) +{ + bufferlist in, out; + cls_rgw_gc_list_op op; + op.marker = marker; + op.max = max; + op.expired_only = expired_only; + encode(op, in); + + int r = io_ctx.exec(oid, RGW_GC_CLASS, RGW_GC_QUEUE_LIST_ENTRIES, in, out); + if (r < 0) + return r; + + cls_rgw_gc_list_ret ret; + auto iter = out.cbegin(); + try { + decode(ret, iter); + } catch (buffer::error& err) { + return -EIO; + } + + entries.swap(ret.entries); + + *truncated = ret.truncated; + + next_marker = std::move(ret.next_marker); + + return 0; +} + +void cls_rgw_gc_queue_remove_entries(ObjectWriteOperation& op, uint32_t num_entries) +{ + bufferlist in, out; + cls_rgw_gc_queue_remove_entries_op rem_op; + rem_op.num_entries = num_entries; + encode(rem_op, in); + op.exec(RGW_GC_CLASS, RGW_GC_QUEUE_REMOVE_ENTRIES, in); +} + +void cls_rgw_gc_queue_defer_entry(ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info) +{ + bufferlist in; + cls_rgw_gc_queue_defer_entry_op defer_op; + defer_op.expiration_secs = expiration_secs; + defer_op.info = info; + encode(defer_op, in); + op.exec(RGW_GC_CLASS, RGW_GC_QUEUE_UPDATE_ENTRY, in); +} diff --git a/src/cls/rgw_gc/cls_rgw_gc_client.h b/src/cls/rgw_gc/cls_rgw_gc_client.h new file mode 100644 index 00000000000..758c09b6aa1 --- /dev/null +++ b/src/cls/rgw_gc/cls_rgw_gc_client.h @@ -0,0 +1,17 @@ +#ifndef CEPH_CLS_RGW_GC_CLIENT_H +#define CEPH_CLS_RGW_GC_CLIENT_H + +#include "include/rados/librados.hpp" +#include "cls/rgw_gc/cls_rgw_gc_types.h" +#include "cls/queue/cls_queue_ops.h" +#include "common/ceph_time.h" + +void cls_rgw_gc_queue_init(librados::ObjectWriteOperation& op, uint64_t size, uint64_t num_urgent_data_entries); +int cls_rgw_gc_queue_get_capacity(librados::IoCtx& io_ctx, const string& oid, uint64_t& size); +void cls_rgw_gc_queue_enqueue(librados::ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info); +int cls_rgw_gc_queue_list_entries(librados::IoCtx& io_ctx, const string& oid, const string& marker, uint32_t max, bool expired_only, + list& entries, bool *truncated, string& next_marker); +void cls_rgw_gc_queue_remove_entries(librados::ObjectWriteOperation& op, uint32_t num_entries); +void cls_rgw_gc_queue_defer_entry(librados::ObjectWriteOperation& op, uint32_t expiration_secs, cls_rgw_gc_obj_info& info); + +#endif \ No newline at end of file diff --git a/src/cls/rgw_gc/cls_rgw_gc_const.h b/src/cls/rgw_gc/cls_rgw_gc_const.h new file mode 100644 index 00000000000..5a3d2b1d19e --- /dev/null +++ b/src/cls/rgw_gc/cls_rgw_gc_const.h @@ -0,0 +1,12 @@ +#ifndef CEPH_CLS_RGW_GC_CONSTS_H +#define CEPH_CLS_RGW_GC_CONSTS_H + +#define RGW_GC_CLASS "rgw_gc" + +#define RGW_GC_QUEUE_INIT "rgw_gc_queue_init" +#define RGW_GC_QUEUE_ENQUEUE "rgw_gc_queue_enqueue" +#define RGW_GC_QUEUE_LIST_ENTRIES "rgw_gc_queue_list_entries" +#define RGW_GC_QUEUE_REMOVE_ENTRIES "rgw_gc_queue_remove_entries" +#define RGW_GC_QUEUE_UPDATE_ENTRY "rgw_gc_queue_update_entry" + +#endif \ No newline at end of file diff --git a/src/cls/rgw_gc/cls_rgw_gc_ops.h b/src/cls/rgw_gc/cls_rgw_gc_ops.h new file mode 100644 index 00000000000..e51ff946ae1 --- /dev/null +++ b/src/cls/rgw_gc/cls_rgw_gc_ops.h @@ -0,0 +1,68 @@ +#ifndef CEPH_CLS_RGW_GC_OPS_H +#define CEPH_CLS_RGW_GC_OPS_H + +#include "cls/rgw/cls_rgw_types.h" + +struct cls_rgw_gc_queue_init_op { + uint64_t size; + uint64_t num_urgent_data_entries{0}; + + cls_rgw_gc_queue_init_op() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(size, bl); + encode(num_urgent_data_entries, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(size, bl); + decode(num_urgent_data_entries, bl); + DECODE_FINISH(bl); + } + +}; +WRITE_CLASS_ENCODER(cls_rgw_gc_queue_init_op) + +struct cls_rgw_gc_queue_remove_entries_op { + uint64_t num_entries; + + cls_rgw_gc_queue_remove_entries_op() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(num_entries, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(num_entries, bl); + DECODE_FINISH(bl); + } +}; +WRITE_CLASS_ENCODER(cls_rgw_gc_queue_remove_entries_op) + +struct cls_rgw_gc_queue_defer_entry_op { + uint32_t expiration_secs; + cls_rgw_gc_obj_info info; + cls_rgw_gc_queue_defer_entry_op() : expiration_secs(0) {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(expiration_secs, bl); + encode(info, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(expiration_secs, bl); + decode(info, bl); + DECODE_FINISH(bl); + } +}; +WRITE_CLASS_ENCODER(cls_rgw_gc_queue_defer_entry_op) +#endif /* CEPH_CLS_RGW_GC_OPS_H */ \ No newline at end of file diff --git a/src/cls/rgw_gc/cls_rgw_gc_types.h b/src/cls/rgw_gc/cls_rgw_gc_types.h new file mode 100644 index 00000000000..cfcac55f5be --- /dev/null +++ b/src/cls/rgw_gc/cls_rgw_gc_types.h @@ -0,0 +1,34 @@ +#ifndef CEPH_CLS_RGW_GC_TYPES_H +#define CEPH_CLS_RGW_GC_TYPES_H + +#include "include/types.h" +#include + +struct cls_rgw_gc_urgent_data +{ + std::unordered_map urgent_data_map; + uint32_t num_urgent_data_entries{0}; // requested by user + uint32_t num_head_urgent_entries{0}; // actual number of entries in queue head + uint32_t num_xattr_urgent_entries{0}; // actual number of entries in xattr in case of spill over + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(urgent_data_map, bl); + encode(num_urgent_data_entries, bl); + encode(num_head_urgent_entries, bl); + encode(num_xattr_urgent_entries, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(urgent_data_map, bl); + decode(num_urgent_data_entries, bl); + decode(num_head_urgent_entries, bl); + decode(num_xattr_urgent_entries, bl); + DECODE_FINISH(bl); + } +}; +WRITE_CLASS_ENCODER(cls_rgw_gc_urgent_data) + +#endif \ No newline at end of file diff --git a/src/osd/CMakeLists.txt b/src/osd/CMakeLists.txt index 080b07cdda0..d21e93164f1 100644 --- a/src/osd/CMakeLists.txt +++ b/src/osd/CMakeLists.txt @@ -70,5 +70,5 @@ if(WITH_RBD) add_dependencies(osd cls_rbd) endif() if(WITH_RADOSGW) - add_dependencies(osd cls_otp cls_rgw cls_queue) + add_dependencies(osd cls_otp cls_rgw cls_queue cls_rgw_gc) endif() diff --git a/src/rgw/CMakeLists.txt b/src/rgw/CMakeLists.txt index 730d004cf29..fb17473bc93 100644 --- a/src/rgw/CMakeLists.txt +++ b/src/rgw/CMakeLists.txt @@ -214,7 +214,7 @@ target_link_libraries(rgw_a PRIVATE librados cls_otp_client cls_lock_client cls_rgw_client cls_refcount_client cls_log_client cls_timeindex_client cls_version_client - cls_user_client cls_queue_client ceph-common common_utf8 global + cls_user_client cls_rgw_gc_client ceph-common common_utf8 global ${CURL_LIBRARIES} ${EXPAT_LIBRARIES} ${OPENLDAP_LIBRARIES} ${CRYPTO_LIBS} @@ -371,7 +371,7 @@ target_link_libraries(rgw_admin_user PRIVATE cls_timeindex_client cls_version_client cls_user_client - cls_queue_client + cls_rgw_gc_client global ${CURL_LIBRARIES} ${EXPAT_LIBRARIES} diff --git a/src/rgw/rgw_gc.cc b/src/rgw/rgw_gc.cc index fbc7b4589ee..04be90cf837 100644 --- a/src/rgw/rgw_gc.cc +++ b/src/rgw/rgw_gc.cc @@ -7,7 +7,7 @@ #include "include/scope_guard.h" #include "include/rados/librados.hpp" #include "cls/rgw/cls_rgw_client.h" -#include "cls/queue/cls_queue_client.h" +#include "cls/rgw_gc/cls_rgw_gc_client.h" #include "cls/refcount/cls_refcount_client.h" #include "rgw_perf_counters.h" #include "cls/lock/cls_lock_client.h" @@ -46,7 +46,7 @@ void RGWGC::initialize(CephContext *_cct, RGWRados *_store) { librados::ObjectWriteOperation op; op.create(true); uint64_t queue_size = 1048576, num_urgent_data_entries = 50; - cls_rgw_gc_init_queue(op, obj_names[i], queue_size, num_urgent_data_entries); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); store->gc_operate(obj_names[i], &op); } } @@ -68,7 +68,7 @@ void RGWGC::add_chain(ObjectWriteOperation& op, cls_rgw_obj_chain& chain, const info.tag = tag; //cls_rgw_gc_set_entry(op, cct->_conf->rgw_gc_obj_min_wait, info); - cls_rgw_gc_enqueue(op, cct->_conf->rgw_gc_obj_min_wait, info); + cls_rgw_gc_queue_enqueue(op, cct->_conf->rgw_gc_obj_min_wait, info); } int RGWGC::send_chain(cls_rgw_obj_chain& chain, const string& tag, bool sync) @@ -93,7 +93,7 @@ int RGWGC::defer_chain(const string& tag, cls_rgw_obj_chain& chain, bool sync) ObjectWriteOperation op; //cls_rgw_gc_defer_entry(op, cct->_conf->rgw_gc_obj_min_wait, tag); - cls_rgw_gc_defer_entry_queue(op, cct->_conf->rgw_gc_obj_min_wait, info); + cls_rgw_gc_queue_defer_entry(op, cct->_conf->rgw_gc_obj_min_wait, info); int i = tag_index(tag); @@ -113,7 +113,7 @@ int RGWGC::remove(int index, const std::vector& tags, AioCompletion **pc int RGWGC::remove(int index, int num_entries, librados::AioCompletion **pc) { ObjectWriteOperation op; - cls_rgw_gc_remove_entries_queue(op, num_entries); + cls_rgw_gc_queue_remove_entries(op, num_entries); return store->gc_aio_operate(obj_names[index], &op, pc); } @@ -125,7 +125,7 @@ int RGWGC::list(int *index, string& marker, uint32_t max, bool expired_only, std for (; *index < max_objs && result.size() < max; (*index)++, marker.clear()) { std::list entries; //int ret = cls_rgw_gc_list(store->gc_pool_ctx, obj_names[*index], marker, max - result.size(), expired_only, entries, truncated, next_marker); - int ret = cls_rgw_gc_list_queue(store->gc_pool_ctx, obj_names[*index], marker, max - result.size(), expired_only, entries, truncated, next_marker); + int ret = cls_rgw_gc_queue_list_entries(store->gc_pool_ctx, obj_names[*index], marker, max - result.size(), expired_only, entries, truncated, next_marker); if (ret == -ENOENT) continue; if (ret < 0) @@ -393,9 +393,9 @@ int RGWGC::process(int index, int max_secs, bool expired_only, //ret = cls_rgw_gc_list(store->gc_pool_ctx, obj_names[index], marker, max, // expired_only, entries, &truncated, next_marker); - ret = cls_rgw_gc_list_queue(store->gc_pool_ctx, obj_names[index], marker, max, expired_only, entries, &truncated, next_marker); + ret = cls_rgw_gc_queue_list_entries(store->gc_pool_ctx, obj_names[index], marker, max, expired_only, entries, &truncated, next_marker); ldpp_dout(this, 20) << - "RGWGC::process cls_rgw_gc_list_queue returned with returned:" << ret << + "RGWGC::process cls_rgw_gc_queue_list_entries returned with returned:" << ret << ", entries.size=" << entries.size() << ", truncated=" << truncated << ", next_marker='" << next_marker << "'" << dendl; diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 7830fd2222e..363935d01e7 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -4619,7 +4619,7 @@ int RGWRados::defer_gc(void *ctx, const RGWBucketInfo& bucket_info, const rgw_ob ldout(cct, 0) << "defer chain tag=" << tag << dendl; cls_rgw_obj_chain chain; - update_gc_chain(state->obj, state->manifest, &chain); + update_gc_chain(state->obj, *state->manifest, &chain); return gc->defer_chain(tag, chain, false); } diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index e6829f59302..19ba0d53a2e 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -20,7 +20,7 @@ add_subdirectory(cls_refcount) add_subdirectory(cls_rgw) add_subdirectory(cls_version) add_subdirectory(cls_lua) -add_subdirectory(cls_queue) +add_subdirectory(cls_rgw_gc) add_subdirectory(common) add_subdirectory(compressor) add_subdirectory(crush) diff --git a/src/test/cls_queue/CMakeLists.txt b/src/test/cls_queue/CMakeLists.txt deleted file mode 100644 index 2898df836a7..00000000000 --- a/src/test/cls_queue/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -if(${WITH_RADOSGW}) - add_executable(ceph_test_cls_queue - test_cls_queue.cc - ) - target_link_libraries(ceph_test_cls_queue - cls_queue_client - librados - global - ${UNITTEST_LIBS} - ${EXTRALIBS} - ${BLKID_LIBRARIES} - ${CMAKE_DL_LIBS} - radostest-cxx) - install(TARGETS - ceph_test_cls_queue - DESTINATION ${CMAKE_INSTALL_BINDIR}) -endif(${WITH_RADOSGW}) - diff --git a/src/test/cls_queue/test_cls_queue.cc b/src/test/cls_queue/test_cls_queue.cc deleted file mode 100644 index b8d4bae1f17..00000000000 --- a/src/test/cls_queue/test_cls_queue.cc +++ /dev/null @@ -1,697 +0,0 @@ -// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "include/types.h" - -#include "cls/rgw/cls_rgw_types.h" -#include "cls/queue/cls_queue_client.h" -#include "cls/queue/cls_queue_ops.h" - -#include "gtest/gtest.h" -#include "test/librados/test_cxx.h" -#include "global/global_context.h" - -#include -#include -#include -#include -#include - -using namespace librados; - -librados::Rados rados; -librados::IoCtx ioctx; -string pool_name; - - -/* must be the first test! */ -TEST(cls_queue, init) -{ - pool_name = get_temp_pool_name(); - /* create pool */ - ASSERT_EQ("", create_one_pool_pp(pool_name, rados)); - ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); -} - - -string str_int(string s, int i) -{ - char buf[32]; - snprintf(buf, sizeof(buf), "-%d", i); - s.append(buf); - - return s; -} - -/* test garbage collection */ -static void create_obj(cls_rgw_obj& obj, int i, int j) -{ - char buf[32]; - snprintf(buf, sizeof(buf), "-%d.%d", i, j); - obj.pool = "pool"; - obj.pool.append(buf); - obj.key.name = "oid"; - obj.key.name.append(buf); - obj.loc = "loc"; - obj.loc.append(buf); -} - -TEST(cls_queue, gc_queue_ops1) -{ - //Testing queue ops when data size is NOT a multiple of queue size - string queue_name = "my-queue"; - uint64_t queue_size = 322, num_urgent_data_entries = 10; - librados::ObjectWriteOperation op; - op.create(true); - cls_rgw_gc_init_queue(op, queue_name, queue_size, num_urgent_data_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - - uint64_t size = 0; - int ret = cls_rgw_gc_get_queue_size(ioctx, queue_name, size); - ASSERT_EQ(0, ret); - ASSERT_EQ(queue_size, size); - - //Test enqueue - for (int i = 0; i < 2; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - cls_rgw_gc_enqueue(op, 0, info); - if (i == 1) { - ASSERT_EQ(-ENOSPC, ioctx.operate(queue_name, &op)); - } else { - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - } - } - - //Test remove queue entries - librados::ObjectWriteOperation remove_op; - string marker1; - uint64_t num_entries = 1; - cls_rgw_gc_remove_entries_queue(remove_op, num_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); - - //Test enqueue again - for (int i = 0; i < 1; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - cls_rgw_gc_enqueue(op, 0, info); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - } - - //Test list queue - list list_info1; - string marker, next_marker; - uint64_t max = 1; - bool expired_only = false, truncated; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); - ASSERT_EQ(1, list_info1.size()); - - for (auto it : list_info1) { - std::cerr << "[ ] list info tag = " << it.tag << std::endl; - ASSERT_EQ("chain-0", it.tag); - } -} - -TEST(cls_queue, gc_queue_ops2) -{ - //Testing list queue - string queue_name = "my-second-queue"; - uint64_t queue_size = 334, num_urgent_data_entries = 10; - librados::ObjectWriteOperation op; - op.create(true); - cls_rgw_gc_init_queue(op, queue_name, queue_size, num_urgent_data_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - - uint64_t size = 0; - int ret = cls_rgw_gc_get_queue_size(ioctx, queue_name, size); - ASSERT_EQ(0, ret); - ASSERT_EQ(size, queue_size); - - //Test list queue, when queue is empty - list list_info; - string marker1, next_marker1; - uint64_t max1 = 2; - bool expired_only1 = false, truncated1; - cls_rgw_gc_list_queue(ioctx, queue_name, marker1, max1, expired_only1, list_info, &truncated1, next_marker1); - ASSERT_EQ(0, list_info.size()); - - //Test enqueue - for (int i = 0; i < 3; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - cls_rgw_gc_enqueue(op, 0, info); - if (i == 2) { - ASSERT_EQ(-ENOSPC, ioctx.operate(queue_name, &op)); - } else { - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - } - } - - //Test list queue - list list_info1, list_info2, list_info3; - string marker, next_marker; - uint64_t max = 2; - bool expired_only = false, truncated; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); - ASSERT_EQ(2, list_info1.size()); - - int i = 0; - for (auto it : list_info1) { - string tag = "chain-" + to_string(i); - ASSERT_EQ(tag, it.tag); - i++; - } - - max = 1; - truncated = false; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info2, &truncated, next_marker); - auto it = list_info2.front(); - ASSERT_EQ(1, list_info2.size()); - ASSERT_EQ(true, truncated); - ASSERT_EQ("chain-0", it.tag); - std::cerr << "[ ] next_marker is: = " << next_marker << std::endl; - - marker = next_marker; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info3, &truncated, next_marker); - it = list_info3.front(); - ASSERT_EQ(1, list_info3.size()); - ASSERT_EQ(false, truncated); - ASSERT_EQ("chain-1", it.tag); -} - -TEST(cls_queue, gc_queue_ops3) -{ - //Testing remove queue entries - string queue_name = "my-third-queue"; - uint64_t queue_size = 501, num_urgent_data_entries = 10; - librados::ObjectWriteOperation op; - op.create(true); - cls_rgw_gc_init_queue(op, queue_name, queue_size, num_urgent_data_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - - uint64_t size = 0; - int ret = cls_rgw_gc_get_queue_size(ioctx, queue_name, size); - ASSERT_EQ(0, ret); - ASSERT_EQ(size, queue_size); - - //Test remove queue, when queue is empty - librados::ObjectWriteOperation remove_op; - string marker1; - uint64_t num_entries = 2; - cls_rgw_gc_remove_entries_queue(remove_op, num_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); - - cls_rgw_gc_obj_info defer_info; - - //Test enqueue - for (int i = 0; i < 2; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - cls_rgw_gc_enqueue(op, 5, info); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - if (i == 0) - defer_info = info; - } - - //Test defer entry for 1st element - librados::ObjectWriteOperation defer_op; - cls_rgw_gc_defer_entry_queue(defer_op, 10, defer_info); - ASSERT_EQ(0, ioctx.operate(queue_name, &defer_op)); - - //Test list queue - list list_info1, list_info2; - string marker, next_marker; - uint64_t max = 2; - bool expired_only = false, truncated; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); - ASSERT_EQ(2, list_info1.size()); - - int i = 0; - for (auto it : list_info1) { - std::cerr << "[ ] list info tag = " << it.tag << std::endl; - if (i == 0) { - ASSERT_EQ("chain-1", it.tag); - } - if (i == 1) { - ASSERT_EQ("chain-0", it.tag); - } - i++; - } - - //Test remove entries - num_entries = 2; - cls_rgw_gc_remove_entries_queue(remove_op, num_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); - - //Test list queue again - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info2, &truncated, next_marker); - ASSERT_EQ(0, list_info2.size()); - -} - -TEST(cls_queue, gc_queue_ops4) -{ - //Testing remove queue entries - string queue_name = "my-fourth-queue"; - uint64_t queue_size = 501, num_urgent_data_entries = 10; - librados::ObjectWriteOperation op; - op.create(true); - cls_rgw_gc_init_queue(op, queue_name, queue_size, num_urgent_data_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - - uint64_t size = 0; - int ret = cls_rgw_gc_get_queue_size(ioctx, queue_name, size); - ASSERT_EQ(0, ret); - ASSERT_EQ(size, queue_size); - - //Test remove queue, when queue is empty - librados::ObjectWriteOperation remove_op; - string marker1; - uint64_t num_entries = 2; - - cls_rgw_gc_remove_entries_queue(remove_op, num_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); - - cls_rgw_gc_obj_info defer_info; - - //Test enqueue - for (int i = 0; i < 2; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - cls_rgw_gc_enqueue(op, 5, info); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - defer_info = info; - } - - //Test defer entry for last element - librados::ObjectWriteOperation defer_op; - cls_rgw_gc_defer_entry_queue(defer_op, 10, defer_info); - ASSERT_EQ(0, ioctx.operate(queue_name, &defer_op)); - - //Test list queue - list list_info1, list_info2; - string marker, next_marker; - uint64_t max = 2; - bool expired_only = false, truncated; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); - ASSERT_EQ(2, list_info1.size()); - - int i = 0; - for (auto it : list_info1) { - string tag = "chain-" + to_string(i); - ASSERT_EQ(tag, it.tag); - i++; - } - - //Test remove entries - num_entries = 2; - cls_rgw_gc_remove_entries_queue(remove_op, num_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); - - //Test list queue again - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info2, &truncated, next_marker); - ASSERT_EQ(0, list_info2.size()); - -} - -TEST(cls_queue, gc_queue_ops5) -{ - //Testing remove queue entries - string queue_name = "my-fifth-queue"; - uint64_t queue_size = 501, num_urgent_data_entries = 10; - librados::ObjectWriteOperation op; - op.create(true); - cls_rgw_gc_init_queue(op, queue_name, queue_size, num_urgent_data_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - - uint64_t size = 0; - int ret = cls_rgw_gc_get_queue_size(ioctx, queue_name, size); - ASSERT_EQ(0, ret); - ASSERT_EQ(size, queue_size); - - //Test enqueue - for (int i = 0; i < 3; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - if (i == 2) { - cls_rgw_gc_enqueue(op, 300, info); - } else { - cls_rgw_gc_enqueue(op, 0, info); - } - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - } - //Test list queue for expired entries only - list list_info1, list_info2; - string marker, next_marker, marker1; - uint64_t max = 10; - bool expired_only = true, truncated; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); - ASSERT_EQ(2, list_info1.size()); - - int i = 0; - for (auto it : list_info1) { - string tag = "chain-" + to_string(i); - ASSERT_EQ(tag, it.tag); - i++; - } - - //Test remove entries - librados::ObjectWriteOperation remove_op; - auto num_entries = list_info1.size(); - cls_rgw_gc_remove_entries_queue(remove_op, num_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); - - //Test list queue again for all entries - expired_only = false; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info2, &truncated, next_marker); - ASSERT_EQ(1, list_info2.size()); - -} - -TEST(cls_queue, gc_queue_ops6) -{ - //Testing list queue, when data size is split at the end of the queue - string queue_name = "my-sixth-queue"; - uint64_t queue_size = 341, num_urgent_data_entries = 10; - librados::ObjectWriteOperation op; - op.create(true); - cls_rgw_gc_init_queue(op, queue_name, queue_size, num_urgent_data_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - - uint64_t size = 0; - int ret = cls_rgw_gc_get_queue_size(ioctx, queue_name, size); - ASSERT_EQ(0, ret); - ASSERT_EQ(size, queue_size); - - //Test enqueue - for (int i = 0; i < 2; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - cls_rgw_gc_enqueue(op, 0, info); - - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - } - - //Remove one element from queue - librados::ObjectWriteOperation remove_op; - string marker1; - uint64_t num_entries = 1; - - cls_rgw_gc_remove_entries_queue(remove_op, num_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); - - //Enqueue one more element - librados::ObjectWriteOperation enq_op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, 2, 1); - create_obj(obj2, 2, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = "chain-2"; - cls_rgw_gc_enqueue(enq_op, 0, info); - - ASSERT_EQ(0, ioctx.operate(queue_name, &enq_op)); - - //Test list queue - list list_info1, list_info2, list_info3; - string marker, next_marker; - uint64_t max = 2; - bool expired_only = false, truncated; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); - ASSERT_EQ(2, list_info1.size()); - - int i = 1; - for (auto it : list_info1) { - string tag = "chain-" + to_string(i); - ASSERT_EQ(tag, it.tag); - i++; - } -} - -TEST(cls_queue, gc_queue_ops7) -{ - //Testing list queue, when data size is written at the end of queue and data is written after wrap around - string queue_name = "my-seventh-queue"; - uint64_t queue_size = 342, num_urgent_data_entries = 10; - librados::ObjectWriteOperation op; - op.create(true); - cls_rgw_gc_init_queue(op, queue_name, queue_size, num_urgent_data_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - - uint64_t size = 0; - int ret = cls_rgw_gc_get_queue_size(ioctx, queue_name, size); - ASSERT_EQ(0, ret); - ASSERT_EQ(size, queue_size); - - //Test enqueue - for (int i = 0; i < 2; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - cls_rgw_gc_enqueue(op, 0, info); - - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - } - - //Remove one element from queue - librados::ObjectWriteOperation remove_op; - string marker1; - uint64_t num_entries = 1; - - cls_rgw_gc_remove_entries_queue(remove_op, num_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); - - //Enqueue one more element - librados::ObjectWriteOperation enq_op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, 2, 1); - create_obj(obj2, 2, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = "chain-2"; - cls_rgw_gc_enqueue(enq_op, 0, info); - - ASSERT_EQ(0, ioctx.operate(queue_name, &enq_op)); - - //Test list queue - list list_info1, list_info2, list_info3; - string marker, next_marker; - uint64_t max = 2; - bool expired_only = false, truncated; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); - ASSERT_EQ(2, list_info1.size()); - - int i = 1; - for (auto it : list_info1) { - string tag = "chain-" + to_string(i); - ASSERT_EQ(tag, it.tag); - i++; - } -} - -TEST(cls_queue, gc_queue_ops8) -{ - //Testing list queue, when data is split at the end of the queue - string queue_name = "my-eighth-queue"; - uint64_t queue_size = 344, num_urgent_data_entries = 10; - librados::ObjectWriteOperation op; - op.create(true); - cls_rgw_gc_init_queue(op, queue_name, queue_size, num_urgent_data_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - - uint64_t size = 0; - int ret = cls_rgw_gc_get_queue_size(ioctx, queue_name, size); - ASSERT_EQ(0, ret); - ASSERT_EQ(size, queue_size); - - //Test enqueue - for (int i = 0; i < 2; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - cls_rgw_gc_enqueue(op, 0, info); - - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - } - - //Remove one element from queue - librados::ObjectWriteOperation remove_op; - string marker1; - uint64_t num_entries = 1; - - cls_rgw_gc_remove_entries_queue(remove_op, num_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); - - //Enqueue one more element - librados::ObjectWriteOperation enq_op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, 2, 1); - create_obj(obj2, 2, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = "chain-2"; - cls_rgw_gc_enqueue(enq_op, 0, info); - - ASSERT_EQ(0, ioctx.operate(queue_name, &enq_op)); - - //Test list queue - list list_info1, list_info2, list_info3; - string marker, next_marker; - uint64_t max = 2; - bool expired_only = false, truncated; - cls_rgw_gc_list_queue(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); - ASSERT_EQ(2, list_info1.size()); - - int i = 1; - for (auto it : list_info1) { - string tag = "chain-" + to_string(i); - ASSERT_EQ(tag, it.tag); - i++; - } -} - -TEST(cls_queue, gc_queue_ops9) -{ - //Testing remove queue entries - string queue_name = "my-ninth-queue"; - uint64_t queue_size = 668, num_urgent_data_entries = 1; - librados::ObjectWriteOperation op; - op.create(true); - cls_rgw_gc_init_queue(op, queue_name, queue_size, num_urgent_data_entries); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - - uint64_t size = 0; - int ret = cls_rgw_gc_get_queue_size(ioctx, queue_name, size); - ASSERT_EQ(0, ret); - ASSERT_EQ(size, queue_size); - - cls_rgw_gc_obj_info defer_info1, defer_info2; - - //Test enqueue - for (int i = 0; i < 2; i++) { - string tag = "chain-" + to_string(i); - librados::ObjectWriteOperation op; - cls_rgw_gc_obj_info info; - - cls_rgw_obj obj1, obj2; - create_obj(obj1, i, 1); - create_obj(obj2, i, 2); - info.chain.objs.push_back(obj1); - info.chain.objs.push_back(obj2); - - info.tag = tag; - cls_rgw_gc_enqueue(op, 5, info); - ASSERT_EQ(0, ioctx.operate(queue_name, &op)); - if (i == 0) { - defer_info1 = info; - } - if (i == 1) { - defer_info2 = info; - } - } - - //Test defer entry for last element - librados::ObjectWriteOperation defer_op; - cls_rgw_gc_defer_entry_queue(defer_op, 10, defer_info2); - ASSERT_EQ(0, ioctx.operate(queue_name, &defer_op)); - - //Test defer entry for first element - cls_rgw_gc_defer_entry_queue(defer_op, 10, defer_info1); - ASSERT_EQ(-ENOSPC, ioctx.operate(queue_name, &defer_op)); -} - -/* must be last test! */ -TEST(cls_queue, finalize) -{ - /* remove pool */ - ioctx.close(); - ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados)); -} diff --git a/src/test/cls_rgw_gc/CMakeLists.txt b/src/test/cls_rgw_gc/CMakeLists.txt new file mode 100644 index 00000000000..dd16615253b --- /dev/null +++ b/src/test/cls_rgw_gc/CMakeLists.txt @@ -0,0 +1,18 @@ +if(${WITH_RADOSGW}) + add_executable(ceph_test_cls_rgw_gc + test_cls_rgw_gc.cc + ) + target_link_libraries(ceph_test_cls_rgw_gc + cls_rgw_gc_client + librados + global + ${UNITTEST_LIBS} + ${EXTRALIBS} + ${BLKID_LIBRARIES} + ${CMAKE_DL_LIBS} + radostest-cxx) + install(TARGETS + ceph_test_cls_rgw_gc + DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif(${WITH_RADOSGW}) + diff --git a/src/test/cls_rgw_gc/test_cls_rgw_gc.cc b/src/test/cls_rgw_gc/test_cls_rgw_gc.cc new file mode 100644 index 00000000000..387083f27fc --- /dev/null +++ b/src/test/cls_rgw_gc/test_cls_rgw_gc.cc @@ -0,0 +1,697 @@ +// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "include/types.h" + +#include "cls/rgw/cls_rgw_types.h" +#include "cls/rgw_gc/cls_rgw_gc_client.h" +#include "cls/rgw_gc/cls_rgw_gc_ops.h" + +#include "gtest/gtest.h" +#include "test/librados/test_cxx.h" +#include "global/global_context.h" + +#include +#include +#include +#include +#include + +using namespace librados; + +librados::Rados rados; +librados::IoCtx ioctx; +string pool_name; + + +/* must be the first test! */ +TEST(cls_rgw_gc, init) +{ + pool_name = get_temp_pool_name(); + /* create pool */ + ASSERT_EQ("", create_one_pool_pp(pool_name, rados)); + ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); +} + + +string str_int(string s, int i) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "-%d", i); + s.append(buf); + + return s; +} + +/* test garbage collection */ +static void create_obj(cls_rgw_obj& obj, int i, int j) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "-%d.%d", i, j); + obj.pool = "pool"; + obj.pool.append(buf); + obj.key.name = "oid"; + obj.key.name.append(buf); + obj.loc = "loc"; + obj.loc.append(buf); +} + +TEST(cls_rgw_gc, gc_queue_ops1) +{ + //Testing queue ops when data size is NOT a multiple of queue size + string queue_name = "my-queue"; + uint64_t queue_size = 322, num_urgent_data_entries = 10; + librados::ObjectWriteOperation op; + op.create(true); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + + uint64_t size = 0; + int ret = cls_rgw_gc_queue_get_capacity(ioctx, queue_name, size); + ASSERT_EQ(0, ret); + ASSERT_EQ(queue_size, size); + + //Test enqueue + for (int i = 0; i < 2; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + cls_rgw_gc_queue_enqueue(op, 0, info); + if (i == 1) { + ASSERT_EQ(-ENOSPC, ioctx.operate(queue_name, &op)); + } else { + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + } + } + + //Test remove queue entries + librados::ObjectWriteOperation remove_op; + string marker1; + uint64_t num_entries = 1; + cls_rgw_gc_queue_remove_entries(remove_op, num_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); + + //Test enqueue again + for (int i = 0; i < 1; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + cls_rgw_gc_queue_enqueue(op, 0, info); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + } + + //Test list queue + list list_info1; + string marker, next_marker; + uint64_t max = 1; + bool expired_only = false, truncated; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); + ASSERT_EQ(1, list_info1.size()); + + for (auto it : list_info1) { + std::cerr << "[ ] list info tag = " << it.tag << std::endl; + ASSERT_EQ("chain-0", it.tag); + } +} + +TEST(cls_rgw_gc, gc_queue_ops2) +{ + //Testing list queue + string queue_name = "my-second-queue"; + uint64_t queue_size = 334, num_urgent_data_entries = 10; + librados::ObjectWriteOperation op; + op.create(true); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + + uint64_t size = 0; + int ret = cls_rgw_gc_queue_get_capacity(ioctx, queue_name, size); + ASSERT_EQ(0, ret); + ASSERT_EQ(size, queue_size); + + //Test list queue, when queue is empty + list list_info; + string marker1, next_marker1; + uint64_t max1 = 2; + bool expired_only1 = false, truncated1; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker1, max1, expired_only1, list_info, &truncated1, next_marker1); + ASSERT_EQ(0, list_info.size()); + + //Test enqueue + for (int i = 0; i < 3; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + cls_rgw_gc_queue_enqueue(op, 0, info); + if (i == 2) { + ASSERT_EQ(-ENOSPC, ioctx.operate(queue_name, &op)); + } else { + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + } + } + + //Test list queue + list list_info1, list_info2, list_info3; + string marker, next_marker; + uint64_t max = 2; + bool expired_only = false, truncated; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); + ASSERT_EQ(2, list_info1.size()); + + int i = 0; + for (auto it : list_info1) { + string tag = "chain-" + to_string(i); + ASSERT_EQ(tag, it.tag); + i++; + } + + max = 1; + truncated = false; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info2, &truncated, next_marker); + auto it = list_info2.front(); + ASSERT_EQ(1, list_info2.size()); + ASSERT_EQ(true, truncated); + ASSERT_EQ("chain-0", it.tag); + std::cerr << "[ ] next_marker is: = " << next_marker << std::endl; + + marker = next_marker; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info3, &truncated, next_marker); + it = list_info3.front(); + ASSERT_EQ(1, list_info3.size()); + ASSERT_EQ(false, truncated); + ASSERT_EQ("chain-1", it.tag); +} + +TEST(cls_rgw_gc, gc_queue_ops3) +{ + //Testing remove queue entries + string queue_name = "my-third-queue"; + uint64_t queue_size = 501, num_urgent_data_entries = 10; + librados::ObjectWriteOperation op; + op.create(true); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + + uint64_t size = 0; + int ret = cls_rgw_gc_queue_get_capacity(ioctx, queue_name, size); + ASSERT_EQ(0, ret); + ASSERT_EQ(size, queue_size); + + //Test remove queue, when queue is empty + librados::ObjectWriteOperation remove_op; + string marker1; + uint64_t num_entries = 2; + cls_rgw_gc_queue_remove_entries(remove_op, num_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); + + cls_rgw_gc_obj_info defer_info; + + //Test enqueue + for (int i = 0; i < 2; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + cls_rgw_gc_queue_enqueue(op, 5, info); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + if (i == 0) + defer_info = info; + } + + //Test defer entry for 1st element + librados::ObjectWriteOperation defer_op; + cls_rgw_gc_queue_defer_entry(defer_op, 10, defer_info); + ASSERT_EQ(0, ioctx.operate(queue_name, &defer_op)); + + //Test list queue + list list_info1, list_info2; + string marker, next_marker; + uint64_t max = 2; + bool expired_only = false, truncated; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); + ASSERT_EQ(2, list_info1.size()); + + int i = 0; + for (auto it : list_info1) { + std::cerr << "[ ] list info tag = " << it.tag << std::endl; + if (i == 0) { + ASSERT_EQ("chain-1", it.tag); + } + if (i == 1) { + ASSERT_EQ("chain-0", it.tag); + } + i++; + } + + //Test remove entries + num_entries = 2; + cls_rgw_gc_queue_remove_entries(remove_op, num_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); + + //Test list queue again + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info2, &truncated, next_marker); + ASSERT_EQ(0, list_info2.size()); + +} + +TEST(cls_rgw_gc, gc_queue_ops4) +{ + //Testing remove queue entries + string queue_name = "my-fourth-queue"; + uint64_t queue_size = 501, num_urgent_data_entries = 10; + librados::ObjectWriteOperation op; + op.create(true); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + + uint64_t size = 0; + int ret = cls_rgw_gc_queue_get_capacity(ioctx, queue_name, size); + ASSERT_EQ(0, ret); + ASSERT_EQ(size, queue_size); + + //Test remove queue, when queue is empty + librados::ObjectWriteOperation remove_op; + string marker1; + uint64_t num_entries = 2; + + cls_rgw_gc_queue_remove_entries(remove_op, num_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); + + cls_rgw_gc_obj_info defer_info; + + //Test enqueue + for (int i = 0; i < 2; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + cls_rgw_gc_queue_enqueue(op, 5, info); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + defer_info = info; + } + + //Test defer entry for last element + librados::ObjectWriteOperation defer_op; + cls_rgw_gc_queue_defer_entry(defer_op, 10, defer_info); + ASSERT_EQ(0, ioctx.operate(queue_name, &defer_op)); + + //Test list queue + list list_info1, list_info2; + string marker, next_marker; + uint64_t max = 2; + bool expired_only = false, truncated; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); + ASSERT_EQ(2, list_info1.size()); + + int i = 0; + for (auto it : list_info1) { + string tag = "chain-" + to_string(i); + ASSERT_EQ(tag, it.tag); + i++; + } + + //Test remove entries + num_entries = 2; + cls_rgw_gc_queue_remove_entries(remove_op, num_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); + + //Test list queue again + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info2, &truncated, next_marker); + ASSERT_EQ(0, list_info2.size()); + +} + +TEST(cls_rgw_gc, gc_queue_ops5) +{ + //Testing remove queue entries + string queue_name = "my-fifth-queue"; + uint64_t queue_size = 501, num_urgent_data_entries = 10; + librados::ObjectWriteOperation op; + op.create(true); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + + uint64_t size = 0; + int ret = cls_rgw_gc_queue_get_capacity(ioctx, queue_name, size); + ASSERT_EQ(0, ret); + ASSERT_EQ(size, queue_size); + + //Test enqueue + for (int i = 0; i < 3; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + if (i == 2) { + cls_rgw_gc_queue_enqueue(op, 300, info); + } else { + cls_rgw_gc_queue_enqueue(op, 0, info); + } + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + } + //Test list queue for expired entries only + list list_info1, list_info2; + string marker, next_marker, marker1; + uint64_t max = 10; + bool expired_only = true, truncated; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); + ASSERT_EQ(2, list_info1.size()); + + int i = 0; + for (auto it : list_info1) { + string tag = "chain-" + to_string(i); + ASSERT_EQ(tag, it.tag); + i++; + } + + //Test remove entries + librados::ObjectWriteOperation remove_op; + auto num_entries = list_info1.size(); + cls_rgw_gc_queue_remove_entries(remove_op, num_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); + + //Test list queue again for all entries + expired_only = false; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info2, &truncated, next_marker); + ASSERT_EQ(1, list_info2.size()); + +} + +TEST(cls_rgw_gc, gc_queue_ops6) +{ + //Testing list queue, when data size is split at the end of the queue + string queue_name = "my-sixth-queue"; + uint64_t queue_size = 341, num_urgent_data_entries = 10; + librados::ObjectWriteOperation op; + op.create(true); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + + uint64_t size = 0; + int ret = cls_rgw_gc_queue_get_capacity(ioctx, queue_name, size); + ASSERT_EQ(0, ret); + ASSERT_EQ(size, queue_size); + + //Test enqueue + for (int i = 0; i < 2; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + cls_rgw_gc_queue_enqueue(op, 0, info); + + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + } + + //Remove one element from queue + librados::ObjectWriteOperation remove_op; + string marker1; + uint64_t num_entries = 1; + + cls_rgw_gc_queue_remove_entries(remove_op, num_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); + + //Enqueue one more element + librados::ObjectWriteOperation enq_op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, 2, 1); + create_obj(obj2, 2, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = "chain-2"; + cls_rgw_gc_queue_enqueue(enq_op, 0, info); + + ASSERT_EQ(0, ioctx.operate(queue_name, &enq_op)); + + //Test list queue + list list_info1, list_info2, list_info3; + string marker, next_marker; + uint64_t max = 2; + bool expired_only = false, truncated; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); + ASSERT_EQ(2, list_info1.size()); + + int i = 1; + for (auto it : list_info1) { + string tag = "chain-" + to_string(i); + ASSERT_EQ(tag, it.tag); + i++; + } +} + +TEST(cls_rgw_gc, gc_queue_ops7) +{ + //Testing list queue, when data size is written at the end of queue and data is written after wrap around + string queue_name = "my-seventh-queue"; + uint64_t queue_size = 342, num_urgent_data_entries = 10; + librados::ObjectWriteOperation op; + op.create(true); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + + uint64_t size = 0; + int ret = cls_rgw_gc_queue_get_capacity(ioctx, queue_name, size); + ASSERT_EQ(0, ret); + ASSERT_EQ(size, queue_size); + + //Test enqueue + for (int i = 0; i < 2; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + cls_rgw_gc_queue_enqueue(op, 0, info); + + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + } + + //Remove one element from queue + librados::ObjectWriteOperation remove_op; + string marker1; + uint64_t num_entries = 1; + + cls_rgw_gc_queue_remove_entries(remove_op, num_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); + + //Enqueue one more element + librados::ObjectWriteOperation enq_op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, 2, 1); + create_obj(obj2, 2, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = "chain-2"; + cls_rgw_gc_queue_enqueue(enq_op, 0, info); + + ASSERT_EQ(0, ioctx.operate(queue_name, &enq_op)); + + //Test list queue + list list_info1, list_info2, list_info3; + string marker, next_marker; + uint64_t max = 2; + bool expired_only = false, truncated; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); + ASSERT_EQ(2, list_info1.size()); + + int i = 1; + for (auto it : list_info1) { + string tag = "chain-" + to_string(i); + ASSERT_EQ(tag, it.tag); + i++; + } +} + +TEST(cls_rgw_gc, gc_queue_ops8) +{ + //Testing list queue, when data is split at the end of the queue + string queue_name = "my-eighth-queue"; + uint64_t queue_size = 344, num_urgent_data_entries = 10; + librados::ObjectWriteOperation op; + op.create(true); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + + uint64_t size = 0; + int ret = cls_rgw_gc_queue_get_capacity(ioctx, queue_name, size); + ASSERT_EQ(0, ret); + ASSERT_EQ(size, queue_size); + + //Test enqueue + for (int i = 0; i < 2; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + cls_rgw_gc_queue_enqueue(op, 0, info); + + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + } + + //Remove one element from queue + librados::ObjectWriteOperation remove_op; + string marker1; + uint64_t num_entries = 1; + + cls_rgw_gc_queue_remove_entries(remove_op, num_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &remove_op)); + + //Enqueue one more element + librados::ObjectWriteOperation enq_op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, 2, 1); + create_obj(obj2, 2, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = "chain-2"; + cls_rgw_gc_queue_enqueue(enq_op, 0, info); + + ASSERT_EQ(0, ioctx.operate(queue_name, &enq_op)); + + //Test list queue + list list_info1, list_info2, list_info3; + string marker, next_marker; + uint64_t max = 2; + bool expired_only = false, truncated; + cls_rgw_gc_queue_list_entries(ioctx, queue_name, marker, max, expired_only, list_info1, &truncated, next_marker); + ASSERT_EQ(2, list_info1.size()); + + int i = 1; + for (auto it : list_info1) { + string tag = "chain-" + to_string(i); + ASSERT_EQ(tag, it.tag); + i++; + } +} + +TEST(cls_rgw_gc, gc_queue_ops9) +{ + //Testing remove queue entries + string queue_name = "my-ninth-queue"; + uint64_t queue_size = 668, num_urgent_data_entries = 1; + librados::ObjectWriteOperation op; + op.create(true); + cls_rgw_gc_queue_init(op, queue_size, num_urgent_data_entries); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + + uint64_t size = 0; + int ret = cls_rgw_gc_queue_get_capacity(ioctx, queue_name, size); + ASSERT_EQ(0, ret); + ASSERT_EQ(size, queue_size); + + cls_rgw_gc_obj_info defer_info1, defer_info2; + + //Test enqueue + for (int i = 0; i < 2; i++) { + string tag = "chain-" + to_string(i); + librados::ObjectWriteOperation op; + cls_rgw_gc_obj_info info; + + cls_rgw_obj obj1, obj2; + create_obj(obj1, i, 1); + create_obj(obj2, i, 2); + info.chain.objs.push_back(obj1); + info.chain.objs.push_back(obj2); + + info.tag = tag; + cls_rgw_gc_queue_enqueue(op, 5, info); + ASSERT_EQ(0, ioctx.operate(queue_name, &op)); + if (i == 0) { + defer_info1 = info; + } + if (i == 1) { + defer_info2 = info; + } + } + + //Test defer entry for last element + librados::ObjectWriteOperation defer_op; + cls_rgw_gc_queue_defer_entry(defer_op, 10, defer_info2); + ASSERT_EQ(0, ioctx.operate(queue_name, &defer_op)); + + //Test defer entry for first element + cls_rgw_gc_queue_defer_entry(defer_op, 10, defer_info1); + ASSERT_EQ(-ENOSPC, ioctx.operate(queue_name, &defer_op)); +} + +/* must be last test! */ +TEST(cls_rgw_gc, finalize) +{ + /* remove pool */ + ioctx.close(); + ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados)); +}