diff --git a/CHANGELOG.md b/CHANGELOG.md index 356decc..7987afe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ - Less dereferencing - Transactions are now closed with the database - Cursors are now closed if the public transaction that opened them got closed +- New primitive to manage database state - session +- Stricter warnings +- Sanitizer builds ### Bug fixes - SIGSEGV on closing database with opened transactions diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c53f6a..9f9469e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCES base.cpp transaction.cpp cursorcommon.cpp + session.cpp ) set(HEADERS @@ -20,6 +21,7 @@ set(HEADERS cache.hpp operators.hpp transaction.h + session.h ) target_sources(${LMDBAL_NAME} PRIVATE ${SOURCES}) diff --git a/src/base.cpp b/src/base.cpp index 5100c83..ec4524c 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -18,8 +18,10 @@ #include "base.h" #include "exceptions.h" +#include "session.h" #include "storage.h" #include "transaction.h" +#include "session.h" #define UNUSED(x) (void)(x) @@ -39,75 +41,34 @@ */ LMDBAL::Base::Base(const QString& _name, uint16_t _mapSize): name(_name.toStdString()), - opened(false), + sessions(), size(_mapSize), environment(), storages(), - transactions() + transactions(), + mutex() {} /** * \brief Destroys the database */ LMDBAL::Base::~Base() { - close(); + std::lock_guard lock(mutex); + + for (Session* session : sessions) + session->terminate(); + + if (opened()) + deactivate(); for (const std::pair& pair : storages) delete pair.second; } -/** - * \brief Closes the database - * - * Closes all lmdb handles, aborts all public transactions. - * This function will do nothing on a closed database - * - * \exception LMDBAL::Unknown - thrown if something went wrong aborting transactions - */ -void LMDBAL::Base::close() { - if (opened) { - for (const std::pair pair : transactions) { - abortTransaction(pair.first, emptyName); - pair.second->reset(); - } - - for (const std::pair& pair : storages) - pair.second->close(); - - mdb_env_close(environment); - transactions.clear(); - opened = false; - } +LMDBAL::Session LMDBAL::Base::open() { + return {this}; } -/** - * \brief Opens the database - * - * Almost every LMDBAL::Base require it to be opened, this function does it. - * It also creates the directory for the database if it was an initial launch. - * This function will do nothing on an opened database - * - * \exception LMDBAL::Unknown - thrown if something went wrong opening storages and caches - */ -void LMDBAL::Base::open() { - if (!opened) { - mdb_env_create(&environment); - QString path = createDirectory(); - - mdb_env_set_maxdbs(environment, static_cast(storages.size())); - mdb_env_set_mapsize(environment, size * 1024UL * 1024UL); - mdb_env_open(environment, path.toStdString().c_str(), 0, 0664); - - TransactionID txn = beginPrivateTransaction(emptyName); - for (const std::pair& pair : storages) { - StorageCommon* storage = pair.second; - if (const int rc = storage->open(txn)) - throw Unknown(name, mdb_strerror(rc)); - } - commitPrivateTransaction(txn, emptyName); - opened = true; - } -} /** * \brief Removes database directory @@ -117,7 +78,7 @@ void LMDBAL::Base::open() { * \exception LMDBAL::Opened - thrown if this function was called on an opened database */ bool LMDBAL::Base::removeDirectory() { - if (opened) + if (opened()) throw Opened(name, "remove database directory"); QString path = getPath(); @@ -144,7 +105,7 @@ bool LMDBAL::Base::removeDirectory() { * \exception LMDBAL::Directory - if the database couldn't create the folder */ QString LMDBAL::Base::createDirectory() { - if (opened) + if (opened()) throw Opened(name, "create database directory"); QString path = getPath(); @@ -183,8 +144,9 @@ QString LMDBAL::Base::getPath() const { * * \returns true if the database is opened and ready for work, false otherwise */ -bool LMDBAL::Base::ready() const { - return opened;} +bool LMDBAL::Base::opened() const { + return !sessions.empty(); +} /** * \brief Drops the database @@ -195,7 +157,7 @@ bool LMDBAL::Base::ready() const { * \exception LMDBAL::Unknown - thrown if something unexpected happend */ void LMDBAL::Base::drop() { - if (!opened) + if (!opened()) throw Closed("drop", name); TransactionID txn = beginPrivateTransaction(emptyName); @@ -301,7 +263,7 @@ void LMDBAL::Base::commitTransaction(LMDBAL::TransactionID id) { * \exception LMDBAL::Unknown - thrown if something unexpected happened */ LMDBAL::TransactionID LMDBAL::Base::beginReadOnlyTransaction(const std::string& storageName) const { - if (!opened) + if (!opened()) throw Closed("beginReadOnlyTransaction", name, storageName); TransactionID txn = beginPrivateReadOnlyTransaction(storageName); @@ -326,7 +288,7 @@ LMDBAL::TransactionID LMDBAL::Base::beginReadOnlyTransaction(const std::string& * \exception LMDBAL::Unknown - thrown if something unexpected happened */ LMDBAL::TransactionID LMDBAL::Base::beginTransaction(const std::string& storageName) const { - if (!opened) + if (!opened()) throw Closed("beginTransaction", name, storageName); TransactionID txn = beginPrivateTransaction(storageName); @@ -351,7 +313,7 @@ LMDBAL::TransactionID LMDBAL::Base::beginTransaction(const std::string& storageN * \exception LMDBAL::Unknown - thrown if something unexpected happened */ void LMDBAL::Base::abortTransaction(LMDBAL::TransactionID id, const std::string& storageName) const { - if (!opened) + if (!opened()) throw Closed("abortTransaction", name, storageName); abortPrivateTransaction(id, storageName); @@ -374,7 +336,7 @@ void LMDBAL::Base::abortTransaction(LMDBAL::TransactionID id, const std::string& * \exception LMDBAL::Unknown - thrown if something unexpected happened */ void LMDBAL::Base::commitTransaction(LMDBAL::TransactionID id, const std::string& storageName) { - if (!opened) + if (!opened()) throw Closed("abortTransaction", name, storageName); commitPrivateTransaction(id, storageName); @@ -407,7 +369,7 @@ LMDBAL::TransactionID LMDBAL::Base::beginPrivateReadOnlyTransaction(const std::s * \brief Begins writable transaction * * This function is intended to be called from subordinate storage or cache, - * it's not accounted in transaction collection, other storages and caches are not notified about this kind of transaction + * it's not accounted in the transaction collection, other storages and caches are not notified about this kind of transaction * * \param[in] storageName - name of the storage/cache that you begin transaction from, needed just to inform if something went wrong * @@ -428,10 +390,10 @@ LMDBAL::TransactionID LMDBAL::Base::beginPrivateTransaction(const std::string& s /** * \brief Aborts transaction * - * Terminates transaction cancelling changes. + * Terminates transaction, cancelling changes. * This is an optimal way to terminate read-only transactions. * This function is intended to be called from subordinate storage or cache, - * it's not accounted in transaction collection, other storages and caches are not notified about this kind of transaction + * it's not accounted in the transaction collection, other storages and caches are not notified about this kind of transaction * * \param[in] id - transaction ID you want to abort * \param[in] storageName - name of the storage/cache that you begin transaction from, unused here @@ -458,3 +420,104 @@ void LMDBAL::Base::commitPrivateTransaction(LMDBAL::TransactionID id, const std: if (rc != MDB_SUCCESS) throw Unknown(name, mdb_strerror(rc), storageName); } + +/** + * \brief Registers session + * + * Registers the session in the session collection. + * If it was the first accounted session, it activates the database + * + * \exception LMDBAL::Unknown - thrown if this session was already registered + */ +void LMDBAL::Base::registerSession(Session* session) { + std::lock_guard lock(mutex); + + if (sessions.empty()) + activate(); + + if (!sessions.insert(session).second) + throw Unknown(name, "session already registered"); +} + +/** + * \brief Unregisters session + * + * Unregisters the session from the session collection. + * If it was the last accounted session, it deactivates the database + * + * \exception LMDBAL::Unknown - thrown if this session was not registered + */ +void LMDBAL::Base::unregisterSession(Session* session) { + std::lock_guard lock(mutex); + + if (sessions.size() == 1) + deactivate(); + + if (sessions.erase(session) != 1) + throw Unknown(name, "session was not registered"); +} + +/** + * \brief Swaps sessions + * + * Replaces one session by another in the session collection. + * + * \exception LMDBAL::Unknown - thrown if there is some unexpected state with sessions, it means the database is in the wrong state + */ +void LMDBAL::Base::replaceSession(Session* closing, Session* opening) { + std::lock_guard lock(mutex); + + if (sessions.erase(closing) != 1) + throw Unknown(name, "session was not registered"); + + if (!sessions.insert(opening).second) + throw Unknown(name, "session already registered"); +} + +/** + * \brief Deactivates the database, + * + * Closes all lmdb handles, aborts all public transactions. + * This function will emit SIGSEGV on a deactivated database + * + * \exception LMDBAL::Unknown - thrown if something went wrong aborting transactions + */ +void LMDBAL::Base::deactivate() { + for (const std::pair pair : transactions) { + abortTransaction(pair.first, emptyName); + pair.second->reset(); + } + + for (const std::pair& pair : storages) + pair.second->close(); + + mdb_env_close(environment); + transactions.clear(); +} + +/** + * \brief Activates the database + * + * Almost every LMDBAL::Base require it to be opened, this function does it. + * It also creates the directory for the database if it was an initial launch. + * This function will behave unpredictably on an activated database, possible data corruption. + * + * \exception LMDBAL::Unknown - thrown if something went wrong opening storages and caches + */ +void LMDBAL::Base::activate() { + mdb_env_create(&environment); + QString path = createDirectory(); + + mdb_env_set_maxdbs(environment, static_cast(storages.size())); + mdb_env_set_mapsize(environment, size * 1024UL * 1024UL); + mdb_env_open(environment, path.toStdString().c_str(), 0, 0664); + + TransactionID txn = beginPrivateTransaction(emptyName); + for (const std::pair& pair : storages) { + StorageCommon* storage = pair.second; + if (const int rc = storage->open(txn)) + throw Unknown(name, mdb_strerror(rc)); + } + + commitPrivateTransaction(txn, emptyName); +} \ No newline at end of file diff --git a/src/base.h b/src/base.h index 4ccf45d..230cf14 100644 --- a/src/base.h +++ b/src/base.h @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -37,6 +39,7 @@ namespace LMDBAL { class StorageCommon; class Transaction; class WriteTransaction; +class Session; template class Serializer; @@ -54,14 +57,14 @@ class Base { friend class StorageCommon; friend class Transaction; friend class WriteTransaction; -public: + friend class Session; +public: Base(const QString& name, uint16_t mapSize = 10); ~Base(); - void open(); - void close(); - bool ready() const; + Session open(); + bool opened() const; bool removeDirectory(); QString createDirectory(); QString getName() const; @@ -84,8 +87,9 @@ public: LMDBAL::Cache* getCache(const std::string& storageName); private: - typedef std::map Storages; /**<\brief Storage and Cache pointers are saved in the std::map*/ - typedef std::map Transactions; /**<\brief Piblic transaction IDs are saved in the std::set*/ + typedef std::map Storages; /**<\brief Storage and Cache pointers are saved in the std::map*/ + typedef std::map Transactions; /**<\brief Public transaction IDs are saved in the std::map*/ + typedef std::set Sessions; /**<\brief Sessions are saved in the std::set*/ void commitTransaction(TransactionID id); void abortTransaction(TransactionID id) const; @@ -99,13 +103,21 @@ private: void commitPrivateTransaction(TransactionID id, const std::string& storageName); void abortPrivateTransaction(TransactionID id, const std::string& storageName) const; + void registerSession(Session* session); + void unregisterSession(Session* session); + void replaceSession(Session* closing, Session* opening); + + void activate(); + void deactivate(); + private: std::string name; /**<\brief Name of this database*/ - bool opened; /**<\brief State of this database*/ + Sessions sessions; /**<\brief Opened session pointers*/ uint16_t size; /**<\brief lmdb map size in MiB*/ MDB_env* environment; /**<\brief lmdb environment handle*/ Storages storages; /**<\brief Registered storages and caches*/ mutable Transactions transactions; /**<\brief Active public transactions*/ + std::mutex mutex; /**<\brief Mutex for thread safety*/ inline static const std::string emptyName = ""; /**<\brief Empty string for general fallback purposes*/ }; @@ -132,7 +144,7 @@ private: */ template LMDBAL::Storage* LMDBAL::Base::addStorage(const std::string& storageName, bool duplicates) { - if (opened) + if (opened()) throw Opened(name, "add storage " + storageName); auto storage = new Storage(this, storageName, duplicates); @@ -160,7 +172,7 @@ LMDBAL::Storage* LMDBAL::Base::addStorage(const std::string& storageName, */ template LMDBAL::Cache * LMDBAL::Base::addCache(const std::string& storageName) { - if (opened) + if (opened()) throw Opened(name, "add cache " + storageName); auto cache = new Cache(this, storageName, false); diff --git a/src/session.cpp b/src/session.cpp new file mode 100644 index 0000000..a02a745 --- /dev/null +++ b/src/session.cpp @@ -0,0 +1,73 @@ +/* +* LMDB Abstraction Layer. + * Copyright (C) 2023 Yury Gubich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "session.h" + +LMDBAL::Session::Session(): + parent(nullptr) {} + +LMDBAL::Session::Session(Base* parent): + parent(parent) +{ + parent->registerSession(this); +} + +LMDBAL::Session::Session(Session&& other): + parent(other.parent) +{ + if (parent) + parent->replaceSession(&other, this); +} + +LMDBAL::Session::~Session() { + if (parent) + parent->unregisterSession(this); +} + +LMDBAL::Session& LMDBAL::Session::operator = (Session&& other) { + if (parent) + if (other.parent) + parent->unregisterSession(&other); + else + parent->unregisterSession(this); + else + if (other.parent) + other.parent->replaceSession(&other, this); + + parent = other.parent; + other.terminate(); + + return *this; +} + +void LMDBAL::Session::close() { + if (!parent) + return; + + parent->unregisterSession(this); + terminate(); +} + +bool LMDBAL::Session::opened() const { + return parent != nullptr; +} + +void LMDBAL::Session::terminate() { + parent = nullptr; +} + diff --git a/src/session.h b/src/session.h new file mode 100644 index 0000000..c0f8da8 --- /dev/null +++ b/src/session.h @@ -0,0 +1,47 @@ +/* +* LMDB Abstraction Layer. + * Copyright (C) 2023 Yury Gubich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "base.h" + +namespace LMDBAL { + +class Session { + friend class Base; +public: + explicit Session(); + ~Session(); + Session(const Session&) = delete; + Session(Session&&); + + Session& operator = (const Session&) = delete; + Session& operator = (Session&&); + + void close(); + bool opened() const; + +private: + Base* parent; + +private: + Session(Base* parent); + void terminate(); +}; + +} diff --git a/src/storagecommon.cpp b/src/storagecommon.cpp index 7202d23..4feaaa7 100644 --- a/src/storagecommon.cpp +++ b/src/storagecommon.cpp @@ -356,7 +356,7 @@ const std::string & LMDBAL::StorageCommon::dbName() const { * \returns true if database is ipened, false otherwise */ bool LMDBAL::StorageCommon::isDBOpened() const { - return db->opened;} + return db->opened();} /** * \brief Throws LMDBAL::Unknown diff --git a/test/basic.cpp b/test/basic.cpp index fb6b0c5..36880b5 100644 --- a/test/basic.cpp +++ b/test/basic.cpp @@ -3,6 +3,7 @@ #include "base.h" #include "storage.h" #include "cache.h" +#include "session.h" #include #include @@ -34,13 +35,14 @@ protected: } static void TearDownTestSuite() { - db->close(); + session.close(); db->removeDirectory(); delete db; db = nullptr; } static LMDBAL::Base* db; + static LMDBAL::Session session; LMDBAL::Storage* t1; LMDBAL::Storage* t2; @@ -50,19 +52,20 @@ protected: LMDBAL::Base* BaseTest::db = nullptr; +LMDBAL::Session BaseTest::session; TEST_F(BaseTest, RemovingDirectory) { EXPECT_EQ(db->removeDirectory(), true); } TEST_F(BaseTest, OpeningClosingDatabase) { - EXPECT_EQ(db->ready(), false); - db->open(); - EXPECT_EQ(db->ready(), true); - db->close(); - EXPECT_EQ(db->ready(), false); - db->open(); - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), false); + session = db->open(); + EXPECT_EQ(db->opened(), true); + session.close(); + EXPECT_EQ(db->opened(), false); + session = db->open(); + EXPECT_EQ(db->opened(), true); } TEST_F(BaseTest, Flags) { @@ -93,7 +96,7 @@ TEST_F(BaseTest, Flags) { } TEST_F(BaseTest, AddingIntegerKey) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); t1->addRecord(1, 2); t1->addRecord(2, 2); t1->addRecord(3, 15); @@ -101,7 +104,7 @@ TEST_F(BaseTest, AddingIntegerKey) { } TEST_F(BaseTest, AddingQStringKey) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); t2->addRecord("hello", "world"); t2->addRecord("aaa", "gagdfsdf"); t2->addRecord("sdfhga", "DSFFDG"); @@ -110,7 +113,7 @@ TEST_F(BaseTest, AddingQStringKey) { } TEST_F(BaseTest, AddingKeysToCache) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); c1->addRecord(2, "blah balah"); c1->addRecord(-4, "testing goes brrr"); c1->addRecord(40, "whatever"); @@ -119,7 +122,7 @@ TEST_F(BaseTest, AddingKeysToCache) { } TEST_F(BaseTest, AddingKeysToVariableCache) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); c2->addRecord("regrets", "blah balah"); c2->addRecord("fossil fingers", 842); c2->addRecord("preloaded cut", 539.75); @@ -132,7 +135,7 @@ TEST_F(BaseTest, AddingKeysToVariableCache) { } TEST_F(BaseTest, AddingRepeatingKey) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); EXPECT_THROW(t1->addRecord(3, 24), LMDBAL::Exist); EXPECT_EQ(t1->getRecord(3), 15); @@ -148,7 +151,7 @@ TEST_F(BaseTest, AddingRepeatingKey) { } TEST_F(BaseTest, GettingNotExistingKeys) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); EXPECT_THROW(t2->getRecord("almonds"), LMDBAL::NotFound); EXPECT_THROW(t1->getRecord(64), LMDBAL::NotFound); @@ -157,21 +160,21 @@ TEST_F(BaseTest, GettingNotExistingKeys) { } TEST_F(BaseTest, Persistence) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); uint32_t t1Size = t1->count(); uint32_t t2Size = t2->count(); uint32_t c1Size = c1->count(); uint32_t c2Size = c2->count(); - db->close(); delete db; + EXPECT_EQ(session.opened(), false); db = new LMDBAL::Base("testBase"); t1 = db->addStorage("table1"); t2 = db->addStorage("table2"); c1 = db->addCache("cache1"); c2 = db->addCache("cache2"); - db->open(); + session = db->open(); EXPECT_EQ(t1->count(), t1Size); EXPECT_EQ(t1->getRecord(3), 15); @@ -212,7 +215,7 @@ TEST_F(BaseTest, Persistence) { } TEST_F(BaseTest, CountAndDrop) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); EXPECT_EQ(t1->count(), 3); EXPECT_EQ(t2->count(), 4); EXPECT_EQ(c1->count(), 4); @@ -237,7 +240,7 @@ TEST_F(BaseTest, CountAndDrop) { } TEST_F(BaseTest, Change) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); EXPECT_EQ(t1->count(), 1); EXPECT_EQ(t2->count(), 1); EXPECT_EQ(c1->count(), 2); @@ -283,7 +286,7 @@ TEST_F(BaseTest, Change) { } TEST_F(BaseTest, Force) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); EXPECT_EQ(t1->forceRecord(58, 35), false); //changing EXPECT_EQ(t1->forceRecord(68, 36), true); //adding @@ -318,7 +321,7 @@ TEST_F(BaseTest, Force) { } TEST_F(BaseTest, ReadAll) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); std::map m1 = t1->readAll(); std::map m2 = t2->readAll(); @@ -349,7 +352,7 @@ TEST_F(BaseTest, ReadAll) { } TEST_F(BaseTest, ReplaceAll) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); t1->replaceAll({ {7, 48}, @@ -417,7 +420,7 @@ TEST_F(BaseTest, ReplaceAll) { } TEST_F(BaseTest, AddRecords) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); LMDBAL::SizeType s1 = t1->addRecords({ {5, 3}, diff --git a/test/cachecursor.cpp b/test/cachecursor.cpp index b965c69..64b4f42 100644 --- a/test/cachecursor.cpp +++ b/test/cachecursor.cpp @@ -4,6 +4,7 @@ #include "storage.h" #include "cache.h" #include "cursor.h" +#include "session.h" class CacheCursorTest : public ::testing::Test { protected: @@ -19,7 +20,7 @@ protected: db = new LMDBAL::Base("testBase"); db->addCache("table1"); db->addCache("empty"); - db->open(); + session = db->open(); } } @@ -30,7 +31,7 @@ protected: static void TearDownTestSuite() { cursor.drop(); transaction.terminate(); - db->close(); + session.close(); db->removeDirectory(); delete db; db = nullptr; @@ -39,6 +40,7 @@ protected: static LMDBAL::Base* db; static LMDBAL::Cursor cursor; static LMDBAL::Transaction transaction; + static LMDBAL::Session session; LMDBAL::Cache* cache; LMDBAL::Cache* emptyCache; @@ -47,6 +49,7 @@ protected: LMDBAL::Base* CacheCursorTest::db = nullptr; LMDBAL::Cursor CacheCursorTest::cursor; LMDBAL::Transaction CacheCursorTest::transaction; +LMDBAL::Session CacheCursorTest::session; static const std::map data({ {245665783, "bothering nerds"}, diff --git a/test/cachetransaction.cpp b/test/cachetransaction.cpp index a2c0e42..5222852 100644 --- a/test/cachetransaction.cpp +++ b/test/cachetransaction.cpp @@ -4,6 +4,7 @@ #include "base.h" #include "cache.h" +#include "session.h" class CacheTransactionsTest : public testing::Test { protected: @@ -39,18 +40,19 @@ protected: db->addStorage("cache2"); } - db->open(); + session = db->open(); db->drop(); } static void TearDownTestSuite() { - db->close(); + session.close(); db->removeDirectory(); delete db; db = nullptr; } static LMDBAL::Base* db; + static LMDBAL::Session session; LMDBAL::Cache* c1; LMDBAL::Cache* c2; @@ -58,9 +60,10 @@ protected: LMDBAL::Base* CacheTransactionsTest::db = nullptr; +LMDBAL::Session CacheTransactionsTest::session; TEST_F(CacheTransactionsTest, Adding) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); EXPECT_EQ(c1->count(), 0); EXPECT_EQ(c2->count(), 0); @@ -90,7 +93,7 @@ TEST_F(CacheTransactionsTest, Adding) { } TEST_F(CacheTransactionsTest, Aborting) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); LMDBAL::SizeType s1 = c1->count(); LMDBAL::SizeType s2 = c2->count(); @@ -114,7 +117,7 @@ TEST_F(CacheTransactionsTest, Aborting) { } TEST_F(CacheTransactionsTest, Reading) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); LMDBAL::Transaction txn = db->beginReadOnlyTransaction(); @@ -132,7 +135,7 @@ TEST_F(CacheTransactionsTest, Reading) { } TEST_F(CacheTransactionsTest, ConcurentReading) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); LMDBAL::SizeType size = c1->count(); LMDBAL::WriteTransaction txn = db->beginTransaction(); @@ -168,7 +171,7 @@ TEST_F(CacheTransactionsTest, ConcurentReading) { TEST_F(CacheTransactionsTest, ConcurentModification) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); //if you start one writable transaction after another //in a single thread like so: @@ -231,7 +234,7 @@ TEST_F(CacheTransactionsTest, ConcurentModification) { } TEST_F(CacheTransactionsTest, RAIIResourceFree) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); int pid = fork(); if (pid == 0) { // I am the child @@ -287,8 +290,8 @@ TEST_F(CacheTransactionsTest, TransactionTerminationOnClose) { EXPECT_EQ(c1->getRecord(578, txn), 4552); EXPECT_EQ(c1->checkRecord(578), false); - db->close(); - db->open(); + session.close(); + session = db->open(); EXPECT_EQ(txn.isActive(), false); EXPECT_THROW(c1->getRecord(578, txn), LMDBAL::TransactionTerminated); diff --git a/test/duplicates.cpp b/test/duplicates.cpp index 0bc6b56..4bb77db 100644 --- a/test/duplicates.cpp +++ b/test/duplicates.cpp @@ -7,6 +7,7 @@ #include "base.h" #include "storage.h" #include "cursor.h" +#include "session.h" class DuplicatesTest : public ::testing::Test { protected: @@ -35,18 +36,19 @@ protected: db->addStorage("intDouble", true); db->addStorage("floatLong", true); - db->open(); + session = db->open(); } } static void TearDownTestSuite() { - db->close(); + session.close(); db->removeDirectory(); delete db; db = nullptr; } static LMDBAL::Base* db; + static LMDBAL::Session session; LMDBAL::Storage* tu1; LMDBAL::Storage* tu2; @@ -56,6 +58,7 @@ protected: }; LMDBAL::Base* DuplicatesTest::db = nullptr; +LMDBAL::Session DuplicatesTest::session; TEST_F(DuplicatesTest, Flags) { uint32_t tu1Flags = getTU1Flags(); diff --git a/test/storagecursor.cpp b/test/storagecursor.cpp index 92279b1..d44e657 100644 --- a/test/storagecursor.cpp +++ b/test/storagecursor.cpp @@ -3,6 +3,7 @@ #include "base.h" #include "storage.h" #include "cursor.h" +#include "session.h" class StorageCursorTest : public ::testing::Test { protected: @@ -18,7 +19,7 @@ protected: db = new LMDBAL::Base("testBase"); db->addStorage("table1"); db->addStorage("empty"); - db->open(); + session = db->open(); } } @@ -29,7 +30,7 @@ protected: static void TearDownTestSuite() { cursor.drop(); transaction.terminate(); - db->close(); + session.close(); db->removeDirectory(); delete db; db = nullptr; @@ -38,6 +39,7 @@ protected: static LMDBAL::Base* db; static LMDBAL::Cursor cursor; static LMDBAL::Transaction transaction; + static LMDBAL::Session session; LMDBAL::Storage* table; LMDBAL::Storage* emptyTable; @@ -46,6 +48,7 @@ protected: LMDBAL::Base* StorageCursorTest::db = nullptr; LMDBAL::Cursor StorageCursorTest::cursor; LMDBAL::Transaction StorageCursorTest::transaction = LMDBAL::Transaction(); +LMDBAL::Session StorageCursorTest::session = LMDBAL::Session(); static const std::map data({ {245665783, "bothering nerds"}, diff --git a/test/storagetransaction.cpp b/test/storagetransaction.cpp index d4b9089..be0fc1d 100644 --- a/test/storagetransaction.cpp +++ b/test/storagetransaction.cpp @@ -4,6 +4,7 @@ #include "base.h" #include "storage.h" +#include "session.h" class StorageTransactionsTest : public testing::Test { protected: @@ -39,18 +40,19 @@ protected: db->addStorage("table2"); } - db->open(); + session = db->open(); db->drop(); } static void TearDownTestSuite() { - db->close(); + session.close(); db->removeDirectory(); delete db; db = nullptr; } static LMDBAL::Base* db; + static LMDBAL::Session session; LMDBAL::Storage* t1; LMDBAL::Storage* t2; @@ -58,9 +60,10 @@ protected: LMDBAL::Base* StorageTransactionsTest::db = nullptr; +LMDBAL::Session StorageTransactionsTest::session; TEST_F(StorageTransactionsTest, Adding) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); EXPECT_EQ(t1->count(), 0); EXPECT_EQ(t2->count(), 0); @@ -90,7 +93,7 @@ TEST_F(StorageTransactionsTest, Adding) { } TEST_F(StorageTransactionsTest, Aborting) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); LMDBAL::SizeType s1 = t1->count(); LMDBAL::SizeType s2 = t2->count(); @@ -114,7 +117,7 @@ TEST_F(StorageTransactionsTest, Aborting) { } TEST_F(StorageTransactionsTest, Reading) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); LMDBAL::Transaction txn = db->beginReadOnlyTransaction(); @@ -132,7 +135,7 @@ TEST_F(StorageTransactionsTest, Reading) { } TEST_F(StorageTransactionsTest, ConcurentReading) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); LMDBAL::SizeType size = t1->count(); LMDBAL::WriteTransaction txn = db->beginTransaction(); @@ -167,7 +170,7 @@ TEST_F(StorageTransactionsTest, ConcurentReading) { } TEST_F(StorageTransactionsTest, ConcurentModification) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); //if you start one writable transaction after another //in a single thread like so: @@ -230,7 +233,7 @@ TEST_F(StorageTransactionsTest, ConcurentModification) { } TEST_F(StorageTransactionsTest, RAIIResourceFree) { - EXPECT_EQ(db->ready(), true); + EXPECT_EQ(db->opened(), true); int pid = fork(); if (pid == 0) { // I am the child @@ -286,8 +289,8 @@ TEST_F(StorageTransactionsTest, TransactionTerminationOnClose) { EXPECT_EQ(t1->getRecord(543, txn), 229); EXPECT_EQ(t1->checkRecord(543), false); - db->close(); - db->open(); + session.close(); + session = db->open(); EXPECT_EQ(txn.isActive(), false); EXPECT_THROW(t1->getRecord(543, txn), LMDBAL::TransactionTerminated);