#ifndef DATABASE_H #define DATABASE_H #include #include #include #include #include "asynccoordinator.h" struct __db; struct __db_env; struct __dbc; struct __db_dbt; #ifdef QT_DEBUG // test if expanding buffer code works well in tryGetKey() #define DEFAULT_READ_BUFFER_START_SIZE (10) #else #define DEFAULT_READ_BUFFER_START_SIZE (2*1024) #endif namespace Helpers { class Database { public: Database(__db_env *environment, int maxBufferSize=DEFAULT_READ_BUFFER_START_SIZE, AsyncCoordinator *finalizeCoordinator=nullptr); virtual ~Database(); public: class Iterator { friend class Database; public: Iterator(__db *database); virtual ~Iterator(); // disable unwanted behavior Iterator(const Iterator &) = delete; Iterator &operator=(const Iterator &) = delete; public: bool moveNext(); const QByteArray &getCurrentKey() const { return m_KeyBuffer; } const QByteArray &getCurrentValue() const { return m_ValueBuffer; } bool isValid() const { return m_IsValid; } private: void initialize(); bool doMoveNext(); int moveCursor(int keyBufferSize, int valueBufferSize); private: __db *m_Database; __dbc *m_Cursor; __db_dbt *m_CurrentKey; __db_dbt *m_CurrentValue; QByteArray m_KeyBuffer; QByteArray m_ValueBuffer; int m_KeyStartBufferSize; int m_ValueStartBufferSize; volatile bool m_IsValid; volatile bool m_IsInitialized; }; public: bool isOpened() const { return m_IsOpened; } public: bool open(const char *dbName); void close(); void sync(); void warmupCache(int percent = 50); public: bool exists(const QByteArray &key); bool tryGetKey(const QByteArray &key, QByteArray &value); bool trySetKey(const QByteArray &key, const QByteArray &data); bool deleteRecord(const QByteArray &key); std::unique_ptr getIterator(); private: int checkExists(const QByteArray &key); int doGetKey(const QByteArray &key, QByteArray &value, int bufferSize); int doSetKey(const QByteArray &key, const QByteArray &value); int doDeleteRecord(const QByteArray &key); int doWarmupCache(int pagesCount); private: AsyncCoordinator *m_FinalizeCoordinator; __db_env *m_Environment; __db *m_Database; volatile int m_StartValueBufferSize; volatile bool m_IsOpened; }; class DatabaseManager: public QObject { Q_OBJECT public: DatabaseManager(); public: bool initialize(); private: void finalize(); int doInitialize(const QString &dbDirName, bool withRecovery); int closeEnvironment(); public: std::shared_ptr openDatabase(const char *dbName); // should be run from time to time void createCheckpoint(); void prepareToFinalize(); private slots: void onReadyToFinalize(int status); private: void closeAll(); private: AsyncCoordinator m_FinalizeCoordinator; __db_env *m_Environment; QString m_DBDirPath; std::vector > m_DatabaseArray; }; } #endif // DATABASE_H