From: Radoslaw Zarzynski Date: Fri, 29 May 2015 12:17:28 +0000 (+0200) Subject: rgw: split rgw-object-expirer. X-Git-Tag: v9.1.0~229^2~15 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=05c90e68c33af9ba2bf1f9690a0a6da2c01f6c0b;p=ceph.git rgw: split rgw-object-expirer. Fixes: #4099 Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/Makefile.am b/src/rgw/Makefile.am index 235ddadfd66..c1baa6a3490 100644 --- a/src/rgw/Makefile.am +++ b/src/rgw/Makefile.am @@ -45,7 +45,8 @@ librgw_la_SOURCES = \ rgw/rgw_replica_log.cc \ rgw/rgw_keystone.cc \ rgw/rgw_quota.cc \ - rgw/rgw_dencoder.cc + rgw/rgw_dencoder.cc \ + rgw/rgw_object_expirer_core.cc librgw_la_CXXFLAGS = -Woverloaded-virtual ${AM_CXXFLAGS} noinst_LTLIBRARIES += librgw.la diff --git a/src/rgw/rgw_object_expirer.cc b/src/rgw/rgw_object_expirer.cc index 97b5a27e58d..b492e82eadc 100644 --- a/src/rgw/rgw_object_expirer.cc +++ b/src/rgw/rgw_object_expirer.cc @@ -31,6 +31,7 @@ using namespace std; #include "rgw_formats.h" #include "rgw_usage.h" #include "rgw_replica_log.h" +#include "rgw_object_expirer_core.h" #define dout_subsys ceph_subsys_rgw @@ -58,141 +59,6 @@ static inline utime_t get_last_run_time(void) return utime_t(); } -static int init_bucket_info(const string& bucket_name, - const string& bucket_id, - RGWBucketInfo& bucket_info) -{ - RGWObjectCtx obj_ctx(store); - const string bucket_instance_id = bucket_name + ":" + bucket_id; - - int ret = store->get_bucket_instance_info(obj_ctx, bucket_instance_id, - bucket_info, NULL, NULL); - - return ret; -} - -static int garbage_single_object(objexp_hint_entry& hint) -{ - RGWBucketInfo bucket_info; - - int ret = init_bucket_info(hint.bucket_name, hint.bucket_id, bucket_info); - if (ret < 0) { - dout(1) << "ERROR: could not init bucket: " << cpp_strerror(-ret) << dendl; - return ret; - } - - RGWObjectCtx rctx(store); - - rgw_obj_key key = hint.obj_key; - if (key.instance.empty()) { - key.instance = "null"; - } - - rgw_obj obj(bucket_info.bucket, key); - store->set_atomic(&rctx, obj); - ret = store->delete_obj(rctx, bucket_info, obj, - bucket_info.versioning_status(), 0, hint.exp_time); - - return ret; -} - -static void garbage_chunk(list& entries, /* in */ - bool& need_trim) /* out */ -{ - need_trim = false; - - for (list::iterator iter = entries.begin(); - iter != entries.end(); - ++iter) - { - objexp_hint_entry hint; - dout(15) << "===== got removal hint for: " << iter->key_ts.sec() << " - " << iter->key_ext << dendl; - - int ret = store->objexp_hint_parse(*iter, hint); - if (ret < 0) { - dout(1) << "cannot parse removal hint for " << hint.obj_key << dendl; - continue; - } - - /* PRECOND_FAILED simply means that our hint is not valid. - * We can silently ignore that and move forward. */ - ret = garbage_single_object(hint); - if (ret == -ERR_PRECONDITION_FAILED) { - dout(15) << "not actual hint for object: " << hint.obj_key << dendl; - } else if (ret < 0) { - dout(1) << "cannot remove expired object: " << hint.obj_key << dendl; - } - - need_trim = true; - } - - return; -} - -static void trim_chunk(const string& shard, - const utime_t& from, - const utime_t& to) -{ - dout(20) << "trying to trim removal hints to " << to << dendl; - - int ret = store->objexp_hint_trim(shard, from, to); - if (ret < 0) { - dout(0) << "ERROR during trim: " << ret << dendl; - } - - return; -} - -static void proceed_single_shard(const string& shard, - const utime_t& last_run, - const utime_t& round_start) -{ - string marker; - string out_marker; - bool truncated = false; - - do { - list entries; - int ret = store->objexp_hint_list(shard, last_run, round_start, - 1000, marker, entries, - &out_marker, &truncated); - if (ret < 0) { - dout(10) << "cannot get removal hints from shard: " << shard << dendl; - continue; - } - - bool need_trim; - garbage_chunk(entries, need_trim); - - if (need_trim) { - trim_chunk(shard, last_run, round_start); - } - - marker = out_marker; - } while (truncated); - - return; -} - -static void inspect_all_shards(const utime_t& last_run, - const utime_t& round_start) -{ - bool is_next_available; - utime_t shard_marker; - - do { - string shard; - store->objexp_get_shard(last_run, round_start, shard_marker, shard, - is_next_available); - - dout(20) << "proceeding shard = " << shard << dendl; - - proceed_single_shard(shard, last_run, round_start); - } while (is_next_available); - - return; -} - int main(const int argc, const char **argv) { vector args; @@ -230,9 +96,10 @@ int main(const int argc, const char **argv) StoreDestructor store_dtor(store); utime_t last_run = get_last_run_time(); + ObjectExpirer objexp(store); while (true) { const utime_t round_start = ceph_clock_now(g_ceph_context); - inspect_all_shards(last_run, round_start); + objexp.inspect_all_shards(last_run, round_start); last_run = round_start; diff --git a/src/rgw/rgw_object_expirer_core.cc b/src/rgw/rgw_object_expirer_core.cc new file mode 100644 index 00000000000..e2cc6b9c206 --- /dev/null +++ b/src/rgw/rgw_object_expirer_core.cc @@ -0,0 +1,172 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include +#include +#include +#include + +using namespace std; + +#include "auth/Crypto.h" + +#include "common/armor.h" +#include "common/ceph_json.h" +#include "common/config.h" +#include "common/ceph_argparse.h" +#include "common/Formatter.h" +#include "common/errno.h" + +#include "global/global_init.h" + +#include "include/utime.h" +#include "include/str_list.h" + +#include "rgw_user.h" +#include "rgw_bucket.h" +#include "rgw_rados.h" +#include "rgw_acl.h" +#include "rgw_acl_s3.h" +#include "rgw_log.h" +#include "rgw_formats.h" +#include "rgw_usage.h" +#include "rgw_replica_log.h" +#include "rgw_object_expirer_core.h" + +#define dout_subsys ceph_subsys_rgw + +int ObjectExpirer::init_bucket_info(const string& bucket_name, + const string& bucket_id, + RGWBucketInfo& bucket_info) +{ + RGWObjectCtx obj_ctx(store); + const string bucket_instance_id = bucket_name + ":" + bucket_id; + + int ret = store->get_bucket_instance_info(obj_ctx, bucket_instance_id, + bucket_info, NULL, NULL); + + return ret; +} + +int ObjectExpirer::garbage_single_object(objexp_hint_entry& hint) +{ + RGWBucketInfo bucket_info; + + int ret = init_bucket_info(hint.bucket_name, hint.bucket_id, bucket_info); + if (ret < 0) { + dout(1) << "ERROR: could not init bucket: " << cpp_strerror(-ret) << dendl; + return ret; + } + + RGWObjectCtx rctx(store); + + rgw_obj_key key = hint.obj_key; + if (key.instance.empty()) { + key.instance = "null"; + } + + rgw_obj obj(bucket_info.bucket, key); + store->set_atomic(&rctx, obj); + ret = store->delete_obj(rctx, bucket_info, obj, + bucket_info.versioning_status(), 0, hint.exp_time); + + return ret; +} + +void ObjectExpirer::garbage_chunk(list& entries, /* in */ + bool& need_trim) /* out */ +{ + need_trim = false; + + for (list::iterator iter = entries.begin(); + iter != entries.end(); + ++iter) + { + objexp_hint_entry hint; + dout(15) << "got removal hint for: " << iter->key_ts.sec() \ + << " - " << iter->key_ext << dendl; + + int ret = store->objexp_hint_parse(*iter, hint); + if (ret < 0) { + dout(1) << "cannot parse removal hint for " << hint.obj_key << dendl; + continue; + } + + /* PRECOND_FAILED simply means that our hint is not valid. + * We can silently ignore that and move forward. */ + ret = garbage_single_object(hint); + if (ret == -ERR_PRECONDITION_FAILED) { + dout(15) << "not actual hint for object: " << hint.obj_key << dendl; + } else if (ret < 0) { + dout(1) << "cannot remove expired object: " << hint.obj_key << dendl; + } + + need_trim = true; + } + + return; +} + +void ObjectExpirer::trim_chunk(const string& shard, + const utime_t& from, + const utime_t& to) +{ + dout(20) << "trying to trim removal hints to " << to << dendl; + + int ret = store->objexp_hint_trim(shard, from, to); + if (ret < 0) { + dout(0) << "ERROR during trim: " << ret << dendl; + } + + return; +} + +void ObjectExpirer::proceed_single_shard(const string& shard, + const utime_t& last_run, + const utime_t& round_start) +{ + string marker; + string out_marker; + bool truncated = false; + + do { + list entries; + int ret = store->objexp_hint_list(shard, last_run, round_start, + 1000, marker, entries, + &out_marker, &truncated); + if (ret < 0) { + dout(10) << "cannot get removal hints from shard: " << shard << dendl; + continue; + } + + bool need_trim; + garbage_chunk(entries, need_trim); + + if (need_trim) { + trim_chunk(shard, last_run, round_start); + } + + marker = out_marker; + } while (truncated); + + return; +} + +void ObjectExpirer::inspect_all_shards(const utime_t& last_run, + const utime_t& round_start) +{ + bool is_next_available; + utime_t shard_marker; + + do { + string shard; + store->objexp_get_shard(last_run, round_start, shard_marker, shard, + is_next_available); + + dout(20) << "proceeding shard = " << shard << dendl; + + proceed_single_shard(shard, last_run, round_start); + } while (is_next_available); + + return; +} diff --git a/src/rgw/rgw_object_expirer_core.h b/src/rgw/rgw_object_expirer_core.h new file mode 100644 index 00000000000..a1701057a6b --- /dev/null +++ b/src/rgw/rgw_object_expirer_core.h @@ -0,0 +1,65 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_OBJEXP_H +#define CEPH_OBJEXP_H + +#include +#include +#include +#include + +#include "auth/Crypto.h" + +#include "common/armor.h" +#include "common/ceph_json.h" +#include "common/config.h" +#include "common/ceph_argparse.h" +#include "common/Formatter.h" +#include "common/errno.h" + +#include "global/global_init.h" + +#include "include/utime.h" +#include "include/str_list.h" + +#include "rgw_user.h" +#include "rgw_bucket.h" +#include "rgw_rados.h" +#include "rgw_acl.h" +#include "rgw_acl_s3.h" +#include "rgw_log.h" +#include "rgw_formats.h" +#include "rgw_usage.h" +#include "rgw_replica_log.h" + +class ObjectExpirer { +protected: + RGWRados * const store; + + int init_bucket_info(const string& bucket_name, + const string& bucket_id, + RGWBucketInfo& bucket_info); + +public: + ObjectExpirer(RGWRados * const _store) + : store(_store) + {} + + int garbage_single_object(objexp_hint_entry& hint); + + void garbage_chunk(list& entries, /* in */ + bool& need_trim); /* out */ + + void trim_chunk(const string& shard, + const utime_t& from, + const utime_t& to); + + void proceed_single_shard(const string& shard, + const utime_t& last_run, + const utime_t& round_start); + + void inspect_all_shards(const utime_t& last_run, + const utime_t& round_start); +}; +#endif /* CEPH_OBJEXP_H */