From 9056c163a738a2f66725ca9a3e48b59b2b0e2603 Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 22 Jun 2014 02:31:24 +0200 Subject: [PATCH] Fix sqlite3 map shutdown fails due to missing to finalize list statement Add error output on fail to shutdown sqlite3 map db Implement shutdown of sqlite3 rollback db --- src/database-sqlite3.cpp | 71 ++++++++++++++++++++++++---------------- src/rollback.cpp | 26 +++++++++++++++ 2 files changed, 69 insertions(+), 28 deletions(-) diff --git a/src/database-sqlite3.cpp b/src/database-sqlite3.cpp index 38fb2ca1..268687c2 100644 --- a/src/database-sqlite3.cpp +++ b/src/database-sqlite3.cpp @@ -20,13 +20,13 @@ with this program; if not, write to the Free Software Foundation, Inc., /* SQLite format specification: - Initially only replaces sectors/ and sectors2/ - + If map.sqlite does not exist in the save dir or the block was not found in the database the map will try to load from sectors folder. In either case, map.sqlite will be created and all future saves will save there. - + Structure of map.sqlite: Tables: blocks @@ -85,27 +85,27 @@ void Database_SQLite3::createDirs(std::string path) void Database_SQLite3::verifyDatabase() { if(m_database) return; - + { std::string dbp = m_savedir + DIR_DELIM + "map.sqlite"; bool needs_create = false; int d; - + /* Open the database connection */ - + createDirs(m_savedir); // ? - + if(!fs::PathExists(dbp)) needs_create = true; - + d = sqlite3_open_v2(dbp.c_str(), &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); if(d != SQLITE_OK) { infostream<<"WARNING: SQLite3 database failed to open: "<getPos(); - - + + #if 0 v2s16 p2d(p3d.X, p3d.Z); std::string sectordir = getSectorDir(p2d); @@ -175,21 +175,21 @@ void Database_SQLite3::saveBlock(MapBlock *block) [0] u8 serialization version [1] data */ - + verifyDatabase(); - + std::ostringstream o(std::ios_base::binary); - + o.write((char*)&version, 1); - + // Write basic data block->serialize(o, version, true); - + // Write block to database - + std::string tmp = o.str(); const char *bytes = tmp.c_str(); - + if(sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK) infostream<<"WARNING: Block position failed to bind: "<resetModified(); } @@ -323,13 +323,13 @@ void Database_SQLite3::createDatabase() throw FileNotGoodException("Could not create sqlite3 database structure"); else infostream<<"ServerMap: SQLite3 database structure was created"; - + } void Database_SQLite3::listAllLoadableBlocks(std::list &dst) { verifyDatabase(); - + while(sqlite3_step(m_database_list) == SQLITE_ROW) { sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0); @@ -339,13 +339,28 @@ void Database_SQLite3::listAllLoadableBlocks(std::list &dst) } } + +#define FINALIZE_STATEMENT(statement) \ + if ( statement ) \ + rc = sqlite3_finalize(statement); \ + if ( rc != SQLITE_OK ) \ + errorstream << "Database_SQLite3::~Database_SQLite3():" \ + << "Failed to finalize: " << #statement << ": rc=" << rc << std::endl; + Database_SQLite3::~Database_SQLite3() { - if(m_database_read) - sqlite3_finalize(m_database_read); - if(m_database_write) - sqlite3_finalize(m_database_write); + int rc = SQLITE_OK; + + FINALIZE_STATEMENT(m_database_read) + FINALIZE_STATEMENT(m_database_write) + FINALIZE_STATEMENT(m_database_list) + if(m_database) - sqlite3_close(m_database); + rc = sqlite3_close(m_database); + + if (rc != SQLITE_OK) { + errorstream << "Database_SQLite3::~Database_SQLite3(): " + << "Failed to close database: rc=" << rc << std::endl; + } } diff --git a/src/rollback.cpp b/src/rollback.cpp index bae81ddb..36ebd729 100644 --- a/src/rollback.cpp +++ b/src/rollback.cpp @@ -1091,10 +1091,36 @@ public: SQL_databaseCheck(); } +#define FINALIZE_STATEMENT(statement) \ + if ( statement ) \ + rc = sqlite3_finalize(statement); \ + if ( rc != SQLITE_OK ) \ + errorstream << "RollbackManager::~RollbackManager():" \ + << "Failed to finalize: " << #statement << ": rc=" << rc << std::endl; ~RollbackManager() { infostream << "RollbackManager::~RollbackManager()" << std::endl; flush(); + + int rc = SQLITE_OK; + + FINALIZE_STATEMENT(dbs_insert) + FINALIZE_STATEMENT(dbs_replace) + FINALIZE_STATEMENT(dbs_select) + FINALIZE_STATEMENT(dbs_select_range) + FINALIZE_STATEMENT(dbs_select_withActor) + FINALIZE_STATEMENT(dbs_knownActor_select) + FINALIZE_STATEMENT(dbs_knownActor_insert) + FINALIZE_STATEMENT(dbs_knownNode_select) + FINALIZE_STATEMENT(dbs_knownNode_insert) + + if(dbh) + rc = sqlite3_close(dbh); + + if (rc != SQLITE_OK) { + errorstream << "RollbackManager::~RollbackManager(): " + << "Failed to close database: rc=" << rc << std::endl; + } } void addAction(const RollbackAction &action) {