]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: bucket quota threshold
authorYehuda Sadeh <yehuda@inktank.com>
Thu, 10 Oct 2013 17:50:39 +0000 (10:50 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Thu, 10 Oct 2013 20:51:24 +0000 (13:51 -0700)
Add bucket quota threshold so that when we're passed that value we
reread the bucket stats before every write and not rely on cached value.

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
src/common/config_opts.h
src/rgw/rgw_quota.cc
src/rgw/rgw_quota.h

index c2784ce287e7e8ce115e9bf76d3507c5c34c67ab..b0dead48763ca10c68d779a7eca0653fc9e36e63 100644 (file)
@@ -716,6 +716,7 @@ OPTION(rgw_data_log_obj_prefix, OPT_STR, "data_log") //
 OPTION(rgw_replica_log_obj_prefix, OPT_STR, "replica_log") // 
 
 OPTION(rgw_bucket_quota_ttl, OPT_INT, 600) // time for cached bucket stats to be cached within rgw instance
+OPTION(rgw_bucket_quota_soft_threshold, OPT_DOUBLE, 0.95) // threshold from which we don't rely on cached info for quota decisions
 OPTION(rgw_bucket_quota_cache_size, OPT_INT, 10000) // number of entries in bucket quota cache
 
 OPTION(mutex_perf_counter, OPT_BOOL, false) // enable/disable mutex perf counter
index 9380403c7bc07468ef04208faa312d8b24af5c6e..d6bad572e35b2e96011f22def296f4f3d32a8b3e 100644 (file)
@@ -31,14 +31,45 @@ public:
     async_refcount->put_wait(); /* wait for all pending async requests to complete */
   }
 
-  int get_bucket_stats(rgw_bucket& bucket, RGWBucketStats& stats);
+  int get_bucket_stats(rgw_bucket& bucket, RGWBucketStats& stats, RGWQuotaInfo& quota);
   void adjust_bucket_stats(rgw_bucket& bucket, int objs_delta, uint64_t added_bytes, uint64_t removed_bytes);
 
+  bool can_use_cached_stats(RGWQuotaInfo& quota, RGWBucketStats& stats);
+
   void set_stats(rgw_bucket& bucket, RGWQuotaBucketStats& qs, RGWBucketStats& stats);
   int async_refresh(rgw_bucket& bucket, RGWQuotaBucketStats& qs);
   void async_refresh_response(rgw_bucket& bucket, RGWBucketStats& stats);
 };
 
+bool RGWBucketStatsCache::can_use_cached_stats(RGWQuotaInfo& quota, RGWBucketStats& cached_stats)
+{
+  if (quota.max_size_kb >= 0) {
+    if (quota.max_size_soft_threshold < 0) {
+      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) {
+      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;
+      return false;
+    }
+  }
+
+  if (quota.max_objects >= 0) {
+    if (quota.max_objs_soft_threshold < 0) {
+      quota.max_objs_soft_threshold = quota.max_objects * store->ctx()->_conf->rgw_bucket_quota_soft_threshold;
+    }
+
+    if (cached_stats.num_objects >= (uint64_t)quota.max_objs_soft_threshold) {
+      ldout(store->ctx(), 20) << "quota: can't use cached stats, exceeded soft threshold (num objs): "
+        << cached_stats.num_objects << " >= " << quota.max_objs_soft_threshold << dendl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
 int RGWBucketStatsCache::fetch_bucket_totals(rgw_bucket& bucket, RGWBucketStats& stats)
 {
   RGWBucketInfo bucket_info;
@@ -176,7 +207,7 @@ void RGWBucketStatsCache::set_stats(rgw_bucket& bucket, RGWQuotaBucketStats& qs,
   stats_map.add(bucket, qs);
 }
 
-int RGWBucketStatsCache::get_bucket_stats(rgw_bucket& bucket, RGWBucketStats& stats) {
+int RGWBucketStatsCache::get_bucket_stats(rgw_bucket& bucket, RGWBucketStats& stats, RGWQuotaInfo& quota) {
   RGWQuotaBucketStats qs;
   utime_t now = ceph_clock_now(store->ctx());
   if (stats_map.find(bucket, qs)) {
@@ -188,7 +219,8 @@ int RGWBucketStatsCache::get_bucket_stats(rgw_bucket& bucket, RGWBucketStats& st
         /* continue processing, might be a transient error, async refresh is just optimization */
       }
     }
-    if (qs.expiration > ceph_clock_now(store->ctx())) {
+
+    if (can_use_cached_stats(quota, qs.stats) && qs.expiration > ceph_clock_now(store->ctx())) {
       stats = qs.stats;
       return 0;
     }
@@ -245,7 +277,7 @@ public:
 
     RGWBucketStats stats;
 
-    int ret = stats_cache.get_bucket_stats(bucket, stats);
+    int ret = stats_cache.get_bucket_stats(bucket, stats, bucket_quota);
     if (ret < 0)
       return ret;
 
index 9af91e3986d8821f7171b38833070f3648f4ce0b..55e2738a0cacf9ed1984253663d5a0da492d2b47 100644 (file)
@@ -13,8 +13,11 @@ struct RGWQuotaInfo {
   int64_t max_size_kb;
   int64_t max_objects;
   bool enabled;
+  int64_t max_size_soft_threshold;
+  int64_t max_objs_soft_threshold;
 
-  RGWQuotaInfo() : max_size_kb(-1), max_objects(-1), enabled(false) {}
+  RGWQuotaInfo() : max_size_kb(-1), max_objects(-1), enabled(false),
+                   max_size_soft_threshold(-1), max_objs_soft_threshold(-1) {}
 
   void encode(bufferlist& bl) const {
     ENCODE_START(1, 1, bl);