forked from Mirrorlandia_minetest/minetest
Don't unload blocks if save failed
Improve error handling in saveBlock()
This commit is contained in:
parent
e14c4cdd4c
commit
8b3ed78e53
@ -45,7 +45,7 @@ int Database_Dummy::Initialized(void)
|
|||||||
void Database_Dummy::beginSave() {}
|
void Database_Dummy::beginSave() {}
|
||||||
void Database_Dummy::endSave() {}
|
void Database_Dummy::endSave() {}
|
||||||
|
|
||||||
void Database_Dummy::saveBlock(MapBlock *block)
|
bool Database_Dummy::saveBlock(MapBlock *block)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
/*
|
/*
|
||||||
@ -53,7 +53,10 @@ void Database_Dummy::saveBlock(MapBlock *block)
|
|||||||
*/
|
*/
|
||||||
if(block->isDummy())
|
if(block->isDummy())
|
||||||
{
|
{
|
||||||
return;
|
v3s16 p = block->getPos();
|
||||||
|
infostream<<"Database_Dummy::saveBlock(): WARNING: Not writing dummy block "
|
||||||
|
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format used for writing
|
// Format used for writing
|
||||||
@ -76,6 +79,7 @@ void Database_Dummy::saveBlock(MapBlock *block)
|
|||||||
m_database[getBlockAsInteger(p3d)] = tmp;
|
m_database[getBlockAsInteger(p3d)] = tmp;
|
||||||
// We just wrote it to the disk so clear modified flag
|
// We just wrote it to the disk so clear modified flag
|
||||||
block->resetModified();
|
block->resetModified();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlock* Database_Dummy::loadBlock(v3s16 blockpos)
|
MapBlock* Database_Dummy::loadBlock(v3s16 blockpos)
|
||||||
|
@ -33,8 +33,8 @@ public:
|
|||||||
Database_Dummy(ServerMap *map);
|
Database_Dummy(ServerMap *map);
|
||||||
virtual void beginSave();
|
virtual void beginSave();
|
||||||
virtual void endSave();
|
virtual void endSave();
|
||||||
virtual void saveBlock(MapBlock *block);
|
virtual bool saveBlock(MapBlock *block);
|
||||||
virtual MapBlock* loadBlock(v3s16 blockpos);
|
virtual MapBlock *loadBlock(v3s16 blockpos);
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
||||||
virtual int Initialized(void);
|
virtual int Initialized(void);
|
||||||
~Database_Dummy();
|
~Database_Dummy();
|
||||||
|
@ -37,8 +37,8 @@ LevelDB databases
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#define ENSURE_STATUS_OK(s) \
|
#define ENSURE_STATUS_OK(s) \
|
||||||
if (!s.ok()) { \
|
if (!(s).ok()) { \
|
||||||
throw FileNotGoodException(std::string("LevelDB error: ") + s.ToString()); \
|
throw FileNotGoodException(std::string("LevelDB error: ") + (s).ToString()); \
|
||||||
}
|
}
|
||||||
|
|
||||||
Database_LevelDB::Database_LevelDB(ServerMap *map, std::string savedir)
|
Database_LevelDB::Database_LevelDB(ServerMap *map, std::string savedir)
|
||||||
@ -58,27 +58,29 @@ int Database_LevelDB::Initialized(void)
|
|||||||
void Database_LevelDB::beginSave() {}
|
void Database_LevelDB::beginSave() {}
|
||||||
void Database_LevelDB::endSave() {}
|
void Database_LevelDB::endSave() {}
|
||||||
|
|
||||||
void Database_LevelDB::saveBlock(MapBlock *block)
|
bool Database_LevelDB::saveBlock(MapBlock *block)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
v3s16 p3d = block->getPos();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Dummy blocks are not written
|
Dummy blocks are not written
|
||||||
*/
|
*/
|
||||||
if(block->isDummy())
|
if(block->isDummy())
|
||||||
{
|
{
|
||||||
return;
|
errorstream << "WARNING: saveBlock: Not writing dummy block "
|
||||||
|
<< PP(p3d) << std::endl;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format used for writing
|
// Format used for writing
|
||||||
u8 version = SER_FMT_VER_HIGHEST_WRITE;
|
u8 version = SER_FMT_VER_HIGHEST_WRITE;
|
||||||
// Get destination
|
|
||||||
v3s16 p3d = block->getPos();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[0] u8 serialization version
|
[0] u8 serialization version
|
||||||
[1] data
|
[1] data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::ostringstream o(std::ios_base::binary);
|
std::ostringstream o(std::ios_base::binary);
|
||||||
o.write((char*)&version, 1);
|
o.write((char*)&version, 1);
|
||||||
// Write basic data
|
// Write basic data
|
||||||
@ -86,11 +88,17 @@ void Database_LevelDB::saveBlock(MapBlock *block)
|
|||||||
// Write block to database
|
// Write block to database
|
||||||
std::string tmp = o.str();
|
std::string tmp = o.str();
|
||||||
|
|
||||||
leveldb::Status status = m_database->Put(leveldb::WriteOptions(), i64tos(getBlockAsInteger(p3d)), tmp);
|
leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
|
||||||
ENSURE_STATUS_OK(status);
|
i64tos(getBlockAsInteger(p3d)), tmp);
|
||||||
|
if (!status.ok()) {
|
||||||
|
errorstream << "WARNING: saveBlock: LevelDB error saving block "
|
||||||
|
<< PP(p3d) << ": " << status.ToString() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// We just wrote it to the disk so clear modified flag
|
// We just wrote it to the disk so clear modified flag
|
||||||
block->resetModified();
|
block->resetModified();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlock* Database_LevelDB::loadBlock(v3s16 blockpos)
|
MapBlock* Database_LevelDB::loadBlock(v3s16 blockpos)
|
||||||
|
@ -36,8 +36,8 @@ public:
|
|||||||
Database_LevelDB(ServerMap *map, std::string savedir);
|
Database_LevelDB(ServerMap *map, std::string savedir);
|
||||||
virtual void beginSave();
|
virtual void beginSave();
|
||||||
virtual void endSave();
|
virtual void endSave();
|
||||||
virtual void saveBlock(MapBlock *block);
|
virtual bool saveBlock(MapBlock *block);
|
||||||
virtual MapBlock* loadBlock(v3s16 blockpos);
|
virtual MapBlock *loadBlock(v3s16 blockpos);
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
||||||
virtual int Initialized(void);
|
virtual int Initialized(void);
|
||||||
~Database_LevelDB();
|
~Database_LevelDB();
|
||||||
|
@ -81,21 +81,24 @@ void Database_Redis::endSave() {
|
|||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database_Redis::saveBlock(MapBlock *block)
|
bool Database_Redis::saveBlock(MapBlock *block)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
v3s16 p3d = block->getPos();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Dummy blocks are not written
|
Dummy blocks are not written
|
||||||
*/
|
*/
|
||||||
if(block->isDummy())
|
if(block->isDummy())
|
||||||
{
|
{
|
||||||
return;
|
errorstream << "WARNING: saveBlock: Not writing dummy block "
|
||||||
|
<< PP(p3d) << std::endl;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format used for writing
|
// Format used for writing
|
||||||
u8 version = SER_FMT_VER_HIGHEST_WRITE;
|
u8 version = SER_FMT_VER_HIGHEST_WRITE;
|
||||||
// Get destination
|
|
||||||
v3s16 p3d = block->getPos();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[0] u8 serialization version
|
[0] u8 serialization version
|
||||||
@ -110,16 +113,26 @@ void Database_Redis::saveBlock(MapBlock *block)
|
|||||||
std::string tmp1 = o.str();
|
std::string tmp1 = o.str();
|
||||||
std::string tmp2 = i64tos(getBlockAsInteger(p3d));
|
std::string tmp2 = i64tos(getBlockAsInteger(p3d));
|
||||||
|
|
||||||
redisReply *reply;
|
redisReply *reply = (redisReply *)redisCommand(ctx, "HSET %s %s %b",
|
||||||
reply = (redisReply*) redisCommand(ctx, "HSET %s %s %b", hash.c_str(), tmp2.c_str(), tmp1.c_str(), tmp1.size());
|
hash.c_str(), tmp2.c_str(), tmp1.c_str(), tmp1.size());
|
||||||
if(!reply)
|
if (!reply) {
|
||||||
throw FileNotGoodException(std::string("redis command 'HSET %s %s %b' failed: ") + ctx->errstr);
|
errorstream << "WARNING: saveBlock: redis command 'HSET' failed on "
|
||||||
if(reply->type == REDIS_REPLY_ERROR)
|
"block " << PP(p3d) << ": " << ctx->errstr << std::endl;
|
||||||
throw FileNotGoodException("Failed to store block in Database");
|
freeReplyObject(reply);
|
||||||
freeReplyObject(reply);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reply->type == REDIS_REPLY_ERROR) {
|
||||||
|
errorstream << "WARNING: saveBlock: save block " << PP(p3d)
|
||||||
|
<< "failed" << std::endl;
|
||||||
|
freeReplyObject(reply);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// We just wrote it to the disk so clear modified flag
|
// We just wrote it to the disk so clear modified flag
|
||||||
block->resetModified();
|
block->resetModified();
|
||||||
|
freeReplyObject(reply);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlock* Database_Redis::loadBlock(v3s16 blockpos)
|
MapBlock* Database_Redis::loadBlock(v3s16 blockpos)
|
||||||
|
@ -36,8 +36,8 @@ public:
|
|||||||
Database_Redis(ServerMap *map, std::string savedir);
|
Database_Redis(ServerMap *map, std::string savedir);
|
||||||
virtual void beginSave();
|
virtual void beginSave();
|
||||||
virtual void endSave();
|
virtual void endSave();
|
||||||
virtual void saveBlock(MapBlock *block);
|
virtual bool saveBlock(MapBlock *block);
|
||||||
virtual MapBlock* loadBlock(v3s16 blockpos);
|
virtual MapBlock *loadBlock(v3s16 blockpos);
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
||||||
virtual int Initialized(void);
|
virtual int Initialized(void);
|
||||||
~Database_Redis();
|
~Database_Redis();
|
||||||
|
@ -136,25 +136,24 @@ void Database_SQLite3::verifyDatabase() {
|
|||||||
infostream<<"ServerMap: SQLite3 database opened"<<std::endl;
|
infostream<<"ServerMap: SQLite3 database opened"<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database_SQLite3::saveBlock(MapBlock *block)
|
bool Database_SQLite3::saveBlock(MapBlock *block)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
v3s16 p3d = block->getPos();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Dummy blocks are not written
|
Dummy blocks are not written, but is not a save failure
|
||||||
*/
|
*/
|
||||||
if(block->isDummy())
|
if(block->isDummy())
|
||||||
{
|
{
|
||||||
/*v3s16 p = block->getPos();
|
errorstream << "WARNING: saveBlock: Not writing dummy block "
|
||||||
infostream<<"Database_SQLite3::saveBlock(): WARNING: Not writing dummy block "
|
<< PP(p3d) << std::endl;
|
||||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
|
return true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format used for writing
|
// Format used for writing
|
||||||
u8 version = SER_FMT_VER_HIGHEST_WRITE;
|
u8 version = SER_FMT_VER_HIGHEST_WRITE;
|
||||||
// Get destination
|
|
||||||
v3s16 p3d = block->getPos();
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
v2s16 p2d(p3d.X, p3d.Z);
|
v2s16 p2d(p3d.X, p3d.Z);
|
||||||
@ -176,29 +175,39 @@ void Database_SQLite3::saveBlock(MapBlock *block)
|
|||||||
|
|
||||||
std::ostringstream o(std::ios_base::binary);
|
std::ostringstream o(std::ios_base::binary);
|
||||||
|
|
||||||
o.write((char*)&version, 1);
|
o.write((char *)&version, 1);
|
||||||
|
|
||||||
// Write basic data
|
// Write basic data
|
||||||
block->serialize(o, version, true);
|
block->serialize(o, version, true);
|
||||||
|
|
||||||
// Write block to database
|
// Write block to database
|
||||||
|
|
||||||
std::string tmp = o.str();
|
std::string tmp = o.str();
|
||||||
const char *bytes = tmp.c_str();
|
|
||||||
|
|
||||||
if(sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK)
|
if (sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK) {
|
||||||
errorstream<<"WARNING: Block position failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
|
errorstream << "WARNING: saveBlock: Block position failed to bind: "
|
||||||
if(sqlite3_bind_blob(m_database_write, 2, (void *)bytes, o.tellp(), NULL) != SQLITE_OK) // TODO this mught not be the right length
|
<< PP(p3d) << ": " << sqlite3_errmsg(m_database) << std::endl;
|
||||||
errorstream<<"WARNING: Block data failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
|
sqlite3_reset(m_database_write);
|
||||||
int written = sqlite3_step(m_database_write);
|
return false;
|
||||||
if(written != SQLITE_DONE)
|
}
|
||||||
errorstream<<"WARNING: Block failed to save ("<<p3d.X<<", "<<p3d.Y<<", "<<p3d.Z<<") "
|
|
||||||
<<sqlite3_errmsg(m_database)<<std::endl;
|
if (sqlite3_bind_blob(m_database_write, 2, (void *)tmp.c_str(), tmp.size(), NULL) != SQLITE_OK) {
|
||||||
// Make ready for later reuse
|
errorstream << "WARNING: saveBlock: Block data failed to bind: "
|
||||||
sqlite3_reset(m_database_write);
|
<< PP(p3d) << ": " << sqlite3_errmsg(m_database) << std::endl;
|
||||||
|
sqlite3_reset(m_database_write);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sqlite3_step(m_database_write) != SQLITE_DONE) {
|
||||||
|
errorstream << "WARNING: saveBlock: Block failed to save "
|
||||||
|
<< PP(p3d) << ": " << sqlite3_errmsg(m_database) << std::endl;
|
||||||
|
sqlite3_reset(m_database_write);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// We just wrote it to the disk so clear modified flag
|
// We just wrote it to the disk so clear modified flag
|
||||||
block->resetModified();
|
block->resetModified();
|
||||||
|
sqlite3_reset(m_database_write);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlock* Database_SQLite3::loadBlock(v3s16 blockpos)
|
MapBlock* Database_SQLite3::loadBlock(v3s16 blockpos)
|
||||||
|
@ -36,8 +36,8 @@ public:
|
|||||||
virtual void beginSave();
|
virtual void beginSave();
|
||||||
virtual void endSave();
|
virtual void endSave();
|
||||||
|
|
||||||
virtual void saveBlock(MapBlock *block);
|
virtual bool saveBlock(MapBlock *block);
|
||||||
virtual MapBlock* loadBlock(v3s16 blockpos);
|
virtual MapBlock *loadBlock(v3s16 blockpos);
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
||||||
virtual int Initialized(void);
|
virtual int Initialized(void);
|
||||||
~Database_SQLite3();
|
~Database_SQLite3();
|
||||||
|
@ -24,19 +24,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "irr_v3d.h"
|
#include "irr_v3d.h"
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
|
|
||||||
|
#ifndef PP
|
||||||
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
#endif
|
||||||
|
|
||||||
class MapBlock;
|
class MapBlock;
|
||||||
|
|
||||||
class Database
|
class Database
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void beginSave()=0;
|
virtual void beginSave() = 0;
|
||||||
virtual void endSave()=0;
|
virtual void endSave() = 0;
|
||||||
|
|
||||||
virtual void saveBlock(MapBlock *block)=0;
|
virtual bool saveBlock(MapBlock *block) = 0;
|
||||||
virtual MapBlock* loadBlock(v3s16 blockpos)=0;
|
virtual MapBlock *loadBlock(v3s16 blockpos) = 0;
|
||||||
s64 getBlockAsInteger(const v3s16 pos) const;
|
s64 getBlockAsInteger(const v3s16 pos) const;
|
||||||
v3s16 getIntegerAsBlock(s64 i) const;
|
v3s16 getIntegerAsBlock(s64 i) const;
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst)=0;
|
virtual void listAllLoadableBlocks(std::list<v3s16> &dst) = 0;
|
||||||
virtual int Initialized(void)=0;
|
virtual int Initialized(void)=0;
|
||||||
virtual ~Database() {};
|
virtual ~Database() {};
|
||||||
};
|
};
|
||||||
|
19
src/map.cpp
19
src/map.cpp
@ -1473,11 +1473,11 @@ void Map::timerUpdate(float dtime, float unload_timeout,
|
|||||||
v3s16 p = block->getPos();
|
v3s16 p = block->getPos();
|
||||||
|
|
||||||
// Save if modified
|
// Save if modified
|
||||||
if(block->getModified() != MOD_STATE_CLEAN
|
if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading)
|
||||||
&& save_before_unloading)
|
|
||||||
{
|
{
|
||||||
modprofiler.add(block->getModifiedReason(), 1);
|
modprofiler.add(block->getModifiedReason(), 1);
|
||||||
saveBlock(block);
|
if (!saveBlock(block))
|
||||||
|
continue;
|
||||||
saved_blocks_count++;
|
saved_blocks_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3253,20 +3253,23 @@ bool ServerMap::loadSectorFull(v2s16 p2d)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ServerMap::beginSave() {
|
void ServerMap::beginSave()
|
||||||
|
{
|
||||||
dbase->beginSave();
|
dbase->beginSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerMap::endSave() {
|
void ServerMap::endSave()
|
||||||
|
{
|
||||||
dbase->endSave();
|
dbase->endSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerMap::saveBlock(MapBlock *block)
|
bool ServerMap::saveBlock(MapBlock *block)
|
||||||
{
|
{
|
||||||
dbase->saveBlock(block);
|
return dbase->saveBlock(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load)
|
void ServerMap::loadBlock(std::string sectordir, std::string blockfile,
|
||||||
|
MapSector *sector, bool save_after_load)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ public:
|
|||||||
|
|
||||||
// Server implements this.
|
// Server implements this.
|
||||||
// Client leaves it as no-op.
|
// Client leaves it as no-op.
|
||||||
virtual void saveBlock(MapBlock *block){};
|
virtual bool saveBlock(MapBlock *block){ return false; };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Updates usage timers and unloads unused blocks and sectors.
|
Updates usage timers and unloads unused blocks and sectors.
|
||||||
@ -485,7 +485,7 @@ public:
|
|||||||
// Returns true if sector now resides in memory
|
// Returns true if sector now resides in memory
|
||||||
//bool deFlushSector(v2s16 p2d);
|
//bool deFlushSector(v2s16 p2d);
|
||||||
|
|
||||||
void saveBlock(MapBlock *block);
|
bool saveBlock(MapBlock *block);
|
||||||
// This will generate a sector with getSector if not found.
|
// This will generate a sector with getSector if not found.
|
||||||
void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
|
void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
|
||||||
MapBlock* loadBlock(v3s16 p);
|
MapBlock* loadBlock(v3s16 p);
|
||||||
|
Loading…
Reference in New Issue
Block a user