set(librgw_common_srcs
services/svc_quota.cc
services/svc_rados.cc
+ services/svc_sys_obj.cc
services/svc_zone.cc
services/svc_zone_utils.cc
rgw_service.cc
#include "rgw_multi.h"
#include "rgw_op.h"
+#include "services/svc_sys_obj.h"
+
#define dout_subsys ceph_subsys_rgw
{
map<string, bufferlist> parts_map;
map<string, bufferlist>::iterator iter;
- bufferlist header;
rgw_obj obj;
obj.init_ns(bucket_info.bucket, meta_oid, RGW_OBJ_NS_MULTIPART);
parts.clear();
+
+ auto obj_ctx = store->svc.sysobj->init_obj_ctx();
+ auto sysobj = obj_ctx.get_obj(raw_obj);
+
if (sorted_omap) {
string p;
p = "part.";
snprintf(buf, sizeof(buf), "%08d", marker);
p.append(buf);
- ret = store->omap_get_vals(raw_obj, header, p, num_parts + 1, parts_map);
+ ret = sysobj.omap().get_vals(p, num_parts + 1, &parts_map, nullptr);
} else {
- ret = store->omap_get_all(raw_obj, header, parts_map);
+ ret = sysobj.omap().get_all(&parts_map);
}
if (ret < 0)
return ret;
#include "services/svc_zone.h"
#include "services/svc_quota.h"
+#include "services/svc_sys_obj.h"
#include "cls/lock/cls_lock_client.h"
#include "cls/rgw/cls_rgw_client.h"
op_ret = -ERR_INVALID_PART;
return;
} else {
- manifest.append(obj_part.manifest, store);
+ manifest.append(obj_part.manifest, store->svc.zone.get());
}
bool part_compressed = (obj_part.cs_info.compression_type != "none");
#include "rgw_putobj_aio.h"
#include "rgw_putobj_processor.h"
#include "rgw_multi.h"
+#include "services/svc_sys_obj.h"
#define dout_subsys ceph_subsys_rgw
rgw_raw_obj raw_meta_obj;
store->obj_to_raw(bucket_info.placement_rule, meta_obj, &raw_meta_obj);
- const bool must_exist = true;// detect races with abort
- r = store->omap_set(raw_meta_obj, p, bl, must_exist);
+
+ auto obj_ctx = store->svc.sysobj->init_obj_ctx();
+ auto sysobj = obj_ctx.get_obj(raw_meta_obj);
+
+ r = sysobj.omap()
+ .set_must_exist(true)
+ .set(p, bl);
if (r < 0) {
return r;
}
#include "rgw_realm_watcher.h"
#include "rgw_reshard.h"
+#include "services/svc_zone.h"
+#include "services/svc_zone_utils.h"
+#include "services/svc_quota.h"
+#include "services/svc_sys_obj.h"
+
#include "compressor/Compressor.h"
#ifdef WITH_LTTNG
static string *notify_oids = NULL;
static string shadow_ns = "shadow";
static string dir_oid_prefix = ".dir.";
-static string default_storage_pool_suffix = "rgw.buckets.data";
static string default_bucket_index_pool_suffix = "rgw.buckets.index";
static string default_storage_extra_pool_suffix = "rgw.buckets.non-ec";
-static string avail_pools = ".pools.avail";
static string log_lock_name = "rgw_log_lock";
static RGWObjCategory main_category = RGW_OBJ_CATEGORY_MAIN;
#define RGW_USAGE_OBJ_PREFIX "usage."
#define FIRST_EPOCH 1
-static string RGW_DEFAULT_ZONE_ROOT_POOL = "rgw.root";
-static string RGW_DEFAULT_ZONEGROUP_ROOT_POOL = "rgw.root";
-static string RGW_DEFAULT_REALM_ROOT_POOL = "rgw.root";
-static string RGW_DEFAULT_PERIOD_ROOT_POOL = "rgw.root";
+
#define dout_subsys ceph_subsys_rgw
{
map<string,string> metadata = meta;
metadata["num_handles"] = stringify(rados.size());
- metadata["zonegroup_id"] = zonegroup.get_id();
- metadata["zonegroup_name"] = zonegroup.get_name();
- metadata["zone_name"] = zone_name();
- metadata["zone_id"] = zone_id();;
+ metadata["zonegroup_id"] = svc.zone->get_zonegroup().get_id();
+ metadata["zonegroup_name"] = svc.zone->get_zonegroup().get_name();
+ metadata["zone_name"] = svc.zone->zone_name();
+ metadata["zone_id"] = svc.zone->zone_id();
string name = cct->_conf->name.get_id();
if (name.compare(0, 4, "rgw.") == 0) {
name = name.substr(4);
return 0;
}
-bool RGWRados::zone_syncs_from(RGWZone& target_zone, RGWZone& source_zone)
-{
- return target_zone.syncs_from(source_zone.name) &&
- sync_modules_manager->supports_data_export(source_zone.tier_type);
-}
-
/**
* Initialize the RADOS instance and prepare to do other ops
* Returns 0 on success, -ERR# on failure.
*/
int RGWRados::init_complete()
{
+ int ret;
+
if (run_sync_thread) {
- ret = sync_modules_manager->create_instance(cct, svc.zone->get_zone_public_config()->tier_type, svc.zone->get_zone_params()->tier_config, &sync_module);
+ auto& zone_public_config = svc.zone->get_zone();
+ ret = sync_modules_manager->create_instance(cct, zone_public_config.tier_type, svc.zone->get_zone_params().tier_config, &sync_module);
if (ret < 0) {
lderr(cct) << "ERROR: failed to init sync module instance, ret=" << ret << dendl;
if (ret == -ENOENT) {
- lderr(cct) << "ERROR: " << zone_public_config->tier_type
+ lderr(cct) << "ERROR: " << zone_public_config.tier_type
<< " sync module does not exist. valid sync modules: "
<< sync_modules_manager->get_registered_module_names()
<< dendl;
period_puller.reset(new RGWPeriodPuller(this));
period_history.reset(new RGWPeriodHistory(cct, period_puller.get(),
- current_period));
+ svc.zone->get_current_period()));
if (need_watch_notify()) {
ret = init_watch();
}
}
- /* first build all zones index */
- for (auto ziter : get_zonegroup().zones) {
- const string& id = ziter.first;
- RGWZone& z = ziter.second;
- zone_id_by_name[z.name] = id;
- zone_by_id[id] = z;
- }
-
- if (zone_by_id.find(zone_id()) == zone_by_id.end()) {
- ldout(cct, 0) << "WARNING: could not find zone config in zonegroup for local zone (" << zone_id() << "), will use defaults" << dendl;
- }
- zone_public_config = zone_by_id[zone_id()];
- for (auto ziter : get_zonegroup().zones) {
- const string& id = ziter.first;
- RGWZone& z = ziter.second;
- if (id == zone_id()) {
- continue;
- }
- if (z.endpoints.empty()) {
- ldout(cct, 0) << "WARNING: can't generate connection for zone " << z.id << " id " << z.name << ": no endpoints defined" << dendl;
- continue;
- }
- ldout(cct, 20) << "generating connection object for zone " << z.name << " id " << z.id << dendl;
- RGWRESTConn *conn = new RGWRESTConn(cct, this, z.id, z.endpoints);
- zone_conn_map[id] = conn;
- if (zone_syncs_from(zone_public_config, z) ||
- zone_syncs_from(z, zone_public_config)) {
- if (zone_syncs_from(zone_public_config, z)) {
- zone_data_sync_from_map[id] = conn;
- }
- if (zone_syncs_from(z, zone_public_config)) {
- zone_data_notify_to_map[id] = conn;
- }
- } else {
- ldout(cct, 20) << "NOTICE: not syncing to/from zone " << z.name << " id " << z.id << dendl;
- }
- }
-
ret = open_root_pool_ctx();
if (ret < 0)
return ret;
obj_expirer->start_processor();
}
+ auto& current_period = svc.zone->get_current_period();
+ auto& zonegroup = svc.zone->get_zonegroup();
+ auto& zone_params = svc.zone->get_zone_params();
+ auto& zone = svc.zone->get_zone();
+
+#warning sync service needed
/* no point of running sync thread if we don't have a master zone configured
or there is no rest_master_conn */
- if (get_zonegroup().master_zone.empty() || !rest_master_conn
+ if (zonegroup.master_zone.empty() || !svc.zone->get_master_conn()
|| current_period.get_id().empty()) {
run_sync_thread = false;
}
}
if (run_sync_thread) {
-
- for (const auto &pt: get_zonegroup().placement_targets) {
- if (get_zone_params().placement_pools.find(pt.second.name)
- == get_zone_params().placement_pools.end()){
+ for (const auto &pt: zonegroup.placement_targets) {
+ if (zone_params.placement_pools.find(pt.second.name)
+ == zone_params.placement_pools.end()){
ldout(cct, 0) << "WARNING: This zone does not contain the placement target "
<< pt.second.name << " present in zonegroup" << dendl;
}
data_log->set_observer(&*bucket_trim);
Mutex::Locker dl(data_sync_thread_lock);
- for (auto iter : zone_data_sync_from_map) {
+ for (auto iter : svc.zone->get_zone_data_sync_from_map()) {
ldout(cct, 5) << "starting data sync thread for zone " << iter.first << dendl;
auto *thread = new RGWDataSyncProcessorThread(this, async_rados, iter.first);
ret = thread->init();
quota_handler = RGWQuotaHandler::generate_handler(this, quota_threads);
bucket_index_max_shards = (cct->_conf->rgw_override_bucket_index_max_shards ? cct->_conf->rgw_override_bucket_index_max_shards :
- get_zone().bucket_index_max_shards);
+ zone.bucket_index_max_shards);
if (bucket_index_max_shards > get_max_bucket_shards()) {
bucket_index_max_shards = get_max_bucket_shards();
ldout(cct, 1) << __func__ << " bucket index max shards is too large, reset to value: "
binfo_cache = new RGWChainedCacheImpl<bucket_info_entry>;
binfo_cache->init(this);
- bool need_tombstone_cache = !zone_data_notify_to_map.empty(); /* have zones syncing from us */
+ bool need_tombstone_cache = !svc.zone->get_zone_data_notify_to_map().empty(); /* have zones syncing from us */
if (need_tombstone_cache) {
obj_tombstone_cache = new tombstone_cache_t(cct->_conf->rgw_obj_tombstone_cache_size);
reshard = new RGWReshard(this);
/* only the master zone in the zonegroup reshards buckets */
- run_reshard_thread = run_reshard_thread && (get_zonegroup().master_zone == zone_public_config.id);
+ run_reshard_thread = run_reshard_thread && (zonegroup.master_zone == zone.id);
if (run_reshard_thread) {
reshard->start_processor();
}
cct->_conf.get_val<double>("rgw_inject_notify_timeout_probability");
max_notify_retries = cct->_conf.get_val<uint64_t>("rgw_max_notify_retries");
- svc_registry = std::make_unique<RGWServiceRegistry>();
- svc_registry->register_all();
+ svc_registry = std::make_unique<RGWServiceRegistry>(cct);
JSONFormattable zone_svc_conf;
ret = svc_registry->get_instance("zone", zone_svc_conf, &svc.zone);
*/
int RGWRados::open_root_pool_ctx()
{
- return rgw_init_ioctx(get_rados_handle(), get_zone_params().domain_root, root_pool_ctx, true);
+ return rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().domain_root, root_pool_ctx, true);
}
int RGWRados::open_gc_pool_ctx()
{
- return rgw_init_ioctx(get_rados_handle(), get_zone_params().gc_pool, gc_pool_ctx, true);
+ return rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().gc_pool, gc_pool_ctx, true);
}
int RGWRados::open_lc_pool_ctx()
{
- return rgw_init_ioctx(get_rados_handle(), get_zone_params().lc_pool, lc_pool_ctx, true);
+ return rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().lc_pool, lc_pool_ctx, true);
}
int RGWRados::open_objexp_pool_ctx()
{
- return rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, objexp_pool_ctx, true);
+ return rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().log_pool, objexp_pool_ctx, true);
}
int RGWRados::open_reshard_pool_ctx()
{
- return rgw_init_ioctx(get_rados_handle(), get_zone_params().reshard_pool, reshard_pool_ctx, true);
+ return rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().reshard_pool, reshard_pool_ctx, true);
}
int RGWRados::init_watch()
{
- int r = rgw_init_ioctx(&rados[0], get_zone_params().control_pool, control_pool_ctx, true);
+#warning needs to be part of the sysobj/cache service
+ int r = rgw_init_ioctx(&rados[0], svc.zone->get_zone_params().control_pool, control_pool_ctx, true);
if (r < 0) {
return r;
}
return open_pool_ctx(explicit_pool, index_ctx);
}
+ auto& zonegroup = svc.zone->get_zonegroup();
+ auto& zone_params = svc.zone->get_zone_params();
+
const string *rule = &bucket_info.placement_rule;
if (rule->empty()) {
rule = &zonegroup.default_placement;
int RGWRados::log_list_init(const string& prefix, RGWAccessHandle *handle)
{
log_list_state *state = new log_list_state;
- int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, state->io_ctx);
+ int r = rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().log_pool, state->io_ctx);
if (r < 0) {
delete state;
return r;
int RGWRados::log_remove(const string& name)
{
librados::IoCtx io_ctx;
- int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
+ int r = rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().log_pool, io_ctx);
if (r < 0)
return r;
return io_ctx.remove(name);
int RGWRados::log_show_init(const string& name, RGWAccessHandle *handle)
{
log_show_state *state = new log_show_state;
- int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, state->io_ctx);
+ int r = rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().log_pool, state->io_ctx);
if (r < 0) {
delete state;
return r;
int RGWRados::time_log_add_init(librados::IoCtx& io_ctx)
{
- return rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx, true);
+ return rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().log_pool, io_ctx, true);
}
{
librados::IoCtx io_ctx;
- int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
+ int r = rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().log_pool, io_ctx);
if (r < 0)
return r;
librados::ObjectReadOperation op;
{
librados::IoCtx io_ctx;
- int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
+ int r = rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().log_pool, io_ctx);
if (r < 0)
return r;
librados::ObjectReadOperation op;
int RGWRados::time_log_info_async(librados::IoCtx& io_ctx, const string& oid, cls_log_header *header, librados::AioCompletion *completion)
{
- int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
+ int r = rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().log_pool, io_ctx);
if (r < 0)
return r;
{
librados::IoCtx io_ctx;
- int r = rgw_init_ioctx(get_rados_handle(), get_zone_params().log_pool, io_ctx);
+ int r = rgw_init_ioctx(get_rados_handle(), svc.zone->get_zone_params().log_pool, io_ctx);
if (r < 0)
return r;
{
uint64_t iid = instance_id();
uint64_t bid = next_bucket_id();
- char buf[get_zone_params().get_id().size() + 48];
+ char buf[svc.zone->get_zone_params().get_id().size() + 48];
snprintf(buf, sizeof(buf), "%s.%" PRIu64 ".%" PRIu64,
- get_zone_params().get_id().c_str(), iid, bid);
+ svc.zone->get_zone_params().get_id().c_str(), iid, bid);
*bucket_id = buf;
}
for (int i = 0; i < MAX_CREATE_RETRIES; i++) {
int ret = 0;
- ret = select_bucket_placement(owner, zonegroup_id, placement_rule,
- &selected_placement_rule_name, &rule_info);
+ ret = svc.zone->select_bucket_placement(owner, zonegroup_id, placement_rule,
+ &selected_placement_rule_name, &rule_info);
if (ret < 0)
return ret;
return -ENOENT;
}
-int RGWRados::select_new_bucket_location(RGWUserInfo& user_info, const string& zonegroup_id, const string& request_rule,
- string *pselected_rule_name, RGWZonePlacementInfo *rule_info)
-
-{
- /* first check that zonegroup exists within current period. */
- RGWZoneGroup zonegroup;
- int ret = get_zonegroup(zonegroup_id, zonegroup);
- if (ret < 0) {
- ldout(cct, 0) << "could not find zonegroup " << zonegroup_id << " in current period" << dendl;
- return ret;
- }
-
- /* find placement rule. Hierarchy: request rule > user default rule > zonegroup default rule */
- std::map<std::string, RGWZoneGroupPlacementTarget>::const_iterator titer;
-
- if (!request_rule.empty()) {
- titer = zonegroup.placement_targets.find(request_rule);
- if (titer == zonegroup.placement_targets.end()) {
- ldout(cct, 0) << "could not find requested placement id " << request_rule
- << " within zonegroup " << dendl;
- return -ERR_INVALID_LOCATION_CONSTRAINT;
- }
- } else if (!user_info.default_placement.empty()) {
- titer = zonegroup.placement_targets.find(user_info.default_placement);
- if (titer == zonegroup.placement_targets.end()) {
- ldout(cct, 0) << "could not find user default placement id " << user_info.default_placement
- << " within zonegroup " << dendl;
- return -ERR_INVALID_LOCATION_CONSTRAINT;
- }
- } else {
- if (zonegroup.default_placement.empty()) { // zonegroup default rule as fallback, it should not be empty.
- ldout(cct, 0) << "misconfiguration, zonegroup default placement id should not be empty." << dendl;
- return -ERR_ZONEGROUP_DEFAULT_PLACEMENT_MISCONFIGURATION;
- } else {
- titer = zonegroup.placement_targets.find(zonegroup.default_placement);
- if (titer == zonegroup.placement_targets.end()) {
- ldout(cct, 0) << "could not find zonegroup default placement id " << zonegroup.default_placement
- << " within zonegroup " << dendl;
- return -ERR_INVALID_LOCATION_CONSTRAINT;
- }
- }
- }
-
- /* now check tag for the rule, whether user is permitted to use rule */
- const auto& target_rule = titer->second;
- if (!target_rule.user_permitted(user_info.placement_tags)) {
- ldout(cct, 0) << "user not permitted to use placement rule " << titer->first << dendl;
- return -EPERM;
- }
-
- if (pselected_rule_name)
- *pselected_rule_name = titer->first;
-
- return select_bucket_location_by_rule(titer->first, rule_info);
-}
-
-int RGWRados::select_bucket_location_by_rule(const string& location_rule, RGWZonePlacementInfo *rule_info)
-{
- if (location_rule.empty()) {
- /* we can only reach here if we're trying to set a bucket location from a bucket
- * created on a different zone, using a legacy / default pool configuration
- */
- if (rule_info) {
- return select_legacy_bucket_placement(rule_info);
- }
-
- return 0;
- }
-
- /*
- * make sure that zone has this rule configured. We're
- * checking it for the local zone, because that's where this bucket object is going to
- * reside.
- */
- map<string, RGWZonePlacementInfo>::iterator piter = get_zone_params().placement_pools.find(location_rule);
- if (piter == get_zone_params().placement_pools.end()) {
- /* couldn't find, means we cannot really place data for this bucket in this zone */
- if (get_zonegroup().equals(zonegroup.get_id())) {
- /* that's a configuration error, zone should have that rule, as we're within the requested
- * zonegroup */
- ldout(cct, 0) << "ERROR: This zone does not contain placement rule"
- << location_rule << " present in the zonegroup!" << dendl;
- return -EINVAL;
- } else {
- /* oh, well, data is not going to be placed here, bucket object is just a placeholder */
- return 0;
- }
- }
-
- RGWZonePlacementInfo& placement_info = piter->second;
-
- if (rule_info) {
- *rule_info = placement_info;
- }
-
- return 0;
-}
-
-int RGWRados::select_bucket_placement(RGWUserInfo& user_info, const string& zonegroup_id, const string& placement_rule,
- string *pselected_rule_name, RGWZonePlacementInfo *rule_info)
-{
- if (!get_zone_params().placement_pools.empty()) {
- return select_new_bucket_location(user_info, zonegroup_id, placement_rule,
- pselected_rule_name, rule_info);
- }
-
- if (pselected_rule_name) {
- pselected_rule_name->clear();
- }
-
- if (rule_info) {
- return select_legacy_bucket_placement(rule_info);
- }
-
- return 0;
-}
-
-int RGWRados::select_legacy_bucket_placement(RGWZonePlacementInfo *rule_info)
-{
- bufferlist map_bl;
- map<string, bufferlist> m;
- string pool_name;
- bool write_map = false;
-
- rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
-
- RGWObjectCtx obj_ctx(this);
- int ret = rgw_get_system_obj(this, obj_ctx, get_zone_params().domain_root, avail_pools, map_bl, NULL, NULL);
- if (ret < 0) {
- goto read_omap;
- }
-
- try {
- auto iter = map_bl.cbegin();
- decode(m, iter);
- } catch (buffer::error& err) {
- ldout(cct, 0) << "ERROR: couldn't decode avail_pools" << dendl;
- }
-
-read_omap:
- if (m.empty()) {
- bufferlist header;
- ret = omap_get_all(obj, header, m);
-
- write_map = true;
- }
-
- if (ret < 0 || m.empty()) {
- vector<rgw_pool> pools;
- string s = string("default.") + default_storage_pool_suffix;
- pools.push_back(rgw_pool(s));
- vector<int> retcodes;
- bufferlist bl;
- ret = create_pools(pools, retcodes);
- if (ret < 0)
- return ret;
- ret = omap_set(obj, s, bl);
- if (ret < 0)
- return ret;
- m[s] = bl;
- }
-
- if (write_map) {
- bufferlist new_bl;
- encode(m, new_bl);
- ret = put_system_obj_data(NULL, obj, new_bl, -1, false);
- if (ret < 0) {
- ldout(cct, 0) << "WARNING: could not save avail pools map info ret=" << ret << dendl;
- }
- }
-
- auto miter = m.begin();
- if (m.size() > 1) {
- // choose a pool at random
- auto r = ceph::util::generate_random_number<size_t>(0, m.size() - 1);
- std::advance(miter, r);
- }
- pool_name = miter->first;
-
- rule_info->data_pool = pool_name;
- rule_info->data_extra_pool = pool_name;
- rule_info->index_pool = pool_name;
- rule_info->index_type = RGWBIType_Normal;
-
- return 0;
-}
-
bool RGWRados::get_obj_data_pool(const string& placement_rule, const rgw_obj& obj, rgw_pool *pool)
{
- return rgw_get_obj_data_pool(zonegroup, zone_params, placement_rule, obj, pool);
+ return rgw_get_obj_data_pool(svc.zone->get_zonegroup(), svc.zone->get_zone_params(), placement_rule, obj, pool);
}
bool RGWRados::obj_to_raw(const string& placement_rule, const rgw_obj& obj, rgw_raw_obj *raw_obj)
return get_obj_data_pool(placement_rule, obj, &raw_obj->pool);
}
-int RGWRados::update_placement_map()
-{
- bufferlist header;
- map<string, bufferlist> m;
- rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
- int ret = omap_get_all(obj, header, m);
- if (ret < 0)
- return ret;
-
- bufferlist new_bl;
- encode(m, new_bl);
- ret = put_system_obj_data(NULL, obj, new_bl, -1, false);
- if (ret < 0) {
- ldout(cct, 0) << "WARNING: could not save avail pools map info ret=" << ret << dendl;
- }
-
- return ret;
-}
-
-int RGWRados::add_bucket_placement(const rgw_pool& new_pool)
-{
- librados::Rados *rad = get_rados_handle();
- int ret = rad->pool_lookup(new_pool.name.c_str());
- if (ret < 0) // DNE, or something
- return ret;
-
- rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
- bufferlist empty_bl;
- ret = omap_set(obj, new_pool.to_str(), empty_bl);
-
- // don't care about return value
- update_placement_map();
-
- return ret;
-}
-
-int RGWRados::remove_bucket_placement(const rgw_pool& old_pool)
-{
- rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
- int ret = omap_del(obj, old_pool.to_str());
-
- // don't care about return value
- update_placement_map();
-
- return ret;
-}
-
-int RGWRados::list_placement_set(set<rgw_pool>& names)
-{
- bufferlist header;
- map<string, bufferlist> m;
-
- rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
- int ret = omap_get_all(obj, header, m);
- if (ret < 0)
- return ret;
-
- names.clear();
- map<string, bufferlist>::iterator miter;
- for (miter = m.begin(); miter != m.end(); ++miter) {
- names.insert(rgw_pool(miter->first));
- }
-
- return names.size();
-}
-
int RGWRados::create_pools(vector<rgw_pool>& pools, vector<int>& retcodes)
{
vector<librados::PoolAsyncCompletion *> completions;
if (ref->oid.empty()) {
ref->oid = obj.pool.to_str();
- ref->pool = get_zone_params().domain_root;
+ ref->pool = svc.zone->get_zone_params().domain_root;
} else {
ref->pool = obj.pool;
}
string req_id;
if (!s) {
// fake req_id
- req_id = store->unique_id(store->get_new_req_id());
+ req_id = store->svc.zone_utils->unique_id(store->get_new_req_id());
} else {
req_id = s->req_id;
}
if (attrs.find(RGW_ATTR_SOURCE_ZONE) == attrs.end()) {
bufferlist bl;
- encode(store->get_zone_short_id(), bl);
+ encode(store->svc.zone->get_zone_short_id(), bl);
op.setxattr(RGW_ATTR_SOURCE_ZONE, bl);
}
if (source_zone.empty()) {
if (src_bucket_info.zonegroup.empty()) {
/* source is in the master zonegroup */
- conn = rest_master_conn;
+ conn = svc.zone->get_master_conn();
} else {
+ auto& zonegroup_conn_map = svc.zone->get_zonegroup_conn_map();
map<string, RGWRESTConn *>::iterator iter = zonegroup_conn_map.find(src_bucket_info.zonegroup);
if (iter == zonegroup_conn_map.end()) {
ldout(cct, 0) << "could not find zonegroup connection to zonegroup: " << source_zone << dendl;
conn = iter->second;
}
} else {
+ auto& zone_conn_map = svc.zone->get_zone_conn_map();
map<string, RGWRESTConn *>::iterator iter = zone_conn_map.find(source_zone);
if (iter == zone_conn_map.end()) {
ldout(cct, 0) << "could not find zone connection to zone: " << source_zone << dendl;
}
RGWRESTConn *conn;
+ auto& zone_conn_map = svc.zone->get_zone_conn_map();
+ auto& zonegroup_conn_map = svc.zone->get_zonegroup_conn_map();
if (source_zone.empty()) {
if (dest_bucket_info.zonegroup.empty()) {
/* source is in the master zonegroup */
- conn = rest_master_conn;
+ conn = svc.zone->get_master_conn();
} else {
map<string, RGWRESTConn *>::iterator iter = zonegroup_conn_map.find(src_bucket_info.zonegroup);
if (iter == zonegroup_conn_map.end()) {
boost::optional<RGWPutObj_Compress> compressor;
CompressorRef plugin;
- const auto& compression_type = zone_params.get_compression_type(
+ const auto& compression_type = svc.zone->get_zone_params().get_compression_type(
dest_bucket_info.placement_rule);
if (compression_type != "none") {
plugin = Compressor::create(cct, compression_type);
/* non critical error */
}
}
- set_mtime_weight.init(set_mtime, get_zone_short_id(), pg_ver);
+ set_mtime_weight.init(set_mtime, svc.zone->get_zone_short_id(), pg_ver);
}
#define MAX_COMPLETE_RETRY 100
RGWRESTStreamS3PutObj *out_stream_req;
+ auto rest_master_conn = svc.zone->get_master_conn();
+
int ret = rest_master_conn->put_obj_async(user_id, dest_obj, astate->size, src_attrs, true, &out_stream_req);
if (ret < 0) {
return ret;
append_rand_alpha(cct, dest_obj.get_oid(), shadow_oid, 32);
shadow_obj.init_ns(dest_obj.bucket, shadow_oid, shadow_ns);
- remote_dest = !get_zonegroup().equals(dest_bucket_info.zonegroup);
- remote_src = !get_zonegroup().equals(src_bucket_info.zonegroup);
+ auto& zonegroup = svc.zone->get_zonegroup();
+
+ remote_dest = !zonegroup.equals(dest_bucket_info.zonegroup);
+ remote_src = !zonegroup.equals(src_bucket_info.zonegroup);
if (remote_src && remote_dest) {
ldout(cct, 0) << "ERROR: can't copy object when both src and dest buckets are remote" << dendl;
nullptr, nullptr, nullptr, nullptr, nullptr);
}
-/**
- * Check to see if the bucket metadata could be synced
- * bucket: the bucket to check
- * Returns false is the bucket is not synced
- */
-bool RGWRados::is_syncing_bucket_meta(const rgw_bucket& bucket)
-{
-
- /* no current period */
- if (current_period.get_id().empty()) {
- return false;
- }
-
- /* zonegroup is not master zonegroup */
- if (!get_zonegroup().is_master_zonegroup()) {
- return false;
- }
-
- /* single zonegroup and a single zone */
- if (current_period.is_single_zonegroup() && get_zonegroup().zones.size() == 1) {
- return false;
- }
-
- /* zone is not master */
- if (get_zonegroup().master_zone.compare(zone_public_config.id) != 0) {
- return false;
- }
-
- return true;
-}
-
int RGWRados::check_bucket_empty(RGWBucketInfo& bucket_info)
{
std::vector<rgw_bucket_dir_entry> ent_list;
return r;
/* if the bucket is not synced we can remove the meta file */
- if (!is_syncing_bucket_meta(bucket)) {
+ if (!svc.zone->is_syncing_bucket_meta(bucket)) {
RGWObjVersionTracker objv_tracker;
string entry = bucket.get_key();
r= rgw_bucket_instance_remove_entry(this, entry, &objv_tracker);
if (_zones_trace) {
zones_trace = *_zones_trace;
}
- zones_trace.insert(get_zone().id);
+ zones_trace.insert(svc.zone->get_zone().id);
BucketShard bs(this);
return cls_rgw_bucket_link_olh(bs->index_ctx, op,
bs->bucket_obj, key, olh_state.olh_tag, delete_marker, op_tag, meta, olh_epoch,
unmod_since, high_precision_time,
- get_zone().log_data, zones_trace);
+ svc.zone->get_zone().log_data, zones_trace);
});
if (r < 0) {
ldout(cct, 20) << "cls_rgw_bucket_link_olh() returned r=" << r << dendl;
if (_zones_trace) {
zones_trace = *_zones_trace;
}
- zones_trace.insert(get_zone().id);
+ zones_trace.insert(svc.zone->get_zone().id);
BucketShard bs(this);
librados::ObjectWriteOperation op;
cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
return cls_rgw_bucket_unlink_instance(bs->index_ctx, op, bs->bucket_obj, key, op_tag,
- olh_tag, olh_epoch, get_zone().log_data, zones_trace);
+ olh_tag, olh_epoch, svc.zone->get_zone().log_data, zones_trace);
});
if (r < 0) {
ldout(cct, 20) << "cls_rgw_bucket_link_olh() returned r=" << r << dendl;
target_obj->key.set_instance(buf);
}
-static void filter_attrset(map<string, bufferlist>& unfiltered_attrset, const string& check_prefix,
- map<string, bufferlist> *attrset)
-{
- attrset->clear();
- map<string, bufferlist>::iterator iter;
- for (iter = unfiltered_attrset.lower_bound(check_prefix);
- iter != unfiltered_attrset.end(); ++iter) {
- if (!boost::algorithm::starts_with(iter->first, check_prefix))
- break;
- (*attrset)[iter->first] = iter->second;
- }
-}
-
int RGWRados::get_olh(const RGWBucketInfo& bucket_info, const rgw_obj& obj, RGWOLHInfo *olh)
{
map<string, bufferlist> unfiltered_attrset;
}
map<string, bufferlist> attrset;
- filter_attrset(unfiltered_attrset, RGW_ATTR_OLH_PREFIX, &attrset);
+ rgw_filter_attrset(unfiltered_attrset, RGW_ATTR_OLH_PREFIX, &attrset);
map<string, bufferlist>::iterator iter = attrset.find(RGW_ATTR_OLH_INFO);
if (iter == attrset.end()) { /* not an olh */
int RGWRados::follow_olh(const RGWBucketInfo& bucket_info, RGWObjectCtx& obj_ctx, RGWObjState *state, const rgw_obj& olh_obj, rgw_obj *target)
{
map<string, bufferlist> pending_entries;
- filter_attrset(state->attrset, RGW_ATTR_OLH_PENDING_PREFIX, &pending_entries);
+ rgw_filter_attrset(state->attrset, RGW_ATTR_OLH_PENDING_PREFIX, &pending_entries);
map<string, bufferlist> rm_pending_entries;
check_pending_olh_entries(pending_entries, &rm_pending_entries);
if (pmtime)
*pmtime = ceph::real_clock::from_timespec(mtime_ts);
if (attrs) {
- filter_attrset(unfiltered_attrset, RGW_ATTR_PREFIX, attrs);
+ rgw_filter_attrset(unfiltered_attrset, RGW_ATTR_PREFIX, attrs);
}
return 0;
void RGWRados::get_bucket_instance_obj(const rgw_bucket& bucket, rgw_raw_obj& obj)
{
if (!bucket.oid.empty()) {
- obj.init(get_zone_params().domain_root, bucket.oid);
+ obj.init(svc.zone->get_zone_params().domain_root, bucket.oid);
} else {
string oid;
get_bucket_meta_oid(bucket, oid);
- obj.init(get_zone_params().domain_root, oid);
+ obj.init(svc.zone->get_zone_params().domain_root, oid);
}
}
rgw_cache_entry_info *cache_info,
boost::optional<obj_version> refresh_version)
{
- ldout(cct, 20) << "reading from " << get_zone_params().domain_root << ":" << oid << dendl;
+ auto& domain_root = svc.zone->get_zone_params().domain_root;
+
+ ldout(cct, 20) << "reading from " << domain_root << ":" << oid << dendl;
bufferlist epbl;
- int ret = rgw_get_system_obj(this, obj_ctx, get_zone_params().domain_root,
+ int ret = rgw_get_system_obj(this, obj_ctx, domain_root,
oid, epbl, &info.objv_tracker, pmtime, pattrs,
cache_info, refresh_version);
if (ret < 0) {
string bucket_entry;
rgw_make_bucket_entry_name(tenant_name, bucket_name, bucket_entry);
- int ret = rgw_get_system_obj(this, obj_ctx, get_zone_params().domain_root,
+ int ret = rgw_get_system_obj(this, obj_ctx, svc.zone->get_zone_params().domain_root,
bucket_entry, bl, objv_tracker, pmtime, pattrs,
cache_info, refresh_version);
if (ret < 0) {
return 0;
}
-int RGWRados::omap_get_vals(rgw_raw_obj& obj, bufferlist& header, const string& marker, uint64_t count, std::map<string, bufferlist>& m)
-{
- rgw_rados_ref ref;
- int r = get_raw_obj_ref(obj, &ref);
- if (r < 0) {
- return r;
- }
-
- r = ref.ioctx.omap_get_vals(ref.oid, marker, count, &m);
- if (r < 0)
- return r;
-
- return 0;
-
-}
-
-int RGWRados::omap_get_all(rgw_raw_obj& obj, bufferlist& header,
- std::map<string, bufferlist>& m)
-{
- rgw_rados_ref ref;
- int r = get_raw_obj_ref(obj, &ref);
- if (r < 0) {
- return r;
- }
-
-#define MAX_OMAP_GET_ENTRIES 1024
- const int count = MAX_OMAP_GET_ENTRIES;
- string start_after;
-
- while (true) {
- std::map<string, bufferlist> t;
- r = ref.ioctx.omap_get_vals(ref.oid, start_after, count, &t);
- if (r < 0) {
- return r;
- }
- if (t.empty()) {
- break;
- }
- start_after = t.rbegin()->first;
- m.insert(t.begin(), t.end());
- }
- return 0;
-}
-
-int RGWRados::omap_set(rgw_raw_obj& obj, const std::string& key, bufferlist& bl, bool must_exist)
-{
- rgw_rados_ref ref;
- int r = get_raw_obj_ref(obj, &ref);
- if (r < 0) {
- return r;
- }
- ldout(cct, 15) << "omap_set obj=" << obj << " key=" << key << dendl;
-
- map<string, bufferlist> m;
- m[key] = bl;
- ObjectWriteOperation op;
- if (must_exist)
- op.assert_exists();
- op.omap_set(m);
- r = ref.ioctx.operate(ref.oid, &op);
- return r;
-}
-
-int RGWRados::omap_set(rgw_raw_obj& obj, std::map<std::string, bufferlist>& m, bool must_exist)
-{
- rgw_rados_ref ref;
- int r = get_raw_obj_ref(obj, &ref);
- if (r < 0) {
- return r;
- }
-
- ObjectWriteOperation op;
- if (must_exist)
- op.assert_exists();
- op.omap_set(m);
- r = ref.ioctx.operate(ref.oid, &op);
- return r;
-}
-
-int RGWRados::omap_del(rgw_raw_obj& obj, const std::string& key)
-{
- rgw_rados_ref ref;
- int r = get_raw_obj_ref(obj, &ref);
- if (r < 0) {
- return r;
- }
-
- set<string> k;
- k.insert(key);
-
- r = ref.ioctx.omap_rm_keys(ref.oid, k);
- return r;
-}
-
int RGWRados::update_containers_stats(map<string, RGWBucketEnt>& m)
{
RGWObjectCtx obj_ctx(this);
return objs.size();
}
-struct RGWAccessListFilterPrefix : public RGWAccessListFilter {
- string prefix;
-
- explicit RGWAccessListFilterPrefix(const string& _prefix) : prefix(_prefix) {}
- bool filter(string& name, string& key) override {
- return (prefix.compare(key.substr(0, prefix.size())) == 0);
- }
-};
int RGWRados::list_raw_objects_init(const rgw_pool& pool, const string& marker, RGWListRawObjsCtx *ctx)
{
if (_zones_trace) {
zones_trace = *_zones_trace;
}
- zones_trace.insert(get_zone().id);
+ zones_trace.insert(svc.zone->get_zone().id);
ObjectWriteOperation o;
cls_rgw_obj_key key(obj.key.get_index_key_name(), obj.key.instance);
cls_rgw_guard_bucket_resharding(o, -ERR_BUSY_RESHARDING);
- cls_rgw_bucket_prepare_op(o, op, tag, key, obj.key.get_loc(), get_zone().log_data, bilog_flags, zones_trace);
+ cls_rgw_bucket_prepare_op(o, op, tag, key, obj.key.get_loc(), svc.zone->get_zone().log_data, bilog_flags, zones_trace);
return bs.index_ctx.operate(bs.bucket_obj, &o);
}
if (_zones_trace) {
zones_trace = *_zones_trace;
}
- zones_trace.insert(get_zone().id);
+ zones_trace.insert(svc.zone->get_zone().id);
rgw_bucket_entry_ver ver;
ver.pool = pool;
cls_rgw_obj_key key(ent.key.name, ent.key.instance);
cls_rgw_guard_bucket_resharding(o, -ERR_BUSY_RESHARDING);
cls_rgw_bucket_complete_op(o, op, tag, ver, key, dir_meta, remove_objs,
- get_zone().log_data, bilog_flags, &zones_trace);
+ svc.zone->get_zone().log_data, bilog_flags, &zones_trace);
complete_op_data *arg;
index_completion_manager->create_completion(obj, op, tag, ver, key, dir_meta, remove_objs,
- get_zone().log_data, bilog_flags, &zones_trace, &arg);
+ svc.zone->get_zone().log_data, bilog_flags, &zones_trace, &arg);
librados::AioCompletion *completion = arg->rados_completion;
int ret = bs.index_ctx.aio_operate(bs.bucket_obj, arg->rados_completion, &o);
completion->release(); /* can't reference arg here, as it might have already been released */
int RGWRados::cls_obj_usage_log_add(const string& oid,
rgw_usage_log_info& info)
{
- rgw_raw_obj obj(get_zone_params().usage_log_pool, oid);
+ rgw_raw_obj obj(svc.zone->get_zone_params().usage_log_pool, oid);
rgw_rados_ref ref;
int r = get_raw_obj_ref(obj, &ref);
int RGWRados::cls_obj_usage_log_read(string& oid, string& user, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
string& read_iter, map<rgw_user_bucket, rgw_usage_log_entry>& usage, bool *is_truncated)
{
- rgw_raw_obj obj(get_zone_params().usage_log_pool, oid);
+ rgw_raw_obj obj(svc.zone->get_zone_params().usage_log_pool, oid);
rgw_rados_ref ref;
int r = get_raw_obj_ref(obj, &ref);
int RGWRados::cls_obj_usage_log_trim(string& oid, string& user, uint64_t start_epoch, uint64_t end_epoch)
{
- rgw_raw_obj obj(get_zone_params().usage_log_pool, oid);
+ rgw_raw_obj obj(svc.zone->get_zone_params().usage_log_pool, oid);
rgw_rados_ref ref;
int r = get_raw_obj_ref(obj, &ref);
int RGWRados::cls_obj_usage_log_clear(string& oid)
{
- rgw_raw_obj obj(get_zone_params().usage_log_pool, oid);
+ rgw_raw_obj obj(svc.zone->get_zone_params().usage_log_pool, oid);
rgw_rados_ref ref;
int r = get_raw_obj_ref(obj, &ref);
librados::IoCtx index_ctx;
string dir_oid;
- uint8_t suggest_flag = (get_zone().log_data ? CEPH_RGW_DIR_SUGGEST_LOG_OP : 0);
+ uint8_t suggest_flag = (svc.zone->get_zone().log_data ? CEPH_RGW_DIR_SUGGEST_LOG_OP : 0);
int r = open_bucket_index(bucket_info, index_ctx, dir_oid);
if (r < 0)
bufferlist& suggested_updates)
{
const rgw_bucket& bucket = bucket_info.bucket;
- uint8_t suggest_flag = (get_zone().log_data ? CEPH_RGW_DIR_SUGGEST_LOG_OP : 0);
+ uint8_t suggest_flag = (svc.zone->get_zone().log_data ? CEPH_RGW_DIR_SUGGEST_LOG_OP : 0);
std::string loc;
{
string buckets_obj_id;
rgw_get_buckets_obj(user_id, buckets_obj_id);
- rgw_raw_obj obj(get_zone_params().user_uid_pool, buckets_obj_id);
+ rgw_raw_obj obj(svc.zone->get_zone_params().user_uid_pool, buckets_obj_id);
rgw_rados_ref ref;
int r = get_raw_obj_ref(obj, &ref);
{
string buckets_obj_id;
rgw_get_buckets_obj(user_id, buckets_obj_id);
- rgw_raw_obj obj(get_zone_params().user_uid_pool, buckets_obj_id);
+ rgw_raw_obj obj(svc.zone->get_zone_params().user_uid_pool, buckets_obj_id);
rgw_rados_ref ref;
int r = get_raw_obj_ref(obj, &ref);
{
string buckets_obj_id;
rgw_get_buckets_obj(user_id, buckets_obj_id);
- rgw_raw_obj obj(get_zone_params().user_uid_pool, buckets_obj_id);
+ rgw_raw_obj obj(svc.zone->get_zone_params().user_uid_pool, buckets_obj_id);
rgw_rados_ref ref;
int r = get_raw_obj_ref(obj, &ref);
{
string buckets_obj_id;
rgw_get_buckets_obj(user_id, buckets_obj_id);
- rgw_raw_obj obj(get_zone_params().user_uid_pool, buckets_obj_id);
+ rgw_raw_obj obj(svc.zone->get_zone_params().user_uid_pool, buckets_obj_id);
return cls_user_complete_stats_sync(obj);
}
int RGWRados::get_mfa_ref(const rgw_user& user, rgw_rados_ref *ref)
{
string oid = get_mfa_oid(user);
- rgw_raw_obj obj(get_zone_params().otp_pool, oid);
+ rgw_raw_obj obj(svc.zone->get_zone_params().otp_pool, oid);
return get_system_obj_ref(obj, ref);
}
bool reset_obj, RGWObjVersionTracker *objv_tracker,
const real_time& mtime)
{
- rgw_raw_obj obj(get_zone_params().otp_pool, oid);
+ rgw_raw_obj obj(svc.zone->get_zone_params().otp_pool, oid);
rgw_rados_ref ref;
int r = get_system_obj_ref(obj, &ref);
if (r < 0) {
int RGWRados::list_mfa(const string& oid, list<rados::cls::otp::otp_info_t> *result,
RGWObjVersionTracker *objv_tracker, ceph::real_time *pmtime)
{
- rgw_raw_obj obj(get_zone_params().otp_pool, oid);
+ rgw_raw_obj obj(svc.zone->get_zone_params().otp_pool, oid);
rgw_rados_ref ref;
int r = get_system_obj_ref(obj, &ref);
if (r < 0) {
virtual ~RGWGetDataCB() {}
};
-class RGWAccessListFilter {
-public:
- virtual ~RGWAccessListFilter() {}
- virtual bool filter(string& name, string& key) = 0;
-};
-
struct RGWCloneRangeInfo {
rgw_obj src;
off_t src_ofs;
*/
int delete_bucket(RGWBucketInfo& bucket_info, RGWObjVersionTracker& objv_tracker, bool check_empty = true);
- /**
- * Check to see if the bucket metadata is synced
- */
- bool is_syncing_bucket_meta(const rgw_bucket& bucket);
void wakeup_meta_sync_shards(set<int>& shard_ids);
void wakeup_data_sync_shards(const string& source_zone, map<int, set<string> >& shard_ids);
void gen_rand_obj_instance_name(rgw_obj *target);
- int omap_get_vals(rgw_raw_obj& obj, bufferlist& header, const std::string& marker, uint64_t count, std::map<string, bufferlist>& m);
- int omap_get_all(rgw_raw_obj& obj, bufferlist& header, std::map<string, bufferlist>& m);
- int omap_set(rgw_raw_obj& obj, const std::string& key, bufferlist& bl, bool must_exist = false);
- int omap_set(rgw_raw_obj& obj, map<std::string, bufferlist>& m, bool must_exist = false);
- int omap_del(rgw_raw_obj& obj, const std::string& key);
int update_containers_stats(map<string, RGWBucketEnt>& m);
int append_async(rgw_raw_obj& obj, size_t size, bufferlist& bl);
period.set_id(period_id);
period.set_epoch(epoch);
- http_ret = period.init(store->ctx(), store, realm_id, realm_name);
+ http_ret = period.init(store->ctx(), store->svc.sysobj.get(), realm_id, realm_name);
if (http_ret < 0)
ldout(store->ctx(), 5) << "failed to read period" << dendl;
}
auto cct = store->ctx();
// initialize the period without reading from rados
- period.init(cct, store, false);
+ period.init(cct, store->svc.sysobj.get(), false);
// decode the period from input
const auto max_size = cct->_conf->rgw_max_put_param_size;
// period that we haven't restarted with yet. we also don't want to modify
// the objects in use by RGWRados
RGWRealm realm(period.get_realm());
- http_ret = realm.init(cct, store);
+ http_ret = realm.init(cct, store->svc.sysobj.get());
if (http_ret < 0) {
lderr(cct) << "failed to read current realm: "
<< cpp_strerror(-http_ret) << dendl;
}
RGWPeriod current_period;
- http_ret = current_period.init(cct, store, realm.get_id());
+ http_ret = current_period.init(cct, store->svc.sysobj.get(), realm.get_id());
if (http_ret < 0) {
lderr(cct) << "failed to read current period: "
<< cpp_strerror(-http_ret) << dendl;
// read realm
realm.reset(new RGWRealm(id, name));
- http_ret = realm->init(g_ceph_context, store);
+ http_ret = realm->init(g_ceph_context, store->svc.sysobj.get());
if (http_ret < 0)
lderr(store->ctx()) << "failed to read realm id=" << id
<< " name=" << name << dendl;
}
bool find(const string& name, RGWServiceRef *svc);
+ /* returns existing or creates a new one */
int get_instance(RGWServiceRef& svc,
const string& conf,
RGWServiceInstanceRef *ref); /* returns existing or creates a new one */
+
+ /* returns existing or creates a new one */
+ template <class T>
+ int get_instance(RGWServiceRef& svc,
+ const string& conf,
+ T *ref) {
+ RGWServiceInstanceRef r;
+ int ret = get_instance(svc, conf, &r);
+ if (ret < 0) {
+ return ret;
+ }
+ *ref = std::static_pointer_cast<typename T::element_type>(r);
+ return 0;
+ }
+
+ template <class T>
int get_instance(const string& svc_name,
const string& conf,
- RGWServiceInstanceRef *ref) {
+ T *ref) {
auto iter = services.find(svc_name);
if (iter == services.end()) {
return -ENOENT;
void remove_instance(RGWServiceInstance *instance);
};
+
#endif
return iter->second.c_str();
}
+void rgw_filter_attrset(map<string, bufferlist>& unfiltered_attrset, const string& check_prefix,
+ map<string, bufferlist> *attrset)
+{
+ attrset->clear();
+ map<string, bufferlist>::iterator iter;
+ for (iter = unfiltered_attrset.lower_bound(check_prefix);
+ iter != unfiltered_attrset.end(); ++iter) {
+ if (!boost::algorithm::starts_with(iter->first, check_prefix))
+ break;
+ (*attrset)[iter->first] = iter->second;
+ }
+}
+
int rgw_tools_init(CephContext *cct)
{
ext_mime_map = new std::map<std::string, std::string>;
int rgw_delete_system_obj(RGWRados *rgwstore, const rgw_pool& pool, const string& oid,
RGWObjVersionTracker *objv_tracker);
+const char *rgw_find_mime_by_ext(string& ext);
+
+void rgw_filter_attrset(map<string, bufferlist>& unfiltered_attrset, const string& check_prefix,
+ map<string, bufferlist> *attrset);
+
int rgw_tools_init(CephContext *cct);
void rgw_tools_cleanup();
-const char *rgw_find_mime_by_ext(string& ext);
#endif
#include "include/str_list.h"
#include "include/rados/librados.hpp"
+#include "services/svc_sys_obj.h"
+
#define dout_subsys ceph_subsys_rgw
using ceph::crypto::MD5;
rgw_raw_obj raw_obj;
store->obj_to_raw(s->bucket_info.placement_rule, obj, &raw_obj);
- op_ret = store->omap_set(raw_obj, key, bl);
+ auto obj_ctx = store->svc.sysobj->init_obj_ctx();
+ auto sysobj = obj_ctx.get_obj(raw_obj);
+
+ op_ret = sysobj.omap().set(key, bl);
if (op_ret < 0)
{
ldout(s->cct, 0) << "ERROR: failed to omap_set() op_ret = " << op_ret << dendl;
return init_ioctx(cct, get_rados_handle(), pool, io_ctx, create);
}
+int RGWSI_RADOS::pool_iterate(librados::IoCtx& io_ctx,
+ librados::NObjectIterator& iter,
+ uint32_t num, vector<rgw_bucket_dir_entry>& objs,
+ RGWAccessListFilter *filter,
+ bool *is_truncated)
+{
+ if (iter == io_ctx.nobjects_end())
+ return -ENOENT;
+
+ uint32_t i;
+
+ for (i = 0; i < num && iter != io_ctx.nobjects_end(); ++i, ++iter) {
+ rgw_bucket_dir_entry e;
+
+ string oid = iter->get_oid();
+ ldout(cct, 20) << "RGWRados::pool_iterate: got " << oid << dendl;
+
+ // fill it in with initial values; we may correct later
+ if (filter && !filter->filter(oid, oid))
+ continue;
+
+ e.key = oid;
+ objs.push_back(e);
+ }
+
+ if (is_truncated)
+ *is_truncated = (iter != io_ctx.nobjects_end());
+
+ return objs.size();
+}
void RGWSI_RADOS::Obj::init(const rgw_raw_obj& obj)
{
ref.oid = obj.oid;
int RGWSI_RADOS::Obj::open()
{
int r = rados_svc->open_pool_ctx(ref.pool, ref.ioctx);
- if (r < 0)
+ if (r < 0) {
return r;
+ }
ref.ioctx.locator_set_key(ref.key);
{
return ref.ioctx.get_last_version();
}
+
+int RGWSI_RADOS::Pool::create(const vector<rgw_pool>& pools, vector<int> *retcodes)
+{
+ vector<librados::PoolAsyncCompletion *> completions;
+ vector<int> rets;
+
+ librados::Rados *rad = rados_svc->get_rados_handle();
+ for (auto iter = pools.begin(); iter != pools.end(); ++iter) {
+ librados::PoolAsyncCompletion *c = librados::Rados::pool_async_create_completion();
+ completions.push_back(c);
+ auto& pool = *iter;
+ int ret = rad->pool_create_async(pool.name.c_str(), c);
+ rets.push_back(ret);
+ }
+
+ vector<int>::iterator riter;
+ vector<librados::PoolAsyncCompletion *>::iterator citer;
+
+ bool error = false;
+ assert(rets.size() == completions.size());
+ for (riter = rets.begin(), citer = completions.begin(); riter != rets.end(); ++riter, ++citer) {
+ int r = *riter;
+ librados::PoolAsyncCompletion *c = *citer;
+ if (r == 0) {
+ c->wait();
+ r = c->get_return_value();
+ if (r < 0) {
+ ldout(rados_svc->cct, 0) << "WARNING: async pool_create returned " << r << dendl;
+ error = true;
+ }
+ }
+ c->release();
+ retcodes->push_back(r);
+ }
+ if (error) {
+ return 0;
+ }
+
+ std::vector<librados::IoCtx> io_ctxs;
+ retcodes->clear();
+ for (auto pool : pools) {
+ io_ctxs.emplace_back();
+ int ret = rad->ioctx_create(pool.name.c_str(), io_ctxs.back());
+ if (ret < 0) {
+ ldout(rados_svc->cct, 0) << "WARNING: ioctx_create returned " << ret << dendl;
+ error = true;
+ }
+ retcodes->push_back(ret);
+ }
+ if (error) {
+ return 0;
+ }
+
+ completions.clear();
+ for (auto &io_ctx : io_ctxs) {
+ librados::PoolAsyncCompletion *c =
+ librados::Rados::pool_async_create_completion();
+ completions.push_back(c);
+ int ret = io_ctx.application_enable_async(pg_pool_t::APPLICATION_NAME_RGW,
+ false, c);
+ assert(ret == 0);
+ }
+
+ retcodes->clear();
+ for (auto c : completions) {
+ c->wait();
+ int ret = c->get_return_value();
+ if (ret == -EOPNOTSUPP) {
+ ret = 0;
+ } else if (ret < 0) {
+ ldout(rados_svc->cct, 0) << "WARNING: async application_enable returned " << ret
+ << dendl;
+ error = true;
+ }
+ c->release();
+ retcodes->push_back(ret);
+ }
+ return 0;
+}
+
+int RGWSI_RADOS::Pool::lookup(const rgw_pool& pool)
+{
+ librados::Rados *rad = rados_svc->get_rados_handle();
+ int ret = rad->pool_lookup(pool.name.c_str());
+ if (ret < 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+int RGWSI_RADOS::Pool::List::init(const string& marker, RGWAccessListFilter *filter)
+{
+ if (ctx.initialized) {
+ return -EINVAL;
+ }
+
+ int r = pool.rados_svc->open_pool_ctx(pool.pool, ctx.ioctx);
+ if (r < 0) {
+ return r;
+ }
+
+ librados::ObjectCursor oc;
+ if (!oc.from_str(marker)) {
+ ldout(pool.rados_svc->cct, 10) << "failed to parse cursor: " << marker << dendl;
+ return -EINVAL;
+ }
+
+ ctx.iter = ctx.ioctx.nobjects_begin(oc);
+ ctx.filter = filter;
+ ctx.initialized = true;
+
+ return 0;
+}
+
+int RGWSI_RADOS::Pool::List::get_next(int max,
+ std::list<string> *oids,
+ bool *is_truncated)
+{
+ if (!ctx.initialized) {
+ return -EINVAL;
+ }
+ vector<rgw_bucket_dir_entry> objs;
+ int r = pool.rados_svc->pool_iterate(ctx.ioctx, ctx.iter, max, objs, ctx.filter, is_truncated);
+ if (r < 0) {
+ if(r != -ENOENT) {
+ ldout(pool.rados_svc->cct, 10) << "failed to list objects pool_iterate returned r=" << r << dendl;
+ }
+ return r;
+ }
+
+ vector<rgw_bucket_dir_entry>::iterator iter;
+ for (auto& o : objs) {
+ oids->push_back(o.key.name);
+ }
+
+ return oids->size();
+}
+
#include "include/rados/librados.hpp"
+class RGWAccessListFilter {
+public:
+ virtual ~RGWAccessListFilter() {}
+ virtual bool filter(string& name, string& key) = 0;
+};
+
+struct RGWAccessListFilterPrefix : public RGWAccessListFilter {
+ string prefix;
+
+ explicit RGWAccessListFilterPrefix(const string& _prefix) : prefix(_prefix) {}
+ bool filter(string& name, string& key) override {
+ return (prefix.compare(key.substr(0, prefix.size())) == 0);
+ }
+};
+
class RGWS_RADOS : public RGWService
{
std::vector<std::string> get_deps();
librados::Rados* get_rados_handle();
int open_pool_ctx(const rgw_pool& pool, librados::IoCtx& io_ctx);
+ int pool_iterate(librados::IoCtx& ioctx,
+ librados::NObjectIterator& iter,
+ uint32_t num, vector<rgw_bucket_dir_entry>& objs,
+ RGWAccessListFilter *filter,
+ bool *is_truncated);
+
public:
RGWSI_RADOS(RGWService *svc, CephContext *cct): RGWServiceInstance(svc, cct),
handle_lock("rados_handle_lock") {}
Obj(Obj&& o) : rados_svc(o.rados_svc),
ref(std::move(o.ref)) {}
+ Obj& operator=(Obj&& o) {
+ rados_svc = o.rados_svc;
+ ref = std::move(o.ref);
+ return *this;
+ }
+
int open();
int operate(librados::ObjectWriteOperation *op);
uint64_t get_last_version();
};
+ class Pool {
+ friend class RGWSI_RADOS;
+
+ RGWSI_RADOS *rados_svc{nullptr};
+ rgw_pool pool;
+
+ Pool(RGWSI_RADOS *_rados_svc, const rgw_pool& _pool) : rados_svc(_rados_svc),
+ pool(_pool) {}
+
+ Pool(RGWSI_RADOS *_rados_svc) : rados_svc(_rados_svc) {}
+ public:
+ Pool() {}
+ Pool(const Pool& p) : rados_svc(p.rados_svc),
+ pool(p.pool) {}
+
+ int create(const std::vector<rgw_pool>& pools, std::vector<int> *retcodes);
+ int lookup(const rgw_pool& pool);
+
+ struct List {
+ Pool& pool;
+
+ struct Ctx {
+ bool initialized{false};
+ librados::IoCtx ioctx;
+ librados::NObjectIterator iter;
+ RGWAccessListFilter *filter{nullptr};
+ } ctx;
+
+ List(Pool& _pool) : pool(_pool) {}
+
+ int init(const string& marker, RGWAccessListFilter *filter = nullptr);
+ int get_next(int max,
+ std::list<string> *oids,
+ bool *is_truncated);
+ };
+
+ List op() {
+ return List(*this);
+ }
+
+ friend class List;
+ };
+
Obj obj(const rgw_raw_obj& o) {
return Obj(this, o);
}
+ Pool pool() {
+ return Pool(this);
+ }
+
+ Pool pool(const rgw_pool& p) {
+ return Pool(this, p);
+ }
+
+ friend class Obj;
+ friend class Pool;
+ friend class Pool::List;
};
#endif
#include "svc_sys_obj.h"
#include "svc_rados.h"
+#include "svc_zone.h"
+
+#include "rgw/rgw_tools.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+RGWSysObjectCtx&& RGWSI_SysObj::init_obj_ctx()
+{
+ return std::move(RGWSysObjectCtx(this));
+}
+
+RGWSI_SysObj::Obj&& RGWSI_SysObj::get_obj(RGWSysObjectCtx& obj_ctx, const rgw_raw_obj& obj)
+{
+ return std::move(Obj(this, obj_ctx, obj));
+}
int RGWS_SysObj::create_instance(const string& conf, RGWServiceInstanceRef *instance)
{
RGWServiceInstance::dependency dep2 = { .name = "zone",
.conf = "{}" };
map<string, RGWServiceInstance::dependency> deps;
- deps["rados_dep"] = dep1
- deps["zone_dep"] = dep2
+ deps["rados_dep"] = dep1;
+ deps["zone_dep"] = dep2;
return deps;
}
int RGWSI_SysObj::get_rados_obj(RGWSI_Zone *zone_svc,
rgw_raw_obj& obj,
- RGWSI_Rados::Obj *pobj)
+ RGWSI_RADOS::Obj *pobj)
{
zone_svc->canonicalize_raw_obj(&obj);
- *pobj = rados_svc->obj(obj);
+ *pobj = std::move(rados_svc->obj(obj));
int r = pobj->open();
if (r < 0) {
return r;
s->obj = obj;
- int r = raw_stat(obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : NULL), objv_tracker);
+ int r = raw_stat(obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : nullptr), objv_tracker);
if (r == -ENOENT) {
s->exists = false;
s->has_attrs = true;
map<string, bufferlist> *attrs, bufferlist *first_chunk,
RGWObjVersionTracker *objv_tracker)
{
- RGWSI_Rados::Obj rados_obj;
- int r = get_rados_obj(obj, &rados_obj);
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
if (r < 0) {
return r;
}
objv_tracker->prepare_op_for_read(&op);
}
if (attrs) {
- op.getxattrs(&unfiltered_attrset, NULL);
+ op.getxattrs(&unfiltered_attrset, nullptr);
}
if (psize || pmtime) {
- op.stat2(&size, &mtime_ts, NULL);
+ op.stat2(&size, &mtime_ts, nullptr);
}
if (first_chunk) {
- op.read(0, cct->_conf->rgw_max_chunk_size, first_chunk, NULL);
+ op.read(0, cct->_conf->rgw_max_chunk_size, first_chunk, nullptr);
}
bufferlist outbl;
r = rados_obj.operate(&op, &outbl);
if (pmtime)
*pmtime = ceph::real_clock::from_timespec(mtime_ts);
if (attrs) {
- filter_attrset(unfiltered_attrset, RGW_ATTR_PREFIX, attrs);
+ rgw_filter_attrset(unfiltered_attrset, RGW_ATTR_PREFIX, attrs);
}
return 0;
}
int RGWSI_SysObj::stat(RGWSysObjectCtx& obj_ctx,
- RGWSI_SysObj::SystemObject::Read::GetObjState& state,
+ RGWSI_SysObj::Obj::ROp::GetObjState& state,
rgw_raw_obj& obj,
map<string, bufferlist> *attrs,
real_time *lastmod,
uint64_t *obj_size,
RGWObjVersionTracker *objv_tracker)
{
- RGWSysObjState *astate = NULL;
+ RGWSysObjState *astate = nullptr;
int r = get_system_obj_state(&obj_ctx, obj, &astate, objv_tracker);
if (r < 0)
return 0;
}
-int RGWSI_SysObj::read_obj(RGWObjectCtx& obj_ctx,
- Obj::Read::GetObjState& read_state,
- RGWObjVersionTracker *objv_tracker,
- rgw_raw_obj& obj,
- bufferlist *bl, off_t ofs, off_t end,
- map<string, bufferlist> *attrs,
- boost::optional<obj_version>)
+int RGWSI_SysObj::read(RGWSysObjectCtx& obj_ctx,
+ Obj::ROp::GetObjState& read_state,
+ RGWObjVersionTracker *objv_tracker,
+ rgw_raw_obj& obj,
+ bufferlist *bl, off_t ofs, off_t end,
+ map<string, bufferlist> *attrs,
+ boost::optional<obj_version>)
{
uint64_t len;
librados::ObjectReadOperation op;
}
ldout(cct, 20) << "rados->read ofs=" << ofs << " len=" << len << dendl;
- op.read(ofs, len, bl, NULL);
+ op.read(ofs, len, bl, nullptr);
if (attrs) {
- op.getxattrs(attrs, NULL);
+ op.getxattrs(attrs, nullptr);
}
- RGWSI_Rados::Obj rados_obj;
- int r = get_rados_obj(obj, &rados_obj);
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
if (r < 0) {
ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
return r;
}
- r = rados_obj.operate(&op, NULL);
+ r = rados_obj.operate(&op, nullptr);
if (r < 0) {
ldout(cct, 20) << "rados_obj.operate() r=" << r << " bl.length=" << bl->length() << dendl;
return r;
read_state.last_ver = op_ver;
- return bl.length();
+ return bl->length();
}
/**
* dest: bufferlist to store the result in
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWSI_SysObj::get_attr(rgw_raw_obj& obj, std::string_view name, bufferlist *dest)
+int RGWSI_SysObj::get_attr(rgw_raw_obj& obj,
+ const char *name,
+ bufferlist *dest)
{
- RGWSI_Rados::Obj rados_obj;
- int r = get_rados_obj(obj, &rados_obj);
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
if (r < 0) {
ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
return r;
return 0;
}
+int RGWSI_SysObj::omap_get_vals(rgw_raw_obj& obj,
+ const string& marker,
+ uint64_t count,
+ std::map<string, bufferlist> *m,
+ bool *pmore)
+{
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
+ if (r < 0) {
+ ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
+ return r;
+ }
+
+ string start_after = marker;
+ bool more;
+
+ do {
+ librados::ObjectReadOperation op;
+
+ std::map<string, bufferlist> t;
+ int rval;
+ op.omap_get_vals2(start_after, count, &t, &more, &rval);
+
+ r = rados_obj.operate(&op, nullptr);
+ if (r < 0) {
+ return r;
+ }
+ if (t.empty()) {
+ break;
+ }
+ count -= t.size();
+ start_after = t.rbegin()->first;
+ m->insert(t.begin(), t.end());
+ } while (more && count > 0);
+
+ if (pmore) {
+ *pmore = more;
+ }
+ return 0;
+}
+
+int RGWSI_SysObj::omap_get_all(rgw_raw_obj& obj, std::map<string, bufferlist> *m)
+{
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
+ if (r < 0) {
+ ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
+ return r;
+ }
+
+#define MAX_OMAP_GET_ENTRIES 1024
+ const int count = MAX_OMAP_GET_ENTRIES;
+ string start_after;
+ bool more;
+
+ do {
+ librados::ObjectReadOperation op;
+
+ std::map<string, bufferlist> t;
+ int rval;
+ op.omap_get_vals2(start_after, count, &t, &more, &rval);
+
+ r = rados_obj.operate(&op, nullptr);
+ if (r < 0) {
+ return r;
+ }
+ if (t.empty()) {
+ break;
+ }
+ start_after = t.rbegin()->first;
+ m->insert(t.begin(), t.end());
+ } while (more);
+ return 0;
+}
+
+int RGWSI_SysObj::omap_set(rgw_raw_obj& obj, const std::string& key, bufferlist& bl, bool must_exist)
+{
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
+ if (r < 0) {
+ ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
+ return r;
+ }
+
+ ldout(cct, 15) << "omap_set obj=" << obj << " key=" << key << dendl;
+
+ map<string, bufferlist> m;
+ m[key] = bl;
+ librados::ObjectWriteOperation op;
+ if (must_exist)
+ op.assert_exists();
+ op.omap_set(m);
+ r = rados_obj.operate(&op);
+ return r;
+}
+
+int RGWSI_SysObj::omap_set(rgw_raw_obj& obj, const std::map<std::string, bufferlist>& m, bool must_exist)
+{
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
+ if (r < 0) {
+ ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
+ return r;
+ }
+
+ librados::ObjectWriteOperation op;
+ if (must_exist)
+ op.assert_exists();
+ op.omap_set(m);
+ r = rados_obj.operate(&op);
+ return r;
+}
+
+int RGWSI_SysObj::omap_del(rgw_raw_obj& obj, const std::string& key)
+{
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
+ if (r < 0) {
+ ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
+ return r;
+ }
+
+ set<string> k;
+ k.insert(key);
+
+ librados::ObjectWriteOperation op;
+
+ op.omap_rm_keys(k);
+
+ r = rados_obj.operate(&op);
+ return r;
+}
+
+int RGWSI_SysObj::remove(RGWSysObjectCtx& obj_ctx,
+ RGWObjVersionTracker *objv_tracker,
+ rgw_raw_obj& obj)
+{
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
+ if (r < 0) {
+ ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
+ return r;
+ }
+
+ librados::ObjectWriteOperation op;
+
+ if (objv_tracker) {
+ objv_tracker->prepare_op_for_write(&op);
+ }
+
+ op.remove();
+ r = rados_obj.operate(&op);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int RGWSI_SysObj::write(rgw_raw_obj& obj,
+ real_time *pmtime,
+ map<std::string, bufferlist>& attrs,
+ bool exclusive,
+ const bufferlist& data,
+ RGWObjVersionTracker *objv_tracker,
+ real_time set_mtime)
+{
+ RGWSI_RADOS::Obj rados_obj;
+ int r = get_rados_obj(zone_svc.get(), obj, &rados_obj);
+ if (r < 0) {
+ ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
+ return r;
+ }
+
+ librados::ObjectWriteOperation op;
+
+ if (exclusive) {
+ op.create(true); // exclusive create
+ } else {
+ op.remove();
+ op.set_op_flags2(LIBRADOS_OP_FLAG_FAILOK);
+ op.create(false);
+ }
+
+ if (objv_tracker) {
+ objv_tracker->prepare_op_for_write(&op);
+ }
+
+ if (real_clock::is_zero(set_mtime)) {
+ set_mtime = real_clock::now();
+ }
+
+ struct timespec mtime_ts = real_clock::to_timespec(set_mtime);
+ op.mtime2(&mtime_ts);
+ op.write_full(data);
+
+ bufferlist acl_bl;
+
+ for (map<string, bufferlist>::iterator iter = attrs.begin(); iter != attrs.end(); ++iter) {
+ const string& name = iter->first;
+ bufferlist& bl = iter->second;
+
+ if (!bl.length())
+ continue;
+
+ op.setxattr(name.c_str(), bl);
+ }
+
+ r = rados_obj.operate(&op);
+ if (r < 0) {
+ return r;
+ }
+
+ if (objv_tracker) {
+ objv_tracker->apply_write();
+ }
+
+ if (pmtime) {
+ *pmtime = set_mtime;
+ }
+
+ return 0;
+}
+
+
void RGWSI_SysObj::Obj::invalidate_state()
{
ctx.invalidate(obj);
}
-int RGWSI_SysObj::Obj::Read::GetObjState::get_rados_obj(RGWSI_RADOS *rados_svc,
- RGWSI_Zone *zone_svc,
- rgw_raw_obj& obj,
- RGWSI_Rados::Obj **pobj)
+int RGWSI_SysObj::Obj::ROp::GetObjState::get_rados_obj(RGWSI_RADOS *rados_svc,
+ RGWSI_Zone *zone_svc,
+ rgw_raw_obj& obj,
+ RGWSI_RADOS::Obj **pobj)
{
if (!has_rados_obj) {
zone_svc->canonicalize_raw_obj(&obj);
return 0;
}
-int RGWSI_SysObj::Obj::Read::stat()
+int RGWSI_SysObj::Obj::ROp::stat()
{
RGWSI_SysObj *svc = source.sysobj_svc;
rgw_raw_obj& obj = source.obj;
- return sysobj_svc->stat(source.ctx(), state, obj, stat_params.attrs,
- stat_params.lastmod, stat_params.obj_size,
- stat_params.objv_tracker);
+ return svc->stat(source.get_ctx(), state, obj, attrs,
+ lastmod, obj_size,
+ objv_tracker);
}
-
-int RGWSI_SysObj::Obj::Read::read(int64_t ofs, int64_t end, bufferlist *bl)
+int RGWSI_SysObj::Obj::ROp::read(int64_t ofs, int64_t end, bufferlist *bl)
{
RGWSI_SysObj *svc = source.sysobj_svc;
rgw_raw_obj& obj = source.get_obj();
return svc->read(source.get_ctx(), state,
- read_params.objv_tracker,
+ objv_tracker,
obj, bl, ofs, end,
- read_params.attrs,
+ attrs,
refresh_version);
}
-int RGWSI_SysObj::Obj::Read::get_attr(std::string_view name, bufferlist *dest)
+int RGWSI_SysObj::Obj::ROp::get_attr(const char *name, bufferlist *dest)
{
RGWSI_SysObj *svc = source.sysobj_svc;
rgw_raw_obj& obj = source.get_obj();
return svc->get_attr(obj, name, dest);
}
+int RGWSI_SysObj::Obj::WOp::remove()
+{
+ RGWSI_SysObj *svc = source.sysobj_svc;
+ rgw_raw_obj& obj = source.get_obj();
+
+ return svc->remove(source.get_ctx(),
+ objv_tracker,
+ obj);
+}
+
+int RGWSI_SysObj::Obj::WOp::write(bufferlist& bl)
+{
+ RGWSI_SysObj *svc = source.sysobj_svc;
+ rgw_raw_obj& obj = source.get_obj();
+
+ return svc->write(obj, pmtime, attrs, exclusive,
+ bl, objv_tracker, mtime);
+}
+
+int RGWSI_SysObj::Pool::Op::list_prefixed_objs(const string& prefix, list<string> *result)
+{
+ bool is_truncated;
+
+ auto rados_svc = source.get_rados_svc();
+ auto rados_pool = rados_svc->pool(source.pool);
+
+ auto op = rados_pool.op();
+
+ RGWAccessListFilterPrefix filter(prefix);
+
+ int r = op.init(string(), &filter);
+ if (r < 0) {
+ return r;
+ }
+
+ do {
+ list<string> oids;
+#define MAX_OBJS_DEFAULT 1000
+ int r = op.get_next(MAX_OBJS_DEFAULT, &oids, &is_truncated);
+ if (r < 0) {
+ return r;
+ }
+ for (auto& val : oids) {
+ if (val.size() > prefix.size()) {
+ result->push_back(val.substr(prefix.size()));
+ }
+ }
+ } while (is_truncated);
+
+ return 0;
+}
+
+int RGWSI_SysObj::Obj::OmapOp::get_all(std::map<string, bufferlist> *m)
+{
+ RGWSI_SysObj *svc = source.sysobj_svc;
+ rgw_raw_obj& obj = source.obj;
+
+ return svc->omap_get_all(obj, m);
+}
+
+int RGWSI_SysObj::Obj::OmapOp::get_vals(const string& marker,
+ uint64_t count,
+ std::map<string, bufferlist> *m,
+ bool *pmore)
+{
+ RGWSI_SysObj *svc = source.sysobj_svc;
+ rgw_raw_obj& obj = source.obj;
+
+ return svc->omap_get_vals(obj, marker, count, m, pmore);
+}
+
+int RGWSI_SysObj::Obj::OmapOp::set(const std::string& key, bufferlist& bl)
+{
+ RGWSI_SysObj *svc = source.sysobj_svc;
+ rgw_raw_obj& obj = source.obj;
+
+ return svc->omap_set(obj, key, bl, must_exist);
+}
+
+int RGWSI_SysObj::Obj::OmapOp::set(const map<std::string, bufferlist>& m)
+{
+ RGWSI_SysObj *svc = source.sysobj_svc;
+ rgw_raw_obj& obj = source.obj;
+
+ return svc->omap_set(obj, m, must_exist);
+}
+
+int RGWSI_SysObj::Obj::OmapOp::del(const std::string& key)
+{
+ RGWSI_SysObj *svc = source.sysobj_svc;
+ rgw_raw_obj& obj = source.obj;
+
+ return svc->omap_del(obj, key);
+}
};
template <class T, class S>
-class RGWSysObjectCtxImpl {
- RGWSI_SysObj *sysobj_svc;
- std::map<T, S> objs_state;
- RWLock lock;
-
-public:
- explicit RGWSysObjectCtxImpl(RGWSI_SysObj *_sysobj_svc) : sysobj_svc(_sysobj_svc), lock("RGWSysObjectCtxImpl") {}
-
- RGWSysObjectCtxImpl(const RGWSysObjectCtxImpl& rhs) : sysobj_svc(rhs.sysobj_svc),
- objs_state(rhs.objs_state),
- lock("RGWSysObjectCtxImpl") {}
- RGWSysObjectCtxImpl(const RGWSysObjectCtxImpl&& rhs) : sysobj_svc(rhs.sysobj_svc),
- objs_state(std::move(rhs.objs_state)),
- lock("RGWSysObjectCtxImpl") {}
-
- S *get_state(const T& obj) {
- S *result;
- typename std::map<T, S>::iterator iter;
- lock.get_read();
- assert (!obj.empty());
- iter = objs_state.find(obj);
- if (iter != objs_state.end()) {
- result = &iter->second;
- lock.unlock();
- } else {
- lock.unlock();
- lock.get_write();
- result = &objs_state[obj];
- lock.unlock();
- }
- return result;
- }
-
- void set_atomic(T& obj) {
- RWLock::WLocker wl(lock);
- assert (!obj.empty());
- objs_state[obj].is_atomic = true;
- }
- void set_prefetch_data(T& obj) {
- RWLock::WLocker wl(lock);
- assert (!obj.empty());
- objs_state[obj].prefetch_data = true;
- }
- void invalidate(T& obj) {
- RWLock::WLocker wl(lock);
- auto iter = objs_state.find(obj);
- if (iter == objs_state.end()) {
- return;
- }
- bool is_atomic = iter->second.is_atomic;
- bool prefetch_data = iter->second.prefetch_data;
-
- objs_state.erase(iter);
-
- if (is_atomic || prefetch_data) {
- auto& s = objs_state[obj];
- s.is_atomic = is_atomic;
- s.prefetch_data = prefetch_data;
- }
- }
-};
+class RGWSysObjectCtxImpl;
using RGWSysObjectCtx = RGWSysObjectCtxImpl<rgw_raw_obj, RGWSysObjState>;
{
public:
class Obj {
- friend class Read;
+ friend class ROp;
RGWSI_SysObj *sysobj_svc;
RGWSysObjectCtx& ctx;
return obj;
}
- struct Read {
+ struct ROp {
Obj& source;
struct GetObjState {
GetObjState() {}
- int get_rados_obj(RGWSI_SysObj *sysobj_svc, rgw_raw_obj& obj, RGWSI_RADOS::Obj **pobj);
+ int get_rados_obj(RGWSI_RADOS *rados_svc,
+ RGWSI_Zone *zone_svc,
+ rgw_raw_obj& obj,
+ RGWSI_RADOS::Obj **pobj);
} state;
- struct StatParams {
- RGWObjVersionTracker *objv_tracker{nullptr};
- ceph::real_time *lastmod{nullptr};
- uint64_t *obj_size{nullptr};
- map<string, bufferlist> *attrs{nullptr};
-
- StatParams& set_last_mod(ceph::real_time *_lastmod) {
- lastmod = _lastmod;
- return *this;
- }
- StatParams& set_obj_size(uint64_t *_obj_size) {
- obj_size = _obj_size;
- return *this;
- }
- StatParams& set_attrs(map<string, bufferlist> *_attrs) {
- attrs = _attrs;
- return *this;
- }
- } stat_params;
-
- struct ReadParams {
- RGWObjVersionTracker *objv_tracker{nullptr};
- map<string, bufferlist> *attrs{nullptr};
- boost::optional<obj_version> refresh_version{boost::none};
-
- ReadParams& set_attrs(map<string, bufferlist> *_attrs) {
- attrs = _attrs;
- return *this;
- }
- ReadParams& set_obj_tracker(RGWObjVersionTracker *_objv_tracker) {
- objv_tracker = _objv_tracker;
- return *this;
- }
- ReadParams& set_refresh_version(const obj_version& rf) {
- refresh_version = rf;
- return *this;
- }
- } read_params;
-
- Read(Obj& _source) : source(_source) {}
+ RGWObjVersionTracker *objv_tracker{nullptr};
+ map<string, bufferlist> *attrs{nullptr};
+ boost::optional<obj_version> refresh_version{boost::none};
+ ceph::real_time *lastmod{nullptr};
+ uint64_t *obj_size{nullptr};
+
+ ROp& set_last_mod(ceph::real_time *_lastmod) {
+ lastmod = _lastmod;
+ return *this;
+ }
+
+ ROp& set_obj_size(uint64_t *_obj_size) {
+ obj_size = _obj_size;
+ return *this;
+ }
+
+ ROp& set_attrs(map<string, bufferlist> *_attrs) {
+ attrs = _attrs;
+ return *this;
+ }
+
+ ROp& set_refresh_version(const obj_version& rf) {
+ refresh_version = rf;
+ return *this;
+ }
+
+ ROp(Obj& _source) : source(_source) {}
int stat();
int read(int64_t ofs, int64_t end, bufferlist *pbl);
int read(bufferlist *pbl) {
return read(0, -1, pbl);
}
- int get_attr(std::string_view name, bufferlist *dest);
+ int get_attr(const char *name, bufferlist *dest);
};
+
+ struct WOp {
+ Obj& source;
+
+ RGWObjVersionTracker *objv_tracker{nullptr};
+ map<string, bufferlist> attrs;
+ ceph::real_time mtime;
+ ceph::real_time *pmtime;
+ bool exclusive{false};
+
+ WOp& set_attrs(map<string, bufferlist>&& _attrs) {
+ attrs = _attrs;
+ return *this;
+ }
+
+ WOp& set_mtime(const ceph::real_time& _mtime) {
+ mtime = _mtime;
+ return *this;
+ }
+
+ WOp& set_pmtime(ceph::real_time *_pmtime) {
+ pmtime = _pmtime;
+ return *this;
+ }
+
+ WOp& set_exclusive(bool _exclusive = true) {
+ exclusive = _exclusive;
+ return *this;
+ }
+
+ WOp(Obj& _source) : source(_source) {}
+
+ int remove();
+ int write(bufferlist& bl);
+ };
+
+ struct OmapOp {
+ Obj& source;
+
+ bool must_exist{false};
+
+ OmapOp& set_must_exist(bool _must_exist = true) {
+ must_exist = _must_exist;
+ return *this;
+ }
+
+ OmapOp(Obj& _source) : source(_source) {}
+
+ int get_all(std::map<string, bufferlist> *m);
+ int get_vals(const string& marker,
+ uint64_t count,
+ std::map<string, bufferlist> *m,
+ bool *pmore);
+ int set(const std::string& key, bufferlist& bl);
+ int set(const map<std::string, bufferlist>& m);
+ int del(const std::string& key);
+ };
+ ROp rop() {
+ return ROp(*this);
+ }
+
+ WOp wop() {
+ return WOp(*this);
+ }
+
+ OmapOp omap() {
+ return OmapOp(*this);
+ }
+ };
+
+ class Pool {
+ friend class Op;
+
+ RGWSI_SysObj *sysobj_svc;
+ rgw_pool pool;
+
+ RGWSI_RADOS *get_rados_svc();
+
+ public:
+ Pool(RGWSI_SysObj *_sysobj_svc,
+ const rgw_pool& _pool) : sysobj_svc(_sysobj_svc),
+ pool(_pool) {}
+
+ rgw_pool& get_pool() {
+ return pool;
+ }
+
+ struct Op {
+ Pool& source;
+
+ Op(Pool& _source) : source(_source) {}
+
+ int list_prefixed_objs(const std::string& prefix, std::list<std::string> *result);
+ };
+
+ Op op() {
+ return Op(*this);
+ }
};
friend class Obj;
- friend class Obj::Read;
+ friend class Obj::ROp;
+ friend class Obj::WOp;
+ friend class Pool;
+ friend class Pool::Op;
private:
std::shared_ptr<RGWSI_RADOS> rados_svc;
RGWObjVersionTracker *objv_tracker);
int stat(RGWSysObjectCtx& obj_ctx,
- RGWSI_SysObj::Obj::Read::GetObjState& state,
+ RGWSI_SysObj::Obj::ROp::GetObjState& state,
rgw_raw_obj& obj,
map<string, bufferlist> *attrs,
real_time *lastmod,
RGWObjVersionTracker *objv_tracker);
int read(RGWSysObjectCtx& obj_ctx,
- Obj::Read::GetObjState& read_state,
+ Obj::ROp::GetObjState& read_state,
RGWObjVersionTracker *objv_tracker,
rgw_raw_obj& obj,
bufferlist *bl, off_t ofs, off_t end,
map<string, bufferlist> *attrs,
boost::optional<obj_version>);
- int get_attr(rgw_raw_obj& obj, std::string_view name, bufferlist *dest);
-
+ int get_attr(rgw_raw_obj& obj, const char *name, bufferlist *dest);
+
+ int omap_get_all(rgw_raw_obj& obj, std::map<string, bufferlist> *m);
+ int omap_get_vals(rgw_raw_obj& obj,
+ const string& marker,
+ uint64_t count,
+ std::map<string, bufferlist> *m,
+ bool *pmore);
+ int omap_set(rgw_raw_obj& obj, const std::string& key, bufferlist& bl, bool must_exist = false);
+ int omap_set(rgw_raw_obj& obj, const map<std::string, bufferlist>& m, bool must_exist = false);
+ int omap_del(rgw_raw_obj& obj, const std::string& key);
+
+ int remove(RGWSysObjectCtx& obj_ctx,
+ RGWObjVersionTracker *objv_tracker,
+ rgw_raw_obj& obj);
+
+ int write(rgw_raw_obj& obj,
+ real_time *pmtime,
+ map<std::string, bufferlist>& attrs,
+ bool exclusive,
+ const bufferlist& data,
+ RGWObjVersionTracker *objv_tracker,
+ real_time set_mtime);
public:
RGWSI_SysObj(RGWService *svc, CephContext *cct): RGWServiceInstance(svc, cct) {}
- RGWSysObjectCtx&& init_obj_ctx() {
- return std::move(RGWSysObjectCtx(this));
- }
+ RGWSysObjectCtx&& init_obj_ctx();
+ Obj&& get_obj(RGWSysObjectCtx& obj_ctx, const rgw_raw_obj& obj);
- Obj&& get_obj(RGWSysObjectCtx& obj_ctx, const rgw_raw_obj& obj) {
- return std::move(Obj(this, obj_ctx, obj));
+ Pool&& get_pool(const rgw_pool& pool) {
+ return std::move(Pool(this, pool));
}
};
using RGWSysObj = RGWSI_SysObj::Obj;
+template <class T, class S>
+class RGWSysObjectCtxImpl {
+ RGWSI_SysObj *sysobj_svc;
+ std::map<T, S> objs_state;
+ RWLock lock;
+
+public:
+ explicit RGWSysObjectCtxImpl(RGWSI_SysObj *_sysobj_svc) : sysobj_svc(_sysobj_svc), lock("RGWSysObjectCtxImpl") {}
+
+ RGWSysObjectCtxImpl(const RGWSysObjectCtxImpl& rhs) : sysobj_svc(rhs.sysobj_svc),
+ objs_state(rhs.objs_state),
+ lock("RGWSysObjectCtxImpl") {}
+ RGWSysObjectCtxImpl(const RGWSysObjectCtxImpl&& rhs) : sysobj_svc(rhs.sysobj_svc),
+ objs_state(std::move(rhs.objs_state)),
+ lock("RGWSysObjectCtxImpl") {}
+
+ S *get_state(const T& obj) {
+ S *result;
+ typename std::map<T, S>::iterator iter;
+ lock.get_read();
+ assert (!obj.empty());
+ iter = objs_state.find(obj);
+ if (iter != objs_state.end()) {
+ result = &iter->second;
+ lock.unlock();
+ } else {
+ lock.unlock();
+ lock.get_write();
+ result = &objs_state[obj];
+ lock.unlock();
+ }
+ return result;
+ }
+
+ void set_atomic(T& obj) {
+ RWLock::WLocker wl(lock);
+ assert (!obj.empty());
+ }
+ void set_prefetch_data(T& obj) {
+ RWLock::WLocker wl(lock);
+ assert (!obj.empty());
+ objs_state[obj].prefetch_data = true;
+ }
+ void invalidate(T& obj) {
+ RWLock::WLocker wl(lock);
+ auto iter = objs_state.find(obj);
+ if (iter == objs_state.end()) {
+ return;
+ }
+ objs_state.erase(iter);
+ }
+
+ RGWSI_SysObj::Obj&& get_obj(const rgw_raw_obj& obj) {
+ return sysobj_svc->get_obj(*this, obj);
+ }
+};
+
#endif
#include "rgw/rgw_rest_conn.h"
#include "common/errno.h"
+#include "include/random.h"
#define dout_subsys ceph_subsys_rgw
static string RGW_DEFAULT_ZONEGROUP_ROOT_POOL = "rgw.root";
static string RGW_DEFAULT_REALM_ROOT_POOL = "rgw.root";
static string RGW_DEFAULT_PERIOD_ROOT_POOL = "rgw.root";
+static string avail_pools = ".pools.avail";
+static string default_storage_pool_suffix = "rgw.buckets.data";
int RGWS_Zone::create_instance(const string& conf, RGWServiceInstanceRef *instance)
{
std::map<string, RGWServiceInstance::dependency> RGWSI_Zone::get_deps()
{
- RGWServiceInstance::dependency dep1 = { .name = "rados",
- .conf = "{}" };
- RGWServiceInstance::dependency dep2 = { .name = "sys_obj",
+ RGWServiceInstance::dependency dep1 = { .name = "sys_obj",
.conf = "{}" };
map<string, RGWServiceInstance::dependency> deps;
- deps["rados_dep"] = dep1;
- deps["sys_obj_dep"] = dep2;
+ deps["sys_obj_dep"] = dep1;
+
+ RGWServiceInstance::dependency dep2 = { .name = "rados_obj",
+ .conf = "{}" };
+ map<string, RGWServiceInstance::dependency> deps2;
+ deps["rados_dep"] = dep2;
return deps;
}
int RGWSI_Zone::load(const string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs)
{
- rados_svc = static_pointer_cast<RGWSI_RADOS>(dep_refs["rados_dep"]);
- assert(rados_svc);
-
sysobj_svc = static_pointer_cast<RGWSI_SysObj>(dep_refs["sys_obj_dep"]);
assert(sysobj_svc);
zone_params = make_shared<RGWZoneParams>();
current_period = make_shared<RGWPeriod>();
+ rados_svc = static_pointer_cast<RGWSI_RADOS>(dep_refs["rados_dep"]);
+ assert(rados_svc);
+
return 0;
}
writeable_zone = (zone_public_config->tier_type.empty() || zone_public_config->tier_type == "rgw");
+ /* first build all zones index */
+ for (auto ziter : zonegroup->zones) {
+ const string& id = ziter.first;
+ RGWZone& z = ziter.second;
+ zone_id_by_name[z.name] = id;
+ zone_by_id[id] = z;
+ }
+
+ if (zone_by_id.find(zone_id()) == zone_by_id.end()) {
+ ldout(cct, 0) << "WARNING: could not find zone config in zonegroup for local zone (" << zone_id() << "), will use defaults" << dendl;
+ }
+ *zone_public_config = zone_by_id[zone_id()];
+ for (auto ziter : get_zonegroup().zones) {
+ const string& id = ziter.first;
+ RGWZone& z = ziter.second;
+ if (id == zone_id()) {
+ continue;
+ }
+ if (z.endpoints.empty()) {
+ ldout(cct, 0) << "WARNING: can't generate connection for zone " << z.id << " id " << z.name << ": no endpoints defined" << dendl;
+ continue;
+ }
+ ldout(cct, 20) << "generating connection object for zone " << z.name << " id " << z.id << dendl;
+ RGWRESTConn *conn = new RGWRESTConn(cct, this, z.id, z.endpoints);
+ zone_conn_map[id] = conn;
+ if (zone_syncs_from(*zone_public_config, z) ||
+ zone_syncs_from(z, *zone_public_config)) {
+ if (zone_syncs_from(*zone_public_config, z)) {
+ zone_data_sync_from_map[id] = conn;
+ }
+ if (zone_syncs_from(z, *zone_public_config)) {
+ zone_data_notify_to_map[id] = conn;
+ }
+ } else {
+ ldout(cct, 20) << "NOTICE: not syncing to/from zone " << z.name << " id " << z.id << dendl;
+ }
+ }
+
return 0;
}
int RGWSI_Zone::list_regions(list<string>& regions)
{
RGWZoneGroup zonegroup;
+ RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(zonegroup.get_pool(cct));
- return list_raw_prefixed_objs(zonegroup.get_pool(cct), region_info_oid_prefix, regions);
+ return syspool.op().list_prefixed_objs(region_info_oid_prefix, ®ions);
}
int RGWSI_Zone::list_zonegroups(list<string>& zonegroups)
{
RGWZoneGroup zonegroup;
+ RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(zonegroup.get_pool(cct));
- return list_raw_prefixed_objs(zonegroup.get_pool(cct), zonegroup_names_oid_prefix, zonegroups);
+ return syspool.op().list_prefixed_objs(zonegroup_names_oid_prefix, &zonegroups);
}
int RGWSI_Zone::list_zones(list<string>& zones)
{
RGWZoneParams zoneparams;
+ RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(zoneparams.get_pool(cct));
- return list_raw_prefixed_objs(zoneparams.get_pool(cct), zone_names_oid_prefix, zones);
+ return syspool.op().list_prefixed_objs(zonegroup_names_oid_prefix, &zones);
}
int RGWSI_Zone::list_realms(list<string>& realms)
{
RGWRealm realm(cct, sysobj_svc.get());
- return list_raw_prefixed_objs(realm.get_pool(cct), realm_names_oid_prefix, realms);
+ RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(realm.get_pool(cct));
+
+ return syspool.op().list_prefixed_objs(zonegroup_names_oid_prefix, &realms);
}
int RGWSI_Zone::list_periods(list<string>& periods)
{
RGWPeriod period;
list<string> raw_periods;
- int ret = list_raw_prefixed_objs(period.get_pool(cct), period.get_info_oid_prefix(), raw_periods);
+ RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(period.get_pool(cct));
+ int ret = syspool.op().list_prefixed_objs(period.get_info_oid_prefix(), &raw_periods);
if (ret < 0) {
return ret;
}
RGWSysObjectCtx obj_ctx = sysobj_svc->init_obj_ctx();
RGWSysObj sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
- RGWSysObj::Read rop(sysobj);
- int ret = rop.read(&bl);
+ int ret = sysobj.rop().read(&bl);
if (ret < 0 && ret != -ENOENT) {
ldout(cct, 0) << __func__ << " failed to read converted: ret "<< ret << " " << cpp_strerror(-ret)
<< dendl;
ldout(cct, 0) << __func__ << " Error setting realm as default: " << cpp_strerror(-ret) << dendl;
return ret;
}
- ret = realm.init(cct, this);
+ ret = realm->init(cct, sysobj_svc.get());
if (ret < 0) {
ldout(cct, 0) << __func__ << " Error initing realm: " << cpp_strerror(-ret) << dendl;
return ret;
}
- ret = current_period->init(cct, this, realm->get_id(), realm->get_name());
+ ret = current_period->init(cct, sysobj_svc.get(), realm->get_id(), realm->get_name());
if (ret < 0) {
ldout(cct, 0) << __func__ << " Error initing current period: " << cpp_strerror(-ret) << dendl;
return ret;
}
RGWZoneGroup zonegroup(*iter);
zonegroup.set_id(*iter);
- int ret = zonegroup.init(cct, this, true, true);
+ int ret = zonegroup.init(cct, sysobj_svc.get(), true, true);
if (ret < 0) {
ldout(cct, 0) << __func__ << " failed init zonegroup: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
return ret;
for (auto const& iter : regions) {
RGWZoneGroup zonegroup(iter);
- int ret = zonegroup.init(cct, this, true, true);
+ int ret = zonegroup.init(cct, sysobj_svc.get(), true, true);
if (ret < 0) {
ldout(cct, 0) << __func__ << " failed init zonegroup" << iter << ": ret "<< ret << " " << cpp_strerror(-ret) << dendl;
return ret;
}
/* mark as converted */
- ret = rgw_put_system_obj(this, pool, oid, bl,
- true, NULL, real_time(), NULL);
+ ret = sysobj.wop()
+ .set_exclusive(true)
+ .write(bl);
if (ret < 0 ) {
ldout(cct, 0) << __func__ << " failed to mark cluster as converted: ret "<< ret << " " << cpp_strerror(-ret)
<< dendl;
RGWSysObjectCtx obj_ctx = sysobj_svc->init_obj_ctx();
RGWSysObj sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
- RGWSysObj::Read rop(sysobj);
- int ret = rop.read(&bl);
+ int ret = sysobj.rop().read(&bl);
if (ret < 0 && ret != -ENOENT) {
return ret;
} else if (ret == -ENOENT) {
current_period->set_bucket_quota(zonegroupmap.bucket_quota);
// remove the region_map so we don't try to convert again
- rgw_raw_obj obj(pool, oid);
- ret = delete_system_obj(obj);
+ ret = sysobj.wop().remove();
if (ret < 0) {
- ldout(cct, 0) << "Error could not remove " << obj
+ ldout(cct, 0) << "Error could not remove " << sysobj.get_obj()
<< " after upgrading to zonegroup map: " << cpp_strerror(ret) << dendl;
return ret;
}
(zonegroup->zones.size() == 1 && current_period->is_single_zonegroup());
}
+/**
+ * Check to see if the bucket metadata could be synced
+ * bucket: the bucket to check
+ * Returns false is the bucket is not synced
+ */
+bool RGWSI_Zone::is_syncing_bucket_meta(const rgw_bucket& bucket)
+{
+
+ /* no current period */
+ if (current_period->get_id().empty()) {
+ return false;
+ }
+
+ /* zonegroup is not master zonegroup */
+ if (!zonegroup->is_master_zonegroup()) {
+ return false;
+ }
+
+ /* single zonegroup and a single zone */
+ if (current_period->is_single_zonegroup() && zonegroup->zones.size() == 1) {
+ return false;
+ }
+
+ /* zone is not master */
+ if (zonegroup->master_zone.compare(zone_public_config->id) != 0) {
+ return false;
+ }
+
+ return true;
+}
+
void RGWSI_Zone::canonicalize_raw_obj(rgw_raw_obj *obj)
{
obj->pool = zone_params->domain_root;
}
}
+
+int RGWSI_Zone::select_new_bucket_location(RGWUserInfo& user_info, const string& zonegroup_id, const string& request_rule,
+ string *pselected_rule_name, RGWZonePlacementInfo *rule_info)
+
+{
+ /* first check that zonegroup exists within current period. */
+ RGWZoneGroup zonegroup;
+ int ret = get_zonegroup(zonegroup_id, zonegroup);
+ if (ret < 0) {
+ ldout(cct, 0) << "could not find zonegroup " << zonegroup_id << " in current period" << dendl;
+ return ret;
+ }
+
+ /* find placement rule. Hierarchy: request rule > user default rule > zonegroup default rule */
+ std::map<std::string, RGWZoneGroupPlacementTarget>::const_iterator titer;
+
+ if (!request_rule.empty()) {
+ titer = zonegroup.placement_targets.find(request_rule);
+ if (titer == zonegroup.placement_targets.end()) {
+ ldout(cct, 0) << "could not find requested placement id " << request_rule
+ << " within zonegroup " << dendl;
+ return -ERR_INVALID_LOCATION_CONSTRAINT;
+ }
+ } else if (!user_info.default_placement.empty()) {
+ titer = zonegroup.placement_targets.find(user_info.default_placement);
+ if (titer == zonegroup.placement_targets.end()) {
+ ldout(cct, 0) << "could not find user default placement id " << user_info.default_placement
+ << " within zonegroup " << dendl;
+ return -ERR_INVALID_LOCATION_CONSTRAINT;
+ }
+ } else {
+ if (zonegroup.default_placement.empty()) { // zonegroup default rule as fallback, it should not be empty.
+ ldout(cct, 0) << "misconfiguration, zonegroup default placement id should not be empty." << dendl;
+ return -ERR_ZONEGROUP_DEFAULT_PLACEMENT_MISCONFIGURATION;
+ } else {
+ titer = zonegroup.placement_targets.find(zonegroup.default_placement);
+ if (titer == zonegroup.placement_targets.end()) {
+ ldout(cct, 0) << "could not find zonegroup default placement id " << zonegroup.default_placement
+ << " within zonegroup " << dendl;
+ return -ERR_INVALID_LOCATION_CONSTRAINT;
+ }
+ }
+ }
+
+ /* now check tag for the rule, whether user is permitted to use rule */
+ const auto& target_rule = titer->second;
+ if (!target_rule.user_permitted(user_info.placement_tags)) {
+ ldout(cct, 0) << "user not permitted to use placement rule " << titer->first << dendl;
+ return -EPERM;
+ }
+
+ if (pselected_rule_name)
+ *pselected_rule_name = titer->first;
+
+ return select_bucket_location_by_rule(titer->first, rule_info);
+}
+
+int RGWSI_Zone::select_bucket_location_by_rule(const string& location_rule, RGWZonePlacementInfo *rule_info)
+{
+ if (location_rule.empty()) {
+ /* we can only reach here if we're trying to set a bucket location from a bucket
+ * created on a different zone, using a legacy / default pool configuration
+ */
+ if (rule_info) {
+ return select_legacy_bucket_placement(rule_info);
+ }
+
+ return 0;
+ }
+
+ /*
+ * make sure that zone has this rule configured. We're
+ * checking it for the local zone, because that's where this bucket object is going to
+ * reside.
+ */
+ map<string, RGWZonePlacementInfo>::iterator piter = get_zone_params().placement_pools.find(location_rule);
+ if (piter == get_zone_params().placement_pools.end()) {
+ /* couldn't find, means we cannot really place data for this bucket in this zone */
+ if (get_zonegroup().equals(zonegroup->get_id())) {
+ /* that's a configuration error, zone should have that rule, as we're within the requested
+ * zonegroup */
+ ldout(cct, 0) << "ERROR: This zone does not contain placement rule"
+ << location_rule << " present in the zonegroup!" << dendl;
+ return -EINVAL;
+ } else {
+ /* oh, well, data is not going to be placed here, bucket object is just a placeholder */
+ return 0;
+ }
+ }
+
+ RGWZonePlacementInfo& placement_info = piter->second;
+
+ if (rule_info) {
+ *rule_info = placement_info;
+ }
+
+ return 0;
+}
+
+int RGWSI_Zone::select_bucket_placement(RGWUserInfo& user_info, const string& zonegroup_id, const string& placement_rule,
+ string *pselected_rule_name, RGWZonePlacementInfo *rule_info)
+{
+ if (!get_zone_params().placement_pools.empty()) {
+ return select_new_bucket_location(user_info, zonegroup_id, placement_rule,
+ pselected_rule_name, rule_info);
+ }
+
+ if (pselected_rule_name) {
+ pselected_rule_name->clear();
+ }
+
+ if (rule_info) {
+ return select_legacy_bucket_placement(rule_info);
+ }
+
+ return 0;
+}
+
+int RGWSI_Zone::select_legacy_bucket_placement(RGWZonePlacementInfo *rule_info)
+{
+ bufferlist map_bl;
+ map<string, bufferlist> m;
+ string pool_name;
+ bool write_map = false;
+
+ rgw_raw_obj obj(get_zone_params().domain_root, avail_pools);
+
+ auto obj_ctx = sysobj_svc->init_obj_ctx();
+ auto sysobj = obj_ctx.get_obj(obj);
+
+ int ret = sysobj.rop().read(&map_bl);
+ if (ret < 0) {
+ goto read_omap;
+ }
+
+ try {
+ auto iter = map_bl.cbegin();
+ decode(m, iter);
+ } catch (buffer::error& err) {
+ ldout(cct, 0) << "ERROR: couldn't decode avail_pools" << dendl;
+ }
+
+read_omap:
+ if (m.empty()) {
+ ret = sysobj.omap().get_all(&m);
+
+ write_map = true;
+ }
+
+ if (ret < 0 || m.empty()) {
+ vector<rgw_pool> pools;
+ string s = string("default.") + default_storage_pool_suffix;
+ pools.push_back(rgw_pool(s));
+ vector<int> retcodes;
+ bufferlist bl;
+ ret = rados_svc->pool().create(pools, &retcodes);
+ if (ret < 0)
+ return ret;
+ ret = sysobj.omap().set(s, bl);
+ if (ret < 0)
+ return ret;
+ m[s] = bl;
+ }
+
+ if (write_map) {
+ bufferlist new_bl;
+ encode(m, new_bl);
+ ret = sysobj.wop().write(new_bl);
+ if (ret < 0) {
+ ldout(cct, 0) << "WARNING: could not save avail pools map info ret=" << ret << dendl;
+ }
+ }
+
+ auto miter = m.begin();
+ if (m.size() > 1) {
+ // choose a pool at random
+ auto r = ceph::util::generate_random_number<size_t>(0, m.size() - 1);
+ std::advance(miter, r);
+ }
+ pool_name = miter->first;
+
+ rule_info->data_pool = pool_name;
+ rule_info->data_extra_pool = pool_name;
+ rule_info->index_pool = pool_name;
+ rule_info->index_type = RGWBIType_Normal;
+
+ return 0;
+}
+
+int RGWSI_Zone::update_placement_map()
+{
+ bufferlist header;
+ map<string, bufferlist> m;
+ rgw_raw_obj obj(zone_params->domain_root, avail_pools);
+
+ auto obj_ctx = sysobj_svc->init_obj_ctx();
+ auto sysobj = obj_ctx.get_obj(obj);
+
+ int ret = sysobj.omap().get_all(&m);
+ if (ret < 0)
+ return ret;
+
+ bufferlist new_bl;
+ encode(m, new_bl);
+ ret = sysobj.wop().write(new_bl);
+ if (ret < 0) {
+ ldout(cct, 0) << "WARNING: could not save avail pools map info ret=" << ret << dendl;
+ }
+
+ return ret;
+}
+
+int RGWSI_Zone::add_bucket_placement(const rgw_pool& new_pool)
+{
+ int ret = rados_svc->pool().lookup(new_pool);
+ if (ret < 0) { // DNE, or something
+ return ret;
+ }
+
+ rgw_raw_obj obj(zone_params->domain_root, avail_pools);
+ auto obj_ctx = sysobj_svc->init_obj_ctx();
+ auto sysobj = obj_ctx.get_obj(obj);
+
+ bufferlist empty_bl;
+ ret = sysobj.omap().set(new_pool.to_str(), empty_bl);
+
+ // don't care about return value
+ update_placement_map();
+
+ return ret;
+}
+
+int RGWSI_Zone::remove_bucket_placement(const rgw_pool& old_pool)
+{
+ rgw_raw_obj obj(zone_params->domain_root, avail_pools);
+ auto obj_ctx = sysobj_svc->init_obj_ctx();
+ auto sysobj = obj_ctx.get_obj(obj);
+
+ int ret = sysobj.omap().del(old_pool.to_str());
+
+ // don't care about return value
+ update_placement_map();
+
+ return ret;
+}
+
+int RGWSI_Zone::list_placement_set(set<rgw_pool>& names)
+{
+ bufferlist header;
+ map<string, bufferlist> m;
+
+ rgw_raw_obj obj(zone_params->domain_root, avail_pools);
+ auto obj_ctx = sysobj_svc->init_obj_ctx();
+ auto sysobj = obj_ctx.get_obj(obj);
+ int ret = sysobj.omap().get_all(&m);
+ if (ret < 0)
+ return ret;
+
+ names.clear();
+ map<string, bufferlist>::iterator miter;
+ for (miter = m.begin(); miter != m.end(); ++miter) {
+ names.insert(rgw_pool(miter->first));
+ }
+
+ return names.size();
+}
+
class RGWSI_Zone : public RGWServiceInstance
{
- std::shared_ptr<RGWSI_RADOS> rados_svc;
std::shared_ptr<RGWSI_SysObj> sysobj_svc;
+ std::shared_ptr<RGWSI_RADOS> rados_svc;
std::shared_ptr<RGWRealm> realm;
std::shared_ptr<RGWZoneGroup> zonegroup;
int init_zg_from_local(bool *creating_defaults);
int convert_regionmap();
+ int update_placement_map();
+ int add_bucket_placement(const rgw_pool& new_pool);
+ int remove_bucket_placement(const rgw_pool& old_pool);
+ int list_placement_set(set<rgw_pool>& names);
public:
RGWSI_Zone(RGWService *svc, CephContext *cct): RGWServiceInstance(svc, cct) {}
return rest_master_conn;
}
+ map<string, RGWRESTConn *>& get_zonegroup_conn_map() {
+ return zonegroup_conn_map;
+ }
+
map<string, RGWRESTConn *>& get_zone_conn_map() {
return zone_conn_map;
}
+ map<string, RGWRESTConn *>& get_zone_data_sync_from_map() {
+ return zone_data_sync_from_map;
+ }
+
map<string, RGWRESTConn *>& get_zone_data_notify_to_map() {
return zone_data_notify_to_map;
}
bool need_to_log_data() const;
bool need_to_log_metadata() const;
bool can_reshard() const;
+ bool is_syncing_bucket_meta(const rgw_bucket& bucket);
int list_zonegroups(list<string>& zonegroups);
int list_regions(list<string>& regions);
int list_realms(list<string>& realms);
int list_periods(list<string>& periods);
int list_periods(const string& current_period, list<string>& periods);
+
+ void canonicalize_raw_obj(rgw_raw_obj *obj);
};
#endif