cout << " lc list list all bucket lifecycle progress\n";
cout << " lc get get a lifecycle bucket configuration\n";
cout << " lc process manually process lifecycle\n";
+ cout << " lc fix fix LC for a resharded bucket\n";
cout << " metadata get get metadata info\n";
cout << " metadata put put metadata info\n";
cout << " metadata rm remove metadata info\n";
OPT_LC_LIST,
OPT_LC_GET,
OPT_LC_PROCESS,
+ OPT_LC_FIX,
OPT_ORPHANS_FIND,
OPT_ORPHANS_FINISH,
OPT_ORPHANS_LIST_JOBS,
return OPT_LC_GET;
if (strcmp(cmd, "process") == 0)
return OPT_LC_PROCESS;
+ if (strcmp(cmd, "fix") == 0)
+ return OPT_LC_FIX;
} else if (strcmp(prev_cmd, "orphans") == 0) {
if (strcmp(cmd, "find") == 0)
return OPT_ORPHANS_FIND;
}
}
+
+ if (opt_cmd == OPT_LC_FIX) {
+ rgw_bucket bucket;
+ RGWBucketInfo bucket_info;
+ map<string, bufferlist> attrs;
+ ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket, &attrs);
+ if (ret < 0) {
+ cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
+ return -ret;
+ }
+
+ ret = rgw::lc::fix_lc_shard_entry(store, bucket_info, attrs);
+ if (ret < 0) {
+ cerr << "ERROR: fixing lc shard entry failed with" << cpp_strerror(-ret) << std::endl;
+ }
+ }
+
if (opt_cmd == OPT_ORPHANS_FIND) {
if (!yes_i_really_mean_it) {
cerr << "accidental removal of active objects can not be reversed; "
#include "rgw_common.h"
#include "rgw_bucket.h"
#include "rgw_lc.h"
+#include "rgw_string.h"
#include "services/svc_sys_obj.h"
o.push_back(new RGWLifecycleConfiguration);
}
-static void get_lc_oid(CephContext *cct, const string& shard_id, string *oid)
+void get_lc_oid(CephContext *cct, const string& shard_id, string *oid)
{
int max_objs = (cct->_conf->rgw_lc_max_objs > HASH_PRIME ? HASH_PRIME : cct->_conf->rgw_lc_max_objs);
int index = ceph_str_hash_linux(shard_id.c_str(), shard_id.size()) % HASH_PRIME % max_objs;
return;
}
+
+
+static std::string get_lc_shard_name(const rgw_bucket& bucket){
+ return string_join_reserve(':', bucket.tenant, bucket.name, bucket.marker);
+}
+
template<typename F>
static int guard_lc_modify(RGWRados* store, const rgw_bucket& bucket, const string& cookie, const F& f) {
CephContext *cct = store->ctx();
- string shard_id = bucket.tenant + ':' + bucket.name + ':' + bucket.marker;
+ string shard_id = get_lc_shard_name(bucket);
string oid;
get_lc_oid(cct, shard_id, &oid);
return ret;
}
+namespace rgw::lc {
+
+int fix_lc_shard_entry(RGWRados* store, const RGWBucketInfo& bucket_info,
+ const map<std::string,bufferlist>& battrs)
+{
+ if (auto aiter = battrs.find(RGW_ATTR_LC);
+ aiter == battrs.end()) {
+ return 0; // No entry, nothing to fix
+ }
+
+ auto shard_name = get_lc_shard_name(bucket_info.bucket);
+ std::string lc_oid;
+ get_lc_oid(store->ctx(), shard_name, &lc_oid);
+
+ rgw_lc_entry_t entry;
+ // There are multiple cases we need to encounter here
+ // 1. entry exists and is already set to marker, happens in plain buckets & newly resharded buckets
+ // 2. entry doesn't exist, which usually happens when reshard has happened prior to update and next LC process has already dropped the update
+ // 3. entry exists matching the current bucket id which was after a reshard (needs to be updated to the marker)
+ // We are not dropping the old marker here as that would be caught by the next LC process update
+ auto lc_pool_ctx = store->get_lc_pool_ctx();
+ int ret = cls_rgw_lc_get_entry(*lc_pool_ctx,
+ lc_oid, shard_name, entry);
+ if (ret == 0) {
+ ldout(store->ctx(), 5) << "Entry already exists, nothing to do" << dendl;
+ return ret; // entry is already existing correctly set to marker
+ }
+ ldout(store->ctx(), 5) << "cls_rgw_lc_get_entry errored ret code=" << ret << dendl;
+ if (ret == -ENOENT) {
+ ldout(store->ctx(), 1) << "No entry for bucket=" << bucket_info.bucket.name
+ << " creating " << dendl;
+ // TODO: we have too many ppl making cookies like this!
+ char cookie_buf[COOKIE_LEN + 1];
+ gen_rand_alphanumeric(store->ctx(), cookie_buf, sizeof(cookie_buf) - 1);
+ std::string cookie = cookie_buf;
+
+ ret = guard_lc_modify(store, bucket_info.bucket, cookie,
+ [&lc_pool_ctx, &lc_oid](librados::IoCtx *ctx, const string& oid,
+ const pair<string, int>& entry) {
+ return cls_rgw_lc_set_entry(*lc_pool_ctx,
+ lc_oid, entry);
+ });
+
+ }
+
+ return ret;
+}
+
+}