]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: RGWStorageStats does store sizes with byte precision.
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Fri, 29 Apr 2016 22:39:59 +0000 (00:39 +0200)
committerRadoslaw Zarzynski <rzarzynski@mirantis.com>
Mon, 30 May 2016 09:33:51 +0000 (11:33 +0200)
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
src/rgw/rgw_admin.cc
src/rgw/rgw_bucket.cc
src/rgw/rgw_common.h
src/rgw/rgw_json_enc.cc
src/rgw/rgw_quota.cc
src/rgw/rgw_rados.cc

index 48d40fb45b9b362b52c3193309cfc4948978f2fc..bdc4e313c4b3a39e57f5e5542afec55f0a4c6c8f 100644 (file)
@@ -811,8 +811,10 @@ static void dump_bucket_usage(map<RGWObjCategory, RGWStorageStats>& stats, Forma
     RGWStorageStats& s = iter->second;
     const char *cat_name = rgw_obj_category_name(iter->first);
     formatter->open_object_section(cat_name);
-    formatter->dump_int("size_kb", s.num_kb);
-    formatter->dump_int("size_kb_actual", s.num_kb_rounded);
+    formatter->dump_int("size", s.size);
+    formatter->dump_int("size_actual", s.size_rounded);
+    formatter->dump_int("size_kb", rgw_rounded_kb(s.size));
+    formatter->dump_int("size_kb_actual", rgw_rounded_kb(s.size_rounded));
     formatter->dump_int("num_objects", s.num_objects);
     formatter->close_section();
     formatter->flush(cout);
index 685968cd66c17ef071ab43fcecd88f1c9ea429e5..b4462bf71c2244ab179bedad11f808d2d90a5bb0 100644 (file)
@@ -736,8 +736,10 @@ static void dump_bucket_usage(map<RGWObjCategory, RGWStorageStats>& stats, Forma
     RGWStorageStats& s = iter->second;
     const char *cat_name = rgw_obj_category_name(iter->first);
     formatter->open_object_section(cat_name);
-    formatter->dump_int("size_kb", s.num_kb);
-    formatter->dump_int("size_kb_actual", s.num_kb_rounded);
+    formatter->dump_int("size", s.size);
+    formatter->dump_int("size_actual", s.size_rounded);
+    formatter->dump_int("size_kb", rgw_rounded_kb(s.size));
+    formatter->dump_int("size_kb_actual", rgw_rounded_kb(s.size_rounded));
     formatter->dump_int("num_objects", s.num_objects);
     formatter->close_section();
   }
index 3520b722815cb13110937712af62d0bd255a7774..d70c1a029803536fac7483927cb9b9850fdf8d9c 100644 (file)
@@ -1061,11 +1061,15 @@ WRITE_CLASS_ENCODER(RGWBucketEntryPoint)
 struct RGWStorageStats
 {
   RGWObjCategory category;
-  uint64_t num_kb;
-  uint64_t num_kb_rounded;
+  uint64_t size;
+  uint64_t size_rounded;
   uint64_t num_objects;
 
-  RGWStorageStats() : category(RGW_OBJ_CATEGORY_NONE), num_kb(0), num_kb_rounded(0), num_objects(0) {}
+  RGWStorageStats()
+    : category(RGW_OBJ_CATEGORY_NONE),
+      size(0),
+      size_rounded(0),
+      num_objects(0) {}
 
   void dump(Formatter *f) const;
 };
@@ -1822,6 +1826,11 @@ static inline uint64_t rgw_rounded_kb(uint64_t bytes)
   return (bytes + 1023) / 1024;
 }
 
