]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tests: fix objectstore tests 1220/head
authorLoic Dachary <loic@dachary.org>
Wed, 12 Feb 2014 10:52:37 +0000 (11:52 +0100)
committerLoic Dachary <loic@dachary.org>
Wed, 12 Feb 2014 10:52:37 +0000 (11:52 +0100)
The objectstore test from 1a588f18ba0e57df64f8a48c1393a4bc65019571 was
missing a few changes.

Signed-off-by: Loic Dachary <loic@dachary.org>
src/test/objectstore/TestFileStoreState.cc [deleted file]
src/test/objectstore/TestFileStoreState.h [deleted file]
src/test/objectstore/TestObjectStoreState.cc [new file with mode: 0644]
src/test/objectstore/TestObjectStoreState.h [new file with mode: 0644]
src/test/objectstore/store_test.cc

diff --git a/src/test/objectstore/TestFileStoreState.cc b/src/test/objectstore/TestFileStoreState.cc
deleted file mode 100644 (file)
index 34e25fb..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
-* Ceph - scalable distributed file system
-*
-* Copyright (C) 2012 New Dream Network
-*
-* This is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License version 2.1, as published by the Free Software
-* Foundation. See file COPYING.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <iostream>
-#include <time.h>
-#include <stdlib.h>
-#include <signal.h>
-#include "os/ObjectStore.h"
-#include "common/ceph_argparse.h"
-#include "global/global_init.h"
-#include "common/debug.h"
-#include <boost/scoped_ptr.hpp>
-#include <boost/lexical_cast.hpp>
-#include "TestObjectStoreState.h"
-#include "include/assert.h"
-
-#define dout_subsys ceph_subsys_filestore
-#undef dout_prefix
-#define dout_prefix *_dout << "ceph_test_filestore_state "
-
-const coll_t TestObjectStoreState::META_COLL("meta");
-const coll_t TestObjectStoreState::TEMP_COLL("temp");
-
-void TestObjectStoreState::init(int colls, int objs)
-{
-  dout(5) << "init " << colls << " colls " << objs << " objs" << dendl;
-
-  ObjectStore::Transaction *t;
-  t = new ObjectStore::Transaction;
-
-  t->create_collection(META_COLL);
-  t->create_collection(TEMP_COLL);
-  m_store->apply_transaction(*t);
-
-  wait_for_ready();
-
-  int baseid = 0;
-  for (int i = 0; i < colls; i++) {
-    int coll_id = i;
-    coll_entry_t *entry = coll_create(coll_id);
-    dout(5) << "init create collection " << entry->m_coll.to_str()
-        << " meta " << entry->m_meta_obj.oid.name << dendl;
-
-    t = new ObjectStore::Transaction;
-    t->create_collection(entry->m_coll);
-    t->touch(META_COLL, entry->m_meta_obj);
-
-    for (int i = 0; i < objs; i++) {
-      hobject_t *obj = entry->touch_obj(i + baseid);
-      t->touch(entry->m_coll, *obj);
-      ceph_assert(i + baseid == m_num_objects);
-      m_num_objects++;
-    }
-    baseid += objs;
-
-    m_store->queue_transaction(&(entry->m_osr), t,
-        new C_OnFinished(this, t));
-    inc_in_flight();
-
-    m_collections.insert(make_pair(coll_id, entry));
-    m_collections_ids.push_back(coll_id);
-    m_next_coll_nr++;
-  }
-  dout(5) << "init has " << m_in_flight.read() << "in-flight transactions" << dendl;
-  wait_for_done();
-  dout(5) << "init finished" << dendl;
-}
-
-TestObjectStoreState::coll_entry_t *TestObjectStoreState::coll_create(int id)
-{
-  char buf[100];
-  char meta_buf[100];
-  memset(buf, 0, 100);
-  memset(meta_buf, 0, 100);
-  snprintf(buf, 100, "0.%d_head", id);
-  snprintf(meta_buf, 100, "pglog_0.%d_head", id);
-  return (new coll_entry_t(id, buf, meta_buf));
-}
-
-TestObjectStoreState::coll_entry_t*
-TestObjectStoreState::get_coll(int key, bool erase)
-{
-  dout(5) << "get_coll id " << key << dendl;
-
-  coll_entry_t *entry = NULL;
-  map<int, coll_entry_t*>::iterator it = m_collections.find(key);
-  if (it != m_collections.end()) {
-    entry = it->second;
-    if (erase) {
-      m_collections.erase(it);
-      vector<int>::iterator cid_it = m_collections_ids.begin()+(entry->m_id);
-      dout(20) << __func__ << " removing key " << key << " coll_id " << entry->m_id
-             << " iterator's entry id " << (*cid_it) << dendl;
-      m_collections_ids.erase(cid_it);
-    }
-  }
-
-  dout(5) << "get_coll id " << key;
-  if (!entry)
-    *_dout << " non-existent";
-  else
-    *_dout << " name " << entry->m_coll.to_str();
-  *_dout << dendl;
-  return entry;
-}
-
-TestObjectStoreState::coll_entry_t*
-TestObjectStoreState::get_coll_at(int pos, bool erase)
-{
-  dout(5) << "get_coll_at pos " << pos << dendl;
-
-  if (m_collections.empty())
-    return NULL;
-
-  assert((size_t) pos < m_collections_ids.size());
-
-  int coll_id = m_collections_ids[pos];
-  coll_entry_t *entry = m_collections[coll_id];
-
-  if (entry == NULL) {
-    dout(5) << "get_coll_at pos " << pos << " non-existent" << dendl;
-    return NULL;
-  }
-
-  if (erase) {
-    m_collections.erase(coll_id);
-    vector<int>::iterator it = m_collections_ids.begin()+(pos);
-    dout(20) << __func__ << " removing pos " << pos << " coll_id " << coll_id
-           << " iterator's entry id " << (*it) << dendl;
-    m_collections_ids.erase(it);
-  }
-
-  dout(5) << "get_coll_at pos " << pos << ": "
-      << entry->m_coll << "(removed: " << erase << ")" << dendl;
-
-  return entry;
-}
-
-TestObjectStoreState::coll_entry_t::~coll_entry_t()
-{
-  if (m_objects.size() > 0) {
-    map<int, hobject_t*>::iterator it = m_objects.begin();
-    for (; it != m_objects.end(); ++it) {
-      hobject_t *obj = it->second;
-      if (obj) {
-        delete obj;
-      }
-    }
-    m_objects.clear();
-  }
-}
-
-bool TestObjectStoreState::coll_entry_t::check_for_obj(int id)
-{
-  if (m_objects.count(id))
-    return true;
-  return false;
-}
-
-hobject_t *TestObjectStoreState::coll_entry_t::touch_obj(int id)
-{
-  map<int, hobject_t*>::iterator it = m_objects.find(id);
-  if (it != m_objects.end()) {
-    dout(5) << "touch_obj coll id " << m_id
-        << " name " << it->second->oid.name << dendl;
-    return it->second;
-  }
-
-  char buf[100];
-  memset(buf, 0, 100);
-  snprintf(buf, 100, "obj%d", id);
-
-  hobject_t *obj = new hobject_t(sobject_t(object_t(buf), CEPH_NOSNAP));
-  m_objects.insert(make_pair(id, obj));
-
-  dout(5) << "touch_obj coll id " << m_id << " name " << buf << dendl;
-  return obj;
-}
-
-hobject_t *TestObjectStoreState::coll_entry_t::get_obj(int id)
-{
-  return get_obj(id, false);
-}
-
-/**
- * remove_obj - Removes object without freeing it.
- * @param id Object's id in the map.
- * @return The object or NULL in case of error.
- */
-hobject_t *TestObjectStoreState::coll_entry_t::remove_obj(int id)
-{
-  return get_obj(id, true);
-}
-
-hobject_t *TestObjectStoreState::coll_entry_t::get_obj(int id, bool remove)
-{
-  map<int, hobject_t*>::iterator it = m_objects.find(id);
-  if (it == m_objects.end()) {
-    dout(5) << "get_obj coll " << m_coll.to_str()
-        << " obj #" << id << " non-existent" << dendl;
-    return NULL;
-  }
-
-  hobject_t *obj = it->second;
-  if (remove)
-    m_objects.erase(it);
-
-  dout(5) << "get_obj coll " << m_coll.to_str() << " id " << id
-      << ": " << obj->oid.name << "(removed: " << remove << ")" << dendl;
-
-  return obj;
-}
-
-hobject_t *TestObjectStoreState::coll_entry_t::get_obj_at(int pos, int *key)
-{
-  return get_obj_at(pos, false, key);
-}
-
-/**
- * remove_obj_at - Removes object without freeing it.
- * @param pos The map's position in which the object lies.
- * @return The object or NULL in case of error.
- */
-hobject_t *TestObjectStoreState::coll_entry_t::remove_obj_at(int pos, int *key)
-{
-  return get_obj_at(pos, true, key);
-}
-
-hobject_t *TestObjectStoreState::coll_entry_t::get_obj_at(int pos,
-    bool remove, int *key)
-{
-  if (m_objects.empty()) {
-    dout(5) << "get_obj_at coll " << m_coll.to_str() << " pos " << pos
-        << " in an empty collection" << dendl;
-    return NULL;
-  }
-
-  hobject_t *ret = NULL;
-  map<int, hobject_t*>::iterator it = m_objects.begin();
-  for (int i = 0; it != m_objects.end(); ++it, i++) {
-    if (i == pos) {
-      ret = it->second;
-      break;
-    }
-  }
-
-  if (ret == NULL) {
-    dout(5) << "get_obj_at coll " << m_coll.to_str() << " pos " << pos
-        << " non-existent" << dendl;
-    return NULL;
-  }
-
-  if (key != NULL)
-    *key = it->first;
-
-  if (remove)
-    m_objects.erase(it);
-
-  dout(5) << "get_obj_at coll id " << m_id << " pos " << pos
-      << ": " << ret->oid.name << "(removed: " << remove << ")" << dendl;
-
-  return ret;
-}
-
-hobject_t*
-TestObjectStoreState::coll_entry_t::replace_obj(int id, hobject_t *obj) {
-  hobject_t *old_obj = remove_obj(id);
-  m_objects.insert(make_pair(id, obj));
-  return old_obj;
-}
-
-int TestObjectStoreState::coll_entry_t::get_random_obj_id(rngen_t& gen)
-{
-  ceph_assert(!m_objects.empty());
-
-  boost::uniform_int<> orig_obj_rng(0, m_objects.size()-1);
-  int pos = orig_obj_rng(gen);
-  map<int, hobject_t*>::iterator it = m_objects.begin();
-  for (int i = 0; it != m_objects.end(); ++it, i++) {
-    if (i == pos) {
-      return it->first;
-    }
-  }
-  ceph_assert(0 == "INTERNAL ERROR");
-}
diff --git a/src/test/objectstore/TestFileStoreState.h b/src/test/objectstore/TestFileStoreState.h
deleted file mode 100644 (file)
index dad2aab..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
-* Ceph - scalable distributed file system
-*
-* Copyright (C) 2012 New Dream Network
-*
-* This is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License version 2.1, as published by the Free Software
-* Foundation. See file COPYING.
-*/
-#ifndef TEST_OBJECTSTORE_STATE_H_
-#define TEST_OBJECTSTORE_STATE_H_
-
-#include "os/ObjectStore.h"
-#include <boost/scoped_ptr.hpp>
-#include <boost/random/mersenne_twister.hpp>
-#include <boost/random/uniform_int.hpp>
-#include <map>
-#include <vector>
-
-typedef boost::mt11213b rngen_t;
-
-class TestObjectStoreState {
-public:
-  struct coll_entry_t {
-    int m_id;
-    coll_t m_coll;
-    hobject_t m_meta_obj;
-    ObjectStore::Sequencer m_osr;
-    map<int, hobject_t*> m_objects;
-    int m_next_object_id;
-
-    coll_entry_t(int i, char *coll_buf, char *meta_obj_buf)
-    : m_id(i), m_coll(coll_buf),
-      m_meta_obj(sobject_t(object_t(meta_obj_buf), CEPH_NOSNAP)),
-      m_osr(coll_buf), m_next_object_id(0) {
-    }
-    ~coll_entry_t();
-
-    hobject_t *touch_obj(int id);
-    bool check_for_obj(int id);
-    hobject_t *get_obj(int id);
-    hobject_t *remove_obj(int id);
-    hobject_t *get_obj_at(int pos, int *key = NULL);
-    hobject_t *remove_obj_at(int pos, int *key = NULL);
-    hobject_t *replace_obj(int id, hobject_t *obj);
-    int get_random_obj_id(rngen_t& gen);
-
-   private:
-    hobject_t *get_obj(int id, bool remove);
-    hobject_t *get_obj_at(int pos, bool remove, int *key = NULL);
-  };
-
-  /* kept in upper case for consistency with coll_t's */
-  static const coll_t META_COLL;
-  static const coll_t TEMP_COLL;
-
- protected:
-  boost::shared_ptr<ObjectStore> m_store;
-  map<int, coll_entry_t*> m_collections;
-  vector<int> m_collections_ids;
-  int m_next_coll_nr;
-  int m_num_objs_per_coll;
-  int m_num_objects;
-
-  int m_max_in_flight;
-  atomic_t m_in_flight;
-  Mutex m_finished_lock;
-  Cond m_finished_cond;
-
-  void wait_for_ready() {
-    Mutex::Locker locker(m_finished_lock);
-    while ((m_max_in_flight > 0) && ((int)m_in_flight.read() >= m_max_in_flight))
-      m_finished_cond.Wait(m_finished_lock);
-  }
-
-  void wait_for_done() {
-    Mutex::Locker locker(m_finished_lock);
-    while (m_in_flight.read())
-      m_finished_cond.Wait(m_finished_lock);
-  }
-
-  void set_max_in_flight(int max) {
-    m_max_in_flight = max;
-  }
-  void set_num_objs_per_coll(int val) {
-    m_num_objs_per_coll = val;
-  }
-
-  coll_entry_t *get_coll(int key, bool erase = false);
-  coll_entry_t *get_coll_at(int pos, bool erase = false);
-
- private:
-  static const int m_default_num_colls = 30;
-
- public:
-  TestObjectStoreState(ObjectStore *store) :
-    m_next_coll_nr(0), m_num_objs_per_coll(10), m_num_objects(0),
-    m_max_in_flight(0), m_finished_lock("Finished Lock") {
-    m_in_flight.set(0);
-    m_store.reset(store);
-  }
-  ~TestObjectStoreState() { 
-    map<int, coll_entry_t*>::iterator it = m_collections.begin();
-    while (it != m_collections.end()) {
-      if (it->second)
-       delete it->second;
-      m_collections.erase(it++);
-    }
-  }
-
-  void init(int colls, int objs);
-  void init() {
-    init(m_default_num_colls, 0);
-  }
-
-  int inc_in_flight() {
-    return ((int) m_in_flight.inc());
-  }
-
-  int dec_in_flight() {
-    return ((int) m_in_flight.dec());
-  }
-
-  coll_entry_t *coll_create(int id);
-
-  class C_OnFinished: public Context {
-   protected:
-    TestObjectStoreState *m_state;
-    ObjectStore::Transaction *m_tx;
-
-   public:
-    C_OnFinished(TestObjectStoreState *state,
-        ObjectStore::Transaction *t) : m_state(state), m_tx(t) { }
-
-    void finish(int r) {
-      Mutex::Locker locker(m_state->m_finished_lock);
-      m_state->dec_in_flight();
-      m_state->m_finished_cond.Signal();
-
-      delete m_tx;
-    }
-  };
-};
-
-#endif /* TEST_OBJECTSTORE_STATE_H_ */
diff --git a/src/test/objectstore/TestObjectStoreState.cc b/src/test/objectstore/TestObjectStoreState.cc
new file mode 100644 (file)
index 0000000..34e25fb
--- /dev/null
@@ -0,0 +1,296 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+* Ceph - scalable distributed file system
+*
+* Copyright (C) 2012 New Dream Network
+*
+* This is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License version 2.1, as published by the Free Software
+* Foundation. See file COPYING.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <time.h>
+#include <stdlib.h>
+#include <signal.h>
+#include "os/ObjectStore.h"
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+#include "common/debug.h"
+#include <boost/scoped_ptr.hpp>
+#include <boost/lexical_cast.hpp>
+#include "TestObjectStoreState.h"
+#include "include/assert.h"
+
+#define dout_subsys ceph_subsys_filestore
+#undef dout_prefix
+#define dout_prefix *_dout << "ceph_test_filestore_state "
+
+const coll_t TestObjectStoreState::META_COLL("meta");
+const coll_t TestObjectStoreState::TEMP_COLL("temp");
+
+void TestObjectStoreState::init(int colls, int objs)
+{
+  dout(5) << "init " << colls << " colls " << objs << " objs" << dendl;
+
+  ObjectStore::Transaction *t;
+  t = new ObjectStore::Transaction;
+
+  t->create_collection(META_COLL);
+  t->create_collection(TEMP_COLL);
+  m_store->apply_transaction(*t);
+
+  wait_for_ready();
+
+  int baseid = 0;
+  for (int i = 0; i < colls; i++) {
+    int coll_id = i;
+    coll_entry_t *entry = coll_create(coll_id);
+    dout(5) << "init create collection " << entry->m_coll.to_str()
+        << " meta " << entry->m_meta_obj.oid.name << dendl;
+
+    t = new ObjectStore::Transaction;
+    t->create_collection(entry->m_coll);
+    t->touch(META_COLL, entry->m_meta_obj);
+
+    for (int i = 0; i < objs; i++) {
+      hobject_t *obj = entry->touch_obj(i + baseid);
+      t->touch(entry->m_coll, *obj);
+      ceph_assert(i + baseid == m_num_objects);
+      m_num_objects++;
+    }
+    baseid += objs;
+
+    m_store->queue_transaction(&(entry->m_osr), t,
+        new C_OnFinished(this, t));
+    inc_in_flight();
+
+    m_collections.insert(make_pair(coll_id, entry));
+    m_collections_ids.push_back(coll_id);
+    m_next_coll_nr++;
+  }
+  dout(5) << "init has " << m_in_flight.read() << "in-flight transactions" << dendl;
+  wait_for_done();
+  dout(5) << "init finished" << dendl;
+}
+
+TestObjectStoreState::coll_entry_t *TestObjectStoreState::coll_create(int id)
+{
+  char buf[100];
+  char meta_buf[100];
+  memset(buf, 0, 100);
+  memset(meta_buf, 0, 100);
+  snprintf(buf, 100, "0.%d_head", id);
+  snprintf(meta_buf, 100, "pglog_0.%d_head", id);
+  return (new coll_entry_t(id, buf, meta_buf));
+}
+
+TestObjectStoreState::coll_entry_t*
+TestObjectStoreState::get_coll(int key, bool erase)
+{
+  dout(5) << "get_coll id " << key << dendl;
+
+  coll_entry_t *entry = NULL;
+  map<int, coll_entry_t*>::iterator it = m_collections.find(key);
+  if (it != m_collections.end()) {
+    entry = it->second;
+    if (erase) {
+      m_collections.erase(it);
+      vector<int>::iterator cid_it = m_collections_ids.begin()+(entry->m_id);
+      dout(20) << __func__ << " removing key " << key << " coll_id " << entry->m_id
+             << " iterator's entry id " << (*cid_it) << dendl;
+      m_collections_ids.erase(cid_it);
+    }
+  }
+
+  dout(5) << "get_coll id " << key;
+  if (!entry)
+    *_dout << " non-existent";
+  else
+    *_dout << " name " << entry->m_coll.to_str();
+  *_dout << dendl;
+  return entry;
+}
+
+TestObjectStoreState::coll_entry_t*
+TestObjectStoreState::get_coll_at(int pos, bool erase)
+{
+  dout(5) << "get_coll_at pos " << pos << dendl;
+
+  if (m_collections.empty())
+    return NULL;
+
+  assert((size_t) pos < m_collections_ids.size());
+
+  int coll_id = m_collections_ids[pos];
+  coll_entry_t *entry = m_collections[coll_id];
+
+  if (entry == NULL) {
+    dout(5) << "get_coll_at pos " << pos << " non-existent" << dendl;
+    return NULL;
+  }
+
+  if (erase) {
+    m_collections.erase(coll_id);
+    vector<int>::iterator it = m_collections_ids.begin()+(pos);
+    dout(20) << __func__ << " removing pos " << pos << " coll_id " << coll_id
+           << " iterator's entry id " << (*it) << dendl;
+    m_collections_ids.erase(it);
+  }
+
+  dout(5) << "get_coll_at pos " << pos << ": "
+      << entry->m_coll << "(removed: " << erase << ")" << dendl;
+
+  return entry;
+}
+
+TestObjectStoreState::coll_entry_t::~coll_entry_t()
+{
+  if (m_objects.size() > 0) {
+    map<int, hobject_t*>::iterator it = m_objects.begin();
+    for (; it != m_objects.end(); ++it) {
+      hobject_t *obj = it->second;
+      if (obj) {
+        delete obj;
+      }
+    }
+    m_objects.clear();
+  }
+}
+
+bool TestObjectStoreState::coll_entry_t::check_for_obj(int id)
+{
+  if (m_objects.count(id))
+    return true;
+  return false;
+}
+
+hobject_t *TestObjectStoreState::coll_entry_t::touch_obj(int id)
+{
+  map<int, hobject_t*>::iterator it = m_objects.find(id);
+  if (it != m_objects.end()) {
+    dout(5) << "touch_obj coll id " << m_id
+        << " name " << it->second->oid.name << dendl;
+    return it->second;
+  }
+
+  char buf[100];
+  memset(buf, 0, 100);
+  snprintf(buf, 100, "obj%d", id);
+
+  hobject_t *obj = new hobject_t(sobject_t(object_t(buf), CEPH_NOSNAP));
+  m_objects.insert(make_pair(id, obj));
+
+  dout(5) << "touch_obj coll id " << m_id << " name " << buf << dendl;
+  return obj;
+}
+
+hobject_t *TestObjectStoreState::coll_entry_t::get_obj(int id)
+{
+  return get_obj(id, false);
+}
+
+/**
+ * remove_obj - Removes object without freeing it.
+ * @param id Object's id in the map.
+ * @return The object or NULL in case of error.
+ */
+hobject_t *TestObjectStoreState::coll_entry_t::remove_obj(int id)
+{
+  return get_obj(id, true);
+}
+
+hobject_t *TestObjectStoreState::coll_entry_t::get_obj(int id, bool remove)
+{
+  map<int, hobject_t*>::iterator it = m_objects.find(id);
+  if (it == m_objects.end()) {
+    dout(5) << "get_obj coll " << m_coll.to_str()
+        << " obj #" << id << " non-existent" << dendl;
+    return NULL;
+  }
+
+  hobject_t *obj = it->second;
+  if (remove)
+    m_objects.erase(it);
+
+  dout(5) << "get_obj coll " << m_coll.to_str() << " id " << id
+      << ": " << obj->oid.name << "(removed: " << remove << ")" << dendl;
+
+  return obj;
+}
+
+hobject_t *TestObjectStoreState::coll_entry_t::get_obj_at(int pos, int *key)
+{
+  return get_obj_at(pos, false, key);
+}
+
+/**
+ * remove_obj_at - Removes object without freeing it.
+ * @param pos The map's position in which the object lies.
+ * @return The object or NULL in case of error.
+ */
+hobject_t *TestObjectStoreState::coll_entry_t::remove_obj_at(int pos, int *key)
+{
+  return get_obj_at(pos, true, key);
+}
+
+hobject_t *TestObjectStoreState::coll_entry_t::get_obj_at(int pos,
+    bool remove, int *key)
+{
+  if (m_objects.empty()) {
+    dout(5) << "get_obj_at coll " << m_coll.to_str() << " pos " << pos
+        << " in an empty collection" << dendl;
+    return NULL;
+  }
+
+  hobject_t *ret = NULL;
+  map<int, hobject_t*>::iterator it = m_objects.begin();
+  for (int i = 0; it != m_objects.end(); ++it, i++) {
+    if (i == pos) {
+      ret = it->second;
+      break;
+    }
+  }
+
+  if (ret == NULL) {
+    dout(5) << "get_obj_at coll " << m_coll.to_str() << " pos " << pos
+        << " non-existent" << dendl;
+    return NULL;
+  }
+
+  if (key != NULL)
+    *key = it->first;
+
+  if (remove)
+    m_objects.erase(it);
+
+  dout(5) << "get_obj_at coll id " << m_id << " pos " << pos
+      << ": " << ret->oid.name << "(removed: " << remove << ")" << dendl;
+
+  return ret;
+}
+
+hobject_t*
+TestObjectStoreState::coll_entry_t::replace_obj(int id, hobject_t *obj) {
+  hobject_t *old_obj = remove_obj(id);
+  m_objects.insert(make_pair(id, obj));
+  return old_obj;
+}
+
+int TestObjectStoreState::coll_entry_t::get_random_obj_id(rngen_t& gen)
+{
+  ceph_assert(!m_objects.empty());
+
+  boost::uniform_int<> orig_obj_rng(0, m_objects.size()-1);
+  int pos = orig_obj_rng(gen);
+  map<int, hobject_t*>::iterator it = m_objects.begin();
+  for (int i = 0; it != m_objects.end(); ++it, i++) {
+    if (i == pos) {
+      return it->first;
+    }
+  }
+  ceph_assert(0 == "INTERNAL ERROR");
+}
diff --git a/src/test/objectstore/TestObjectStoreState.h b/src/test/objectstore/TestObjectStoreState.h
new file mode 100644 (file)
index 0000000..dad2aab
--- /dev/null
@@ -0,0 +1,148 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+* Ceph - scalable distributed file system
+*
+* Copyright (C) 2012 New Dream Network
+*
+* This is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License version 2.1, as published by the Free Software
+* Foundation. See file COPYING.
+*/
+#ifndef TEST_OBJECTSTORE_STATE_H_
+#define TEST_OBJECTSTORE_STATE_H_
+
+#include "os/ObjectStore.h"
+#include <boost/scoped_ptr.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/uniform_int.hpp>
+#include <map>
+#include <vector>
+
+typedef boost::mt11213b rngen_t;
+
+class TestObjectStoreState {
+public:
+  struct coll_entry_t {
+    int m_id;
+    coll_t m_coll;
+    hobject_t m_meta_obj;
+    ObjectStore::Sequencer m_osr;
+    map<int, hobject_t*> m_objects;
+    int m_next_object_id;
+
+    coll_entry_t(int i, char *coll_buf, char *meta_obj_buf)
+    : m_id(i), m_coll(coll_buf),
+      m_meta_obj(sobject_t(object_t(meta_obj_buf), CEPH_NOSNAP)),
+      m_osr(coll_buf), m_next_object_id(0) {
+    }
+    ~coll_entry_t();
+
+    hobject_t *touch_obj(int id);
+    bool check_for_obj(int id);
+    hobject_t *get_obj(int id);
+    hobject_t *remove_obj(int id);
+    hobject_t *get_obj_at(int pos, int *key = NULL);
+    hobject_t *remove_obj_at(int pos, int *key = NULL);
+    hobject_t *replace_obj(int id, hobject_t *obj);
+    int get_random_obj_id(rngen_t& gen);
+
+   private:
+    hobject_t *get_obj(int id, bool remove);
+    hobject_t *get_obj_at(int pos, bool remove, int *key = NULL);
+  };
+
+  /* kept in upper case for consistency with coll_t's */
+  static const coll_t META_COLL;
+  static const coll_t TEMP_COLL;
+
+ protected:
+  boost::shared_ptr<ObjectStore> m_store;
+  map<int, coll_entry_t*> m_collections;
+  vector<int> m_collections_ids;
+  int m_next_coll_nr;
+  int m_num_objs_per_coll;
+  int m_num_objects;
+
+  int m_max_in_flight;
+  atomic_t m_in_flight;
+  Mutex m_finished_lock;
+  Cond m_finished_cond;
+
+  void wait_for_ready() {
+    Mutex::Locker locker(m_finished_lock);
+    while ((m_max_in_flight > 0) && ((int)m_in_flight.read() >= m_max_in_flight))
+      m_finished_cond.Wait(m_finished_lock);
+  }
+
+  void wait_for_done() {
+    Mutex::Locker locker(m_finished_lock);
+    while (m_in_flight.read())
+      m_finished_cond.Wait(m_finished_lock);
+  }
+
+  void set_max_in_flight(int max) {
+    m_max_in_flight = max;
+  }
+  void set_num_objs_per_coll(int val) {
+    m_num_objs_per_coll = val;
+  }
+
+  coll_entry_t *get_coll(int key, bool erase = false);
+  coll_entry_t *get_coll_at(int pos, bool erase = false);
+
+ private:
+  static const int m_default_num_colls = 30;
+
+ public:
+  TestObjectStoreState(ObjectStore *store) :
+    m_next_coll_nr(0), m_num_objs_per_coll(10), m_num_objects(0),
+    m_max_in_flight(0), m_finished_lock("Finished Lock") {
+    m_in_flight.set(0);
+    m_store.reset(store);
+  }
+  ~TestObjectStoreState() { 
+    map<int, coll_entry_t*>::iterator it = m_collections.begin();
+    while (it != m_collections.end()) {
+      if (it->second)
+       delete it->second;
+      m_collections.erase(it++);
+    }
+  }
+
+  void init(int colls, int objs);
+  void init() {
+    init(m_default_num_colls, 0);
+  }
+
+  int inc_in_flight() {
+    return ((int) m_in_flight.inc());
+  }
+
+  int dec_in_flight() {
+    return ((int) m_in_flight.dec());
+  }
+
+  coll_entry_t *coll_create(int id);
+
+  class C_OnFinished: public Context {
+   protected:
+    TestObjectStoreState *m_state;
+    ObjectStore::Transaction *m_tx;
+
+   public:
+    C_OnFinished(TestObjectStoreState *state,
+        ObjectStore::Transaction *t) : m_state(state), m_tx(t) { }
+
+    void finish(int r) {
+      Mutex::Locker locker(m_state->m_finished_lock);
+      m_state->dec_in_flight();
+      m_state->m_finished_cond.Signal();
+
+      delete m_tx;
+    }
+  };
+};
+
+#endif /* TEST_OBJECTSTORE_STATE_H_ */
index 4f66bd6d8929ed60acc068215c969171f9898b8f..e51678e3ea785431c9a53c6648cc975547a10ed9 100644 (file)
@@ -18,6 +18,7 @@
 #include <time.h>
 #include <sys/mount.h>
 #include "os/ObjectStore.h"
+#include "os/FileStore.h"
 #include "os/KeyValueStore.h"
 #include "include/Context.h"
 #include "common/ceph_argparse.h"