<< s->user->user_id << dendl;
break;
}
- map<string, RGWBucketEnt>& m = buckets.get_buckets();
- map<string, RGWBucketEnt>::iterator iter;
- for (iter = m.begin(); iter != m.end(); ++iter) {
- RGWBucketEnt& bucket = iter->second;
- buckets_size += bucket.size;
- buckets_size_rounded += bucket.size_rounded;
- buckets_objcount += bucket.count;
- }
- buckets_count += m.size();
+
+ /* We need to have stats for all our policies - even if a given policy
+ * isn't actually used in a given account. In such situation its usage
+ * stats would be simply full of zeros. */
+ for (const auto& policy : store->get_zonegroup().placement_targets) {
+ policies_stats.emplace(policy.second.name,
+ decltype(policies_stats)::mapped_type());
+ }
+
+ std::map<std::string, RGWBucketEnt>& m = buckets.get_buckets();
+ for (const auto& kv : m) {
+ const auto& bucket = kv.second;
+
+ global_stats.bytes_used += bucket.size;
+ global_stats.bytes_used_rounded += bucket.size_rounded;
+ global_stats.objects_count += bucket.count;
+
+ /* operator[] still can create a new entry for storage policy seen
+ * for first time. */
+ auto& policy_stats = policies_stats[bucket.placement_rule];
+ policy_stats.bytes_used += bucket.size;
+ policy_stats.bytes_used_rounded += bucket.size_rounded;
+ policy_stats.buckets_count++;
+ policy_stats.objects_count += bucket.count;
+ }
+ global_stats.buckets_count += m.size();
total_count += m.size();
done = (m.size() < read_count || (limit >= 0 && total_count >= (uint64_t)limit));
<< s->user->user_id << dendl;
break;
} else {
- map<string, RGWBucketEnt>& m = buckets.get_buckets();
- map<string, RGWBucketEnt>::iterator iter;
- for (iter = m.begin(); iter != m.end(); ++iter) {
- RGWBucketEnt& bucket = iter->second;
- buckets_size += bucket.size;
- buckets_size_rounded += bucket.size_rounded;
- buckets_objcount += bucket.count;
-
- marker = iter->first;
+ /* We need to have stats for all our policies - even if a given policy
+ * isn't actually used in a given account. In such situation its usage
+ * stats would be simply full of zeros. */
+ for (const auto& policy : store->get_zonegroup().placement_targets) {
+ policies_stats.emplace(policy.second.name,
+ decltype(policies_stats)::mapped_type());
+ }
+
+ std::map<std::string, RGWBucketEnt>& m = buckets.get_buckets();
+ for (const auto& kv : m) {
+ const auto& bucket = kv.second;
+
+ global_stats.bytes_used += bucket.size;
+ global_stats.bytes_used_rounded += bucket.size_rounded;
+ global_stats.objects_count += bucket.count;
+
+ /* operator[] still can create a new entry for storage policy seen
+ * for first time. */
+ auto& policy_stats = policies_stats[bucket.placement_rule];
+ policy_stats.bytes_used += bucket.size;
+ policy_stats.bytes_used_rounded += bucket.size_rounded;
+ policy_stats.buckets_count++;
+ policy_stats.objects_count += bucket.count;
}
- buckets_count += m.size();
+ global_stats.buckets_count += m.size();
}
} while (is_truncated);
}; /* RGWBulkUploadOp::AlignedStreamGetter */
+struct RGWUsageStats {
+ uint64_t bytes_used = 0;
+ uint64_t bytes_used_rounded = 0;
+ uint64_t buckets_count = 0;
+ uint64_t objects_count = 0;
+};
+
#define RGW_LIST_BUCKETS_LIMIT_MAX 10000
class RGWListBuckets : public RGWOp {
protected:
bool sent_data;
- string marker;
- string end_marker;
+ std::string marker;
+ std::string end_marker;
int64_t limit;
uint64_t limit_max;
- uint32_t buckets_count;
- uint64_t buckets_objcount;
- uint64_t buckets_size;
- uint64_t buckets_size_rounded;
- map<string, bufferlist> attrs;
+ std::map<std::string, ceph::bufferlist> attrs;
bool is_truncated;
+ RGWUsageStats global_stats;
+ std::map<std::string, RGWUsageStats> policies_stats;
+
virtual uint64_t get_default_max() const {
return 1000;
}
public:
- RGWListBuckets() : sent_data(false) {
- limit = limit_max = RGW_LIST_BUCKETS_LIMIT_MAX;
- buckets_count = 0;
- buckets_objcount = 0;
- buckets_size = 0;
- buckets_size_rounded = 0;
- is_truncated = false;
+ RGWListBuckets()
+ : sent_data(false),
+ limit(RGW_LIST_BUCKETS_LIMIT_MAX),
+ limit_max(RGW_LIST_BUCKETS_LIMIT_MAX),
+ is_truncated(false) {
}
int verify_permission() override;
class RGWStatAccount : public RGWOp {
protected:
- uint32_t buckets_count;
- uint64_t buckets_objcount;
- uint64_t buckets_size;
- uint64_t buckets_size_rounded;
+ RGWUsageStats global_stats;
+ std::map<std::string, RGWUsageStats> policies_stats;
public:
- RGWStatAccount() {
- buckets_count = 0;
- buckets_objcount = 0;
- buckets_size = 0;
- buckets_size_rounded = 0;
- }
+ RGWStatAccount() = default;
int verify_permission() override;
void execute() override;
void send_response() override = 0;
- const string name() override { return "stat_account"; }
+ const std::string name() override { return "stat_account"; }
RGWOpType get_type() override { return RGW_OP_STAT_ACCOUNT; }
uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
};
extern void dump_header(struct req_state* s,
const boost::string_ref& name,
const utime_t& val);
+
template <class... Args>
static inline void dump_header_prefixed(struct req_state* s,
const boost::string_ref& name_prefix,
return dump_header(s, std::move(full_name), std::forward<Args>(args)...);
}
+template <class... Args>
+static inline void dump_header_infixed(struct req_state* s,
+ const boost::string_ref& prefix,
+ const boost::string_ref& infix,
+ const boost::string_ref& sufix,
+ Args&&... args) {
+ char full_name_buf[prefix.size() + infix.size() + sufix.size() + 1];
+ const auto len = snprintf(full_name_buf, sizeof(full_name_buf), "%.*s%.*s%.*s",
+ static_cast<int>(prefix.length()),
+ prefix.data(),
+ static_cast<int>(infix.length()),
+ infix.data(),
+ static_cast<int>(sufix.length()),
+ sufix.data());
+ boost::string_ref full_name(full_name_buf, len);
+ return dump_header(s, std::move(full_name), std::forward<Args>(args)...);
+}
+
template <class... Args>
static inline void dump_header_quoted(struct req_state* s,
const boost::string_ref& name,
}
static void dump_account_metadata(struct req_state * const s,
- const uint32_t buckets_count,
- const uint64_t buckets_object_count,
- const uint64_t buckets_size,
- const uint64_t buckets_size_rounded,
+ const RGWUsageStats& global_stats,
+ const std::map<std::string, RGWUsageStats> policies_stats,
/* const */map<string, bufferlist>& attrs,
const RGWQuotaInfo& quota,
const RGWAccessControlPolicy_SWIFTAcct &policy)
/* Adding X-Timestamp to keep align with Swift API */
dump_header(s, "X-Timestamp", ceph_clock_now());
- dump_header(s, "X-Account-Container-Count", buckets_count);
- dump_header(s, "X-Account-Object-Count", buckets_object_count);
- dump_header(s, "X-Account-Bytes-Used", buckets_size);
- dump_header(s, "X-Account-Bytes-Used-Actual", buckets_size_rounded);
+ dump_header(s, "X-Account-Container-Count", global_stats.buckets_count);
+ dump_header(s, "X-Account-Object-Count", global_stats.objects_count);
+ dump_header(s, "X-Account-Bytes-Used", global_stats.bytes_used);
+ dump_header(s, "X-Account-Bytes-Used-Actual", global_stats.bytes_used_rounded);
+
+ for (const auto& kv : policies_stats) {
+ const auto& policy_name = camelcase_dash_http_attr(kv.first);
+ const auto& policy_stats = kv.second;
+
+ dump_header_infixed(s, "X-Account-Storage-Policy-", policy_name,
+ "-Container-Count", policy_stats.buckets_count);
+ dump_header_infixed(s, "X-Account-Storage-Policy-", policy_name,
+ "-Object-Count", policy_stats.objects_count);
+ dump_header_infixed(s, "X-Account-Storage-Policy-", policy_name,
+ "-Bytes-Used", policy_stats.bytes_used);
+ dump_header_infixed(s, "X-Account-Storage-Policy-", policy_name,
+ "-Bytes-Used-Actual", policy_stats.bytes_used_rounded);
+ }
/* Dump TempURL-related stuff */
if (s->perm_mask == RGW_PERM_FULL_CONTROL) {
if (! s->cct->_conf->rgw_swift_enforce_content_length) {
/* Adding account stats in the header to keep align with Swift API */
dump_account_metadata(s,
- buckets_count,
- buckets_objcount,
- buckets_size,
- buckets_size_rounded,
+ global_stats,
+ policies_stats,
attrs,
user_quota,
static_cast<RGWAccessControlPolicy_SWIFTAcct&>(*s->user_acl));
if (s->cct->_conf->rgw_swift_enforce_content_length) {
/* Adding account stats in the header to keep align with Swift API */
dump_account_metadata(s,
- buckets_count,
- buckets_objcount,
- buckets_size,
- buckets_size_rounded,
+ global_stats,
+ policies_stats,
attrs,
user_quota,
static_cast<RGWAccessControlPolicy_SWIFTAcct&>(*s->user_acl));
if (op_ret >= 0) {
op_ret = STATUS_NO_CONTENT;
dump_account_metadata(s,
- buckets_count,
- buckets_objcount,
- buckets_size,
- buckets_size_rounded,
+ global_stats,
+ policies_stats,
attrs,
user_quota,
static_cast<RGWAccessControlPolicy_SWIFTAcct&>(*s->user_acl));