+static inline uint64_t rgw_rounded_objsize(uint64_t bytes)
+{
+  return ((bytes + 4095) & ~4095);
+}
+
 static inline uint64_t rgw_rounded_objsize_kb(uint64_t bytes)
 {
   return ((bytes + 4095) & ~4095) / 1024;
index f5d18dcd225cab2c61b8e77dbd61342797a66b2e..333cf1bb447180de6ee428756d15c6a97530fdac 100644 (file)
@@ -545,8 +545,10 @@ void RGWBucketEntryPoint::decode_json(JSONObj *obj) {
 
 void RGWStorageStats::dump(Formatter *f) const
 {
-  encode_json("num_kb", num_kb, f);
-  encode_json("num_kb_rounded", num_kb_rounded, f);
+  encode_json("size", size, f);
+  encode_json("size_rounded", size_rounded, f);
+  encode_json("num_kb", rgw_rounded_kb(size), f);
+  encode_json("num_kb_rounded", rgw_rounded_kb(size_rounded), f);
   encode_json("num_objects", num_objects, f);
 }
 
index 0ea17d5e7e889fa6e8177ad329a3ad709e190a46..6bda6ebe486b3324e253ae89bb54fc70e35a4dec 100644 (file)
@@ -106,9 +106,10 @@ bool RGWQuotaCache<T>::can_use_cached_stats(RGWQuotaInfo& quota, RGWStorageStats
       quota.max_size_soft_threshold = quota.max_size_kb * store->ctx()->_conf->rgw_bucket_quota_soft_threshold;
     }
 
-    if (cached_stats.num_kb_rounded >= (uint64_t)quota.max_size_soft_threshold) {
+    const auto cached_stats_num_kb_rounded = rgw_rounded_kb(cached_stats.size_rounded);
+    if (cached_stats_num_kb_rounded >= (uint64_t)quota.max_size_soft_threshold) {
       ldout(store->ctx(), 20) << "quota: can't use cached stats, exceeded soft threshold (size): "
-        << cached_stats.num_kb_rounded << " >= " << quota.max_size_soft_threshold << dendl;
+        << cached_stats_num_kb_rounded << " >= " << quota.max_size_soft_threshold << dendl;
       return false;
     }
   }
@@ -211,18 +212,24 @@ int RGWQuotaCache<T>::get_stats(const rgw_user& user, rgw_bucket& bucket, RGWSto
 
 template<class T>
 class RGWQuotaStatsUpdate : public lru_map<T, RGWQuotaCacheStats>::UpdateContext {
-  int objs_delta;
-  uint64_t added_bytes;
-  uint64_t removed_bytes;
+  const int objs_delta;
+  const uint64_t added_bytes;
+  const uint64_t removed_bytes;
 public:
-  RGWQuotaStatsUpdate(int _objs_delta, uint64_t _added_bytes, uint64_t _removed_bytes) : 
-                    objs_delta(_objs_delta), added_bytes(_added_bytes), removed_bytes(_removed_bytes) {}
-  bool update(RGWQuotaCacheStats *entry) {
-    uint64_t rounded_kb_added = rgw_rounded_objsize_kb(added_bytes);
-    uint64_t rounded_kb_removed = rgw_rounded_objsize_kb(removed_bytes);
-
-    entry->stats.num_kb_rounded += (rounded_kb_added - rounded_kb_removed);
-    entry->stats.num_kb += (added_bytes - removed_bytes) / 1024;
+  RGWQuotaStatsUpdate(const int objs_delta,
+                      const uint64_t added_bytes,
+                      const uint64_t removed_bytes)
+    : objs_delta(objs_delta),
+      added_bytes(added_bytes),
+      removed_bytes(removed_bytes) {
+  }
+
+  bool update(RGWQuotaCacheStats * const entry) override {
+    const uint64_t rounded_added = rgw_rounded_objsize(added_bytes);
+    const uint64_t rounded_removed = rgw_rounded_objsize(removed_bytes);
+
+    entry->stats.size += added_bytes - removed_bytes;
+    entry->stats.size_rounded += rounded_added - rounded_removed;
     entry->stats.num_objects += objs_delta;
 
     return true;
@@ -269,7 +276,7 @@ int BucketAsyncRefreshHandler::init_fetch()
   return 0;
 }
 
-void BucketAsyncRefreshHandler::handle_response(int r)
+void BucketAsyncRefreshHandler::handle_response(const int r)
 {
   if (r < 0) {
     ldout(store->ctx(), 20) << "AsyncRefreshHandler::handle_response() r=" << r << dendl;
@@ -278,11 +285,11 @@ void BucketAsyncRefreshHandler::handle_response(int r)
 
   RGWStorageStats bs;
 
-  map<RGWObjCategory, RGWStorageStats>::iterator iter;
-  for (iter = stats->begin(); iter != stats->end(); ++iter) {
-    RGWStorageStats& s = iter->second;
-    bs.num_kb += s.num_kb;
-    bs.num_kb_rounded += s.num_kb_rounded;
+  for (const auto& pair : *stats) {
+    const RGWStorageStats& s = pair.second;
+
+    bs.size += s.size;
+    bs.size_rounded += s.size_rounded;
     bs.num_objects += s.num_objects;
   }
 
@@ -322,19 +329,21 @@ int RGWBucketStatsCache::fetch_stats_from_storage(const rgw_user& user, rgw_buck
   string master_ver;
 
   map<RGWObjCategory, RGWStorageStats> bucket_stats;
-  int r = store->get_bucket_stats(bucket, RGW_NO_SHARD, &bucket_ver, &master_ver, bucket_stats, NULL);
+  int r = store->get_bucket_stats(bucket, RGW_NO_SHARD, &bucket_ver,
+                                  &master_ver, bucket_stats, nullptr);
   if (r < 0) {
-    ldout(store->ctx(), 0) << "could not get bucket info for bucket=" << bucket.name << dendl;
+    ldout(store->ctx(), 0) << "could not get bucket info for bucket="
+                           << bucket.name << dendl;
     return r;
   }
 
   stats = RGWStorageStats();
 
-  map<RGWObjCategory, RGWStorageStats>::iterator iter;
-  for (iter = bucket_stats.begin(); iter != bucket_stats.end(); ++iter) {
-    RGWStorageStats& s = iter->second;
-    stats.num_kb += s.num_kb;
-    stats.num_kb_rounded += s.num_kb_rounded;
+  for (const auto& pair : bucket_stats) {
+    const RGWStorageStats& s = pair.second;
+
+    stats.size += s.size;
+    stats.size_rounded += s.size_rounded;
     stats.num_objects += s.num_objects;
   }
 
@@ -669,26 +678,44 @@ class RGWQuotaHandlerImpl : public RGWQuotaHandler {
   RGWQuotaInfo def_bucket_quota;
   RGWQuotaInfo def_user_quota;
 
-  int check_quota(const char *entity, RGWQuotaInfo& quota, RGWStorageStats& stats,
-                  uint64_t num_objs, uint64_t size_kb) {
-    if (!quota.enabled)
+  int check_quota(const char * const entity,
+                  const RGWQuotaInfo& quota,
+                  const RGWStorageStats& stats,
+                  const uint64_t num_objs,
+                  const uint64_t size) {
+    if (!quota.enabled) {
       return 0;
+    }
 
-    ldout(store->ctx(), 20) << entity << " quota: max_objects=" << quota.max_objects
+    ldout(store->ctx(), 20) << entity
+                            << " quota: max_objects=" << quota.max_objects
                             << " max_size_kb=" << quota.max_size_kb << dendl;
 
     if (quota.max_objects >= 0 &&
         stats.num_objects + num_objs > (uint64_t)quota.max_objects) {
-      ldout(store->ctx(), 10) << "quota exceeded: stats.num_objects=" << stats.num_objects
-                              << " " << entity << "_quota.max_objects=" << quota.max_objects << dendl;
+      ldout(store->ctx(), 10) << "quota exceeded: stats.num_objects="
+                              << stats.num_objects
+                              << " " << entity << "_quota.max_objects="
+                              << quota.max_objects << dendl;
 
       return -ERR_QUOTA_EXCEEDED;
     }
-    if (quota.max_size_kb >= 0 &&
-               stats.num_kb_rounded + size_kb > (uint64_t)quota.max_size_kb) {
-      ldout(store->ctx(), 10) << "quota exceeded: stats.num_kb_rounded=" << stats.num_kb_rounded << " size_kb=" << size_kb
-                              << " " << entity << "_quota.max_size_kb=" << quota.max_size_kb << dendl;
-      return -ERR_QUOTA_EXCEEDED;
+
+    /* Handling quota in KiBs due to backward compatibility. */
+    if (quota.max_size_kb >= 0) {
+      const uint64_t size_kb = rgw_rounded_objsize_kb(size);
+      /* XXX: just div 1024 should be enough. */
+      const uint64_t stats_num_kb_rounded = rgw_rounded_kb(stats.size_rounded);
+
+      if (stats_num_kb_rounded + size_kb > (uint64_t)quota.max_size_kb) {
+        ldout(store->ctx(), 10) << "quota exceeded: stats_num_kb_rounded="
+                                << stats_num_kb_rounded
+                                << " size_kb=" << size_kb << " " << entity
+                                << "_quota.max_size_kb="
+                                << quota.max_size_kb << dendl;
+
+        return -ERR_QUOTA_EXCEEDED;
+      }
     }
 
     return 0;
@@ -712,54 +739,66 @@ public:
       def_user_quota.enabled = true;
     }
   }
-  virtual int check_quota(const rgw_user& user, rgw_bucket& bucket,
-                          RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota,
-                         uint64_t num_objs, uint64_t size) {
+
+  virtual int check_quota(const rgw_user& user,
+                          rgw_bucket& bucket,
+                          RGWQuotaInfo& user_quota,
+                          RGWQuotaInfo& bucket_quota,
+                          uint64_t num_objs,
+                          uint64_t size) override {
 
     if (!bucket_quota.enabled && !user_quota.enabled && !def_bucket_quota.enabled && !def_user_quota.enabled)
       return 0;
 
-    uint64_t size_kb = rgw_rounded_objsize_kb(size);
-
     RGWStorageStats bucket_stats;
 
     /*
-     * we need to fetch bucket stats if the user quota is enabled, because the whole system relies
-     * on us periodically updating the user's bucket stats in the user's header, this happens in
-     * get_stats() if we actually fetch that info and not rely on cached data
+     * we need to fetch bucket stats if the user quota is enabled, because
+     * the whole system relies on us periodically updating the user's bucket
+     * stats in the user's header, this happens in get_stats() if we actually
+     * fetch that info and not rely on cached data
      */
 
-    int ret = bucket_stats_cache.get_stats(user, bucket, bucket_stats, bucket_quota);
-    if (ret < 0)
+    int ret = bucket_stats_cache.get_stats(user, bucket, bucket_stats,
+                                           bucket_quota);
+    if (ret < 0) {
       return ret;
+    }
 
     if (bucket_quota.enabled) {
-      ret = check_quota("bucket", bucket_quota, bucket_stats, num_objs, size_kb);
-      if (ret < 0)
+      ret = check_quota("bucket", bucket_quota, bucket_stats, num_objs, size);
+      if (ret < 0) {
         return ret;
+      }
     }
 
     if (def_bucket_quota.enabled) {
-      ret = check_quota("def_bucket", def_bucket_quota, bucket_stats, num_objs, size_kb);
-      if (ret < 0)
+      ret = check_quota("def_bucket", def_bucket_quota, bucket_stats,
+                        num_objs, size);
+      if (ret < 0) {
         return ret;
+      }
     }
 
     if (user_quota.enabled || def_user_quota.enabled) {
       RGWStorageStats user_stats;
 
       ret = user_stats_cache.get_stats(user, bucket, user_stats, user_quota);
-      if (ret < 0)
+      if (ret < 0) {
         return ret;
+      }
 
       if (user_quota.enabled) {
-       ret = check_quota("user", user_quota, user_stats, num_objs, size_kb);
-       if (ret < 0)
+       ret = check_quota("user", user_quota, user_stats, num_objs, size);
+       if (ret < 0) {
          return ret;
+        }
       } else if (def_user_quota.enabled) {
-        ret = check_quota("def_user", def_user_quota, user_stats, num_objs, size_kb);
-        if (ret < 0)
+        ret = check_quota("def_user", def_user_quota, user_stats,
+                          num_objs, size);
+        if (ret < 0) {
           return ret;
+        }
       }
     }
 
index 5346dca65a33563b9223c31f3e4858beea1df3a2..446d78e66b382248e2416dcb943d94a388f0e6ca 100644 (file)
@@ -7336,16 +7336,18 @@ int RGWRados::open_bucket_index_shard(rgw_bucket& bucket, librados::IoCtx& index
   return 0;
 }
 
-static void accumulate_raw_stats(rgw_bucket_dir_header& header, map<RGWObjCategory, RGWStorageStats>& stats)
+static void accumulate_raw_stats(const rgw_bucket_dir_header& header,
+                                 map<RGWObjCategory, RGWStorageStats>& stats)
 {
-  map<uint8_t, struct rgw_bucket_category_stats>::iterator iter = header.stats.begin();
-  for (; iter != header.stats.end(); ++iter) {
-    RGWObjCategory category = (RGWObjCategory)iter->first;
+  for (const auto& pair : header.stats) {
+    const RGWObjCategory category = static_cast<RGWObjCategory>(pair.first);
+    const rgw_bucket_category_stats& header_stats = pair.second;
+
     RGWStorageStats& s = stats[category];
-    struct rgw_bucket_category_stats& header_stats = iter->second;
-    s.category = (RGWObjCategory)iter->first;
-    s.num_kb += ((header_stats.total_size + 1023) / 1024);
-    s.num_kb_rounded += ((header_stats.total_size_rounded + 1023) / 1024);
+
+    s.category = category;
+    s.size += header_stats.total_size;
+    s.size_rounded += header_stats.total_size_rounded;
     s.num_objects += header_stats.num_entries;
   }
 }
@@ -10250,14 +10252,16 @@ class RGWGetUserStatsContext : public RGWGetUserHeader_CB {
   RGWGetUserStats_CB *cb;
 
 public:
-  explicit RGWGetUserStatsContext(RGWGetUserStats_CB *_cb) : cb(_cb) {}
+  explicit RGWGetUserStatsContext(RGWGetUserStats_CB * const cb)
+    : cb(cb) {}
+
   void handle_response(int r, cls_user_header& header) {
-    cls_user_stats& hs = header.stats;
+    const cls_user_stats& hs = header.stats;
     if (r >= 0) {
       RGWStorageStats stats;
 
-      stats.num_kb = (hs.total_bytes + 1023) / 1024;
-      stats.num_kb_rounded = (hs.total_bytes_rounded + 1023) / 1024;
+      stats.size = hs.total_bytes;
+      stats.size_rounded = hs.total_bytes_rounded;
       stats.num_objects = hs.total_entries;
 
       cb->set_response(stats);
@@ -10278,10 +10282,10 @@ int RGWRados::get_user_stats(const rgw_user& user, RGWStorageStats& stats)
   if (r < 0)
     return r;
 
-  cls_user_stats& hs = header.stats;
+  const cls_user_stats& hs = header.stats;
 
-  stats.num_kb = (hs.total_bytes + 1023) / 1024;
-  stats.num_kb_rounded = (hs.total_bytes_rounded + 1023) / 1024;
+  stats.size = hs.total_bytes;
+  stats.size_rounded = hs.total_bytes_rounded;
   stats.num_objects = hs.total_entries;
 
   return 0;
@@ -11589,8 +11593,8 @@ int RGWRados::update_user_bucket_stats(const string& user_id, rgw_bucket& bucket
 {
   cls_user_bucket_entry entry;
 
-  entry.size = stats.num_kb * 1024;
-  entry.size_rounded = stats.num_kb_rounded * 1024;
+  entry.size = stats.size;
+  entry.size_rounded = stats.size_rounded;
   entry.count += stats.num_objects;
 
   list<cls_user_bucket_entry> entries;