From f0779ae2aa6be26405967ef1cc6d029af4d61a66 Mon Sep 17 00:00:00 2001 From: blue Date: Sun, 2 Apr 2023 16:00:21 +0300 Subject: [PATCH] some ideas about transaction --- CMakeLists.txt | 11 ++++ src/base.cpp | 101 ++++++++++++++++++++++-------------- src/base.h | 23 ++++---- src/storage.cpp | 24 +++++++-- src/storage.h | 19 ++++--- src/storage.hpp | 2 +- test/storagetransaction.cpp | 10 ++-- 7 files changed, 125 insertions(+), 65 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d301fa2..fbbeb34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,17 @@ else () add_library(${PROJECT_NAME} SHARED) endif() +if (CMAKE_BUILD_TYPE STREQUAL "Release") + list(APPEND COMPILE_OPTIONS -O3) +elseif (CMAKE_BUILD_TYPE STREQUAL "Debug") + list(APPEND COMPILE_OPTIONS -g) + list(APPEND COMPILE_OPTIONS -Wall) + list(APPEND COMPILE_OPTIONS -Wextra) +endif() + +message("Compilation options: " ${COMPILE_OPTIONS}) +target_compile_options(${PROJECT_NAME} PRIVATE ${COMPILE_OPTIONS}) + set_property(TARGET ${PROJECT_NAME} PROPERTY VERSION ${version}) set_property(TARGET ${PROJECT_NAME} PROPERTY SOVERSION 1) set_property(TARGET ${PROJECT_NAME} PROPERTY diff --git a/src/base.cpp b/src/base.cpp index 15e833b..48f7dcf 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -20,12 +20,14 @@ #include "exceptions.h" #include "storage.h" +#define UNUSED(x) (void)(x) + LMDBAL::Base::Base(const QString& p_name, uint16_t mapSize): name(p_name.toStdString()), opened(false), size(mapSize), environment(), - tables(), + storages(), transactions(new Transactions()) {} @@ -34,18 +36,18 @@ LMDBAL::Base::~Base() { delete transactions; - for (const std::pair& pair : tables) + for (const std::pair& pair : storages) delete pair.second; } void LMDBAL::Base::close() { if (opened) { for (LMDBAL::TransactionID id : *transactions) - mdb_txn_abort(id); + abortTransaction(id, emptyName); - for (const std::pair& pair : tables) { - iStorage* table = pair.second; - mdb_dbi_close(environment, table->dbi); + for (const std::pair& pair : storages) { + iStorage* storage = pair.second; + mdb_dbi_close(environment, storage->dbi); } mdb_env_close(environment); transactions->clear(); @@ -61,20 +63,18 @@ void LMDBAL::Base::open() { mdb_env_create(&environment); QString path = createDirectory(); - mdb_env_set_maxdbs(environment, tables.size()); + mdb_env_set_maxdbs(environment, storages.size()); mdb_env_set_mapsize(environment, size * 1024UL * 1024UL); mdb_env_open(environment, path.toStdString().c_str(), 0, 0664); - MDB_txn *txn; - mdb_txn_begin(environment, NULL, 0, &txn); - - for (const std::pair& pair : tables) { - iStorage* table = pair.second; - int rc = table->createTable(txn); + TransactionID txn = beginPrivateTransaction(emptyName); + for (const std::pair& pair : storages) { + iStorage* storage = pair.second; + int rc = storage->createStorage(txn); if (rc) throw Unknown(name, mdb_strerror(rc)); } - mdb_txn_commit(txn); + commitPrivateTransaction(txn, emptyName); opened = true; } } @@ -120,18 +120,13 @@ void LMDBAL::Base::drop() { if (!opened) throw Closed("drop", name); - MDB_txn *txn; - int rc = mdb_txn_begin(environment, NULL, 0, &txn); - if (rc) - throw Unknown(name, mdb_strerror(rc)); - - for (const std::pair& pair : tables) { - rc = pair.second->drop(txn); + TransactionID txn = beginPrivateTransaction(emptyName); + for (const std::pair& pair : storages) { + int rc = pair.second->drop(txn); if (rc) throw Unknown(name, mdb_strerror(rc), pair.first); } - - mdb_txn_commit(txn); + commitPrivateTransaction(txn, emptyName); } LMDBAL::TransactionID LMDBAL::Base::beginReadOnlyTransaction() const { @@ -146,18 +141,15 @@ void LMDBAL::Base::abortTransaction(LMDBAL::TransactionID id) const { void LMDBAL::Base::commitTransaction(LMDBAL::TransactionID id) const { return commitTransaction(id, emptyName);} - LMDBAL::TransactionID LMDBAL::Base::beginReadOnlyTransaction(const std::string& storageName) const { if (!opened) throw Closed("beginReadOnlyTransaction", name, storageName); - MDB_txn* txn; - int rc = mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn); - if (rc) { - mdb_txn_abort(txn); - throw Unknown(name, mdb_strerror(rc), storageName); - } + TransactionID txn = beginPrivateReadOnlyTransaction(storageName); transactions->emplace(txn); + for (const std::pair& pair : storages) + pair.second->transactionStarted(txn, true); + return txn; } @@ -165,13 +157,11 @@ LMDBAL::TransactionID LMDBAL::Base::beginTransaction(const std::string& storageN if (!opened) throw Closed("beginTransaction", name, storageName); - MDB_txn* txn; - int rc = mdb_txn_begin(environment, NULL, 0, &txn); - if (rc) { - mdb_txn_abort(txn); - throw Unknown(name, mdb_strerror(rc), storageName); - } + TransactionID txn = beginPrivateTransaction(storageName); transactions->emplace(txn); + for (const std::pair& pair : storages) + pair.second->transactionStarted(txn, false); + return txn; } @@ -183,7 +173,10 @@ void LMDBAL::Base::abortTransaction(LMDBAL::TransactionID id, const std::string& if (itr == transactions->end()) //TODO may be it's a good idea to make an exception class for this throw Unknown(name, "unable to abort transaction: transaction was not found", storageName); - mdb_txn_abort(id); + abortPrivateTransaction(id, storageName); + for (const std::pair& pair : storages) + pair.second->transactionAborted(id); + transactions->erase(itr); } @@ -195,8 +188,40 @@ void LMDBAL::Base::commitTransaction(LMDBAL::TransactionID id, const std::string if (itr == transactions->end()) //TODO may be it's a good idea to make an exception class for this throw Unknown(name, "unable to commit transaction: transaction was not found", storageName); - int rc = mdb_txn_commit(id); + commitPrivateTransaction(id, storageName); + for (const std::pair& pair : storages) + pair.second->transactionCommited(id); + transactions->erase(itr); +} + +LMDBAL::TransactionID LMDBAL::Base::beginPrivateReadOnlyTransaction(const std::string& storageName) const { + MDB_txn* txn; + int rc = mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn); + if (rc) { + mdb_txn_abort(txn); + throw Unknown(name, mdb_strerror(rc), storageName); + } + return txn; +} + +LMDBAL::TransactionID LMDBAL::Base::beginPrivateTransaction(const std::string& storageName) const { + MDB_txn* txn; + int rc = mdb_txn_begin(environment, NULL, 0, &txn); + if (rc) { + mdb_txn_abort(txn); + throw Unknown(name, mdb_strerror(rc), storageName); + } + return txn; +} + +void LMDBAL::Base::abortPrivateTransaction(LMDBAL::TransactionID id, const std::string& storageName) const { + UNUSED(storageName); + mdb_txn_abort(id); +} + +void LMDBAL::Base::commitPrivateTransaction(LMDBAL::TransactionID id, const std::string& storageName) const { + int rc = mdb_txn_commit(id); if (rc != MDB_SUCCESS) throw Unknown(name, mdb_strerror(rc), storageName); } diff --git a/src/base.h b/src/base.h index 024eb98..c1110cb 100644 --- a/src/base.h +++ b/src/base.h @@ -81,7 +81,7 @@ public: LMDBAL::Cache* getCache(const std::string& name); private: - typedef std::map Tables; + typedef std::map Storages; typedef std::set Transactions; TransactionID beginReadOnlyTransaction(const std::string& storageName) const; @@ -89,12 +89,17 @@ private: void commitTransaction(TransactionID id, const std::string& storageName) const; void abortTransaction(TransactionID id, const std::string& storageName) const; + TransactionID beginPrivateReadOnlyTransaction(const std::string& storageName) const; + TransactionID beginPrivateTransaction(const std::string& storageName) const; + void commitPrivateTransaction(TransactionID id, const std::string& storageName) const; + void abortPrivateTransaction(TransactionID id, const std::string& storageName) const; + private: std::string name; bool opened; uint16_t size; MDB_env* environment; - Tables tables; + Storages storages; Transactions* transactions; inline static const std::string emptyName = ""; @@ -109,11 +114,11 @@ private: template LMDBAL::Storage* LMDBAL::Base::addStorage(const std::string& p_name) { if (opened) { - throw Opened(name, "add table " + p_name); + throw Opened(name, "add storage " + p_name); } - Storage* table = new Storage(p_name, this); - tables.insert(std::make_pair(p_name, (iStorage*)table)); - return table; + Storage* storage = new Storage(p_name, this); + storages.insert(std::make_pair(p_name, (iStorage*)storage)); + return storage; } /** @@ -125,7 +130,7 @@ LMDBAL::Cache * LMDBAL::Base::addCache(const std::string& p_name) { throw Opened(name, "add cache " + p_name); } Cache* cache = new Cache(p_name, this); - tables.insert(std::make_pair(p_name, (iStorage*)cache)); + storages.insert(std::make_pair(p_name, (iStorage*)cache)); return cache; } @@ -134,7 +139,7 @@ LMDBAL::Cache * LMDBAL::Base::addCache(const std::string& p_name) { */ template LMDBAL::Storage* LMDBAL::Base::getStorage(const std::string& p_name) { - return static_cast*>(tables.at(p_name)); + return static_cast*>(storages.at(p_name)); } /** @@ -142,7 +147,7 @@ LMDBAL::Storage* LMDBAL::Base::getStorage(const std::string& p_name) { */ template LMDBAL::Cache* LMDBAL::Base::getCache(const std::string& p_name) { - return static_cast*>(tables.at(p_name)); + return static_cast*>(storages.at(p_name)); } #endif //LMDBAL_BASE_H diff --git a/src/storage.cpp b/src/storage.cpp index b28afc3..8768654 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -18,6 +18,8 @@ #include "storage.h" +#define UNUSED(x) (void)(x) + LMDBAL::iStorage::iStorage(const std::string& p_name, Base* parent): dbi(), db(parent), @@ -125,13 +127,27 @@ void LMDBAL::iStorage::throwNotFound(const std::string& key) const { throw NotFound(key, db->name, name);} LMDBAL::TransactionID LMDBAL::iStorage::beginReadOnlyTransaction() const { - return db->beginReadOnlyTransaction(name);} + return db->beginPrivateReadOnlyTransaction(name);} LMDBAL::TransactionID LMDBAL::iStorage::beginTransaction() const { - return db->beginTransaction(name);} + return db->beginPrivateTransaction(name);} void LMDBAL::iStorage::abortTransaction(LMDBAL::TransactionID id) const { - db->abortTransaction(id);} + db->abortPrivateTransaction(id, name);} void LMDBAL::iStorage::commitTransaction(LMDBAL::TransactionID id) const { - db->commitTransaction(id);} + db->commitPrivateTransaction(id, name);} + +void LMDBAL::iStorage::transactionStarted(LMDBAL::TransactionID txn, bool readOnly) const { + UNUSED(txn); + UNUSED(readOnly); +} +void LMDBAL::iStorage::transactionCommited(LMDBAL::TransactionID txn) const { + UNUSED(txn); +} +void LMDBAL::iStorage::transactionAborted(LMDBAL::TransactionID txn) const { + UNUSED(txn); +} + + + diff --git a/src/storage.h b/src/storage.h index dc00d38..3986c20 100644 --- a/src/storage.h +++ b/src/storage.h @@ -34,7 +34,7 @@ protected: iStorage(const std::string& name, Base* parent); virtual ~iStorage(); - virtual int createTable(MDB_txn * transaction) = 0; + virtual int createStorage(MDB_txn * transaction) = 0; virtual int drop(MDB_txn * transaction); bool isDBOpened() const; @@ -48,17 +48,20 @@ protected: void throwUnknown(int rc, TransactionID txn) const; void throwUnknown(int rc) const; void throwDuplicate(const std::string& key) const; - void throwNotFound(const std::string& key)const ; - -public: - virtual void drop(); - virtual SizeType count() const; - virtual SizeType count(TransactionID txn) const; + void throwNotFound(const std::string& key) const; TransactionID beginReadOnlyTransaction() const; TransactionID beginTransaction() const; void commitTransaction(TransactionID id) const; void abortTransaction(TransactionID id) const; + void transactionStarted(TransactionID txn, bool readOnly) const; + void transactionCommited(TransactionID txn) const; + void transactionAborted(TransactionID txn) const; + +public: + virtual void drop(); + virtual SizeType count() const; + virtual SizeType count(TransactionID txn) const; protected: MDB_dbi dbi; @@ -122,7 +125,7 @@ protected: Serializer* keySerializer; Serializer* valueSerializer; - int createTable(MDB_txn* transaction) override; + int createStorage(MDB_txn* transaction) override; }; } diff --git a/src/storage.hpp b/src/storage.hpp index 8e7da60..52e4422 100644 --- a/src/storage.hpp +++ b/src/storage.hpp @@ -372,7 +372,7 @@ void LMDBAL::Storage::removeRecord(const K& key, TransactionID txn) { } template -int LMDBAL::Storage::createTable(MDB_txn* transaction) { +int LMDBAL::Storage::createStorage(MDB_txn* transaction) { return makeTable(transaction); } diff --git a/test/storagetransaction.cpp b/test/storagetransaction.cpp index 294c1d2..e756931 100644 --- a/test/storagetransaction.cpp +++ b/test/storagetransaction.cpp @@ -46,7 +46,7 @@ TEST_F(StorageTransactionsTest, Adding) { LMDBAL::TransactionID txn = db->beginTransaction(); t1->addRecord(5, 13, txn); t1->addRecord(-53, 782, txn); - t1->addRecord(58392, -37829, txn); + t1->addRecord(5892, -37829, txn); t2->addRecord("lorem", 481, txn); t2->addRecord("decallence", 8532.48, txn); @@ -60,7 +60,7 @@ TEST_F(StorageTransactionsTest, Adding) { EXPECT_EQ(t1->count(), 3); EXPECT_EQ(t1->getRecord(5), 13); EXPECT_EQ(t1->getRecord(-53), 782); - EXPECT_EQ(t1->getRecord(58392), -37829); + EXPECT_EQ(t1->getRecord(5892), -37829); EXPECT_EQ(t2->count(), 3); EXPECT_FLOAT_EQ(t2->getRecord("lorem"), 481); @@ -74,7 +74,7 @@ TEST_F(StorageTransactionsTest, Aborting) { LMDBAL::SizeType s1 = t1->count(); LMDBAL::SizeType s2 = t2->count(); - LMDBAL::TransactionID txn = t1->beginTransaction(); + LMDBAL::TransactionID txn = db->beginTransaction(); t1->addRecord(18, 40, txn); t1->addRecord(85, -4, txn); t1->addRecord(-5, -3, txn); @@ -86,7 +86,7 @@ TEST_F(StorageTransactionsTest, Aborting) { EXPECT_EQ(t1->count(), s1); EXPECT_EQ(t2->count(), s2); - t1->abortTransaction(txn); + db->abortTransaction(txn); EXPECT_EQ(t1->count(), s1); EXPECT_EQ(t2->count(), s2); @@ -100,7 +100,7 @@ TEST_F(StorageTransactionsTest, Reading) { EXPECT_EQ(t1->count(txn), 3); EXPECT_EQ(t1->getRecord(5, txn), 13); EXPECT_EQ(t1->getRecord(-53, txn), 782); - EXPECT_EQ(t1->getRecord(58392, txn), -37829); + EXPECT_EQ(t1->getRecord(5892, txn), -37829); EXPECT_EQ(t2->count(txn), 3); EXPECT_FLOAT_EQ(t2->getRecord("lorem", txn), 481);