]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
test: Add KeyValueDB atomicity checker
authorSamuel Just <samuel.just@dreamhost.com>
Thu, 23 Feb 2012 04:07:02 +0000 (20:07 -0800)
committerSamuel Just <samuel.just@dreamhost.com>
Thu, 1 Mar 2012 18:11:42 +0000 (10:11 -0800)
Signed-off-by: Samuel Just <samuel.just@dreamhost.com>
src/Makefile.am
src/include/buffer.h
src/test/ObjectMap/test_keyvaluedb_atomicity.cc [new file with mode: 0644]

index ef3a1647034e000787350514d34459207c30fb2e..bad5c46a60252cbb3a707ac5ff6668750e21762e 100644 (file)
@@ -720,6 +720,14 @@ test_object_map_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS} \
        -I$(top_srcdir)/src/leveldb/include
 bin_DEBUGPROGRAMS += test_object_map
 
+test_keyvaluedb_atomicity_SOURCES = test/ObjectMap/test_keyvaluedb_atomicity.cc os/LevelDBStore.cc
+test_keyvaluedb_atomicity_LDFLAGS = ${AM_LDFLAGS}
+test_keyvaluedb_atomicity_LDADD =  ${UNITTEST_STATIC_LDADD} libos.la leveldb/libleveldb.a $(LIBGLOBAL_LDA)
+test_keyvaluedb_atomicity_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS} \
+       -I$(top_srcdir)/src/leveldb/include
+bin_DEBUGPROGRAMS += test_keyvaluedb_atomicity
+
+
 # shell scripts
 editpaths = sed \
        -e 's|@bindir[@]|$(bindir)|g' \
index 7733121b7b497e72b3ee52099f4e9fadf27bc61d..12dec986ea951e460faa1de5dbc96be4404720cc 100644 (file)
@@ -446,6 +446,16 @@ inline bool operator>=(bufferlist& l, bufferlist& r) {
     p++;
   }
 }
+
+inline bool operator==(bufferlist &l, bufferlist &r) {
+  if (l.length() != r.length())
+    return false;
+  for (unsigned p = 0; p < l.length(); p++) {
+    if (l[p] != r[p])
+      return false;
+  }
+  return true;
+}
 inline bool operator<(bufferlist& l, bufferlist& r) {
   return r > l;
 }
diff --git a/src/test/ObjectMap/test_keyvaluedb_atomicity.cc b/src/test/ObjectMap/test_keyvaluedb_atomicity.cc
new file mode 100644 (file)
index 0000000..8a25af6
--- /dev/null
@@ -0,0 +1,106 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+#include <pthread.h>
+#include "include/buffer.h"
+#include "os/LevelDBStore.h"
+#include <sys/types.h>
+#include <dirent.h>
+#include <string>
+#include <vector>
+#include <tr1/memory>
+#include <boost/scoped_ptr.hpp>
+#include <sstream>
+#include "stdlib.h"
+
+const string CONTROL_PREFIX = "CONTROL";
+const string PRIMARY_PREFIX = "PREFIX";
+const int NUM_COPIES = 100;
+const int NUM_THREADS = 30;
+
+string prefix_gen(int i) {
+  stringstream ss;
+  ss << PRIMARY_PREFIX << "_" << i << std::endl;
+  return ss.str();
+}
+
+int verify(KeyValueDB *db) {
+  // Verify
+  {
+    map<int, KeyValueDB::Iterator> iterators;
+    for (int i = 0; i < NUM_COPIES; ++i) {
+      iterators[i] = db->get_iterator(prefix_gen(i));
+      iterators[i]->seek_to_first();
+    }
+    while (iterators.rbegin()->second->valid()) {
+      for (map<int, KeyValueDB::Iterator>::iterator i = iterators.begin();
+          i != iterators.end();
+          ++i) {
+       assert(i->second->valid());
+       assert(i->second->key() == iterators.rbegin()->second->key());
+       bufferlist r = i->second->value();
+       bufferlist l = iterators.rbegin()->second->value();
+       i->second->next();
+      }
+    }
+    for (map<int, KeyValueDB::Iterator>::iterator i = iterators.begin();
+        i != iterators.end();
+        ++i) {
+      assert(!i->second->valid());
+    }
+  }
+  return 0;
+}
+
+void *write(void *_db) {
+  KeyValueDB *db = static_cast<KeyValueDB*>(_db);
+  std::cout << "Writing..." << std::endl;
+  for (int i = 0; i < 12000; ++i) {
+    if (!(i % 10)) {
+      std::cout << "Iteration: " << i << std::endl;
+    }
+    int key_num = rand();
+    stringstream key;
+    key << key_num << std::endl;
+    map<string, bufferlist> to_set;
+    stringstream val;
+    val << i << std::endl;
+    bufferptr bp(val.str().c_str(), val.str().size() + 1);
+    to_set[key.str()].push_back(bp);
+    
+    KeyValueDB::Transaction t = db->get_transaction();
+    for (int j = 0; j < NUM_COPIES; ++j) {
+      t->set(prefix_gen(j), to_set);
+    }
+    assert(!db->submit_transaction(t));
+  }
+  return 0;
+}
+
+int main() {
+  char *path = getenv("OBJECT_MAP_PATH");
+  boost::scoped_ptr< KeyValueDB > db;
+  if (!path) {
+    std::cerr << "No path found, OBJECT_MAP_PATH undefined" << std::endl;
+    return 0;
+  }
+  string strpath(path);
+  std::cerr << "Using path: " << strpath << std::endl;
+  LevelDBStore *store = new LevelDBStore(strpath);
+  assert(!store->init(std::cerr));
+  db.reset(store);
+
+  verify(db.get());
+
+  vector<pthread_t> threads(NUM_THREADS);
+  for (vector<pthread_t>::iterator i = threads.begin();
+       i != threads.end();
+       ++i) {
+    pthread_create(&*i, 0, &write, static_cast<void *>(db.get()));
+  }
+  for (vector<pthread_t>::iterator i = threads.begin();
+       i != threads.end();
+       ++i) {
+    void *tmp;
+    pthread_join(*i, &tmp);
+  }
+  verify(db.get());
+}