params->cct = cct;
//reset params here
+ params->account_table = account_table;
params->user_table = user_table;
params->bucket_table = bucket_table;
params->quota_table = quota_table;
return ret;
}
+int DB::get_account(const DoutPrefixProvider *dpp,
+ const std::string& query_str, const std::string& query_str_val,
+ RGWAccountInfo& ainfo, map<string, bufferlist> *pattrs,
+ RGWObjVersionTracker *pobjv_tracker) {
+ int ret = 0;
+
+ if (query_str.empty() || query_str_val.empty()) {
+ ldpp_dout(dpp, 0)<<"In GetAccount - Invalid query(" << query_str <<"), query_str_val(" << query_str_val <<")" << dendl;
+ return -1;
+ }
+
+ DBOpParams params = {};
+ InitializeParams(dpp, ¶ms);
+
+ params.op.query_str = query_str;
+
+ // validate query_str with AccountTable entries names
+ if (query_str == "name") {
+ params.op.account.info.name = query_str_val;
+ } else if (query_str == "email") {
+ params.op.account.info.email = query_str_val;
+ } else if (query_str == "account_id") {
+ params.op.account.info.id = query_str_val;
+ } else {
+ ldpp_dout(dpp, 0)<<"In GetAccount Invalid query string :" <<query_str.c_str()<<") " << dendl;
+ return -1;
+ }
+
+ ret = ProcessOp(dpp, "GetAccount", ¶ms);
+
+ if (ret) {
+ return ret;
+ }
+
+ /* Verify if its a valid account */
+ if (params.op.account.info.id.empty()) {
+ ldpp_dout(dpp, 0)<<"In GetAccount - No account with query(" <<query_str.c_str()<<"), account_id(" << ainfo.id <<") found" << dendl;
+ return -ENOENT;
+ }
+
+ ainfo = params.op.account.info;
+
+ if (pattrs) {
+ *pattrs = params.op.account.account_attrs;
+ }
+
+ if (pobjv_tracker) {
+ pobjv_tracker->read_version = params.op.account.account_version;
+ }
+
+ return ret;
+}
+
+int DB::store_account(const DoutPrefixProvider *dpp,
+ const RGWAccountInfo& ainfo, bool exclusive, const map<string, bufferlist> *pattrs,
+ RGWObjVersionTracker *pobjv)
+{
+ DBOpParams params = {};
+ InitializeParams(dpp, ¶ms);
+ int ret = 0;
+
+ /* Check if the account already exists and return the old info, caller will have a use for it */
+ RGWAccountInfo orig_info;
+ RGWObjVersionTracker objv_tracker = {};
+ obj_version& obj_ver = objv_tracker.read_version;
+
+ orig_info.id = ainfo.id;
+ ret = get_account(dpp, string("account_id"), ainfo.id, orig_info, nullptr, &objv_tracker);
+
+ if (!ret && obj_ver.ver) {
+ /* already exists. */
+ if (pobjv && (pobjv->read_version.ver != obj_ver.ver)) {
+ /* Object version mismatch.. return ECANCELED */
+ ret = -ECANCELED;
+ ldpp_dout(dpp, 0)<<"Account Read version mismatch err:(" <<ret<<") " << dendl;
+ return ret;
+ }
+
+ if (exclusive) {
+ // return
+ return ret;
+ }
+ obj_ver.ver++;
+ } else {
+ obj_ver.ver = 1;
+ obj_ver.tag = "AccountTAG";
+ }
+
+ params.op.account.account_version = obj_ver;
+ params.op.account.info = ainfo;
+
+ if (pattrs) {
+ params.op.account.account_attrs = *pattrs;
+ }
+
+ ret = ProcessOp(dpp, "InsertAccount", ¶ms);
+
+ if (ret) {
+ ldpp_dout(dpp, 0)<<"store_account failed with err:(" <<ret<<") " << dendl;
+ return ret;
+ }
+ ldpp_dout(dpp, 20)<<"Account creation successful - account_id:(" <<ainfo.id<<") " << dendl;
+
+ if (pobjv) {
+ pobjv->read_version = obj_ver;
+ pobjv->write_version = obj_ver;
+ }
+
+ return ret;
+}
+
+int DB::remove_account(const DoutPrefixProvider *dpp,
+ const RGWAccountInfo &ainfo, RGWObjVersionTracker *pobjv)
+{
+ DBOpParams params = {};
+ InitializeParams(dpp, ¶ms);
+ int ret = 0;
+
+ RGWAccountInfo orig_info;
+ RGWObjVersionTracker objv_tracker = {};
+
+ orig_info.id = ainfo.id;
+ ret = get_account(dpp, string("account_id"), ainfo.id, orig_info, nullptr, &objv_tracker);
+
+ if (ret) {
+ return ret;
+ }
+
+ if (!ret && objv_tracker.read_version.ver) {
+ /* already exists. */
+
+ if (pobjv && (pobjv->read_version.ver != objv_tracker.read_version.ver)) {
+ /* Object version mismatch.. return ECANCELED */
+ ret = -ECANCELED;
+ ldpp_dout(dpp, 0)<<"Account Read version mismatch err:(" <<ret<<") " << dendl;
+ return ret;
+ }
+ }
+
+ params.op.account.info.id = ainfo.id;
+
+ ret = ProcessOp(dpp, "RemoveAccount", ¶ms);
+
+ if (ret) {
+ ldpp_dout(dpp, 0)<<"remove_account failed with err:(" <<ret<<") " << dendl;
+ return ret;
+ }
+
+ return ret;
+}
+
int DB::get_bucket_info(const DoutPrefixProvider *dpp, const std::string& query_str,
const std::string& query_str_val,
RGWBucketInfo& info,
class DB;
+struct DBOpAccountInfo {
+ RGWAccountInfo info = {};
+ obj_version account_version;
+ rgw::sal::Attrs account_attrs;
+};
+
struct DBOpUserInfo {
RGWUserInfo uinfo = {};
obj_version user_version;
* be able to query easily.
*
* XXX: Swift keys and subuser not supported for now */
+ DBOpAccountInfo account;
DBOpUserInfo user;
std::string query_str;
DBOpBucketInfo bucket;
CephContext *cct;
/* Tables */
+ std::string account_table;
std::string user_table;
std::string bucket_table;
std::string object_table;
* These identifiers are used in prepare and bind statements
* to get the right index of each param.
*/
+struct DBOpAccountPrepareInfo {
+ static constexpr const char* account_id = ":account_id";
+ static constexpr const char* tenant = ":tenant";
+ static constexpr const char* account_name = ":account_name";
+ static constexpr const char* email = ":email";
+ static constexpr const char* quota = ":quota";
+ static constexpr const char* bucket_quota = ":bucket_quota";
+ static constexpr const char* max_users = ":max_users";
+ static constexpr const char* max_roles = ":max_roles";
+ static constexpr const char* max_groups = ":max_groups";
+ static constexpr const char* max_buckets = ":max_buckets";
+ static constexpr const char* max_access_keys = ":max_access_keys";
+};
+
struct DBOpUserPrepareInfo {
static constexpr const char* user_id = ":user_id";
static constexpr const char* tenant = ":tenant";
};
struct DBOpPrepareInfo {
+ DBOpAccountPrepareInfo account;
DBOpUserPrepareInfo user;
std::string_view query_str; // view into DBOpInfo::query_str
DBOpBucketPrepareInfo bucket;
struct DBOpPrepareParams {
/* Tables */
+ std::string account_table;
std::string user_table;
std::string bucket_table;
std::string object_table;
};
struct DBOps {
+ std::shared_ptr<class InsertAccountOp> InsertAccount;
+ std::shared_ptr<class RemoveAccountOp> RemoveAccount;
+ std::shared_ptr<class GetAccountOp> GetAccount;
std::shared_ptr<class InsertUserOp> InsertUser;
std::shared_ptr<class RemoveUserOp> RemoveUser;
std::shared_ptr<class GetUserOp> GetUser;
class DBOp {
private:
+ static constexpr std::string_view CreateAccountTableQ =
+ /* Corresponds to RGWAccountInfo
+ *
+ * AccountID is made Primary key.
+ * If multiple tenants are stored in single .db handle, should
+ * make both (AccountID, Tenant) as Primary Key.
+ *
+ * XXX:
+ * - Quota stored as blob .. should be linked to quota table.
+ */
+ "CREATE TABLE IF NOT EXISTS '{}' ( \
+ AccountID TEXT NOT NULL UNIQUE, \
+ Tenant TEXT , \
+ AccountName TEXT , \
+ Email TEXT , \
+ Quota BLOB , \
+ BucketQuota BLOB , \
+ MaxUsers INTEGER , \
+ MaxRoles INTEGER , \
+ MaxGroups INTEGER , \
+ MaxBuckets INTEGER , \
+ MaxAccessKeys INTEGER , \
+ PRIMARY KEY (AccountID) \n);";
+
static constexpr std::string_view CreateUserTableQ =
/* Corresponds to rgw::sal::User
*
static std::string CreateTableSchema(std::string_view type,
const DBOpParams *params) {
+ if (!type.compare("Account"))
+ return fmt::format(CreateAccountTableQ,
+ params->account_table);
if (!type.compare("User"))
return fmt::format(CreateUserTableQ,
params->user_table);
virtual int Execute(const DoutPrefixProvider *dpp, DBOpParams *params) { return 0; }
};
+class InsertAccountOp : virtual public DBOp {
+ private:
+ static constexpr std::string_view Query = "INSERT OR REPLACE INTO '{}' \
+ (AccountID, Tenant, AccountName, Email, \
+ Quota, BucketQuota, MaxUsers, MaxRoles, MaxGroups, \
+ MaxBuckets, MaxAccessKeys) \
+ VALUES ({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});";
+
+ public:
+ virtual ~InsertAccountOp() {}
+
+ static std::string Schema(DBOpPrepareParams ¶ms) {
+ return fmt::format(Query, params.account_table,
+ params.op.account.account_id, params.op.account.tenant,
+ params.op.account.account_name, params.op.account.email,
+ params.op.account.quota, params.op.account.bucket_quota,
+ params.op.account.max_users, params.op.account.max_roles,
+ params.op.account.max_groups, params.op.account.max_buckets,
+ params.op.account.max_access_keys);
+ }
+};
+
+class RemoveAccountOp: virtual public DBOp {
+ private:
+ static constexpr std::string_view Query =
+ "DELETE from '{}' where AccountID = {}";
+
+ public:
+ virtual ~RemoveAccountOp() {}
+
+ static std::string Schema(DBOpPrepareParams ¶ms) {
+ return fmt::format(Query, params.account_table,
+ params.op.account.account_id);
+ }
+};
+
+class GetAccountOp: virtual public DBOp {
+ private:
+ static constexpr std::string_view Query = "SELECT \
+ AccountID, Tenant, AccountName, Email, \
+ Quota, BucketQuota, MaxUsers, MaxRoles, MaxGroups, \
+ MaxBuckets, MaxAccessKeys from '{}' where AccountID = {}";
+
+ static constexpr std::string_view QueryByName = "SELECT \
+ AccountID, Tenant, AccountName, Email, \
+ Quota, BucketQuota, MaxUsers, MaxRoles, MaxGroups, \
+ MaxBuckets, MaxAccessKeys from '{}' where AccountName = {}";
+
+ static constexpr std::string_view QueryByEmail = "SELECT \
+ AccountID, Tenant, AccountName, Email, \
+ Quota, BucketQuota, MaxUsers, MaxRoles, MaxGroups, \
+ MaxBuckets, MaxAccessKeys from '{}' where Email = {}";
+
+ public:
+ virtual ~GetAccountOp() {}
+
+ static std::string Schema(DBOpPrepareParams ¶ms) {
+ if (params.op.query_str == "name") {
+ return fmt::format(QueryByName, params.account_table,
+ params.op.account.account_name);
+ } else if (params.op.query_str == "email") {
+ return fmt::format(QueryByEmail, params.account_table,
+ params.op.account.email);
+ } else {
+ return fmt::format(Query, params.account_table,
+ params.op.account.account_id);
+ }
+ }
+};
+
class InsertUserOp : virtual public DBOp {
private:
/* For existing entires, -
private:
const std::string db_name;
rgw::sal::Driver* driver;
+ const std::string account_table;
const std::string user_table;
const std::string bucket_table;
const std::string quota_table;
public:
DB(std::string db_name, CephContext *_cct) : db_name(db_name),
+ account_table(db_name+"_account_table"),
user_table(db_name+"_user_table"),
bucket_table(db_name+"_bucket_table"),
quota_table(db_name+"_quota_table"),
/* DB() {}*/
DB(CephContext *_cct) : db_name("default_db"),
+ account_table(db_name+"_account_table"),
user_table(db_name+"_user_table"),
bucket_table(db_name+"_bucket_table"),
quota_table(db_name+"_quota_table"),
const std::string getDBname() { return db_name; }
const std::string getDBfile() { return db_name + ".db"; }
+ const std::string getAccountTable() { return account_table; }
const std::string getUserTable() { return user_table; }
const std::string getBucketTable() { return bucket_table; }
const std::string getQuotaTable() { return quota_table; }
RGWObjVersionTracker *pobjv_tracker, RGWUserInfo* pold_info);
int remove_user(const DoutPrefixProvider *dpp,
RGWUserInfo& uinfo, RGWObjVersionTracker *pobjv_tracker);
+ int get_account(const DoutPrefixProvider *dpp,
+ const std::string& query_str, const std::string& query_str_val,
+ RGWAccountInfo& ainfo, std::map<std::string, bufferlist> *pattrs,
+ RGWObjVersionTracker *pobjv_tracker);
+ int store_account(const DoutPrefixProvider *dpp,
+ const RGWAccountInfo& ainfo, bool exclusive, const std::map<std::string, bufferlist> *pattrs,
+ RGWObjVersionTracker *pobjv_tracker);
+ int remove_account(const DoutPrefixProvider *dpp,
+ const RGWAccountInfo &ainfo, RGWObjVersionTracker *pobjv_tracker);
int get_bucket_info(const DoutPrefixProvider *dpp, const std::string& query_str,
const std::string& query_str_val,
RGWBucketInfo& info, rgw::sal::Attrs* pattrs, ceph::real_time* pmtime,
if (!params)
return -1;
- if (params->user_table.empty()) {
- params->user_table = getUserTable();
+ if (params->account_table.empty()) {
+ params->account_table = getAccountTable();
}
if (params->user_table.empty()) {
params->user_table = getUserTable();
params->lc_head_table = getLCHeadTable();
}
+ p_params.account_table = params->account_table;
p_params.user_table = params->user_table;
p_params.bucket_table = params->bucket_table;
p_params.quota_table = params->quota_table;
return 0;
}
+enum GetAccount {
+ AccountID = 0,
+ AccountTenant,
+ AccountName,
+ Email,
+ AccountQuota,
+ AccountBucketQuota,
+ MaxUsers,
+ MaxRoles,
+ MaxGroups,
+ AccountMaxBuckets,
+ MaxAccessKeys,
+};
+
enum GetUser {
UserID = 0,
Tenant,
LCHeadStartDate
};
+static int list_account(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) {
+ if (!stmt)
+ return -1;
+
+ op.account.info.id = (const char*)sqlite3_column_text(stmt, AccountID);
+ op.account.info.tenant = (const char*)sqlite3_column_text(stmt, AccountTenant);
+ op.account.info.name = (const char*)sqlite3_column_text(stmt, AccountName);
+ op.account.info.email = (const char*)sqlite3_column_text(stmt, Email);
+
+ SQL_DECODE_BLOB_PARAM(dpp, stmt, AccountQuota, op.account.info.quota, sdb);
+ SQL_DECODE_BLOB_PARAM(dpp, stmt, AccountBucketQuota, op.account.info.bucket_quota, sdb);
+
+ op.account.info.max_users = sqlite3_column_int(stmt, MaxUsers);
+ op.account.info.max_roles = sqlite3_column_int(stmt, MaxRoles);
+ op.account.info.max_groups = sqlite3_column_int(stmt, MaxGroups);
+ op.account.info.max_buckets = sqlite3_column_int(stmt, AccountMaxBuckets);
+ op.account.info.max_access_keys = sqlite3_column_int(stmt, MaxAccessKeys);
+
+ return 0;
+}
+
static int list_user(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) {
if (!stmt)
return -1;
int SQLiteDB::InitializeDBOps(const DoutPrefixProvider *dpp)
{
(void)createTables(dpp);
+ dbops.InsertAccount = make_shared<SQLInsertAccount>(&this->db, this->getDBname(), cct);
+ dbops.RemoveAccount = make_shared<SQLRemoveAccount>(&this->db, this->getDBname(), cct);
+ dbops.GetAccount = make_shared<SQLGetAccount>(&this->db, this->getDBname(), cct);
dbops.InsertUser = make_shared<SQLInsertUser>(&this->db, this->getDBname(), cct);
dbops.RemoveUser = make_shared<SQLRemoveUser>(&this->db, this->getDBname(), cct);
dbops.GetUser = make_shared<SQLGetUser>(&this->db, this->getDBname(), cct);
int SQLiteDB::createTables(const DoutPrefixProvider *dpp)
{
int ret = -1;
- int cu = 0, cb = 0, cq = 0;
+ int ca = 0, cu = 0, cb = 0, cq = 0;
DBOpParams params = {};
+ params.account_table = getAccountTable();
params.user_table = getUserTable();
params.bucket_table = getBucketTable();
+ if ((ca = createAccountTable(dpp, ¶ms)))
+ goto out;
+
if ((cu = createUserTable(dpp, ¶ms)))
goto out;
ret = 0;
out:
if (ret) {
+ if (ca)
+ DeleteAccountTable(dpp, ¶ms);
if (cu)
DeleteUserTable(dpp, ¶ms);
if (cb)
return ret;
}
+int SQLiteDB::createAccountTable(const DoutPrefixProvider *dpp, DBOpParams *params)
+{
+ int ret = -1;
+ string schema;
+
+ schema = CreateTableSchema("Account", params);
+
+ ret = exec(dpp, schema.c_str(), NULL);
+ if (ret)
+ ldpp_dout(dpp, 0)<<"CreateAccountTable failed" << dendl;
+
+ ldpp_dout(dpp, 20)<<"CreateAccountTable succeeded" << dendl;
+
+ return ret;
+}
+
int SQLiteDB::createUserTable(const DoutPrefixProvider *dpp, DBOpParams *params)
{
int ret = -1;
return ret;
}
+int SQLiteDB::DeleteAccountTable(const DoutPrefixProvider *dpp, DBOpParams *params)
+{
+ int ret = -1;
+ string schema;
+
+ schema = DeleteTableSchema(params->account_table);
+
+ ret = exec(dpp, schema.c_str(), NULL);
+ if (ret)
+ ldpp_dout(dpp, 0)<<"DeleteAccountTable failed " << dendl;
+
+ ldpp_dout(dpp, 20)<<"DeleteAccountTable succeeded " << dendl;
+
+ return ret;
+}
+
int SQLiteDB::DeleteUserTable(const DoutPrefixProvider *dpp, DBOpParams *params)
{
int ret = -1;
return 0;
}
+int SQLInsertAccount::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params)
+{
+ int ret = -1;
+ struct DBOpPrepareParams p_params = PrepareParams;
+
+ if (!*sdb) {
+ ldpp_dout(dpp, 0)<<"In SQLInsertAccount - no db" << dendl;
+ goto out;
+ }
+
+ InitPrepareParams(dpp, p_params, params);
+
+ SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareInsertAccount");
+out:
+ return ret;
+}
+
+int SQLInsertAccount::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.account.account_id, sdb);
+ SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.id.c_str(), sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.tenant, sdb);
+ SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.tenant.c_str(), sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.account_name, sdb);
+ SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.name.c_str(), sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.email, sdb);
+ SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.email.c_str(), sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.quota, sdb);
+ SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.account.info.quota, sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.bucket_quota, sdb);
+ SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.account.info.bucket_quota, sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_users, sdb);
+ SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_users, sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_roles, sdb);
+ SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_roles, sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_groups, sdb);
+ SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_groups, sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_buckets, sdb);
+ SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_buckets, sdb);
+
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_access_keys, sdb);
+ SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_access_keys, sdb);
+
+out:
+ return rc;
+}
+
+int SQLInsertAccount::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params)
+{
+ int ret = -1;
+
+ SQL_EXECUTE(dpp, params, stmt, NULL);
+out:
+ return ret;
+}
+
+int SQLRemoveAccount::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params)
+{
+ int ret = -1;
+ struct DBOpPrepareParams p_params = PrepareParams;
+
+ if (!*sdb) {
+ ldpp_dout(dpp, 0)<<"In SQLRemoveAccount - no db" << dendl;
+ goto out;
+ }
+
+ InitPrepareParams(dpp, p_params, params);
+
+ SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareRemoveAccount");
+out:
+ return ret;
+}
+
+int SQLRemoveAccount::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.account.account_id, sdb);
+ SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.id.c_str(), sdb);
+
+out:
+ return rc;
+}
+
+int SQLRemoveAccount::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params)
+{
+ int ret = -1;
+
+ SQL_EXECUTE(dpp, params, stmt, NULL);
+out:
+ return ret;
+}
+
+int SQLGetAccount::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params)
+{
+ int ret = -1;
+ struct DBOpPrepareParams p_params = PrepareParams;
+
+ if (!*sdb) {
+ ldpp_dout(dpp, 0)<<"In SQLGetAccount - no db" << dendl;
+ goto out;
+ }
+
+ InitPrepareParams(dpp, p_params, params);
+
+ if (params->op.query_str == "name") {
+ SQL_PREPARE(dpp, p_params, sdb, name_stmt, ret, "PrepareGetAccount");
+ } else if (params->op.query_str == "email") {
+ SQL_PREPARE(dpp, p_params, sdb, email_stmt, ret, "PrepareGetAccount");
+ } else { // by default by account_id
+ SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareGetAccount");
+ }
+out:
+ return ret;
+}
+
+int SQLGetAccount::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params)
+{
+ int index = -1;
+ int rc = 0;
+ struct DBOpPrepareParams p_params = PrepareParams;
+
+ if (params->op.query_str == "name") {
+ SQL_BIND_INDEX(dpp, name_stmt, index, p_params.op.account.account_name, sdb);
+ SQL_BIND_TEXT(dpp, name_stmt, index, params->op.account.info.name.c_str(), sdb);
+ } else if (params->op.query_str == "email") {
+ SQL_BIND_INDEX(dpp, email_stmt, index, p_params.op.account.email, sdb);
+ SQL_BIND_TEXT(dpp, email_stmt, index, params->op.account.info.email.c_str(), sdb);
+ } else { // by default by account_id
+ SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.account_id, sdb);
+ SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.id.c_str(), sdb);
+ }
+
+out:
+ return rc;
+}
+
+int SQLGetAccount::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params)
+{
+ int ret = -1;
+
+ if (params->op.query_str == "name") {
+ SQL_EXECUTE(dpp, params, name_stmt, list_account);
+ } else if (params->op.query_str == "email") {
+ SQL_EXECUTE(dpp, params, email_stmt, list_account);
+ } else { // by default by account_id
+ SQL_EXECUTE(dpp, params, stmt, list_account);
+ }
+
+out:
+ return ret;
+}
+
int SQLInsertUser::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params)
{
int ret = -1;
/* default value matches with sqliteDB style */
int createTables(const DoutPrefixProvider *dpp) override;
+ int createAccountTable(const DoutPrefixProvider *dpp, DBOpParams *params);
int createBucketTable(const DoutPrefixProvider *dpp, DBOpParams *params);
int createUserTable(const DoutPrefixProvider *dpp, DBOpParams *params);
int createObjectTable(const DoutPrefixProvider *dpp, DBOpParams *params);
int createLCTables(const DoutPrefixProvider *dpp) override;
+ int DeleteAccountTable(const DoutPrefixProvider *dpp, DBOpParams *params);
int DeleteBucketTable(const DoutPrefixProvider *dpp, DBOpParams *params);
int DeleteUserTable(const DoutPrefixProvider *dpp, DBOpParams *params);
int DeleteObjectTable(const DoutPrefixProvider *dpp, DBOpParams *params);
int InitializeObjectOps(std::string db_name, const DoutPrefixProvider *dpp);
};
+class SQLInsertAccount : public SQLiteDB, public InsertAccountOp {
+ private:
+ sqlite3 **sdb = NULL;
+ sqlite3_stmt *stmt = NULL; // Prepared statement
+
+ public:
+ SQLInsertAccount(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {}
+ ~SQLInsertAccount() {
+ 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 SQLRemoveAccount : public SQLiteDB, public RemoveAccountOp {
+ private:
+ sqlite3 **sdb = NULL;
+ sqlite3_stmt *stmt = NULL; // Prepared statement
+
+ public:
+ SQLRemoveAccount(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {}
+ ~SQLRemoveAccount() {
+ 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 SQLGetAccount : public SQLiteDB, public GetAccountOp {
+ private:
+ sqlite3 **sdb = NULL;
+ sqlite3_stmt *stmt = NULL; // Prepared statement
+ sqlite3_stmt *name_stmt = NULL; // Prepared statement to query by account name
+ sqlite3_stmt *email_stmt = NULL; // Prepared statement to query by email
+
+ public:
+ SQLGetAccount(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {}
+ ~SQLGetAccount() {
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (name_stmt)
+ sqlite3_finalize(name_stmt);
+ if (email_stmt)
+ sqlite3_finalize(email_stmt);
+ }
+ int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params);
+ int Execute(const DoutPrefixProvider *dpp, DBOpParams *params);
+ int Bind(const DoutPrefixProvider *dpp, DBOpParams *params);
+};
+
class SQLInsertUser : public SQLiteDB, public InsertUserOp {
private:
sqlite3 **sdb = NULL;
return 0;
}
+int POSIXAccountDB::ProcessOp(const DoutPrefixProvider *dpp, string_view Op, DBOpParams *params) {
+ int ret = -1;
+ shared_ptr<class DBOp> db_op;
+
+ db_op = getDBOp(dpp, Op, params);
+
+ if (!db_op) {
+ ldpp_dout(dpp, 0)<<"No db_op found for Op("<<Op<<")" << dendl;
+ return ret;
+ }
+ ret = db_op->Execute(dpp, params);
+
+ if (ret) {
+ ldpp_dout(dpp, 0)<<"In Process op Execute failed for fop(" << Op << ")" << dendl;
+ } else {
+ ldpp_dout(dpp, 20)<<"Successfully processed fop(" << Op << ")" << dendl;
+ }
+
+ return ret;
+}
+
+int POSIXAccountDB::Initialize(string logfile, int loglevel)
+{
+ int ret = -1;
+ const DoutPrefixProvider *dpp = get_def_dpp();
+
+ if (!cct) {
+ cout << "Failed to Initialize. No ceph Context \n";
+ return -1;
+ }
+
+ if (loglevel > 0) {
+ cct->_conf->subsys.set_log_level(ceph_subsys_rgw, loglevel);
+ }
+ if (!logfile.empty()) {
+ cct->_log->set_log_file(logfile);
+ cct->_log->reopen_log_file();
+ }
+
+ db = openDB(dpp);
+
+ if (!db) {
+ ldpp_dout(dpp, 0) <<"Failed to open database " << dendl;
+ return ret;
+ }
+
+ ret = InitializeDBOps(dpp);
+
+ if (ret) {
+ ldpp_dout(dpp, 0) <<"InitializePOSIXAccountDBOps failed " << dendl;
+ closeDB(dpp);
+ db = NULL;
+ return ret;
+ }
+
+ ldpp_dout(dpp, 0) << "POSIXAccountDB successfully initialized - name:" \
+ << db_name << "" << dendl;
+
+ return ret;
+}
+
+int POSIXAccountDB::Destroy(const DoutPrefixProvider *dpp)
+{
+ DB::Destroy(dpp);
+
+ ldpp_dout(dpp, 20)<<"POSIXAccountDB successfully destroyed - name:" \
+ <<db_name << dendl;
+
+ return 0;
+}
+
} } // namespace rgw::store
namespace rgw { namespace store {
class POSIXUserDB;
+class POSIXAccountDB;
+
+struct POSIXAccountDBOpAccountInfo : DBOpAccountInfo {};
struct POSIXUserDBOpUserInfo : DBOpUserInfo {};
struct POSIXUserDBOpPrepareParams : DBOpPrepareParams {};
+struct POSIXAccountDBOpInfo : DBOpInfo {};
+
+struct POSIXAccountDBOpPrepareInfo : DBOpPrepareInfo {};
+
+struct POSIXAccountDBOpPrepareParams : DBOpPrepareParams {};
+
+struct POSIXAccountDBOps : DBOps {};
+
+class POSIXAccountDBOp : public DBOp {
+ private:
+ static constexpr std::string_view CreateAccountTableQ =
+ /* Corresponds to RGWAccountInfo
+ *
+ * AccountID is made Primary key.
+ * If multiple tenants are stored in single .db handle, should
+ * make both (AccountID, Tenant) as Primary Key.
+ *
+ * XXX:
+ * - Quota stored as blob .. should be linked to quota table.
+ */
+ "CREATE TABLE IF NOT EXISTS '{}' ( \
+ AccountID TEXT NOT NULL UNIQUE, \
+ Tenant TEXT , \
+ AccountName TEXT , \
+ Email TEXT , \
+ Quota BLOB , \
+ BucketQuota BLOB , \
+ MaxUsers INTEGER , \
+ MaxRoles INTEGER , \
+ MaxGroups INTEGER , \
+ MaxBuckets INTEGER , \
+ MaxAccessKeys INTEGER , \
+ PRIMARY KEY (AccountID) \n);";
+
+ public:
+ POSIXAccountDBOp() : DBOp() {}
+ virtual ~POSIXAccountDBOp() {}
+ std::mutex mtx; // to protect prepared stmt
+};
+
+class InsertPOSIXAccountOp : public SQLInsertAccount {};
+
+class RemovePOSIXAccountOp: public SQLRemoveAccount {};
+
+class GetPOSIXAccountOp: public SQLGetAccount {};
+
struct POSIXUserDBOps : DBOps {};
class POSIXUserDBOp : public DBOp {
virtual int ListAllObjects(const DoutPrefixProvider *dpp, DBOpParams *params) override { return 0; }
};
+class POSIXAccountDB : public SQLiteDB {
+ private:
+ const std::string db_name;
+ const std::string account_table;
+ const std::string user_table;
+ const std::string bucket_table;
+ const std::string quota_table;
+ const std::string lc_head_table;
+ const std::string lc_entry_table;
+
+ rgw::sal::Driver* driver;
+
+ protected:
+ void *db;
+ CephContext *cct;
+ const DoutPrefix dp;
+ // Below mutex is to protect objectmap and other shared
+ // objects if any.
+ std::mutex mtx;
+
+ public:
+ struct DBOps dbops;
+
+ POSIXAccountDB(std::string db_name, CephContext *_cct) : SQLiteDB(db_name, _cct),
+ db_name(db_name),
+ account_table(db_name+"_account_table"),
+ user_table(db_name+"_user_table"),
+ cct(_cct),
+ dp(_cct, ceph_subsys_rgw, "rgw POSIXAccountDBStore backend: ")
+ { DB::set_context(cct); }
+
+ int Initialize(std::string logfile, int loglevel);
+ int ProcessOp(const DoutPrefixProvider *dpp, std::string_view Op, DBOpParams *params);
+ int Destroy(const DoutPrefixProvider *dpp);
+
+ CephContext* ctx() { return this->cct; }
+
+ virtual int InitPrepareParams(const DoutPrefixProvider *dpp,
+ DBOpPrepareParams &p_params,
+ DBOpParams* params) override { return 0; }
+ virtual int createLCTables(const DoutPrefixProvider *dpp) override { return 0; }
+
+ virtual int ListAllBuckets(const DoutPrefixProvider *dpp, DBOpParams *params) override { return 0; }
+ virtual int ListAllUsers(const DoutPrefixProvider *dpp, DBOpParams *params) override { return 0; }
+ virtual int ListAllObjects(const DoutPrefixProvider *dpp, DBOpParams *params) override { return 0; }
+};
+
} } // namespace rgw::store
return -ENOTSUP;
}
+int POSIXDriver::load_account_by_id(const DoutPrefixProvider* dpp,
+ optional_yield y,
+ std::string_view id,
+ RGWAccountInfo& info,
+ Attrs& attrs,
+ RGWObjVersionTracker& objv)
+{
+ RGWObjVersionTracker objv_tracker;
+
+ int ret = accountDB->get_account(dpp, std::string("account_id"), std::string(id), info, &attrs,
+ &objv_tracker);
+
+ if (ret < 0)
+ return ret;
+
+ objv = objv_tracker;
+ return 0;
+}
+
+int POSIXDriver::load_account_by_name(const DoutPrefixProvider* dpp,
+ optional_yield y,
+ std::string_view tenant,
+ std::string_view name,
+ RGWAccountInfo& info,
+ Attrs& attrs,
+ RGWObjVersionTracker& objv)
+{
+ RGWObjVersionTracker objv_tracker;
+
+ int ret = accountDB->get_account(dpp, std::string("name"), std::string(name), info, &attrs,
+ &objv_tracker);
+
+ if (ret < 0)
+ return ret;
+
+ objv = objv_tracker;
+ return 0;
+}
+
+int POSIXDriver::load_account_by_email(const DoutPrefixProvider* dpp,
+ optional_yield y,
+ std::string_view email,
+ RGWAccountInfo& info,
+ Attrs& attrs,
+ RGWObjVersionTracker& objv)
+{
+ RGWObjVersionTracker objv_tracker;
+
+ int ret = accountDB->get_account(dpp, std::string("email"), std::string(email), info, &attrs,
+ &objv_tracker);
+
+ if (ret < 0)
+ return ret;
+
+ objv = objv_tracker;
+ return 0;
+}
+
+int POSIXDriver::store_account(const DoutPrefixProvider* dpp,
+ optional_yield y, bool exclusive,
+ const RGWAccountInfo& info,
+ const RGWAccountInfo* old_info,
+ const Attrs& attrs,
+ RGWObjVersionTracker& objv)
+{
+ int ret = accountDB->store_account(dpp, info, exclusive, &attrs, &objv);
+
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int POSIXDriver::delete_account(const DoutPrefixProvider* dpp,
+ optional_yield y,
+ const RGWAccountInfo& info,
+ RGWObjVersionTracker& objv)
+{
+ int ret = accountDB->remove_account(dpp, info, &objv);
+
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
+
int POSIXDriver::load_owner_by_email(const DoutPrefixProvider* dpp,
optional_yield y,
std::string_view email,
protected:
CephContext *cct;
std::unique_ptr<rgw::store::POSIXUserDB> userDB;
+ std::unique_ptr<rgw::store::POSIXAccountDB> accountDB;
POSIXZone zone;
std::unique_ptr<BucketCache> bucket_cache;
std::string base_path;
auto db_full_path = std::filesystem::path(db_path) / db_name;
userDB = std::make_unique<rgw::store::POSIXUserDB>(db_full_path.string(), cct);
+ accountDB = std::make_unique<rgw::store::POSIXAccountDB>(db_full_path.string(), cct);
}
virtual ~POSIXDriver() { }
std::string_view id,
RGWAccountInfo& info,
Attrs& attrs,
- RGWObjVersionTracker& objv) override { return -ENOTSUP; }
+ RGWObjVersionTracker& objv) override;
virtual int load_account_by_name(const DoutPrefixProvider* dpp,
optional_yield y,
std::string_view tenant,
std::string_view name,
RGWAccountInfo& info,
Attrs& attrs,
- RGWObjVersionTracker& objv) override { return -ENOTSUP; }
+ RGWObjVersionTracker& objv) override;
virtual int load_account_by_email(const DoutPrefixProvider* dpp,
optional_yield y,
std::string_view email,
RGWAccountInfo& info,
Attrs& attrs,
- RGWObjVersionTracker& objv) override { return -ENOTSUP; }
+ RGWObjVersionTracker& objv) override;
virtual int store_account(const DoutPrefixProvider* dpp,
optional_yield y, bool exclusive,
const RGWAccountInfo& info,
const RGWAccountInfo* old_info,
const Attrs& attrs,
- RGWObjVersionTracker& objv) override { return -ENOTSUP; }
+ RGWObjVersionTracker& objv) override;
virtual int delete_account(const DoutPrefixProvider* dpp,
optional_yield y,
const RGWAccountInfo& info,
- RGWObjVersionTracker& objv) override { return -ENOTSUP; }
+ RGWObjVersionTracker& objv) override;
virtual int load_stats(const DoutPrefixProvider* dpp,
optional_yield y,