From: Javier M. Mellid Date: Mon, 1 Oct 2018 18:44:42 +0000 (+0200) Subject: rgw: Add archive zone metadata support X-Git-Tag: v14.1.0~269^2~9 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8c4574dd3cd65e566b4206e9068b24d49e8a8b73;p=ceph.git rgw: Add archive zone metadata support Signed-off-by: Javier M. Mellid --- diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index 3ff965ec510..dd28a479d54 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -2481,6 +2481,174 @@ public: } }; +void get_md5_digest(const RGWBucketEntryPoint *be, string& md5_digest) { + + char md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1]; + unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE]; + bufferlist bl; + + Formatter *f = new JSONFormatter(false); + be->dump(f); + f->flush(bl); + + MD5 hash; + hash.Update((const unsigned char *)bl.c_str(), bl.length()); + hash.Final(m); + + buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, md5); + + delete f; + + md5_digest = md5; +} + +class RGWArchiveBucketMetadataHandler : public RGWBucketMetadataHandler { + +public: + + int remove_by_metakey(RGWRados *store, string& metadata_key) override { + + ldout(store->ctx(), 0) << "SKIP: bucket removal is not allowed on archive zone: " << metadata_key << " ... proceeding to rename" << dendl; + + string type; + string entry; + store->meta_mgr->parse_metadata_key(metadata_key, type, entry); + + RGWMetadataObject *obj; + int ret = get(store, entry, &obj); + if (ret < 0) { + return ret; + } + + RGWBucketEntryPoint be; + RGWObjectCtx obj_ctx(store); + RGWObjVersionTracker objv_tracker; + objv_tracker.read_version = obj->get_version(); + + delete obj; + + string tenant_name, bucket_name; + parse_bucket(entry, &tenant_name, &bucket_name); + + real_time mtime; + + ret = store->get_bucket_entrypoint_info(obj_ctx, tenant_name, bucket_name, be, &objv_tracker, &mtime, NULL); + if (ret < 0) { + return ret; + } + + string md5_digest; + get_md5_digest(&be, md5_digest); + + string archive_zone_suffix = "-deleted-" + md5_digest; + be.bucket.name = be.bucket.name + archive_zone_suffix; + + RGWBucketEntryMetadataObject *be_mdo = new RGWBucketEntryMetadataObject(be, objv_tracker.read_version, mtime); + + JSONFormatter f(false); + f.open_object_section("metadata_info"); + encode_json("key", metadata_key + archive_zone_suffix, &f); + encode_json("ver", be_mdo->get_version(), &f); + mtime = be_mdo->get_mtime(); + if (!real_clock::is_zero(mtime)) { + utime_t ut(mtime); + encode_json("mtime", ut, &f); + } + encode_json("data", *be_mdo, &f); + f.close_section(); + + delete be_mdo; + + ret = rgw_unlink_bucket(store, be.owner, tenant_name, bucket_name, false); + if (ret < 0) { + lderr(store->ctx()) << "could not unlink bucket=" << entry << " owner=" << be.owner << dendl; + } + + // if (ret == -ECANCELED) it means that there was a race here, and someone + // wrote to the bucket entrypoint just before we removed it. The question is + // whether it was a newly created bucket entrypoint ... in which case we + // should ignore the error and move forward, or whether it is a higher version + // of the same bucket instance ... in which we should retry + ret = rgw_bucket_delete_bucket_obj(store, tenant_name, bucket_name, objv_tracker); + if (ret < 0) { + lderr(store->ctx()) << "could not delete bucket=" << entry << dendl; + } + + string new_entry, new_bucket_name; + new_entry = entry + archive_zone_suffix; + parse_bucket(new_entry, &tenant_name, &new_bucket_name); + + bufferlist bl; + f.flush(bl); + + JSONParser parser; + if (!parser.parse(bl.c_str(), bl.length())) { + return -EINVAL; + } + + JSONObj *jo = parser.find_obj("data"); + if (!jo) { + return -EINVAL; + } + + try { + decode_json_obj(be, jo); + } catch (JSONDecoder::err& e) { + return -EINVAL; + } + + RGWBucketEntryPoint ep; + ep.linked = be.linked; + ep.owner = be.owner; + ep.bucket = be.bucket; + + RGWObjVersionTracker ot; + ot.generate_new_write_ver(store->ctx()); + + map attrs; + + ret = store->put_bucket_entrypoint_info(tenant_name, new_bucket_name, ep, false, ot, mtime, &attrs); + if (ret < 0) { + return ret; + } + + ret = rgw_link_bucket(store, be.owner, be.bucket, be.creation_time, false); + if (ret < 0) { + return ret; + } + + // .bucket.meta.my-bucket-1:c0f7ef8c-2309-4ebb-a1d0-1b0a61dc5a78.4226.1 + string meta_name = bucket_name + ":" + be.bucket.marker; + + map attrs_m; + RGWBucketInfo bi_m; + + ret = store->get_bucket_instance_info(obj_ctx, meta_name, bi_m, NULL, &attrs_m); + if (ret < 0) { + return ret; + } + + string new_meta_name = RGW_BUCKET_INSTANCE_MD_PREFIX + new_bucket_name + ":" + be.bucket.marker; + + bi_m.bucket.name = new_bucket_name; + + bufferlist bl_m; + using ceph::encode; + encode(bi_m, bl_m); + + ret = rgw_put_system_obj(store, store->get_zone_params().domain_root, new_meta_name, bl_m, false, NULL, real_time(), NULL); + if (ret < 0) { + return ret; + } + + ret = rgw_delete_system_obj(store, store->get_zone_params().domain_root, RGW_BUCKET_INSTANCE_MD_PREFIX + meta_name, NULL); + + /* idempotent */ + return 0; + } + +}; + class RGWBucketInstanceMetadataHandler : public RGWMetadataHandler { public: @@ -2700,10 +2868,26 @@ public: } }; +class RGWArchiveBucketInstanceMetadataHandler : public RGWBucketInstanceMetadataHandler { + +public: + + int remove_by_metakey(RGWRados *store, string& metadata_key) override { + ldout(store->ctx(), 0) << "SKIP: bucket instance removal is not allowed on archive zone: " << metadata_key << dendl; + return 0; + } + +}; + void rgw_bucket_init(RGWMetadataManager *mm) { - bucket_meta_handler = new RGWBucketMetadataHandler; + if (mm->get_store()->get_zone().tier_type == "archive") { + bucket_meta_handler = new RGWArchiveBucketMetadataHandler; + bucket_instance_meta_handler = new RGWArchiveBucketInstanceMetadataHandler; + } else { + bucket_meta_handler = new RGWBucketMetadataHandler; + bucket_instance_meta_handler = new RGWBucketInstanceMetadataHandler; + } mm->register_handler(bucket_meta_handler); - bucket_instance_meta_handler = new RGWBucketInstanceMetadataHandler; mm->register_handler(bucket_instance_meta_handler); } diff --git a/src/rgw/rgw_data_sync.cc b/src/rgw/rgw_data_sync.cc index 4c53f2faa54..1ad06149bc2 100644 --- a/src/rgw/rgw_data_sync.cc +++ b/src/rgw/rgw_data_sync.cc @@ -1718,8 +1718,7 @@ RGWCoroutine *RGWArchiveDataSyncModule::sync_object(RGWDataSyncEnv *sync_env, RG if (!bucket_info.versioned() || (bucket_info.flags & BUCKET_VERSIONS_SUSPENDED)) { ldout(sync_env->cct, 0) << "SYNC_ARCHIVE: sync_object: enabling object versioning for archive bucket" << dendl; - bucket_info.flags |= BUCKET_VERSIONED; - bucket_info.flags &= ~BUCKET_VERSIONS_SUSPENDED; + bucket_info.flags = (bucket_info.flags & ~BUCKET_VERSIONS_SUSPENDED) | BUCKET_VERSIONED; int op_ret = sync_env->store->put_bucket_instance_info(bucket_info, false, real_time(), NULL); if (op_ret < 0) { ldout(sync_env->cct, 0) << "SYNC_ARCHIVE: sync_object: error versioning archive bucket" << dendl; diff --git a/src/rgw/rgw_metadata.cc b/src/rgw/rgw_metadata.cc index bb6657ee0f8..1d36ce7c2ee 100644 --- a/src/rgw/rgw_metadata.cc +++ b/src/rgw/rgw_metadata.cc @@ -275,6 +275,23 @@ obj_version& RGWMetadataObject::get_version() return objv; } +int RGWMetadataHandler::remove_by_metakey(RGWRados *store, string& metadata_key) { + string entry; + string type; + store->meta_mgr->parse_metadata_key(metadata_key, type, entry); + + RGWMetadataObject *obj; + int ret = get(store, entry, &obj); + if (ret < 0) { + return ret; + } + RGWObjVersionTracker objv_tracker; + objv_tracker.read_version = obj->get_version(); + delete obj; + + return remove(store, entry, objv_tracker); +} + class RGWMetadataTopHandler : public RGWMetadataHandler { struct iter_data { set sections; @@ -293,6 +310,7 @@ public: virtual void get_pool_and_oid(RGWRados *store, const string& key, rgw_pool& pool, string& oid) override {} int remove(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker) override { return -ENOTSUP; } + int remove_by_metakey(RGWRados *store, string& metadata_key) override { return -ENOTSUP; } int list_keys_init(RGWRados *store, const string& marker, void **phandle) override { iter_data *data = new iter_data; @@ -760,8 +778,19 @@ int RGWMetadataManager::put(string& metadata_key, bufferlist& bl, string entry; int ret = find_handler(metadata_key, &handler, entry); - if (ret < 0) + if (ret < 0) { return ret; + } + + // archive existing bucket if needed + if (store->get_zone().tier_type == "archive") { + if (handler->get_type() == "bucket") { + size_t found = metadata_key.find("-deleted-"); + if(found != string::npos) { + remove(metadata_key); + } + } + } JSONParser parser; if (!parser.parse(bl.c_str(), bl.length())) { @@ -832,23 +861,11 @@ int RGWMetadataManager::remove(string& metadata_key) string entry; int ret = find_handler(metadata_key, &handler, entry); - if (ret < 0) - return ret; - - RGWMetadataObject *obj; - - ret = handler->get(store, entry, &obj); if (ret < 0) { return ret; } - RGWObjVersionTracker objv_tracker; - - objv_tracker.read_version = obj->get_version(); - - delete obj; - - return handler->remove(store, entry, objv_tracker); + return handler->remove_by_metakey(store, metadata_key); } int RGWMetadataManager::lock_exclusive(string& metadata_key, timespan duration, string& owner_id) { @@ -1133,8 +1150,9 @@ int RGWMetadataManager::remove_entry(RGWMetadataHandler *handler, string section; RGWMetadataLogData log_data; int ret = pre_modify(handler, section, key, log_data, objv_tracker, MDLOG_STATUS_REMOVE); - if (ret < 0) - return ret; + if (ret < 0) { + return ret; + } string oid; rgw_pool pool; @@ -1151,8 +1169,9 @@ int RGWMetadataManager::remove_entry(RGWMetadataHandler *handler, /* cascading ret into post_modify() */ ret = post_modify(handler, section, key, log_data, objv_tracker, ret); - if (ret < 0) - return ret; + if (ret < 0) { + return ret; + } return 0; } diff --git a/src/rgw/rgw_metadata.h b/src/rgw/rgw_metadata.h index 9ceef74c450..2c8d61db5ba 100644 --- a/src/rgw/rgw_metadata.h +++ b/src/rgw/rgw_metadata.h @@ -72,6 +72,7 @@ public: return false; return true; } + virtual ~RGWMetadataHandler() {} virtual string get_type() = 0; @@ -79,6 +80,7 @@ public: virtual int put(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker, real_time mtime, JSONObj *obj, sync_type_t type) = 0; virtual int remove(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker) = 0; + virtual int remove_by_metakey(RGWRados *store, string& metadata_key); virtual int list_keys_init(RGWRados *store, const string& marker, void **phandle) = 0; virtual int list_keys_next(void *handle, int max, list& keys, bool *truncated) = 0; @@ -300,8 +302,6 @@ class RGWMetadataManager { // use the current period's log for mutating operations RGWMetadataLog* current_log = nullptr; - void parse_metadata_key(const string& metadata_key, string& type, string& entry); - int find_handler(const string& metadata_key, RGWMetadataHandler **handler, string& entry); int pre_modify(RGWMetadataHandler *handler, string& section, const string& key, RGWMetadataLogData& log_data, RGWObjVersionTracker *objv_tracker, @@ -323,6 +323,8 @@ public: RGWMetadataManager(CephContext *_cct, RGWRados *_store); ~RGWMetadataManager(); + RGWRados* get_store() { return store; } + int init(const std::string& current_period); /// initialize the oldest log period if it doesn't exist, and attach it to @@ -382,6 +384,8 @@ public: int unlock(string& metadata_key, string& owner_id); int get_log_shard_id(const string& section, const string& key, int *shard_id); + + void parse_metadata_key(const string& metadata_key, string& type, string& entry); }; template