diff --git a/src/cpp/database/SqliteDatabase.cpp b/src/cpp/database/SqliteDatabase.cpp index ef58f1277..6e78dfb1e 100644 --- a/src/cpp/database/SqliteDatabase.cpp +++ b/src/cpp/database/SqliteDatabase.cpp @@ -19,6 +19,7 @@ using namespace std; SqliteDatabase::SqliteDatabase(const char* host) : Database(host,"",""), mWalQ(NULL), walRunning(false) { mConnection = NULL; + mAuxConnection = NULL; mCurrentStmt = NULL; } @@ -33,10 +34,32 @@ void SqliteDatabase::connect() } } +sqlite3* SqliteDatabase::getAuxConnection() +{ + boost::mutex::scoped_lock sl(walMutex); + if (mAuxConnection == NULL) + { + int rc = sqlite3_open(mHost.c_str(), &mAuxConnection); + if (rc) + { + cLog(lsFATAL) << "Can't aux open " << mHost << " " << rc; + assert((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED)); + if (mAuxConnection != NULL) + { + sqlite3_close(mConnection); + mAuxConnection = NULL; + } + } + } + return mAuxConnection; +} + void SqliteDatabase::disconnect() { sqlite3_finalize(mCurrentStmt); sqlite3_close(mConnection); + if (mAuxConnection != NULL) + sqlite3_close(mAuxConnection); } // returns true if the query went ok @@ -256,18 +279,22 @@ void SqliteDatabase::runWal() } } -SqliteStatement::SqliteStatement(SqliteDatabase* db, const char *sql) +SqliteStatement::SqliteStatement(SqliteDatabase* db, const char *sql, bool aux) { assert(db); - int j = sqlite3_prepare_v2(db->peekConnection(), sql, strlen(sql) + 1, &statement, NULL); + + sqlite3* conn = aux ? db->getAuxConnection() : db->peekConnection(); + int j = sqlite3_prepare_v2(conn, sql, strlen(sql) + 1, &statement, NULL); if (j != SQLITE_OK) throw j; } -SqliteStatement::SqliteStatement(SqliteDatabase* db, const std::string& sql) +SqliteStatement::SqliteStatement(SqliteDatabase* db, const std::string& sql, bool aux) { assert(db); - int j = sqlite3_prepare_v2(db->peekConnection(), sql.c_str(), sql.size() + 1, &statement, NULL); + + sqlite3* conn = aux ? db->getAuxConnection() : db->peekConnection(); + int j = sqlite3_prepare_v2(conn, sql.c_str(), sql.size() + 1, &statement, NULL); if (j != SQLITE_OK) throw j; } diff --git a/src/cpp/database/SqliteDatabase.h b/src/cpp/database/SqliteDatabase.h index 7e6a8c67a..1e675a058 100644 --- a/src/cpp/database/SqliteDatabase.h +++ b/src/cpp/database/SqliteDatabase.h @@ -12,6 +12,7 @@ struct sqlite3_stmt; class SqliteDatabase : public Database { sqlite3* mConnection; + sqlite3* mAuxConnection; sqlite3_stmt* mCurrentStmt; bool mMoreRows; @@ -51,6 +52,7 @@ public: uint64 getBigInt(int colIndex); sqlite3* peekConnection() { return mConnection; } + sqlite3* getAuxConnection(); virtual bool setupCheckpointing(JobQueue*); virtual SqliteDatabase* getSqliteDB() { return this; } @@ -71,8 +73,8 @@ protected: sqlite3_stmt* statement; public: - SqliteStatement(SqliteDatabase* db, const char *statement); - SqliteStatement(SqliteDatabase* db, const std::string& statement); + SqliteStatement(SqliteDatabase* db, const char *statement, bool aux = false); + SqliteStatement(SqliteDatabase* db, const std::string& statement, bool aux = false); ~SqliteStatement(); sqlite3_stmt* peekStatement(); diff --git a/src/cpp/ripple/HashedObject.cpp b/src/cpp/ripple/HashedObject.cpp index b3f4e76d5..95ad26374 100644 --- a/src/cpp/ripple/HashedObject.cpp +++ b/src/cpp/ripple/HashedObject.cpp @@ -94,12 +94,14 @@ void HashedObjectStore::bulkWrite() { Database* db = theApp->getHashNodeDB()->getDB(); - ScopedLock sl(theApp->getHashNodeDB()->getDBLock()); - SqliteStatement pSt(db->getSqliteDB(), + static SqliteStatement pStB(db->getSqliteDB(), "BEGIN TRANSACTION;", true); + static SqliteStatement pStE(db->getSqliteDB(), "END TRANSACTION;", true); + static SqliteStatement pSt(db->getSqliteDB(), "INSERT OR IGNORE INTO CommittedObjects " - "(Hash,ObjType,LedgerIndex,Object) VALUES (?, ?, ?, ?);"); + "(Hash,ObjType,LedgerIndex,Object) VALUES (?, ?, ?, ?);", true); - db->executeSQL("BEGIN TRANSACTION;"); + pStB.step(); + pStB.reset(); BOOST_FOREACH(const boost::shared_ptr& it, set) { @@ -127,7 +129,8 @@ void HashedObjectStore::bulkWrite() pSt.reset(); } - db->executeSQL("END TRANSACTION;"); + pStE.step(); + pStE.reset(); } #else