initStatements();
}
-void Database_PostgreSQL::verifyDatabase()
+void Database_PostgreSQL::pingDatabase()
{
- if (PQstatus(m_conn) == CONNECTION_OK)
- return;
-
- PQreset(m_conn);
- ping();
+ // Verify DB connection with ping
+ try {
+ ping();
+ } catch (const DatabaseException &e) {
+ // If ping failed, show the error and try reconnect
+ PQreset(m_conn);
+
+ errorstream << e.what() << std::endl
+ << "Reconnecting to database " << m_connect_string << std::endl;
+ connectToDatabase();
+ }
}
void Database_PostgreSQL::ping()
void Database_PostgreSQL::beginSave()
{
- verifyDatabase();
+ pingDatabase();
checkResults(PQexec(m_conn, "BEGIN;"));
}
return false;
}
- verifyDatabase();
+ pingDatabase();
s32 x, y, z;
x = htonl(pos.X);
void MapDatabasePostgreSQL::loadBlock(const v3s16 &pos, std::string *block)
{
- verifyDatabase();
+ pingDatabase();
s32 x, y, z;
x = htonl(pos.X);
bool MapDatabasePostgreSQL::deleteBlock(const v3s16 &pos)
{
- verifyDatabase();
+ pingDatabase();
s32 x, y, z;
x = htonl(pos.X);
void MapDatabasePostgreSQL::listAllLoadableBlocks(std::vector<v3s16> &dst)
{
- verifyDatabase();
+ pingDatabase();
PGresult *results = execPrepared("list_all_loadable_blocks", 0,
NULL, NULL, NULL, false, false);
bool PlayerDatabasePostgreSQL::playerDataExists(const std::string &playername)
{
- verifyDatabase();
+ pingDatabase();
const char *values[] = { playername.c_str() };
PGresult *results = execPrepared("load_player", 1, values, false);
if (!sao)
return;
- verifyDatabase();
+ pingDatabase();
v3f pos = sao->getBasePosition();
std::string pitch = ftos(sao->getLookPitch());
bool PlayerDatabasePostgreSQL::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
{
sanity_check(sao);
- verifyDatabase();
+ pingDatabase();
const char *values[] = { player->getName() };
PGresult *results = execPrepared("load_player", 1, values, false, false);
if (!playerDataExists(name))
return false;
- verifyDatabase();
+ pingDatabase();
const char *values[] = { name.c_str() };
execPrepared("remove_player", 1, values);
void PlayerDatabasePostgreSQL::listPlayers(std::vector<std::string> &res)
{
- verifyDatabase();
+ pingDatabase();
PGresult *results = execPrepared("load_player_list", 0, NULL, false);
Database_PostgreSQL(const std::string &connect_string);
~Database_PostgreSQL();
+ virtual void pingDatabase();
+
void beginSave();
void endSave();
bool initialized() const;
-
protected:
// Conversion helpers
inline int pg_to_int(PGresult *res, int row, int col)
}
void createTableIfNotExists(const std::string &table_name, const std::string &definition);
- void verifyDatabase();
// Database initialization
void connectToDatabase();
MapDatabasePostgreSQL(const std::string &connect_string);
virtual ~MapDatabasePostgreSQL() = default;
+ virtual void pingDatabase() { Database_PostgreSQL::pingDatabase(); }
+
bool saveBlock(const v3s16 &pos, const std::string &data);
void loadBlock(const v3s16 &pos, std::string *block);
bool deleteBlock(const v3s16 &pos);
PlayerDatabasePostgreSQL(const std::string &connect_string);
virtual ~PlayerDatabasePostgreSQL() = default;
+ virtual void pingDatabase() { Database_PostgreSQL::pingDatabase(); }
+
void savePlayer(RemotePlayer *player);
bool loadPlayer(RemotePlayer *player, PlayerSAO *sao);
bool removePlayer(const std::string &name);
void Database_SQLite3::beginSave()
{
- verifyDatabase();
+ pingDatabase();
SQLRES(sqlite3_step(m_stmt_begin), SQLITE_DONE,
"Failed to start SQLite3 transaction");
sqlite3_reset(m_stmt_begin);
void Database_SQLite3::endSave()
{
- verifyDatabase();
+ pingDatabase();
SQLRES(sqlite3_step(m_stmt_end), SQLITE_DONE,
"Failed to commit SQLite3 transaction");
sqlite3_reset(m_stmt_end);
"Failed to enable sqlite3 foreign key support");
}
-void Database_SQLite3::verifyDatabase()
+void Database_SQLite3::pingDatabase()
{
if (m_initialized) return;
bool MapDatabaseSQLite3::deleteBlock(const v3s16 &pos)
{
- verifyDatabase();
+ pingDatabase();
bindPos(m_stmt_delete, pos);
bool MapDatabaseSQLite3::saveBlock(const v3s16 &pos, const std::string &data)
{
- verifyDatabase();
+ pingDatabase();
#ifdef __ANDROID__
/**
void MapDatabaseSQLite3::loadBlock(const v3s16 &pos, std::string *block)
{
- verifyDatabase();
+ pingDatabase();
bindPos(m_stmt_read, pos);
void MapDatabaseSQLite3::listAllLoadableBlocks(std::vector<v3s16> &dst)
{
- verifyDatabase();
+ pingDatabase();
while (sqlite3_step(m_stmt_list) == SQLITE_ROW)
dst.push_back(getIntegerAsBlock(sqlite3_column_int64(m_stmt_list, 0)));
bool PlayerDatabaseSQLite3::playerDataExists(const std::string &name)
{
- verifyDatabase();
+ pingDatabase();
str_to_sqlite(m_stmt_player_load, 1, name);
bool res = (sqlite3_step(m_stmt_player_load) == SQLITE_ROW);
sqlite3_reset(m_stmt_player_load);
bool PlayerDatabaseSQLite3::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
{
- verifyDatabase();
+ pingDatabase();
str_to_sqlite(m_stmt_player_load, 1, player->getName());
if (sqlite3_step(m_stmt_player_load) != SQLITE_ROW) {
void PlayerDatabaseSQLite3::listPlayers(std::vector<std::string> &res)
{
- verifyDatabase();
+ pingDatabase();
while (sqlite3_step(m_stmt_player_list) == SQLITE_ROW)
res.push_back(sqlite_to_string(m_stmt_player_list, 0));
bool AuthDatabaseSQLite3::getAuth(const std::string &name, AuthEntry &res)
{
- verifyDatabase();
+ pingDatabase();
str_to_sqlite(m_stmt_read, 1, name);
if (sqlite3_step(m_stmt_read) != SQLITE_ROW) {
sqlite3_reset(m_stmt_read);
bool AuthDatabaseSQLite3::deleteAuth(const std::string &name)
{
- verifyDatabase();
+ pingDatabase();
str_to_sqlite(m_stmt_delete, 1, name);
sqlite3_vrfy(sqlite3_step(m_stmt_delete), SQLITE_DONE);
void AuthDatabaseSQLite3::listNames(std::vector<std::string> &res)
{
- verifyDatabase();
+ pingDatabase();
while (sqlite3_step(m_stmt_list_names) == SQLITE_ROW) {
res.push_back(sqlite_to_string(m_stmt_list_names, 0));
void beginSave();
void endSave();
+ // Open and initialize the database if needed
+ virtual void pingDatabase();
+
bool initialized() const { return m_initialized; }
protected:
Database_SQLite3(const std::string &savedir, const std::string &dbname);
- // Open and initialize the database if needed
- void verifyDatabase();
-
// Convertors
inline void str_to_sqlite(sqlite3_stmt *s, int iCol, const std::string &str) const
{
MapDatabaseSQLite3(const std::string &savedir);
virtual ~MapDatabaseSQLite3();
+ virtual void pingDatabase() { Database_SQLite3::pingDatabase(); }
+
bool saveBlock(const v3s16 &pos, const std::string &data);
void loadBlock(const v3s16 &pos, std::string *block);
bool deleteBlock(const v3s16 &pos);
PlayerDatabaseSQLite3(const std::string &savedir);
virtual ~PlayerDatabaseSQLite3();
+ virtual void pingDatabase() { Database_SQLite3::pingDatabase(); }
+
void savePlayer(RemotePlayer *player);
bool loadPlayer(RemotePlayer *player, PlayerSAO *sao);
bool removePlayer(const std::string &name);
AuthDatabaseSQLite3(const std::string &savedir);
virtual ~AuthDatabaseSQLite3();
+ virtual void pingDatabase() { Database_SQLite3::pingDatabase(); }
+
virtual bool getAuth(const std::string &name, AuthEntry &res);
virtual bool saveAuth(const AuthEntry &authEntry);
virtual bool createAuth(AuthEntry &authEntry);
virtual void beginSave() = 0;
virtual void endSave() = 0;
virtual bool initialized() const { return true; }
+ virtual void pingDatabase() {}
};
class MapDatabase : public Database
public:
virtual ~PlayerDatabase() = default;
+ virtual void pingDatabase() {}
+
virtual void savePlayer(RemotePlayer *player) = 0;
virtual bool loadPlayer(RemotePlayer *player, PlayerSAO *sao) = 0;
virtual bool removePlayer(const std::string &name) = 0;
virtual bool deleteAuth(const std::string &name) = 0;
virtual void listNames(std::vector<std::string> &res) = 0;
virtual void reload() = 0;
+ virtual void pingDatabase() {}
};
throw BaseException(std::string("Database backend ") + name + " not supported.");
}
+void ServerMap::pingDatabase()
+{
+ dbase->pingDatabase();
+}
+
void ServerMap::beginSave()
{
dbase->beginSave();
Database functions
*/
static MapDatabase *createDatabase(const std::string &name, const std::string &savedir, Settings &conf);
+ void pingDatabase();
// Call these before and after saving of blocks
void beginSave();
}
}
+ if (m_database_check_interval.step(dtime, 10.0f)) {
+ m_auth_database->pingDatabase();
+ m_player_database->pingDatabase();
+ m_map->pingDatabase();
+ }
/*
Manage active block list
*/
IntervalLimiter m_object_management_interval;
// List of active blocks
ActiveBlockList m_active_blocks;
+ IntervalLimiter m_database_check_interval;
IntervalLimiter m_active_blocks_management_interval;
IntervalLimiter m_active_block_modifier_interval;
IntervalLimiter m_active_blocks_nodemetadata_interval;