First attempt to make RAII cursors, no tests yet
All checks were successful
Main LMDBAL workfow / Archlinux (push) Successful in 40s
All checks were successful
Main LMDBAL workfow / Archlinux (push) Successful in 40s
This commit is contained in:
parent
a0eebc978d
commit
96d7d9ef64
@ -1,9 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## LMDBAL 0.5.2 (October 21, 2023)
|
||||||
|
### Improvements
|
||||||
|
- RAII cursors
|
||||||
|
|
||||||
## LMDBAL 0.5.1 (October 21, 2023)
|
## LMDBAL 0.5.1 (October 21, 2023)
|
||||||
### Improvements
|
### Improvements
|
||||||
- RAII transactions
|
- RAII transactions
|
||||||
- reduced overhead for private transaction finctions
|
- reduced overhead for private transaction functions
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
- bug fix with cache fallthough
|
- bug fix with cache fallthough
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
project(LMDBAL
|
project(LMDBAL
|
||||||
VERSION 0.5.1
|
VERSION 0.5.2
|
||||||
DESCRIPTION "LMDB (Lightning Memory-Mapped Database Manager) Abstraction Layer"
|
DESCRIPTION "LMDB (Lightning Memory-Mapped Database Manager) Abstraction Layer"
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Maintainer: Yury Gubich <blue@macaw.me>
|
# Maintainer: Yury Gubich <blue@macaw.me>
|
||||||
pkgname=lmdbal
|
pkgname=lmdbal
|
||||||
pkgver=0.5.1
|
pkgver=0.5.2
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="LMDB Abstraction Layer, qt5 version"
|
pkgdesc="LMDB Abstraction Layer, qt5 version"
|
||||||
arch=('i686' 'x86_64')
|
arch=('i686' 'x86_64')
|
||||||
|
46
src/cursor.h
46
src/cursor.h
@ -38,37 +38,49 @@ private:
|
|||||||
openedPrivate /**< - opened with private transaction, only current storage will be notified when cursor is closed*/
|
openedPrivate /**< - opened with private transaction, only current storage will be notified when cursor is closed*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Cursor();
|
||||||
Cursor(Storage<K, V>* parent);
|
Cursor(Storage<K, V>* parent);
|
||||||
|
Cursor(const Cursor& other) = delete;
|
||||||
|
Cursor(Cursor&& other);
|
||||||
~Cursor();
|
~Cursor();
|
||||||
|
|
||||||
public:
|
Cursor& operator = (const Cursor& other) = delete;
|
||||||
void open() const;
|
Cursor& operator = (Cursor&& other);
|
||||||
void open(const Transaction& transaction) const;
|
|
||||||
void renew() const;
|
void open();
|
||||||
void renew(const Transaction& transaction) const;
|
void open(const Transaction& transaction);
|
||||||
void close() const;
|
void renew();
|
||||||
|
void renew(const Transaction& transaction);
|
||||||
|
void close();
|
||||||
bool opened() const;
|
bool opened() const;
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
std::pair<K, V> first() const;
|
void drop();
|
||||||
std::pair<K, V> last() const;
|
|
||||||
std::pair<K, V> next() const;
|
std::pair<K, V> first();
|
||||||
std::pair<K, V> prev() const;
|
std::pair<K, V> last();
|
||||||
|
std::pair<K, V> next();
|
||||||
|
std::pair<K, V> prev();
|
||||||
std::pair<K, V> current() const;
|
std::pair<K, V> current() const;
|
||||||
|
bool set(const K& target);
|
||||||
|
|
||||||
void first(K& key, V& value) const;
|
void first(K& key, V& value);
|
||||||
void last(K& key, V& value) const;
|
void last(K& key, V& value);
|
||||||
void next(K& key, V& value) const;
|
void next(K& key, V& value);
|
||||||
void prev(K& key, V& value) const;
|
void prev(K& key, V& value);
|
||||||
void current(K& key, V& value) const;
|
void current(K& key, V& value) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void terminated() const;
|
void dropped();
|
||||||
|
void terminated();
|
||||||
void operateCursorRead(K& key, V& value, MDB_cursor_op operation, const std::string& methodName, const std::string& operationName) const;
|
void operateCursorRead(K& key, V& value, MDB_cursor_op operation, const std::string& methodName, const std::string& operationName) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Storage<K, V>* storage;
|
Storage<K, V>* storage;
|
||||||
mutable MDB_cursor* cursor;
|
MDB_cursor* cursor;
|
||||||
mutable State state;
|
State state;
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
inline static const std::string openCursorMethodName = "Cursor::open"; /**<\brief member function name, just for exceptions*/
|
inline static const std::string openCursorMethodName = "Cursor::open"; /**<\brief member function name, just for exceptions*/
|
||||||
inline static const std::string closeCursorMethodName = "Cursor::close"; /**<\brief member function name, just for exceptions*/
|
inline static const std::string closeCursorMethodName = "Cursor::close"; /**<\brief member function name, just for exceptions*/
|
||||||
|
168
src/cursor.hpp
168
src/cursor.hpp
@ -41,6 +41,8 @@
|
|||||||
* You are not supposed to instantiate or destory instances of this class yourself!
|
* You are not supposed to instantiate or destory instances of this class yourself!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static uint32_t idCounter = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates a cursor
|
* \brief Creates a cursor
|
||||||
*
|
*
|
||||||
@ -50,9 +52,74 @@ template<class K, class V>
|
|||||||
LMDBAL::Cursor<K, V>::Cursor(Storage<K, V>* parent):
|
LMDBAL::Cursor<K, V>::Cursor(Storage<K, V>* parent):
|
||||||
storage(parent),
|
storage(parent),
|
||||||
cursor(nullptr),
|
cursor(nullptr),
|
||||||
state(closed)
|
state(closed),
|
||||||
|
id(++idCounter)
|
||||||
|
{
|
||||||
|
storage->cursors[id] = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Creates an empty cursor.
|
||||||
|
*
|
||||||
|
* It's not usable, but can exist just to be a target of moves
|
||||||
|
*/
|
||||||
|
template<class K, class V>
|
||||||
|
LMDBAL::Cursor<K, V>::Cursor():
|
||||||
|
storage(nullptr),
|
||||||
|
cursor(nullptr),
|
||||||
|
state(closed),
|
||||||
|
id(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Moves from another cursor
|
||||||
|
*/
|
||||||
|
template<class K, class V>
|
||||||
|
LMDBAL::Cursor<K, V>::Cursor(Cursor&& other):
|
||||||
|
storage(other.storage),
|
||||||
|
cursor(other.cursor),
|
||||||
|
state(other.state),
|
||||||
|
id(other.id)
|
||||||
|
{
|
||||||
|
if (id != 0)
|
||||||
|
storage->cursors[id] = this;
|
||||||
|
|
||||||
|
other.cursor = nullptr;
|
||||||
|
other.storage = nullptr;
|
||||||
|
other.id = 0;
|
||||||
|
other.state = closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A private function that turns cursor into an empty one
|
||||||
|
*
|
||||||
|
* This function is called from LMDBAL::Storage, when it gets destroyed, but still has some valid.
|
||||||
|
* Those cursors will become empty, and can't be used anymore
|
||||||
|
*/
|
||||||
|
template<class K, class V>
|
||||||
|
LMDBAL::Cursor<K, V>& LMDBAL::Cursor<K, V>::operator = (Cursor&& other) {
|
||||||
|
terminated();
|
||||||
|
|
||||||
|
if (id != 0)
|
||||||
|
storage->cursors.erase(id);
|
||||||
|
|
||||||
|
storage = other.storage;
|
||||||
|
cursor = other.cursor;
|
||||||
|
state = other.state;
|
||||||
|
id = other.id;
|
||||||
|
|
||||||
|
if (id != 0) {
|
||||||
|
other.cursor = nullptr;
|
||||||
|
other.storage = nullptr;
|
||||||
|
other.id = 0;
|
||||||
|
other.state = closed;
|
||||||
|
|
||||||
|
storage->cursors[id] = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Destroys a cursor
|
* \brief Destroys a cursor
|
||||||
*
|
*
|
||||||
@ -61,13 +128,58 @@ LMDBAL::Cursor<K, V>::Cursor(Storage<K, V>* parent):
|
|||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
LMDBAL::Cursor<K, V>::~Cursor () {
|
LMDBAL::Cursor<K, V>::~Cursor () {
|
||||||
close();
|
close();
|
||||||
|
|
||||||
|
if (id != 0)
|
||||||
|
storage->cursors.erase(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Turns cursor into an empty one, releasing resources
|
||||||
|
*
|
||||||
|
* This function is called from LMDBAL::Storage, when it gets destroyed, but still has some valid.
|
||||||
|
* Those cursors will become empty, and can't be used anymore
|
||||||
|
*/
|
||||||
|
template<class K, class V>
|
||||||
|
void LMDBAL::Cursor<K, V>::drop () {
|
||||||
|
close();
|
||||||
|
|
||||||
|
if (id != 0)
|
||||||
|
storage->cursors.erase(id);
|
||||||
|
|
||||||
|
cursor = nullptr;
|
||||||
|
storage = nullptr;
|
||||||
|
id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A private method that turns cursor into an empty one
|
||||||
|
*
|
||||||
|
* This function is called from LMDBAL::Storage, when it gets destroyed, but still has some valid.
|
||||||
|
* Those cursors will become empty, and can't be used anymore
|
||||||
|
*/
|
||||||
|
template<class K, class V>
|
||||||
|
void LMDBAL::Cursor<K, V>::dropped () {
|
||||||
|
terminated();
|
||||||
|
cursor = nullptr;
|
||||||
|
storage = nullptr;
|
||||||
|
id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Returns true if the cursor is empty
|
||||||
|
*
|
||||||
|
* Empty cursors can't be used, they can be only targets of move operations
|
||||||
|
*/
|
||||||
|
template<class K, class V>
|
||||||
|
bool LMDBAL::Cursor<K, V>::empty () const {
|
||||||
|
return id == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A private function the storage owning this cursor will call to inform this cursor that the thansaction needs to be aborted
|
* \brief A private function the storage owning this cursor will call to inform this cursor that the thansaction needs to be aborted
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::terminated () const {
|
void LMDBAL::Cursor<K, V>::terminated () {
|
||||||
close(); //for now it's the same, but if I ever going to make writable cursor - here is where it's gonna be different
|
close(); //for now it's the same, but if I ever going to make writable cursor - here is where it's gonna be different
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,11 +192,15 @@ void LMDBAL::Cursor<K, V>::terminated () const {
|
|||||||
* This function should be called when the LMDBAL::Storage is already opened and before any query with this cursor!
|
* This function should be called when the LMDBAL::Storage is already opened and before any query with this cursor!
|
||||||
* It will do nothing to a cursor that was already opened (no matter what way).
|
* It will do nothing to a cursor that was already opened (no matter what way).
|
||||||
*
|
*
|
||||||
* \exception LMDBAL::Closed thrown if you try to open the cursor on a closed database
|
* \exception LMDBAL::Closed thrown if you try to open the cursor on a closed database
|
||||||
* \exception LMDBAL::Unknown thrown if there was a problem opening the cursor by the lmdb, or to begin a transaction
|
* \exception LMDBAL::Unknown thrown if there was a problem opening the cursor by the lmdb, or to begin a transaction
|
||||||
|
* \exception LMDBAL::CursorEmpty thrown if the cursor was empty
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::open () const {
|
void LMDBAL::Cursor<K, V>::open () {
|
||||||
|
if (empty())
|
||||||
|
throw CursorEmpty(openCursorMethodName);
|
||||||
|
|
||||||
storage->ensureOpened(openCursorMethodName);
|
storage->ensureOpened(openCursorMethodName);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case closed: {
|
case closed: {
|
||||||
@ -115,9 +231,13 @@ void LMDBAL::Cursor<K, V>::open () const {
|
|||||||
* \exception LMDBAL::Closed thrown if you try to open the cursor on a closed database
|
* \exception LMDBAL::Closed thrown if you try to open the cursor on a closed database
|
||||||
* \exception LMDBAL::Unknown thrown if there was a problem opening the cursor by the lmdb
|
* \exception LMDBAL::Unknown thrown if there was a problem opening the cursor by the lmdb
|
||||||
* \exception LMDBAL::TransactionTerminated thrown if the passed transaction not active, any action with it's inner ID is an error
|
* \exception LMDBAL::TransactionTerminated thrown if the passed transaction not active, any action with it's inner ID is an error
|
||||||
|
* \exception LMDBAL::CursorEmpty thrown if the cursor was empty
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::open (const Transaction& transaction) const {
|
void LMDBAL::Cursor<K, V>::open (const Transaction& transaction) {
|
||||||
|
if (empty())
|
||||||
|
throw CursorEmpty(openCursorMethodName);
|
||||||
|
|
||||||
storage->ensureOpened(openCursorMethodName);
|
storage->ensureOpened(openCursorMethodName);
|
||||||
TransactionID txn = storage->extractTransactionId(transaction, openCursorMethodName);
|
TransactionID txn = storage->extractTransactionId(transaction, openCursorMethodName);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -146,11 +266,15 @@ void LMDBAL::Cursor<K, V>::open (const Transaction& transaction) const {
|
|||||||
*
|
*
|
||||||
* This function does nothing if the cursor is closed
|
* This function does nothing if the cursor is closed
|
||||||
*
|
*
|
||||||
* \exception LMDBAL::Closed thrown if you try to renew the cursor on a closed database
|
* \exception LMDBAL::Closed thrown if you try to renew the cursor on a closed database
|
||||||
* \exception LMDBAL::Unknown thrown if there was a problem beginning new transaction or if there was a problem renewing the cursor by lmdb
|
* \exception LMDBAL::Unknown thrown if there was a problem beginning new transaction or if there was a problem renewing the cursor by lmdb
|
||||||
|
* \exception LMDBAL::CursorEmpty thrown if the cursor was empty
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::renew () const {
|
void LMDBAL::Cursor<K, V>::renew () {
|
||||||
|
if (empty())
|
||||||
|
throw CursorEmpty(openCursorMethodName);
|
||||||
|
|
||||||
storage->ensureOpened(renewCursorMethodName);
|
storage->ensureOpened(renewCursorMethodName);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case openedPrivate: {
|
case openedPrivate: {
|
||||||
@ -191,9 +315,13 @@ void LMDBAL::Cursor<K, V>::renew () const {
|
|||||||
* \exception LMDBAL::Closed thrown if you try to renew the cursor on a closed database
|
* \exception LMDBAL::Closed thrown if you try to renew the cursor on a closed database
|
||||||
* \exception LMDBAL::Unknown thrown if there was a problem renewing the cursor by lmdb
|
* \exception LMDBAL::Unknown thrown if there was a problem renewing the cursor by lmdb
|
||||||
* \exception LMDBAL::TransactionTerminated thrown if the passed transaction not active, any action with it's inner ID is an error
|
* \exception LMDBAL::TransactionTerminated thrown if the passed transaction not active, any action with it's inner ID is an error
|
||||||
|
* \exception LMDBAL::CursorEmpty thrown if the cursor was empty
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::renew (const Transaction& transaction) const {
|
void LMDBAL::Cursor<K, V>::renew (const Transaction& transaction) {
|
||||||
|
if (empty())
|
||||||
|
throw CursorEmpty(openCursorMethodName);
|
||||||
|
|
||||||
storage->ensureOpened(renewCursorMethodName);
|
storage->ensureOpened(renewCursorMethodName);
|
||||||
TransactionID txn = storage->extractTransactionId(transaction, renewCursorMethodName);
|
TransactionID txn = storage->extractTransactionId(transaction, renewCursorMethodName);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -226,7 +354,7 @@ void LMDBAL::Cursor<K, V>::renew (const Transaction& transaction) const {
|
|||||||
* This function does nothing on a closed cursor.
|
* This function does nothing on a closed cursor.
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::close () const {
|
void LMDBAL::Cursor<K, V>::close () {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case openedPublic: {
|
case openedPublic: {
|
||||||
mdb_cursor_close(cursor);
|
mdb_cursor_close(cursor);
|
||||||
@ -267,7 +395,7 @@ bool LMDBAL::Cursor<K, V>::opened () const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::first (K& key, V& value) const {
|
void LMDBAL::Cursor<K, V>::first (K& key, V& value) {
|
||||||
operateCursorRead(key, value, MDB_FIRST, firstMethodName, firstOperationName);
|
operateCursorRead(key, value, MDB_FIRST, firstMethodName, firstOperationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +412,7 @@ void LMDBAL::Cursor<K, V>::first (K& key, V& value) const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::last (K& key, V& value) const {
|
void LMDBAL::Cursor<K, V>::last (K& key, V& value) {
|
||||||
operateCursorRead(key, value, MDB_LAST, lastMethodName, lastOperationName);
|
operateCursorRead(key, value, MDB_LAST, lastMethodName, lastOperationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +435,7 @@ void LMDBAL::Cursor<K, V>::last (K& key, V& value) const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::next (K& key, V& value) const {
|
void LMDBAL::Cursor<K, V>::next (K& key, V& value) {
|
||||||
operateCursorRead(key, value, MDB_NEXT, nextMethodName, nextOperationName);
|
operateCursorRead(key, value, MDB_NEXT, nextMethodName, nextOperationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +458,7 @@ void LMDBAL::Cursor<K, V>::next (K& key, V& value) const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::prev (K& key, V& value) const {
|
void LMDBAL::Cursor<K, V>::prev (K& key, V& value) {
|
||||||
operateCursorRead(key, value, MDB_PREV, prevMethodName, prevOperationName);
|
operateCursorRead(key, value, MDB_PREV, prevMethodName, prevOperationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +477,7 @@ void LMDBAL::Cursor<K, V>::prev (K& key, V& value) const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Cursor<K, V>::current (K& key, V& value) const {
|
void LMDBAL::Cursor<K, V>::current (K& key, V& value) const {
|
||||||
operateCursorRead(key, value, MDB_GET_CURRENT, currentMethodName, currentOperationName);
|
operateCursorRead(key, value, MDB_GET_CURRENT, currentMethodName, currentOperationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,7 +493,7 @@ void LMDBAL::Cursor<K, V>::current (K& key, V& value) const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
std::pair<K, V> LMDBAL::Cursor<K, V>::first () const {
|
std::pair<K, V> LMDBAL::Cursor<K, V>::first () {
|
||||||
std::pair<K, V> result;
|
std::pair<K, V> result;
|
||||||
operateCursorRead(result.first, result.second, MDB_FIRST, firstMethodName, firstOperationName);
|
operateCursorRead(result.first, result.second, MDB_FIRST, firstMethodName, firstOperationName);
|
||||||
return result;
|
return result;
|
||||||
@ -383,7 +511,7 @@ std::pair<K, V> LMDBAL::Cursor<K, V>::first () const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
std::pair<K, V> LMDBAL::Cursor<K, V>::last () const {
|
std::pair<K, V> LMDBAL::Cursor<K, V>::last () {
|
||||||
std::pair<K, V> result;
|
std::pair<K, V> result;
|
||||||
operateCursorRead(result.first, result.second, MDB_LAST, lastMethodName, lastOperationName);
|
operateCursorRead(result.first, result.second, MDB_LAST, lastMethodName, lastOperationName);
|
||||||
return result;
|
return result;
|
||||||
@ -407,7 +535,7 @@ std::pair<K, V> LMDBAL::Cursor<K, V>::last () const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
std::pair<K, V> LMDBAL::Cursor<K, V>::next () const {
|
std::pair<K, V> LMDBAL::Cursor<K, V>::next () {
|
||||||
std::pair<K, V> result;
|
std::pair<K, V> result;
|
||||||
operateCursorRead(result.first, result.second, MDB_NEXT, nextMethodName, nextOperationName);
|
operateCursorRead(result.first, result.second, MDB_NEXT, nextMethodName, nextOperationName);
|
||||||
return result;
|
return result;
|
||||||
@ -431,7 +559,7 @@ std::pair<K, V> LMDBAL::Cursor<K, V>::next () const {
|
|||||||
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
* \exception LMDBAL::Unknown thrown if there was some unexpected problem with lmdb
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
std::pair<K, V> LMDBAL::Cursor<K, V>::prev () const {
|
std::pair<K, V> LMDBAL::Cursor<K, V>::prev () {
|
||||||
std::pair<K, V> result;
|
std::pair<K, V> result;
|
||||||
operateCursorRead(result.first, result.second, MDB_PREV, prevMethodName, prevOperationName);
|
operateCursorRead(result.first, result.second, MDB_PREV, prevMethodName, prevOperationName);
|
||||||
return result;
|
return result;
|
||||||
|
@ -72,6 +72,14 @@ std::string LMDBAL::CursorNotReady::getMessage() const {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LMDBAL::CursorEmpty::CursorEmpty(const std::string & operation):
|
||||||
|
Exception(),
|
||||||
|
operation(operation) {}
|
||||||
|
|
||||||
|
std::string LMDBAL::CursorEmpty::getMessage() const {
|
||||||
|
return "An attempt to perform an operation \"" + operation + "\" on an empty cursor";
|
||||||
|
}
|
||||||
|
|
||||||
LMDBAL::Opened::Opened(const std::string& p_dbName, const std::string& p_action):
|
LMDBAL::Opened::Opened(const std::string& p_dbName, const std::string& p_action):
|
||||||
Exception(),
|
Exception(),
|
||||||
dbName(p_dbName),
|
dbName(p_dbName),
|
||||||
|
@ -97,6 +97,23 @@ private:
|
|||||||
std::string tableName;
|
std::string tableName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Thrown if an empty cursor was somehow operated
|
||||||
|
*/
|
||||||
|
class CursorEmpty : public Exception {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* \brief Creates exception
|
||||||
|
*
|
||||||
|
* \param operation - text name of the method that was called on an empty cursor
|
||||||
|
*/
|
||||||
|
CursorEmpty(const std::string& operation);
|
||||||
|
|
||||||
|
std::string getMessage() const;
|
||||||
|
private:
|
||||||
|
std::string operation;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Thrown if something in the database was called on opened state and it is not supported
|
* \brief Thrown if something in the database was called on opened state and it is not supported
|
||||||
*/
|
*/
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
class BaseTest;
|
class BaseTest;
|
||||||
class DuplicatesTest;
|
class DuplicatesTest;
|
||||||
|
class CacheCursorTest;
|
||||||
|
class StorageCursorTest;
|
||||||
|
|
||||||
namespace LMDBAL {
|
namespace LMDBAL {
|
||||||
|
|
||||||
@ -113,6 +115,8 @@ template <class K, class V>
|
|||||||
class Storage : public iStorage {
|
class Storage : public iStorage {
|
||||||
friend class ::BaseTest;
|
friend class ::BaseTest;
|
||||||
friend class ::DuplicatesTest;
|
friend class ::DuplicatesTest;
|
||||||
|
friend class ::CacheCursorTest;
|
||||||
|
friend class ::StorageCursorTest;
|
||||||
friend class Base;
|
friend class Base;
|
||||||
friend class Cursor<K, V>;
|
friend class Cursor<K, V>;
|
||||||
protected:
|
protected:
|
||||||
@ -160,13 +164,13 @@ public:
|
|||||||
virtual uint32_t addRecords(const std::map<K, V>& data, bool overwrite = false);
|
virtual uint32_t addRecords(const std::map<K, V>& data, bool overwrite = false);
|
||||||
virtual uint32_t addRecords(const std::map<K, V>& data, const WriteTransaction& txn, bool overwrite = false);
|
virtual uint32_t addRecords(const std::map<K, V>& data, const WriteTransaction& txn, bool overwrite = false);
|
||||||
|
|
||||||
Cursor<K, V>* createCursor();
|
Cursor<K, V> createCursor();
|
||||||
void destroyCursor(Cursor<K, V>* cursor);
|
void destroyCursor(Cursor<K, V>& cursor);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable Serializer<K> keySerializer; /**<\brief internal object that would serialize and deserialize keys*/
|
mutable Serializer<K> keySerializer; /**<\brief internal object that would serialize and deserialize keys*/
|
||||||
mutable Serializer<V> valueSerializer; /**<\brief internal object that would serialize and deserialize values*/
|
mutable Serializer<V> valueSerializer; /**<\brief internal object that would serialize and deserialize values*/
|
||||||
std::set<Cursor<K, V>*> cursors; /**<\brief a set of cursors that has been created under this storage*/
|
std::map<uint32_t, Cursor<K, V>*> cursors; /**<\brief a set of cursors that has been created under this storage*/
|
||||||
|
|
||||||
int open(MDB_txn* transaction) override;
|
int open(MDB_txn* transaction) override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
@ -58,8 +58,8 @@ LMDBAL::Storage<K, V>::Storage(Base* parent, const std::string& name, bool dupli
|
|||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
LMDBAL::Storage<K, V>::~Storage() {
|
LMDBAL::Storage<K, V>::~Storage() {
|
||||||
for (Cursor<K, V>* cursor : cursors)
|
for (const std::pair<const uint32_t, Cursor<K, V>*>& pair : cursors)
|
||||||
delete cursor;
|
pair.second->dropped();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1013,8 +1013,8 @@ int LMDBAL::Storage<K, V>::open(MDB_txn* transaction) {
|
|||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void LMDBAL::Storage<K, V>::close() {
|
void LMDBAL::Storage<K, V>::close() {
|
||||||
for (Cursor<K, V>* cursor : cursors)
|
for (const std::pair<const uint32_t, Cursor<K, V>*>& pair : cursors)
|
||||||
cursor->terminated();
|
pair.second->terminated();
|
||||||
|
|
||||||
iStorage::close();
|
iStorage::close();
|
||||||
}
|
}
|
||||||
@ -1025,11 +1025,8 @@ void LMDBAL::Storage<K, V>::close() {
|
|||||||
* \returns LMDBAL::Cursor for this storage and returs you a pointer to a created cursor
|
* \returns LMDBAL::Cursor for this storage and returs you a pointer to a created cursor
|
||||||
*/
|
*/
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
LMDBAL::Cursor<K, V>* LMDBAL::Storage<K, V>::createCursor() {
|
LMDBAL::Cursor<K, V> LMDBAL::Storage<K, V>::createCursor() {
|
||||||
Cursor<K, V>* cursor = new Cursor<K, V>(this);
|
return Cursor<K, V>(this);
|
||||||
cursors.insert(cursor);
|
|
||||||
|
|
||||||
return cursor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1056,25 +1053,6 @@ uint32_t LMDBAL::Storage<K, V>::flags() const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Destroys cursor
|
|
||||||
*
|
|
||||||
* This a normal way to discard a cursor you don't need anymore
|
|
||||||
*
|
|
||||||
* \param[in] cursor a pointer to a cursor you want to destroy
|
|
||||||
*
|
|
||||||
* \exception LMDBAL::Unknown thrown if you try to destroy something that this storage didn't create
|
|
||||||
*/
|
|
||||||
template<class K, class V>
|
|
||||||
void LMDBAL::Storage<K, V>::destroyCursor(Cursor<K, V>* cursor) {
|
|
||||||
typename std::set<Cursor<K, V>*>::const_iterator itr = cursors.find(cursor);
|
|
||||||
if (itr == cursors.end())
|
|
||||||
throwUnknown("An attempt to destroy a cursor the storage doesn't own");
|
|
||||||
|
|
||||||
cursors.erase(itr);
|
|
||||||
delete cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A private virtual method that cursor calls when he reads a record, does nothing here but populates the LMDBAL::Cache
|
* \brief A private virtual method that cursor calls when he reads a record, does nothing here but populates the LMDBAL::Cache
|
||||||
*
|
*
|
||||||
|
@ -29,13 +29,10 @@ protected:
|
|||||||
db->removeDirectory();
|
db->removeDirectory();
|
||||||
delete db;
|
delete db;
|
||||||
db = nullptr;
|
db = nullptr;
|
||||||
cursor = nullptr;
|
|
||||||
emptyCursor = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static LMDBAL::Base* db;
|
static LMDBAL::Base* db;
|
||||||
static LMDBAL::Cursor<uint64_t, std::string>* cursor;
|
static LMDBAL::Cursor<uint64_t, std::string> cursor;
|
||||||
static LMDBAL::Cursor<uint64_t, std::string>* emptyCursor;
|
|
||||||
static LMDBAL::Transaction transaction;
|
static LMDBAL::Transaction transaction;
|
||||||
|
|
||||||
LMDBAL::Cache<uint64_t, std::string>* cache;
|
LMDBAL::Cache<uint64_t, std::string>* cache;
|
||||||
@ -43,8 +40,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
LMDBAL::Base* CacheCursorTest::db = nullptr;
|
LMDBAL::Base* CacheCursorTest::db = nullptr;
|
||||||
LMDBAL::Cursor<uint64_t, std::string>* CacheCursorTest::cursor = nullptr;
|
LMDBAL::Cursor<uint64_t, std::string> CacheCursorTest::cursor;
|
||||||
LMDBAL::Cursor<uint64_t, std::string>* CacheCursorTest::emptyCursor = nullptr;
|
|
||||||
LMDBAL::Transaction CacheCursorTest::transaction;
|
LMDBAL::Transaction CacheCursorTest::transaction;
|
||||||
|
|
||||||
static const std::map<uint64_t, std::string> data({
|
static const std::map<uint64_t, std::string> data({
|
||||||
@ -67,21 +63,20 @@ TEST_F(CacheCursorTest, PopulatingTheTable) {
|
|||||||
|
|
||||||
TEST_F(CacheCursorTest, Creation) {
|
TEST_F(CacheCursorTest, Creation) {
|
||||||
cursor = cache->createCursor();
|
cursor = cache->createCursor();
|
||||||
emptyCursor = emptyCache->createCursor();
|
|
||||||
|
|
||||||
EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.first(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.last(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.next(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.prev(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.current(), LMDBAL::CursorNotReady);
|
||||||
|
|
||||||
cursor->open();
|
cursor.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, FirstPrivate) {
|
TEST_F(CacheCursorTest, FirstPrivate) {
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -94,16 +89,16 @@ TEST_F(CacheCursorTest, NextPrivate) {
|
|||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.end(); ++reference) {
|
for (; reference != data.end(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->next();
|
std::pair<uint64_t, std::string> element = cursor.next();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
reference = data.begin();
|
reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -114,7 +109,7 @@ TEST_F(CacheCursorTest, NextPrivate) {
|
|||||||
TEST_F(CacheCursorTest, LastPrivate) {
|
TEST_F(CacheCursorTest, LastPrivate) {
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->last();
|
std::pair<uint64_t, std::string> element = cursor.last();
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -127,16 +122,16 @@ TEST_F(CacheCursorTest, PrevPrivate) {
|
|||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.rend(); ++reference) {
|
for (; reference != data.rend(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->prev();
|
std::pair<uint64_t, std::string> element = cursor.prev();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->last();
|
std::pair<uint64_t, std::string> element = cursor.last();
|
||||||
reference = data.rbegin();
|
reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -145,29 +140,29 @@ TEST_F(CacheCursorTest, PrevPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, CurrentPrivate) {
|
TEST_F(CacheCursorTest, CurrentPrivate) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor->next();
|
cursor.next();
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
++reference;
|
++reference;
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor->next();
|
cursor.next();
|
||||||
cursor->next();
|
cursor.next();
|
||||||
cursor->prev();
|
cursor.prev();
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
++reference;
|
++reference;
|
||||||
++reference;
|
++reference;
|
||||||
--reference;
|
--reference;
|
||||||
@ -178,16 +173,15 @@ TEST_F(CacheCursorTest, CurrentPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, Destruction) {
|
TEST_F(CacheCursorTest, Destruction) {
|
||||||
cursor->close();
|
cursor.close();
|
||||||
|
|
||||||
EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.first(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.last(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.next(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.prev(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.current(), LMDBAL::CursorNotReady);
|
||||||
|
|
||||||
EXPECT_THROW(emptyCache->destroyCursor(cursor), LMDBAL::Unknown);
|
cursor = LMDBAL::Cursor<uint64_t, std::string>();
|
||||||
cache->destroyCursor(cursor);
|
|
||||||
|
|
||||||
cursor = cache->createCursor();
|
cursor = cache->createCursor();
|
||||||
}
|
}
|
||||||
@ -195,8 +189,8 @@ TEST_F(CacheCursorTest, Destruction) {
|
|||||||
TEST_F(CacheCursorTest, FirstPublic) {
|
TEST_F(CacheCursorTest, FirstPublic) {
|
||||||
transaction = db->beginTransaction();
|
transaction = db->beginTransaction();
|
||||||
|
|
||||||
cursor->open(transaction);
|
cursor.open(transaction);
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -209,16 +203,16 @@ TEST_F(CacheCursorTest, NextPublic) {
|
|||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.end(); ++reference) {
|
for (; reference != data.end(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->next();
|
std::pair<uint64_t, std::string> element = cursor.next();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
reference = data.begin();
|
reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -226,7 +220,7 @@ TEST_F(CacheCursorTest, NextPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, LastPublic) {
|
TEST_F(CacheCursorTest, LastPublic) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->last();
|
std::pair<uint64_t, std::string> element = cursor.last();
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -239,15 +233,15 @@ TEST_F(CacheCursorTest, PrevPublic) {
|
|||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.rend(); ++reference) {
|
for (; reference != data.rend(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->prev();
|
std::pair<uint64_t, std::string> element = cursor.prev();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->last();
|
std::pair<uint64_t, std::string> element = cursor.last();
|
||||||
reference = data.rbegin();
|
reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -256,29 +250,29 @@ TEST_F(CacheCursorTest, PrevPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CacheCursorTest, CurrentPublic) {
|
TEST_F(CacheCursorTest, CurrentPublic) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
EXPECT_EQ(cache->count(), data.size());
|
EXPECT_EQ(cache->count(), data.size());
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor->next();
|
cursor.next();
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
++reference;
|
++reference;
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor->next();
|
cursor.next();
|
||||||
cursor->next();
|
cursor.next();
|
||||||
cursor->prev();
|
cursor.prev();
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
++reference;
|
++reference;
|
||||||
++reference;
|
++reference;
|
||||||
--reference;
|
--reference;
|
||||||
@ -290,38 +284,39 @@ TEST_F(CacheCursorTest, CurrentPublic) {
|
|||||||
|
|
||||||
TEST_F(CacheCursorTest, CornerCases) {
|
TEST_F(CacheCursorTest, CornerCases) {
|
||||||
transaction.terminate();
|
transaction.terminate();
|
||||||
EXPECT_THROW(cursor->current(), LMDBAL::Unknown);
|
EXPECT_THROW(cursor.current(), LMDBAL::Unknown);
|
||||||
cursor->close();
|
cursor.close();
|
||||||
|
|
||||||
emptyCursor->open();
|
LMDBAL::Cursor<uint64_t, std::string> emptyCursor = emptyCache->createCursor();
|
||||||
EXPECT_THROW(emptyCursor->first(), LMDBAL::NotFound);
|
emptyCursor.open();
|
||||||
EXPECT_THROW(emptyCursor->last(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor.first(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor->next(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor.last(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor->prev(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor.next(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor->current(), LMDBAL::Unknown);
|
EXPECT_THROW(emptyCursor.prev(), LMDBAL::NotFound);
|
||||||
emptyCursor->close();
|
EXPECT_THROW(emptyCursor.current(), LMDBAL::Unknown);
|
||||||
|
emptyCursor.close();
|
||||||
|
|
||||||
cursor->open();
|
cursor.open();
|
||||||
EXPECT_THROW(cursor->current(), LMDBAL::Unknown); //yeah, nice thing to write in the doc
|
EXPECT_THROW(cursor.current(), LMDBAL::Unknown); //yeah, nice thing to write in the doc
|
||||||
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator breference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator breference = data.rbegin();
|
||||||
std::pair<uint64_t, std::string> element(cursor->prev());
|
std::pair<uint64_t, std::string> element(cursor.prev());
|
||||||
EXPECT_EQ(element.first, breference->first); //nice thing to write in the doc, again!
|
EXPECT_EQ(element.first, breference->first); //nice thing to write in the doc, again!
|
||||||
EXPECT_EQ(element.second, breference->second);
|
EXPECT_EQ(element.second, breference->second);
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
EXPECT_EQ(element.first, breference->first);
|
EXPECT_EQ(element.first, breference->first);
|
||||||
EXPECT_EQ(element.second, breference->second);
|
EXPECT_EQ(element.second, breference->second);
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
||||||
cursor->close();
|
cursor.close();
|
||||||
|
|
||||||
cursor->open();
|
cursor.open();
|
||||||
element = cursor->next();
|
element = cursor.next();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,15 +337,15 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
|
|
||||||
std::map<int16_t, uint16_t> m1;
|
std::map<int16_t, uint16_t> m1;
|
||||||
std::set<int16_t> k1;
|
std::set<int16_t> k1;
|
||||||
LMDBAL::Cursor<int16_t, uint16_t>* c1 = tu1->createCursor();
|
LMDBAL::Cursor<int16_t, uint16_t> c1 = tu1->createCursor();
|
||||||
tu1->readAll(m1, txn);
|
tu1->readAll(m1, txn);
|
||||||
c1->open(txn);
|
c1.open(txn);
|
||||||
|
|
||||||
cycle = false;
|
cycle = false;
|
||||||
iterations = 0;
|
iterations = 0;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
std::pair<int16_t, uint16_t> pair = c1->next();
|
std::pair<int16_t, uint16_t> pair = c1.next();
|
||||||
cycle = true;
|
cycle = true;
|
||||||
std::pair<std::set<int16_t>::const_iterator, bool> probe = k1.insert(pair.first);
|
std::pair<std::set<int16_t>::const_iterator, bool> probe = k1.insert(pair.first);
|
||||||
if (probe.second) {
|
if (probe.second) {
|
||||||
@ -359,25 +359,25 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
cycle = false;
|
cycle = false;
|
||||||
}
|
}
|
||||||
} while (cycle);
|
} while (cycle);
|
||||||
tu1->destroyCursor(c1);
|
|
||||||
|
|
||||||
EXPECT_EQ(iterations, tu1->count(txn));
|
EXPECT_EQ(iterations, tu1->count(txn));
|
||||||
EXPECT_EQ(k1.size(), m1.size());
|
EXPECT_EQ(k1.size(), m1.size());
|
||||||
EXPECT_NE(iterations, 0);
|
EXPECT_NE(iterations, 0);
|
||||||
EXPECT_NE(k1.size(), 0);
|
EXPECT_NE(k1.size(), 0);
|
||||||
|
c1.drop();
|
||||||
|
|
||||||
|
|
||||||
std::map<std::string, int8_t> m2;
|
std::map<std::string, int8_t> m2;
|
||||||
std::set<std::string> k2;
|
std::set<std::string> k2;
|
||||||
LMDBAL::Cursor<std::string, int8_t>* c2 = tu2->createCursor();
|
LMDBAL::Cursor<std::string, int8_t> c2 = tu2->createCursor();
|
||||||
tu2->readAll(m2, txn);
|
tu2->readAll(m2, txn);
|
||||||
c2->open(txn);
|
c2.open(txn);
|
||||||
|
|
||||||
cycle = false;
|
cycle = false;
|
||||||
iterations = 0;
|
iterations = 0;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
std::pair<std::string, int8_t> pair = c2->next();
|
std::pair<std::string, int8_t> pair = c2.next();
|
||||||
cycle = true;
|
cycle = true;
|
||||||
std::pair<std::set<std::string>::const_iterator, bool> probe = k2.insert(pair.first);
|
std::pair<std::set<std::string>::const_iterator, bool> probe = k2.insert(pair.first);
|
||||||
if (probe.second) {
|
if (probe.second) {
|
||||||
@ -391,25 +391,25 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
cycle = false;
|
cycle = false;
|
||||||
}
|
}
|
||||||
} while (cycle);
|
} while (cycle);
|
||||||
tu2->destroyCursor(c2);
|
|
||||||
|
|
||||||
EXPECT_EQ(iterations, tu2->count(txn));
|
EXPECT_EQ(iterations, tu2->count(txn));
|
||||||
EXPECT_EQ(k2.size(), m2.size());
|
EXPECT_EQ(k2.size(), m2.size());
|
||||||
EXPECT_NE(iterations, 0);
|
EXPECT_NE(iterations, 0);
|
||||||
EXPECT_NE(k2.size(), 0);
|
EXPECT_NE(k2.size(), 0);
|
||||||
|
c2.drop();
|
||||||
|
|
||||||
|
|
||||||
std::map<float, float> m3;
|
std::map<float, float> m3;
|
||||||
std::set<float> k3;
|
std::set<float> k3;
|
||||||
LMDBAL::Cursor<float, float>* c3 = tu3->createCursor();
|
LMDBAL::Cursor<float, float> c3 = tu3->createCursor();
|
||||||
tu3->readAll(m3, txn);
|
tu3->readAll(m3, txn);
|
||||||
c3->open(txn);
|
c3.open(txn);
|
||||||
|
|
||||||
cycle = false;
|
cycle = false;
|
||||||
iterations = 0;
|
iterations = 0;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
std::pair<float, float> pair = c3->next();
|
std::pair<float, float> pair = c3.next();
|
||||||
cycle = true;
|
cycle = true;
|
||||||
std::pair<std::set<float>::const_iterator, bool> probe = k3.insert(pair.first);
|
std::pair<std::set<float>::const_iterator, bool> probe = k3.insert(pair.first);
|
||||||
if (probe.second) {
|
if (probe.second) {
|
||||||
@ -423,25 +423,25 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
cycle = false;
|
cycle = false;
|
||||||
}
|
}
|
||||||
} while (cycle);
|
} while (cycle);
|
||||||
tu3->destroyCursor(c3);
|
|
||||||
|
|
||||||
EXPECT_EQ(iterations, tu3->count(txn));
|
EXPECT_EQ(iterations, tu3->count(txn));
|
||||||
EXPECT_EQ(k3.size(), m3.size());
|
EXPECT_EQ(k3.size(), m3.size());
|
||||||
EXPECT_NE(iterations, 0);
|
EXPECT_NE(iterations, 0);
|
||||||
EXPECT_NE(k3.size(), 0);
|
EXPECT_NE(k3.size(), 0);
|
||||||
|
c3.drop();
|
||||||
|
|
||||||
|
|
||||||
std::map<uint16_t, double> m4;
|
std::map<uint16_t, double> m4;
|
||||||
std::set<uint16_t> k4;
|
std::set<uint16_t> k4;
|
||||||
LMDBAL::Cursor<uint16_t, double>* c4 = tu4->createCursor();
|
LMDBAL::Cursor<uint16_t, double> c4 = tu4->createCursor();
|
||||||
tu4->readAll(m4, txn);
|
tu4->readAll(m4, txn);
|
||||||
c4->open(txn);
|
c4.open(txn);
|
||||||
|
|
||||||
cycle = false;
|
cycle = false;
|
||||||
iterations = 0;
|
iterations = 0;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
std::pair<uint16_t, double> pair = c4->next();
|
std::pair<uint16_t, double> pair = c4.next();
|
||||||
cycle = true;
|
cycle = true;
|
||||||
std::pair<std::set<uint16_t>::const_iterator, bool> probe = k4.insert(pair.first);
|
std::pair<std::set<uint16_t>::const_iterator, bool> probe = k4.insert(pair.first);
|
||||||
if (probe.second) {
|
if (probe.second) {
|
||||||
@ -455,7 +455,7 @@ TEST_F(DuplicatesTest, GettingAllRecords) {
|
|||||||
cycle = false;
|
cycle = false;
|
||||||
}
|
}
|
||||||
} while (cycle);
|
} while (cycle);
|
||||||
tu4->destroyCursor(c4);
|
c4.drop();
|
||||||
|
|
||||||
EXPECT_EQ(iterations, tu4->count(txn));
|
EXPECT_EQ(iterations, tu4->count(txn));
|
||||||
EXPECT_EQ(k4.size(), m4.size());
|
EXPECT_EQ(k4.size(), m4.size());
|
||||||
|
@ -28,13 +28,10 @@ protected:
|
|||||||
db->removeDirectory();
|
db->removeDirectory();
|
||||||
delete db;
|
delete db;
|
||||||
db = nullptr;
|
db = nullptr;
|
||||||
cursor = nullptr;
|
|
||||||
emptyCursor = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static LMDBAL::Base* db;
|
static LMDBAL::Base* db;
|
||||||
static LMDBAL::Cursor<uint64_t, std::string>* cursor;
|
static LMDBAL::Cursor<uint64_t, std::string> cursor;
|
||||||
static LMDBAL::Cursor<uint64_t, std::string>* emptyCursor;
|
|
||||||
static LMDBAL::Transaction transaction;
|
static LMDBAL::Transaction transaction;
|
||||||
|
|
||||||
LMDBAL::Storage<uint64_t, std::string>* table;
|
LMDBAL::Storage<uint64_t, std::string>* table;
|
||||||
@ -42,8 +39,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
LMDBAL::Base* StorageCursorTest::db = nullptr;
|
LMDBAL::Base* StorageCursorTest::db = nullptr;
|
||||||
LMDBAL::Cursor<uint64_t, std::string>* StorageCursorTest::cursor = nullptr;
|
LMDBAL::Cursor<uint64_t, std::string> StorageCursorTest::cursor;
|
||||||
LMDBAL::Cursor<uint64_t, std::string>* StorageCursorTest::emptyCursor = nullptr;
|
|
||||||
LMDBAL::Transaction StorageCursorTest::transaction = LMDBAL::Transaction();
|
LMDBAL::Transaction StorageCursorTest::transaction = LMDBAL::Transaction();
|
||||||
|
|
||||||
static const std::map<uint64_t, std::string> data({
|
static const std::map<uint64_t, std::string> data({
|
||||||
@ -66,19 +62,18 @@ TEST_F(StorageCursorTest, PopulatingTheTable) {
|
|||||||
|
|
||||||
TEST_F(StorageCursorTest, Creation) {
|
TEST_F(StorageCursorTest, Creation) {
|
||||||
cursor = table->createCursor();
|
cursor = table->createCursor();
|
||||||
emptyCursor = emptyTable->createCursor();
|
|
||||||
|
|
||||||
EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.first(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.last(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.next(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.prev(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.current(), LMDBAL::CursorNotReady);
|
||||||
|
|
||||||
cursor->open();
|
cursor.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, FirstPrivate) {
|
TEST_F(StorageCursorTest, FirstPrivate) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -90,14 +85,14 @@ TEST_F(StorageCursorTest, NextPrivate) {
|
|||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.end(); ++reference) {
|
for (; reference != data.end(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->next();
|
std::pair<uint64_t, std::string> element = cursor.next();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
reference = data.begin();
|
reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -105,7 +100,7 @@ TEST_F(StorageCursorTest, NextPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, LastPrivate) {
|
TEST_F(StorageCursorTest, LastPrivate) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->last();
|
std::pair<uint64_t, std::string> element = cursor.last();
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -117,14 +112,14 @@ TEST_F(StorageCursorTest, PrevPrivate) {
|
|||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.rend(); ++reference) {
|
for (; reference != data.rend(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->prev();
|
std::pair<uint64_t, std::string> element = cursor.prev();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->last();
|
std::pair<uint64_t, std::string> element = cursor.last();
|
||||||
reference = data.rbegin();
|
reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -132,28 +127,28 @@ TEST_F(StorageCursorTest, PrevPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, CurrentPrivate) {
|
TEST_F(StorageCursorTest, CurrentPrivate) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor->next();
|
cursor.next();
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
++reference;
|
++reference;
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor->next();
|
cursor.next();
|
||||||
cursor->next();
|
cursor.next();
|
||||||
cursor->prev();
|
cursor.prev();
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
++reference;
|
++reference;
|
||||||
++reference;
|
++reference;
|
||||||
--reference;
|
--reference;
|
||||||
@ -163,16 +158,15 @@ TEST_F(StorageCursorTest, CurrentPrivate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, Destruction) {
|
TEST_F(StorageCursorTest, Destruction) {
|
||||||
cursor->close();
|
cursor.close();
|
||||||
|
|
||||||
EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.first(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.last(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.next(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.prev(), LMDBAL::CursorNotReady);
|
||||||
EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady);
|
EXPECT_THROW(cursor.current(), LMDBAL::CursorNotReady);
|
||||||
|
|
||||||
EXPECT_THROW(emptyTable->destroyCursor(cursor), LMDBAL::Unknown);
|
cursor = LMDBAL::Cursor<uint64_t, std::string>();
|
||||||
table->destroyCursor(cursor);
|
|
||||||
|
|
||||||
cursor = table->createCursor();
|
cursor = table->createCursor();
|
||||||
}
|
}
|
||||||
@ -180,8 +174,8 @@ TEST_F(StorageCursorTest, Destruction) {
|
|||||||
TEST_F(StorageCursorTest, FirstPublic) {
|
TEST_F(StorageCursorTest, FirstPublic) {
|
||||||
transaction = db->beginReadOnlyTransaction();
|
transaction = db->beginReadOnlyTransaction();
|
||||||
|
|
||||||
cursor->open(transaction);
|
cursor.open(transaction);
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -193,14 +187,14 @@ TEST_F(StorageCursorTest, NextPublic) {
|
|||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.end(); ++reference) {
|
for (; reference != data.end(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->next();
|
std::pair<uint64_t, std::string> element = cursor.next();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
reference = data.begin();
|
reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -208,7 +202,7 @@ TEST_F(StorageCursorTest, NextPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, LastPublic) {
|
TEST_F(StorageCursorTest, LastPublic) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->last();
|
std::pair<uint64_t, std::string> element = cursor.last();
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -220,14 +214,14 @@ TEST_F(StorageCursorTest, PrevPublic) {
|
|||||||
|
|
||||||
reference++;
|
reference++;
|
||||||
for (; reference != data.rend(); ++reference) {
|
for (; reference != data.rend(); ++reference) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->prev();
|
std::pair<uint64_t, std::string> element = cursor.prev();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
||||||
|
|
||||||
std::pair<uint64_t, std::string> element = cursor->last();
|
std::pair<uint64_t, std::string> element = cursor.last();
|
||||||
reference = data.rbegin();
|
reference = data.rbegin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
@ -235,28 +229,28 @@ TEST_F(StorageCursorTest, PrevPublic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StorageCursorTest, CurrentPublic) {
|
TEST_F(StorageCursorTest, CurrentPublic) {
|
||||||
std::pair<uint64_t, std::string> element = cursor->first();
|
std::pair<uint64_t, std::string> element = cursor.first();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor->next();
|
cursor.next();
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
++reference;
|
++reference;
|
||||||
|
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
|
|
||||||
cursor->next();
|
cursor.next();
|
||||||
cursor->next();
|
cursor.next();
|
||||||
cursor->prev();
|
cursor.prev();
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
++reference;
|
++reference;
|
||||||
++reference;
|
++reference;
|
||||||
--reference;
|
--reference;
|
||||||
@ -267,37 +261,38 @@ TEST_F(StorageCursorTest, CurrentPublic) {
|
|||||||
|
|
||||||
TEST_F(StorageCursorTest, CornerCases) {
|
TEST_F(StorageCursorTest, CornerCases) {
|
||||||
transaction.terminate();
|
transaction.terminate();
|
||||||
EXPECT_THROW(cursor->current(), LMDBAL::Unknown);
|
EXPECT_THROW(cursor.current(), LMDBAL::Unknown);
|
||||||
cursor->close();
|
cursor.close();
|
||||||
|
|
||||||
emptyCursor->open();
|
LMDBAL::Cursor<uint64_t, std::string> emptyCursor = emptyTable->createCursor();
|
||||||
EXPECT_THROW(emptyCursor->first(), LMDBAL::NotFound);
|
emptyCursor.open();
|
||||||
EXPECT_THROW(emptyCursor->last(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor.first(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor->next(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor.last(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor->prev(), LMDBAL::NotFound);
|
EXPECT_THROW(emptyCursor.next(), LMDBAL::NotFound);
|
||||||
EXPECT_THROW(emptyCursor->current(), LMDBAL::Unknown);
|
EXPECT_THROW(emptyCursor.prev(), LMDBAL::NotFound);
|
||||||
emptyCursor->close();
|
EXPECT_THROW(emptyCursor.current(), LMDBAL::Unknown);
|
||||||
|
emptyCursor.close();
|
||||||
|
|
||||||
cursor->open();
|
cursor.open();
|
||||||
EXPECT_THROW(cursor->current(), LMDBAL::Unknown); //yeah, nice thing to write in the doc
|
EXPECT_THROW(cursor.current(), LMDBAL::Unknown); //yeah, nice thing to write in the doc
|
||||||
|
|
||||||
std::map<uint64_t, std::string>::const_reverse_iterator breference = data.rbegin();
|
std::map<uint64_t, std::string>::const_reverse_iterator breference = data.rbegin();
|
||||||
std::pair<uint64_t, std::string> element(cursor->prev());
|
std::pair<uint64_t, std::string> element(cursor.prev());
|
||||||
EXPECT_EQ(element.first, breference->first); //nice thing to write in the doc, again!
|
EXPECT_EQ(element.first, breference->first); //nice thing to write in the doc, again!
|
||||||
EXPECT_EQ(element.second, breference->second);
|
EXPECT_EQ(element.second, breference->second);
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
EXPECT_EQ(element.first, breference->first);
|
EXPECT_EQ(element.first, breference->first);
|
||||||
EXPECT_EQ(element.second, breference->second);
|
EXPECT_EQ(element.second, breference->second);
|
||||||
EXPECT_THROW(cursor->next(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.next(), LMDBAL::NotFound);
|
||||||
cursor->close();
|
cursor.close();
|
||||||
|
|
||||||
cursor->open();
|
cursor.open();
|
||||||
element = cursor->next();
|
element = cursor.next();
|
||||||
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
std::map<uint64_t, std::string>::const_iterator reference = data.begin();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
element = cursor->current();
|
element = cursor.current();
|
||||||
EXPECT_EQ(element.first, reference->first);
|
EXPECT_EQ(element.first, reference->first);
|
||||||
EXPECT_EQ(element.second, reference->second);
|
EXPECT_EQ(element.second, reference->second);
|
||||||
EXPECT_THROW(cursor->prev(), LMDBAL::NotFound);
|
EXPECT_THROW(cursor.prev(), LMDBAL::NotFound);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user