]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Make KeyValueStore support set_alloc_hint op
authorHaomai Wang <haomaiwang@gmail.com>
Sat, 7 Jun 2014 10:57:29 +0000 (18:57 +0800)
committerHaomai Wang <haomaiwang@gmail.com>
Sat, 7 Jun 2014 10:57:29 +0000 (18:57 +0800)
Add a new config let KeyValueStore support configurable strip size.
set_alloc_hint op can affect the strip size of the specified object
and the expect write size will become the strip size of the object.

Signed-off-by: Haomai Wang <haomaiwang@gmail.com>
src/common/config_opts.h
src/os/KeyValueStore.cc
src/os/KeyValueStore.h

index d2d884d434bd04fe395a943b7d984fdeacb1bc73..18b0a2ab447470983899dfcf542700154b687ae6 100644 (file)
@@ -692,6 +692,7 @@ OPTION(keyvaluestore_debug_check_backend, OPT_BOOL, 0) // Expensive debugging ch
 OPTION(keyvaluestore_op_threads, OPT_INT, 2)
 OPTION(keyvaluestore_op_thread_timeout, OPT_INT, 60)
 OPTION(keyvaluestore_op_thread_suicide_timeout, OPT_INT, 180)
+OPTION(keyvaluestore_default_strip_size, OPT_INT, 4096) // Only affect new object
 
 // max bytes to search ahead in journal searching for corruption
 OPTION(journal_max_corrupt_search, OPT_U64, 10<<20)
index 08af6391196d0393892848acfa8f21dada1ec2cb..b20f9cae472edce365751c3e7fbb4352d373f5ed 100644 (file)
@@ -509,6 +509,7 @@ KeyValueStore::KeyValueStore(const std::string &base,
   perf_logger(NULL),
   m_keyvaluestore_queue_max_ops(g_conf->keyvaluestore_queue_max_ops),
   m_keyvaluestore_queue_max_bytes(g_conf->keyvaluestore_queue_max_bytes),
+  m_keyvaluestore_strip_size(g_conf->keyvaluestore_default_strip_size),
   do_update(do_update)
 {
   ostringstream oss;
@@ -873,6 +874,7 @@ int KeyValueStore::mount()
       goto close_current_fd;
     }
 
+    default_strip_size = m_keyvaluestore_strip_size;
     backend.reset(dbomap);
   }
 
@@ -1450,11 +1452,12 @@ unsigned KeyValueStore::_do_transaction(Transaction& transaction,
 
     case Transaction::OP_SETALLOCHINT:
       {
-        // TODO: can kvstore make use of the hint?
         coll_t cid(i.decode_cid());
         ghobject_t oid = i.decode_oid();
-        i.decode_length(); // uint64_t expected_object_size
-        i.decode_length(); // uint64_t expected_write_size
+        uint64_t expected_object_size = i.decode_length();
+        uint64_t expected_write_size = i.decode_length();
+        r = _set_alloc_hint(cid, oid, expected_object_size,
+                            expected_write_size, t);
       }
       break;
 
@@ -2974,11 +2977,53 @@ int KeyValueStore::_split_collection(coll_t cid, uint32_t bits, uint32_t rem,
   return 0;
 }
 
+int KeyValueStore::_set_alloc_hint(coll_t cid, const ghobject_t& oid,
+                                   uint64_t expected_object_size,
+                                   uint64_t expected_write_size,
+                                   BufferTransaction &t)
+{
+  dout(15) << __func__ << " " << cid << "/" << oid << " object_size "
+           << expected_object_size << " write_size "
+           << expected_write_size << dendl;
+
+  int r = 0;
+  StripObjectMap::StripObjectHeader *header;
+
+  r = t.lookup_cached_header(cid, oid, &header, false);
+  if (r < 0) {
+    dout(10) << __func__ << " " << cid << "/" << oid
+             << " failed to get header: r = " << r << dendl;
+    return r;
+  }
+
+  bool blank = true;
+  for (vector<char>::iterator it = header->bits.begin();
+       it != header->bits.end(); ++it) {
+    if (*it) {
+      blank = false;
+      break;
+    }
+  }
+
+  // Now only consider to change "strip_size" when the object is blank,
+  // because set_alloc_hint is expected to be very lightweight<O(1)>
+  if (blank) {
+    header->strip_size = expected_write_size;
+  }
+
+  dout(10) << __func__ << "" << cid << "/" << oid << " object_size "
+           << expected_object_size << " write_size "
+           << expected_write_size << " = " << r << dendl;
+
+  return r;
+}
+
 const char** KeyValueStore::get_tracked_conf_keys() const
 {
   static const char* KEYS[] = {
     "keyvaluestore_queue_max_ops",
     "keyvaluestore_queue_max_bytes",
+    "keyvaluestore_strip_size",
     NULL
   };
   return KEYS;
@@ -2992,6 +3037,10 @@ void KeyValueStore::handle_conf_change(const struct md_config_t *conf,
     m_keyvaluestore_queue_max_ops = conf->keyvaluestore_queue_max_ops;
     m_keyvaluestore_queue_max_bytes = conf->keyvaluestore_queue_max_bytes;
   }
+  if (changed.count("keyvaluestore_default_strip_size")) {
+    m_keyvaluestore_strip_size = conf->keyvaluestore_default_strip_size;
+    default_strip_size = m_keyvaluestore_strip_size;
+  }
 }
 
 void KeyValueStore::dump_transactions(list<ObjectStore::Transaction*>& ls, uint64_t seq, OpSequencer *osr)
index 02574596954a77bcba5bb300310dd10651058fbc..27eb993cbe7ac1c5a5ba1345682b814a7fa1b1ef 100644 (file)
@@ -48,6 +48,8 @@ enum kvstore_types {
 };
 
 
+static uint64_t default_strip_size = 1024;
+
 class StripObjectMap: public GenericObjectMap {
  public:
 
@@ -139,8 +141,6 @@ class StripObjectMap: public GenericObjectMap {
     );
 
   StripObjectMap(KeyValueDB *db): GenericObjectMap(db) {}
-
-  static const uint64_t default_strip_size = 1024;
 };
 
 
@@ -478,7 +478,10 @@ class KeyValueStore : public ObjectStore,
                    const ghobject_t& newoid, uint64_t srcoff,
                    uint64_t len, uint64_t dstoff, BufferTransaction &t);
   int _remove(coll_t cid, const ghobject_t& oid, BufferTransaction &t);
-
+  int _set_alloc_hint(coll_t cid, const ghobject_t& oid,
+                      uint64_t expected_object_size,
+                      uint64_t expected_write_size,
+                      BufferTransaction &t);
 
   void start_sync() {}
   void sync() {}
@@ -582,6 +585,7 @@ class KeyValueStore : public ObjectStore,
   std::string m_osd_rollback_to_cluster_snap;
   int m_keyvaluestore_queue_max_ops;
   int m_keyvaluestore_queue_max_bytes;
+  int m_keyvaluestore_strip_size;
 
   int do_update;