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;
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
return ret;
}
+int DB::createGC(const DoutPrefixProvider *dpp) {
+ int ret = 0;
+ /* create gc thread */
+
+ gc_worker = std::make_unique<DB::GC>(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);
return Ob->GetObjectData;
if (!Op.compare("DeleteObjectData"))
return Ob->DeleteObjectData;
+ if (!Op.compare("DeleteStaleObjectData"))
+ return Ob->DeleteStaleObjectData;
return NULL;
}
// 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("\
<<bucket<<"). Not inserted " << dendl;
delete ptr;
return 0;
return ret;
}
-int DB::list_buckets(const DoutPrefixProvider *dpp, const rgw_user& user,
+int DB::list_buckets(const DoutPrefixProvider *dpp, const std::string& query_str,
+ rgw_user& user,
const string& marker,
const string& end_marker,
uint64_t max,
params.op.bucket.min_marker = marker;
params.op.bucket.max_marker = end_marker;
params.op.list_max_count = max;
+ params.op.query_str = query_str;
ret = ProcessOp(dpp, "ListUserBuckets", ¶ms);
}
buckets->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;
}
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);
gen_rand_alphanumeric(store->ctx(), buf, sizeof(buf) - 1);
target->obj_id = target->obj.key.name + "." + buf;
}
-
- ret = 0;
+ ret = 0;
return ret;
}
/* XXX: handle multipart */
params.op.query_str = "meta";
+ params.op.obj.obj_id = target->obj_id;
ret = store->ProcessOp(dpp, "PutObject", ¶ms);
if (ret) {
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:(" <<ret<<")" << dendl;
+ }
+
+ ldpp_dout(dpp, 30) << " Deleting stale_objs of bucket( " << bucket <<")" << dendl;
+ /* XXX: handle reads racing with delete here. Simple approach is maybe
+ * to use locks or sqlite transactions.
+ */
+ InitializeParams(dpp, "DeleteStaleObjectData", ¶ms);
+ params.op.obj.state.mtime = (real_clock::now() + make_timespan(min_wait));
+ ret = ProcessOp(dpp, "DeleteStaleObjectData", ¶ms);
+ if (ret) {
+ ldpp_dout(dpp, 0) << "In DeleteStaleObjectData failed err:(" <<ret<<")" << dendl;
+ }
+
+ return ret;
+}
+
+void *DB::GC::entry() {
+ do {
+ ldpp_dout(dpp, 2) << " DB GC started " << dendl;
+ int max = 100;
+ RGWUserBuckets buckets;
+ bool is_truncated = false;
+
+ do {
+ std::string& marker = bucket_marker;
+ rgw_user user;
+ user.id = user_marker;
+ buckets.clear();
+
+ int r = db->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
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; }
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.
PartNum INTEGER NOT NULL, \
Offset INTEGER, \
Size INTEGER, \
+ Mtime BLOB, \
Data BLOB, \
PRIMARY KEY (ObjName, BucketName, ObjInstance, ObjID, MultipartPartStr, PartNum), \
FOREIGN KEY (BucketName) \
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());
+ }
}
};
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() {}
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());
}
};
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:
}
};
+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 =
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,
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<DB::GC> gc_worker;
+
class Bucket {
friend class DB;
DB* store;
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 {
PartNum,
Offset,
ObjDataSize,
+ ObjDataMtime,
ObjData
};
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;
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;
}
delete UpdateObjectData;
delete GetObjectData;
delete DeleteObjectData;
+ delete DeleteStaleObjectData;
return 0;
}
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);
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;
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;
{
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;
}
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;
}
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;
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);
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;
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;
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");
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<std::string, bufferlist>::iterator it2 = params.op.bucket.bucket_attrs.begin();
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;
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";
} 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;
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;