diff --git a/src/cpp/database/SqliteDatabase.cpp b/src/cpp/database/SqliteDatabase.cpp index 9db0ac3d80..0159212e63 100644 --- a/src/cpp/database/SqliteDatabase.cpp +++ b/src/cpp/database/SqliteDatabase.cpp @@ -1,12 +1,17 @@ #include "SqliteDatabase.h" #include "sqlite3.h" + #include #include #include +#include +#include +#include + using namespace std; -SqliteDatabase::SqliteDatabase(const char* host) : Database(host,"","") +SqliteDatabase::SqliteDatabase(const char* host) : Database(host,"",""), walRunning(false) { mConnection = NULL; mCurrentStmt = NULL; @@ -182,4 +187,56 @@ uint64 SqliteDatabase::getBigInt(int colIndex) return(sqlite3_column_int64(mCurrentStmt, colIndex)); } + +static int SqliteWALHook(void *s, sqlite3* dbCon, const char *dbName, int walSize) +{ + (reinterpret_cast(s))->doHook(dbName, walSize); + return SQLITE_OK; +} + +bool SqliteDatabase::setupCheckpointing() +{ + sqlite3_wal_hook(mConnection, SqliteWALHook, this); + return true; +} + +void SqliteDatabase::doHook(const char *db, int pages) +{ + if (pages < 256) + return; + boost::mutex::scoped_lock sl(walMutex); + if (walDBs.insert(db).second && !walRunning) + { + walRunning = true; + boost::thread(boost::bind(&SqliteDatabase::runWal, this)).detach(); + } +} + +void SqliteDatabase::runWal() +{ + std::set walSet; + + while (1) + { + { + boost::mutex::scoped_lock sl(walMutex); + walDBs.swap(walSet); + if (walSet.empty()) + { + walRunning = false; + return; + } + } + + BOOST_FOREACH(const std::string& db, walSet) + { + int log, ckpt; + sqlite3_wal_checkpoint_v2(mConnection, db.c_str(), SQLITE_CHECKPOINT_PASSIVE, &log, &ckpt); + std::cerr << "Checkpoint " << db << ": " << log << " of " << ckpt << std::endl; + } + walSet.clear(); + + } +} + // vim:ts=4 diff --git a/src/cpp/database/SqliteDatabase.h b/src/cpp/database/SqliteDatabase.h index a3e7d62575..9b99bbf11b 100644 --- a/src/cpp/database/SqliteDatabase.h +++ b/src/cpp/database/SqliteDatabase.h @@ -1,13 +1,24 @@ #include "database.h" +#include +#include + +#include + struct sqlite3; struct sqlite3_stmt; + class SqliteDatabase : public Database { sqlite3* mConnection; sqlite3_stmt* mCurrentStmt; bool mMoreRows; + + boost::mutex walMutex; + std::set walDBs; + bool walRunning; + public: SqliteDatabase(const char* host); @@ -38,6 +49,12 @@ public: int getBinary(int colIndex,unsigned char* buf,int maxSize); std::vector getBinary(int colIndex); uint64 getBigInt(int colIndex); + + sqlite3* peekConnection() { return mConnection; } + virtual bool setupCheckpointing(); + + void runWal(); + void doHook(const char *db, int walSize); }; // vim:ts=4 diff --git a/src/cpp/database/database.h b/src/cpp/database/database.h index 38c946560f..7f9199529f 100644 --- a/src/cpp/database/database.h +++ b/src/cpp/database/database.h @@ -82,6 +82,8 @@ public: // int getSingleDBValueInt(const char* sql); // float getSingleDBValueFloat(const char* sql); // char* getSingleDBValueStr(const char* sql, std::string& retStr); + + virtual bool setupCheckpointing() { return false; } }; #endif diff --git a/src/cpp/ripple/Application.cpp b/src/cpp/ripple/Application.cpp index b3c9c12b7b..6e9043be64 100644 --- a/src/cpp/ripple/Application.cpp +++ b/src/cpp/ripple/Application.cpp @@ -118,6 +118,9 @@ void Application::setup() boost::thread t5(boost::bind(&InitDB, &mHashNodeDB, "hashnode.db", HashNodeDBInit, HashNodeDBCount)); boost::thread t6(boost::bind(&InitDB, &mNetNodeDB, "netnode.db", NetNodeDBInit, NetNodeDBCount)); t1.join(); t2.join(); t3.join(); t4.join(); t5.join(); t6.join(); + mTxnDB->getDB()->setupCheckpointing(); + mLedgerDB->getDB()->setupCheckpointing(); + mHashNodeDB->getDB()->setupCheckpointing(); if (theConfig.START_UP == Config::FRESH) {