2014-03-05 21:41:27 +01:00
|
|
|
#include <stdexcept>
|
2014-03-05 21:46:40 +01:00
|
|
|
#include <unistd.h> // for usleep
|
2016-10-08 21:09:52 +02:00
|
|
|
#include <iostream>
|
2014-04-19 08:13:34 +02:00
|
|
|
#include "db-sqlite3.h"
|
|
|
|
#include "types.h"
|
2014-03-05 21:41:27 +01:00
|
|
|
|
2014-03-28 18:42:37 +01:00
|
|
|
#define SQLRES(f, good) \
|
|
|
|
result = (sqlite3_##f);\
|
|
|
|
if (result != good) {\
|
2014-03-28 21:47:19 +01:00
|
|
|
throw std::runtime_error(sqlite3_errmsg(db));\
|
2014-03-28 18:42:37 +01:00
|
|
|
}
|
|
|
|
#define SQLOK(f) SQLRES(f, SQLITE_OK)
|
|
|
|
|
2014-04-19 08:13:34 +02:00
|
|
|
|
|
|
|
DBSQLite3::DBSQLite3(const std::string &mapdir)
|
|
|
|
{
|
2014-03-28 18:42:37 +01:00
|
|
|
int result;
|
2014-03-05 21:41:27 +01:00
|
|
|
std::string db_name = mapdir + "map.sqlite";
|
2014-03-28 18:42:37 +01:00
|
|
|
|
2014-04-19 08:13:34 +02:00
|
|
|
SQLOK(open_v2(db_name.c_str(), &db, SQLITE_OPEN_READONLY |
|
|
|
|
SQLITE_OPEN_PRIVATECACHE, 0))
|
2014-03-28 18:42:37 +01:00
|
|
|
|
2014-03-28 21:47:19 +01:00
|
|
|
SQLOK(prepare_v2(db,
|
2014-04-19 08:13:34 +02:00
|
|
|
"SELECT pos, data FROM blocks WHERE pos BETWEEN ? AND ?",
|
|
|
|
-1, &stmt_get_blocks_z, NULL))
|
2014-03-28 18:42:37 +01:00
|
|
|
|
2014-03-28 21:47:19 +01:00
|
|
|
SQLOK(prepare_v2(db,
|
2014-03-28 18:42:37 +01:00
|
|
|
"SELECT pos FROM blocks",
|
|
|
|
-1, &stmt_get_block_pos, NULL))
|
2014-03-05 21:41:27 +01:00
|
|
|
}
|
|
|
|
|
2014-04-19 08:13:34 +02:00
|
|
|
|
|
|
|
DBSQLite3::~DBSQLite3()
|
|
|
|
{
|
2016-10-08 21:09:52 +02:00
|
|
|
sqlite3_finalize(stmt_get_blocks_z);
|
|
|
|
sqlite3_finalize(stmt_get_block_pos);
|
2014-03-28 18:42:37 +01:00
|
|
|
|
2016-10-08 21:09:52 +02:00
|
|
|
if (sqlite3_close(db) != SQLITE_OK) {
|
|
|
|
std::cerr << "Error closing SQLite database." << std::endl;
|
|
|
|
};
|
2014-03-05 21:41:27 +01:00
|
|
|
}
|
|
|
|
|
2014-04-19 08:13:34 +02:00
|
|
|
std::vector<BlockPos> DBSQLite3::getBlockPos()
|
|
|
|
{
|
2014-03-28 21:47:19 +01:00
|
|
|
int result;
|
2014-04-19 08:13:34 +02:00
|
|
|
std::vector<BlockPos> positions;
|
2014-03-28 18:42:37 +01:00
|
|
|
while ((result = sqlite3_step(stmt_get_block_pos)) != SQLITE_DONE) {
|
|
|
|
if (result == SQLITE_ROW) {
|
2014-04-19 08:13:34 +02:00
|
|
|
int64_t posHash = sqlite3_column_int64(stmt_get_block_pos, 0);
|
|
|
|
positions.push_back(decodeBlockPos(posHash));
|
2014-03-28 18:42:37 +01:00
|
|
|
} else if (result == SQLITE_BUSY) { // Wait some time and try again
|
|
|
|
usleep(10000);
|
|
|
|
} else {
|
2014-03-28 21:47:19 +01:00
|
|
|
throw std::runtime_error(sqlite3_errmsg(db));
|
2014-03-05 21:41:27 +01:00
|
|
|
}
|
|
|
|
}
|
2014-03-28 21:47:19 +01:00
|
|
|
SQLOK(reset(stmt_get_block_pos));
|
2014-04-19 08:13:34 +02:00
|
|
|
return positions;
|
2014-03-05 21:41:27 +01:00
|
|
|
}
|
|
|
|
|
2014-04-19 08:13:34 +02:00
|
|
|
|
|
|
|
void DBSQLite3::getBlocksOnZ(std::map<int16_t, BlockList> &blocks, int16_t zPos)
|
2014-03-05 21:41:27 +01:00
|
|
|
{
|
2014-04-19 08:13:34 +02:00
|
|
|
int result;
|
2014-03-05 21:41:27 +01:00
|
|
|
|
2014-04-19 08:13:34 +02:00
|
|
|
// Magic numbers!
|
2016-09-18 14:33:13 +02:00
|
|
|
int64_t minPos = encodeBlockPos(BlockPos(0, -2048, zPos));
|
|
|
|
int64_t maxPos = encodeBlockPos(BlockPos(0, 2048, zPos)) - 1;
|
2014-03-05 21:41:27 +01:00
|
|
|
|
2014-04-19 08:13:34 +02:00
|
|
|
SQLOK(bind_int64(stmt_get_blocks_z, 1, minPos));
|
|
|
|
SQLOK(bind_int64(stmt_get_blocks_z, 2, maxPos));
|
2014-03-05 21:41:27 +01:00
|
|
|
|
2014-04-19 08:13:34 +02:00
|
|
|
while ((result = sqlite3_step(stmt_get_blocks_z)) != SQLITE_DONE) {
|
2014-03-28 18:42:37 +01:00
|
|
|
if (result == SQLITE_ROW) {
|
2014-04-19 08:13:34 +02:00
|
|
|
int64_t posHash = sqlite3_column_int64(stmt_get_blocks_z, 0);
|
|
|
|
const unsigned char *data = reinterpret_cast<const unsigned char *>(
|
|
|
|
sqlite3_column_blob(stmt_get_blocks_z, 1));
|
|
|
|
size_t size = sqlite3_column_bytes(stmt_get_blocks_z, 1);
|
|
|
|
Block b(decodeBlockPos(posHash), ustring(data, size));
|
|
|
|
blocks[b.first.x].push_back(b);
|
2014-03-05 21:46:40 +01:00
|
|
|
} else if (result == SQLITE_BUSY) { // Wait some time and try again
|
|
|
|
usleep(10000);
|
|
|
|
} else {
|
2014-03-28 21:47:19 +01:00
|
|
|
throw std::runtime_error(sqlite3_errmsg(db));
|
2014-03-05 21:41:27 +01:00
|
|
|
}
|
|
|
|
}
|
2014-04-19 08:13:34 +02:00
|
|
|
SQLOK(reset(stmt_get_blocks_z));
|
2014-03-05 21:41:27 +01:00
|
|
|
}
|
|
|
|
|
2014-03-28 18:42:37 +01:00
|
|
|
#undef SQLRES
|
|
|
|
#undef SQLOK
|
|
|
|
|