X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Fobjectstore%2FTestObjectStoreState.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Fobjectstore%2FTestObjectStoreState.cc;h=7eab8b3842ffa7718e25f6902f226cbd4a035638;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/test/objectstore/TestObjectStoreState.cc b/src/ceph/src/test/objectstore/TestObjectStoreState.cc new file mode 100644 index 0000000..7eab8b3 --- /dev/null +++ b/src/ceph/src/test/objectstore/TestObjectStoreState.cc @@ -0,0 +1,301 @@ +// -*- 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 +#include +#include +#include +#include +#include +#include "os/ObjectStore.h" +#include "common/ceph_argparse.h" +#include "global/global_init.h" +#include "common/debug.h" +#include +#include +#include "TestObjectStoreState.h" +#include "include/assert.h" + +#define dout_context g_ceph_context +#define dout_subsys ceph_subsys_filestore +#undef dout_prefix +#define dout_prefix *_dout << "ceph_test_objectstore_state " + +void TestObjectStoreState::init(int colls, int objs) +{ + dout(5) << "init " << colls << " colls " << objs << " objs" << dendl; + + ObjectStore::Sequencer osr(__func__); + ObjectStore::Transaction t; + + t.create_collection(coll_t::meta(), 0); + m_store->apply_transaction(&osr, std::move(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 << dendl; + + ObjectStore::Transaction *t = new ObjectStore::Transaction; + t->create_collection(entry->m_coll, 32); + bufferlist hint; + uint32_t pg_num = colls; + uint64_t num_objs = uint64_t(objs / colls); + ::encode(pg_num, hint); + ::encode(num_objs, hint); + t->collection_hint(entry->m_coll, ObjectStore::Transaction::COLL_HINT_EXPECTED_NUM_OBJECTS, hint); + dout(5) << "give collection hint, number of objects per collection: " << num_objs << dendl; + t->touch(coll_t::meta(), entry->m_meta_obj); + + for (int i = 0; i < objs; i++) { + hobject_t *obj = entry->touch_obj(i + baseid); + t->touch(entry->m_coll, ghobject_t(*obj)); + ceph_assert(i + baseid == m_num_objects); + m_num_objects++; + } + baseid += objs; + + m_store->queue_transaction(&(entry->m_osr), std::move(*t), + new C_OnFinished(this)); + delete 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.load() << "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::iterator it = m_collections.find(key); + if (it != m_collections.end()) { + entry = it->second; + if (erase) { + m_collections.erase(it); + vector::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::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::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::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::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::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::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"); +}