#include "db-sqlite3.h" #include #include // for usleep #include "types.h" #define BLOCKPOSLIST_STATEMENT "SELECT pos FROM blocks" #define BLOCK_STATEMENT "SELECT pos, data FROM blocks WHERE pos == ?" DBSQLite3::DBSQLite3(const std::string &mapdir) : m_blocksQueriedCount(0), m_blocksReadCount(0), m_blockPosListStatement(NULL), m_blockOnPosStatement(NULL) { std::string db_name = mapdir + "map.sqlite"; if (sqlite3_open_v2(db_name.c_str(), &m_db, SQLITE_OPEN_READONLY | SQLITE_OPEN_PRIVATECACHE, 0) != SQLITE_OK) { throw std::runtime_error(std::string(sqlite3_errmsg(m_db)) + ", Database file: " + db_name); } if (SQLITE_OK != sqlite3_prepare_v2(m_db, BLOCKPOSLIST_STATEMENT, sizeof(BLOCKPOSLIST_STATEMENT)-1, &m_blockPosListStatement, 0)) { throw std::runtime_error("Failed to prepare SQL statement (blockPosListStatement)"); } if (SQLITE_OK != sqlite3_prepare_v2(m_db, BLOCK_STATEMENT, sizeof(BLOCK_STATEMENT)-1, &m_blockOnPosStatement, 0)) { throw std::runtime_error("Failed to prepare SQL statement (blockOnPosStatement)"); } } DBSQLite3::~DBSQLite3() { if (m_blockPosListStatement) sqlite3_finalize(m_blockPosListStatement); if (m_blockOnPosStatement) sqlite3_finalize(m_blockOnPosStatement); sqlite3_close(m_db); } int DBSQLite3::getBlocksReadCount(void) { return m_blocksReadCount; } int DBSQLite3::getBlocksQueriedCount(void) { return m_blocksQueriedCount; } const DB::BlockPosList &DBSQLite3::getBlockPos() { m_BlockPosList.clear(); int result = 0; while (true) { result = sqlite3_step(m_blockPosListStatement); if(result == SQLITE_ROW) { sqlite3_int64 blocknum = sqlite3_column_int64(m_blockPosListStatement, 0); m_BlockPosList.push_back(blocknum); } else if (result == SQLITE_BUSY) // Wait some time and try again usleep(10000); else break; } sqlite3_reset(m_blockPosListStatement); return m_BlockPosList; } DB::Block DBSQLite3::getBlockOnPos(const BlockPos &pos) { Block block(pos,reinterpret_cast("")); int result = 0; m_blocksQueriedCount++; sqlite3_bind_int64(m_blockOnPosStatement, 1, pos.databasePosI64()); while (true) { result = sqlite3_step(m_blockOnPosStatement); if(result == SQLITE_ROW) { const unsigned char *data = reinterpret_cast(sqlite3_column_blob(m_blockOnPosStatement, 1)); int size = sqlite3_column_bytes(m_blockOnPosStatement, 1); block = Block(pos, ustring(data, size)); m_blocksReadCount++; break; } else if (result == SQLITE_BUSY) { // Wait some time and try again usleep(10000); } else { break; } } sqlite3_reset(m_blockOnPosStatement); return block; }