From a5627d60395915e5f57e6c12293d8221a218f8fe Mon Sep 17 00:00:00 2001 From: Soumya Koduri Date: Thu, 27 Jan 2022 01:12:44 +0530 Subject: [PATCH] rgw/dbstore: Create GC Thread to delete stale objects Create a gc thread to cleanup the stale tail objects data XXX: handle read + delete usecase, simple approach could be to use locks or sqlite transactions in GC Signed-off-by: Soumya Koduri --- src/rgw/rgw_sal_dbstore.cc | 7 +- src/rgw/store/dbstore/common/dbstore.cc | 111 +++++++++++++++- src/rgw/store/dbstore/common/dbstore.h | 83 +++++++++++- src/rgw/store/dbstore/sqlite/sqliteDB.cc | 92 +++++++++++-- src/rgw/store/dbstore/sqlite/sqliteDB.h | 21 +++ src/rgw/store/dbstore/tests/dbstore_tests.cc | 131 ++++++++++++------- 6 files changed, 380 insertions(+), 65 deletions(-) diff --git a/src/rgw/rgw_sal_dbstore.cc b/src/rgw/rgw_sal_dbstore.cc index 3e395fa3764..bd900987311 100644 --- a/src/rgw/rgw_sal_dbstore.cc +++ b/src/rgw/rgw_sal_dbstore.cc @@ -41,7 +41,7 @@ namespace rgw::sal { int ret; buckets.clear(); - ret = store->getDB()->list_buckets(dpp, info.user_id, marker, end_marker, max, + ret = store->getDB()->list_buckets(dpp, "", info.user_id, marker, end_marker, max, need_stats, &ulist, &is_truncated); if (ret < 0) return ret; @@ -1901,6 +1901,11 @@ namespace rgw::sal { lc->start_processor(); } + ret = db->createGC(dpp); + if (ret < 0) { + ldpp_dout(dpp, 0) <<"GC thread creation failed: ret = " << ret << dendl; + } + return ret; } } // namespace rgw::sal diff --git a/src/rgw/store/dbstore/common/dbstore.cc b/src/rgw/store/dbstore/common/dbstore.cc index b0ea5fafc7f..e74f278d5a6 100644 --- a/src/rgw/store/dbstore/common/dbstore.cc +++ b/src/rgw/store/dbstore/common/dbstore.cc @@ -54,11 +54,29 @@ int DB::Initialize(string logfile, int loglevel) return ret; } +int DB::createGC(const DoutPrefixProvider *dpp) { + int ret = 0; + /* create gc thread */ + + gc_worker = std::make_unique(dpp, this); + gc_worker->create("db_gc"); + + return ret; +} + +int DB::stopGC() { + if (gc_worker) + gc_worker->join(); + return 0; +} + int DB::Destroy(const DoutPrefixProvider *dpp) { if (!db) return 0; + stopGC(); + closeDB(dpp); @@ -140,6 +158,8 @@ DBOp *DB::getDBOp(const DoutPrefixProvider *dpp, string Op, struct DBOpParams *p return Ob->GetObjectData; if (!Op.compare("DeleteObjectData")) return Ob->DeleteObjectData; + if (!Op.compare("DeleteStaleObjectData")) + return Ob->DeleteStaleObjectData; return NULL; } @@ -158,7 +178,7 @@ int DB::objectmapInsert(const DoutPrefixProvider *dpp, string bucket, class Obje // return error ? // // return success for now & delete the newly allocated ptr - ldpp_dout(dpp, 20)<<"Objectmap entry already exists for bucket("\ + ldpp_dout(dpp, 30)<<"Objectmap entry already exists for bucket("\ <add(std::move(entry)); } + + if (query_str == "all") { + // userID/OwnerID may have changed. Update it. + user.id = params.op.bucket.info.owner.id; + } + out: return ret; } @@ -1114,6 +1142,7 @@ int DB::raw_obj::write(const DoutPrefixProvider *dpp, int64_t ofs, int64_t write unsigned write_len = std::min((uint64_t)bl.length() - write_ofs, len); bl.begin(write_ofs).copy(write_len, params.op.obj_data.data); params.op.obj_data.size = params.op.obj_data.data.length(); + params.op.obj.state.mtime = real_clock::now(); ret = db->ProcessOp(dpp, "PutObjectData", ¶ms); @@ -1544,9 +1573,8 @@ int DB::Object::Write::prepare(const DoutPrefixProvider* dpp) gen_rand_alphanumeric(store->ctx(), buf, sizeof(buf) - 1); target->obj_id = target->obj.key.name + "." + buf; } - - ret = 0; + ret = 0; return ret; } @@ -1710,6 +1738,7 @@ int DB::Object::Write::_do_write_meta(const DoutPrefixProvider *dpp, /* XXX: handle multipart */ params.op.query_str = "meta"; + params.op.obj.obj_id = target->obj_id; ret = store->ProcessOp(dpp, "PutObject", ¶ms); if (ret) { @@ -1968,5 +1997,79 @@ out: return ret; } +int DB::delete_stale_objs(const DoutPrefixProvider *dpp, const std::string& bucket, + uint32_t min_wait) { + DBOpParams params = {}; + int ret = -1; + + params.op.bucket.info.bucket.name = bucket; + /* Verify if bucket exists. + * XXX: This is needed for now to create objectmap of bucket + * in SQLGetBucket + */ + InitializeParams(dpp, "GetBucket", ¶ms); + ret = ProcessOp(dpp, "GetBucket", ¶ms); + if (ret) { + ldpp_dout(dpp, 0) << "In GetBucket failed err:(" <list_buckets(dpp, "all", user, marker, string(), + max, false, &buckets, &is_truncated); + + if (r < 0) { //do nothing? retry later ? + break; + } + + for (const auto& ent : buckets.get_buckets()) { + const std::string &bname = ent.first; + + r = db->delete_stale_objs(dpp, bname, gc_obj_min_wait); + + if (r < 0) { //do nothing? skip to next entry? + ldpp_dout(dpp, 2) << " delete_stale_objs failed for bucket( " << bname <<")" << dendl; + } + bucket_marker = bname; + user_marker = user.id; + + /* XXX: If using locks, unlock here and reacquire in the next iteration */ + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } while(is_truncated); + + bucket_marker.clear(); + std::this_thread::sleep_for(std::chrono::milliseconds(gc_interval)); + + } while(1); + + return nullptr; +} + } } // namespace rgw::store diff --git a/src/rgw/store/dbstore/common/dbstore.h b/src/rgw/store/dbstore/common/dbstore.h index 1f86a6149e6..2a0e0bc2736 100644 --- a/src/rgw/store/dbstore/common/dbstore.h +++ b/src/rgw/store/dbstore/common/dbstore.h @@ -371,6 +371,7 @@ class ObjectOp { class UpdateObjectDataOp *UpdateObjectData; class GetObjectDataOp *GetObjectData; class DeleteObjectDataOp *DeleteObjectData; + class DeleteStaleObjectDataOp *DeleteStaleObjectData; virtual int InitializeObjectOps(std::string db_name, const DoutPrefixProvider *dpp) { return 0; } virtual int FreeObjectOps(const DoutPrefixProvider *dpp) { return 0; } @@ -426,8 +427,11 @@ class DBOp { const std::string CreateBucketTableQ = /* Corresponds to rgw::sal::Bucket + * + * For now only BucketName is made Primary key. Since buckets should + * be unique across users in rgw, OwnerID is not made part of primary key. + * However it is still referenced as foreign key * - * For now only BucketName is made Primary key. * If multiple tenants are stored in single .db handle, should * make both (BucketName, Tenant) as Primary Key. Also should * reference (UserID, Tenant) as Foreign key. @@ -582,6 +586,7 @@ class DBOp { PartNum INTEGER NOT NULL, \ Offset INTEGER, \ Size INTEGER, \ + Mtime BLOB, \ Data BLOB, \ PRIMARY KEY (ObjName, BucketName, ObjInstance, ObjID, MultipartPartStr, PartNum), \ FOREIGN KEY (BucketName) \ @@ -925,13 +930,31 @@ class ListUserBucketsOp: virtual public DBOp { SyncPolicyInfoGroups, BucketAttrs, BucketVersion, BucketVersionTag, Mtime \ FROM '{}' WHERE OwnerID = {} AND BucketName > {} ORDER BY BucketName ASC LIMIT {}"; + /* BucketNames are unique across users. Hence userid/OwnerID is not used as + * marker or for ordering here in the below query + */ + const std::string AllQuery = "SELECT \ + BucketName, Tenant, Marker, BucketID, Size, SizeRounded, CreationTime, \ + Count, PlacementName, PlacementStorageClass, OwnerID, Flags, Zonegroup, \ + HasInstanceObj, Quota, RequesterPays, HasWebsite, WebsiteConf, \ + SwiftVersioning, SwiftVerLocation, \ + MdsearchConfig, NewBucketInstanceID, ObjectLock, \ + SyncPolicyInfoGroups, BucketAttrs, BucketVersion, BucketVersionTag, Mtime \ + FROM '{}' WHERE BucketName > {} ORDER BY BucketName ASC LIMIT {}"; + public: virtual ~ListUserBucketsOp() {} std::string Schema(DBOpPrepareParams ¶ms) { - return fmt::format(Query.c_str(), params.bucket_table.c_str(), + if (params.op.query_str == "all") { + return fmt::format(AllQuery.c_str(), params.bucket_table.c_str(), + params.op.bucket.min_marker.c_str(), + params.op.list_max_count.c_str()); + } else { + return fmt::format(Query.c_str(), params.bucket_table.c_str(), params.op.user.user_id.c_str(), params.op.bucket.min_marker.c_str(), params.op.list_max_count.c_str()); + } } }; @@ -1148,8 +1171,8 @@ class PutObjectDataOp: virtual public DBOp { private: const std::string Query = "INSERT OR REPLACE INTO '{}' \ - (ObjName, ObjInstance, ObjNS, BucketName, ObjID, MultipartPartStr, PartNum, Offset, Size, Data) \ - VALUES ({}, {}, {}, {}, {}, {}, {}, {}, {}, {})"; + (ObjName, ObjInstance, ObjNS, BucketName, ObjID, MultipartPartStr, PartNum, Offset, Size, Mtime, Data) \ + VALUES ({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {})"; public: virtual ~PutObjectDataOp() {} @@ -1165,6 +1188,7 @@ class PutObjectDataOp: virtual public DBOp { params.op.obj_data.part_num, params.op.obj_data.offset.c_str(), params.op.obj_data.size, + params.op.obj.mtime, params.op.obj_data.data.c_str()); } }; @@ -1195,7 +1219,7 @@ class GetObjectDataOp: virtual public DBOp { private: const std::string Query = "SELECT \ - ObjName, ObjInstance, ObjNS, BucketName, ObjID, MultipartPartStr, PartNum, Offset, Size, Data \ + ObjName, ObjInstance, ObjNS, BucketName, ObjID, MultipartPartStr, PartNum, Offset, Size, Mtime, Data \ from '{}' where BucketName = {} and ObjName = {} and ObjInstance = {} and ObjID = {} ORDER BY MultipartPartStr, PartNum"; public: @@ -1229,6 +1253,23 @@ class DeleteObjectDataOp: virtual public DBOp { } }; +class DeleteStaleObjectDataOp: virtual public DBOp { + private: + const std::string Query = + "DELETE from '{}' WHERE (ObjName, ObjInstance, ObjID) NOT IN (SELECT s.ObjName, s.ObjInstance, s.ObjID from '{}' as s INNER JOIN '{}' USING (ObjName, BucketName, ObjInstance, ObjID)) and Mtime > {}"; + + public: + virtual ~DeleteStaleObjectDataOp() {} + + std::string Schema(DBOpPrepareParams ¶ms) { + return fmt::format(Query.c_str(), + params.objectdata_table.c_str(), + params.objectdata_table.c_str(), + params.object_table.c_str(), + params.op.obj.mtime); + } +}; + class InsertLCEntryOp: virtual public DBOp { private: const std::string Query = @@ -1497,7 +1538,8 @@ class DB { int next_bucket_id() { return ++max_bucket_id; }; int remove_bucket(const DoutPrefixProvider *dpp, const RGWBucketInfo info); - int list_buckets(const DoutPrefixProvider *dpp, const rgw_user& user, + int list_buckets(const DoutPrefixProvider *dpp, const std::string& query_str, + rgw_user& user, const std::string& marker, const std::string& end_marker, uint64_t max, @@ -1591,6 +1633,31 @@ class DB { int write(const DoutPrefixProvider *dpp, int64_t ofs, int64_t write_ofs, uint64_t len, bufferlist& bl); }; + class GC : public Thread { + const DoutPrefixProvider *dpp; + DB *db; + /* Default time interval for GC + * XXX: Make below options configurable + * + * gc_interval: The time between successive gc thread runs + * gc_obj_min_wait: Min. time to wait before deleting any data post its creation. + * + */ + uint32_t gc_interval = 24*60*60*10; //msec ; default: 24*60*60*10 + uint32_t gc_obj_min_wait = 600; //600sec default + std::string bucket_marker; + std::string user_marker; + + public: + GC(const DoutPrefixProvider *_dpp, DB* _db) : + dpp(_dpp), db(_db) {} + + void *entry() override; + + friend class DB; + }; + std::unique_ptr gc_worker; + class Bucket { friend class DB; DB* store; @@ -1849,6 +1916,10 @@ class DB { int rm_entry(const std::string& oid, const rgw::sal::Lifecycle::LCEntry& entry); int get_head(const std::string& oid, rgw::sal::Lifecycle::LCHead& head); int put_head(const std::string& oid, const rgw::sal::Lifecycle::LCHead& head); + int delete_stale_objs(const DoutPrefixProvider *dpp, const std::string& bucket, + uint32_t min_wait); + int createGC(const DoutPrefixProvider *_dpp); + int stopGC(); }; struct db_get_obj_data { diff --git a/src/rgw/store/dbstore/sqlite/sqliteDB.cc b/src/rgw/store/dbstore/sqlite/sqliteDB.cc index f27db5f64cd..ee6eb9667f3 100644 --- a/src/rgw/store/dbstore/sqlite/sqliteDB.cc +++ b/src/rgw/store/dbstore/sqlite/sqliteDB.cc @@ -280,6 +280,7 @@ enum GetObjectData { PartNum, Offset, ObjDataSize, + ObjDataMtime, ObjData }; @@ -493,6 +494,7 @@ static int get_objectdata(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_s op.obj_data.offset = sqlite3_column_int(stmt, Offset); op.obj_data.size = sqlite3_column_int(stmt, ObjDataSize); op.obj_data.multipart_part_str = (const char*)sqlite3_column_text(stmt, MultipartPartStr); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ObjDataMtime, op.obj.state.mtime, sdb); SQL_DECODE_BLOB_PARAM(dpp, stmt, ObjData, op.obj_data.data, sdb); return 0; @@ -991,6 +993,7 @@ int SQLObjectOp::InitializeObjectOps(string db_name, const DoutPrefixProvider *d UpdateObjectData = new SQLUpdateObjectData(sdb, db_name, cct); GetObjectData = new SQLGetObjectData(sdb, db_name, cct); DeleteObjectData = new SQLDeleteObjectData(sdb, db_name, cct); + DeleteStaleObjectData = new SQLDeleteStaleObjectData(sdb, db_name, cct); return 0; } @@ -1005,6 +1008,7 @@ int SQLObjectOp::FreeObjectOps(const DoutPrefixProvider *dpp) delete UpdateObjectData; delete GetObjectData; delete DeleteObjectData; + delete DeleteStaleObjectData; return 0; } @@ -1284,6 +1288,7 @@ int SQLInsertBucket::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *para int rc = 0; struct DBOpPrepareParams p_params = PrepareParams; + // user_id here is copied as OwnerID in the bucket table. SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_id.c_str(), sdb); SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); @@ -1646,7 +1651,12 @@ int SQLListUserBuckets::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams p_params.bucket_table = params->bucket_table; - SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareListUserBuckets"); + p_params.op.query_str = params->op.query_str; + if (params->op.query_str == "all") { + SQL_PREPARE(dpp, p_params, sdb, all_stmt, ret, "PrepareListUserBuckets"); + }else { + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareListUserBuckets"); + } out: return ret; @@ -1657,15 +1667,24 @@ int SQLListUserBuckets::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *p int index = -1; int rc = 0; struct DBOpPrepareParams p_params = PrepareParams; + sqlite3_stmt** pstmt = NULL; // Prepared statement - SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_id.c_str(), sdb); - SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); + if (params->op.query_str == "all") { + pstmt = &all_stmt; + } else { + pstmt = &stmt; + } + + if (params->op.query_str != "all") { + SQL_BIND_INDEX(dpp, *pstmt, index, p_params.op.user.user_id.c_str(), sdb); + SQL_BIND_TEXT(dpp, *pstmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); + } - SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.min_marker.c_str(), sdb); - SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.min_marker.c_str(), sdb); + SQL_BIND_INDEX(dpp, *pstmt, index, p_params.op.bucket.min_marker.c_str(), sdb); + SQL_BIND_TEXT(dpp, *pstmt, index, params->op.bucket.min_marker.c_str(), sdb); - SQL_BIND_INDEX(dpp, stmt, index, p_params.op.list_max_count.c_str(), sdb); - SQL_BIND_INT(dpp, stmt, index, params->op.list_max_count, sdb); + SQL_BIND_INDEX(dpp, *pstmt, index, p_params.op.list_max_count.c_str(), sdb); + SQL_BIND_INT(dpp, *pstmt, index, params->op.list_max_count, sdb); out: return rc; @@ -1675,7 +1694,11 @@ int SQLListUserBuckets::Execute(const DoutPrefixProvider *dpp, struct DBOpParams { int ret = -1; - SQL_EXECUTE(dpp, params, stmt, list_bucket); + if (params->op.query_str == "all") { + SQL_EXECUTE(dpp, params, all_stmt, list_bucket); + } else { + SQL_EXECUTE(dpp, params, stmt, list_bucket); + } out: return ret; } @@ -2347,6 +2370,9 @@ int SQLPutObjectData::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *par SQL_BIND_TEXT(dpp, stmt, index, params->op.obj_data.multipart_part_str.c_str(), sdb); + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.mtime.c_str(), sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.state.mtime, sdb); + out: return rc; } @@ -2554,6 +2580,56 @@ out: return ret; } +int SQLDeleteStaleObjectData::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + struct DBOpParams copy = *params; + string bucket_name = params->op.bucket.info.bucket.name; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLDeleteStaleObjectData - no db" << dendl; + goto out; + } + + if (p_params.object_table.empty()) { + p_params.object_table = getObjectTable(bucket_name); + } + if (p_params.objectdata_table.empty()) { + p_params.objectdata_table = getObjectDataTable(bucket_name); + } + params->object_table = p_params.object_table; + params->objectdata_table = p_params.objectdata_table; + (void)createObjectDataTable(dpp, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareDeleteStaleObjectData"); + +out: + return ret; +} + +int SQLDeleteStaleObjectData::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.mtime.c_str(), sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.state.mtime, sdb); + +out: + return rc; +} + +int SQLDeleteStaleObjectData::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + int SQLInsertLCEntry::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) { int ret = -1; diff --git a/src/rgw/store/dbstore/sqlite/sqliteDB.h b/src/rgw/store/dbstore/sqlite/sqliteDB.h index dd56ab1f9ec..b83296c5a86 100644 --- a/src/rgw/store/dbstore/sqlite/sqliteDB.h +++ b/src/rgw/store/dbstore/sqlite/sqliteDB.h @@ -213,12 +213,15 @@ class SQLListUserBuckets : public SQLiteDB, public ListUserBucketsOp { private: sqlite3 **sdb = NULL; sqlite3_stmt *stmt = NULL; // Prepared statement + sqlite3_stmt *all_stmt = NULL; // Prepared statement public: SQLListUserBuckets(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} ~SQLListUserBuckets() { if (stmt) sqlite3_finalize(stmt); + if (all_stmt) + sqlite3_finalize(all_stmt); } int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); @@ -395,6 +398,24 @@ class SQLDeleteObjectData : public SQLiteDB, public DeleteObjectDataOp { int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); }; +class SQLDeleteStaleObjectData : public SQLiteDB, public DeleteStaleObjectDataOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLDeleteStaleObjectData(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLDeleteStaleObjectData(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLDeleteStaleObjectData() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + class SQLInsertLCEntry : public SQLiteDB, public InsertLCEntryOp { private: sqlite3 **sdb = NULL; diff --git a/src/rgw/store/dbstore/tests/dbstore_tests.cc b/src/rgw/store/dbstore/tests/dbstore_tests.cc index 608def7e83a..481ad5be4c2 100644 --- a/src/rgw/store/dbstore/tests/dbstore_tests.cc +++ b/src/rgw/store/dbstore/tests/dbstore_tests.cc @@ -390,19 +390,6 @@ TEST_F(DBStoreTest, UpdateBucketAttrs) { ASSERT_EQ(objv.read_version.ver, 2); } -TEST_F(DBStoreTest, BucketChown) { - int ret = -1; - RGWBucketInfo info; - rgw_user user; - user.id = "user_id2"; - - info.bucket.name = "bucket1"; - - ret = db->update_bucket(dpp, "owner", info, false, &user, nullptr, &bucket_mtime, nullptr); - ASSERT_EQ(ret, 0); - ASSERT_EQ(info.objv_tracker.read_version.ver, 3); -} - TEST_F(DBStoreTest, UpdateBucketInfo) { struct DBOpParams params = GlobalParams; int ret = -1; @@ -418,13 +405,14 @@ TEST_F(DBStoreTest, UpdateBucketInfo) { info.bucket.marker = "marker2"; ret = db->update_bucket(dpp, "info", info, false, nullptr, nullptr, &bucket_mtime, nullptr); ASSERT_EQ(ret, 0); - ASSERT_EQ(info.objv_tracker.read_version.ver, 4); + ASSERT_EQ(info.objv_tracker.read_version.ver, 3); } TEST_F(DBStoreTest, GetBucket) { struct DBOpParams params = GlobalParams; int ret = -1; + params.op.bucket.info.bucket.name = "bucket1"; ret = db->ProcessOp(dpp, "GetBucket", ¶ms); ASSERT_EQ(ret, 0); ASSERT_EQ(params.op.bucket.info.bucket.name, "bucket1"); @@ -434,10 +422,10 @@ TEST_F(DBStoreTest, GetBucket) { ASSERT_EQ(params.op.bucket.ent.bucket.name, "bucket1"); ASSERT_EQ(params.op.bucket.ent.bucket.tenant, "tenant"); ASSERT_EQ(params.op.bucket.info.has_instance_obj, false); - ASSERT_EQ(params.op.bucket.info.objv_tracker.read_version.ver, 4); + ASSERT_EQ(params.op.bucket.info.objv_tracker.read_version.ver, 3); ASSERT_EQ(params.op.bucket.info.objv_tracker.read_version.tag, "read_tag"); ASSERT_EQ(params.op.bucket.mtime, bucket_mtime); - ASSERT_EQ(params.op.bucket.info.owner.id, "user_id2"); + ASSERT_EQ(params.op.bucket.info.owner.id, "user_id1"); bufferlist k, k2; string acl; map::iterator it2 = params.op.bucket.bucket_attrs.begin(); @@ -450,35 +438,6 @@ TEST_F(DBStoreTest, GetBucket) { ASSERT_EQ(acl, "attrs2"); } -TEST_F(DBStoreTest, RemoveBucketAPI) { - int ret = -1; - RGWBucketInfo info; - - info.bucket.name = "bucket1"; - - ret = db->remove_bucket(dpp, info); - ASSERT_EQ(ret, 0); -} - -TEST_F(DBStoreTest, RemoveUserAPI) { - int ret = -1; - RGWUserInfo uinfo; - RGWObjVersionTracker objv; - - uinfo.user_id.tenant = "tenant"; - uinfo.user_id.id = "user_id2"; - - /* invalid version number...should fail */ - objv.read_version.ver = 4; - ret = db->remove_user(dpp, uinfo, &objv); - ASSERT_EQ(ret, -125); - - /* invalid version number...should fail */ - objv.read_version.ver = 2; - ret = db->remove_user(dpp, uinfo, &objv); - ASSERT_EQ(ret, 0); -} - TEST_F(DBStoreTest, CreateBucket) { struct DBOpParams params = GlobalParams; int ret = -1; @@ -564,7 +523,8 @@ TEST_F(DBStoreTest, ListUserBuckets) { marker1 = ""; do { is_truncated = false; - ret = db->list_buckets(dpp, owner, marker1, "", max, need_stats, &ulist, &is_truncated); + ret = db->list_buckets(dpp, "", owner, marker1, "", max, need_stats, &ulist, + &is_truncated); ASSERT_EQ(ret, 0); cout << "marker1 :" << marker1 << "\n"; @@ -586,6 +546,19 @@ TEST_F(DBStoreTest, ListUserBuckets) { } while(is_truncated); } +TEST_F(DBStoreTest, BucketChown) { + int ret = -1; + RGWBucketInfo info; + rgw_user user; + user.id = "user_id2"; + + info.bucket.name = "bucket5"; + + ret = db->update_bucket(dpp, "owner", info, false, &user, nullptr, &bucket_mtime, nullptr); + ASSERT_EQ(ret, 0); + ASSERT_EQ(info.objv_tracker.read_version.ver, 3); +} + TEST_F(DBStoreTest, ListAllBuckets) { struct DBOpParams params = GlobalParams; int ret = -1; @@ -594,6 +567,72 @@ TEST_F(DBStoreTest, ListAllBuckets) { ASSERT_EQ(ret, 0); } +TEST_F(DBStoreTest, ListAllBuckets2) { + struct DBOpParams params = GlobalParams; + int ret = -1; + rgw_user owner; + int max = 2; + bool need_stats = true; + bool is_truncated = false; + RGWUserBuckets ulist; + + marker1 = ""; + do { + is_truncated = false; + ret = db->list_buckets(dpp, "all", owner, marker1, "", max, need_stats, &ulist, + &is_truncated); + ASSERT_EQ(ret, 0); + + cout << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \n"; + cout << "ownerID : " << owner.id << "\n"; + cout << "marker1 :" << marker1 << "\n"; + + cout << "is_truncated :" << is_truncated << "\n"; + + for (const auto& ent: ulist.get_buckets()) { + RGWBucketEnt e = ent.second; + cout << "###################### \n"; + cout << "ent.bucket.id : " << e.bucket.name << "\n"; + cout << "ent.bucket.marker : " << e.bucket.marker << "\n"; + cout << "ent.bucket.bucket_id : " << e.bucket.bucket_id << "\n"; + cout << "ent.size : " << e.size << "\n"; + cout << "ent.rule.name : " << e.placement_rule.name << "\n"; + + marker1 = e.bucket.name; + } + ulist.clear(); + } while(is_truncated); +} + +TEST_F(DBStoreTest, RemoveBucketAPI) { + int ret = -1; + RGWBucketInfo info; + + info.bucket.name = "bucket5"; + + ret = db->remove_bucket(dpp, info); + ASSERT_EQ(ret, 0); +} + +TEST_F(DBStoreTest, RemoveUserAPI) { + int ret = -1; + RGWUserInfo uinfo; + RGWObjVersionTracker objv; + + uinfo.user_id.tenant = "tenant"; + uinfo.user_id.id = "user_id2"; + + /* invalid version number...should fail */ + objv.read_version.ver = 4; + ret = db->remove_user(dpp, uinfo, &objv); + ASSERT_EQ(ret, -125); + + /* invalid version number...should fail */ + objv.read_version.ver = 2; + ret = db->remove_user(dpp, uinfo, &objv); + ASSERT_EQ(ret, 0); +} + TEST_F(DBStoreTest, PutObject) { struct DBOpParams params = GlobalParams; int ret = -1; -- 2.39.5