void Database_Dummy::beginSave() {}
void Database_Dummy::endSave() {}
-void Database_Dummy::saveBlock(MapBlock *block)
+bool Database_Dummy::saveBlock(MapBlock *block)
{
DSTACK(__FUNCTION_NAME);
/*
*/
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
m_database[getBlockAsInteger(p3d)] = tmp;
// We just wrote it to the disk so clear modified flag
block->resetModified();
+ return true;
}
MapBlock* Database_Dummy::loadBlock(v3s16 blockpos)
Database_Dummy(ServerMap *map);
virtual void beginSave();
virtual void endSave();
- virtual void saveBlock(MapBlock *block);
- virtual MapBlock* loadBlock(v3s16 blockpos);
+ virtual bool saveBlock(MapBlock *block);
+ virtual MapBlock *loadBlock(v3s16 blockpos);
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
virtual int Initialized(void);
~Database_Dummy();
#include "log.h"
#define ENSURE_STATUS_OK(s) \
- if (!s.ok()) { \
- throw FileNotGoodException(std::string("LevelDB error: ") + s.ToString()); \
+ if (!(s).ok()) { \
+ throw FileNotGoodException(std::string("LevelDB error: ") + (s).ToString()); \
}
Database_LevelDB::Database_LevelDB(ServerMap *map, std::string savedir)
void Database_LevelDB::beginSave() {}
void Database_LevelDB::endSave() {}
-void Database_LevelDB::saveBlock(MapBlock *block)
+bool Database_LevelDB::saveBlock(MapBlock *block)
{
DSTACK(__FUNCTION_NAME);
+
+ v3s16 p3d = block->getPos();
+
/*
Dummy blocks are not written
*/
if(block->isDummy())
{
- return;
+ errorstream << "WARNING: saveBlock: Not writing dummy block "
+ << PP(p3d) << std::endl;
+ return true;
}
// Format used for writing
u8 version = SER_FMT_VER_HIGHEST_WRITE;
- // Get destination
- v3s16 p3d = block->getPos();
/*
[0] u8 serialization version
[1] data
*/
-
std::ostringstream o(std::ios_base::binary);
o.write((char*)&version, 1);
// Write basic data
// Write block to database
std::string tmp = o.str();
- leveldb::Status status = m_database->Put(leveldb::WriteOptions(), i64tos(getBlockAsInteger(p3d)), tmp);
- ENSURE_STATUS_OK(status);
+ leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
+ 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
block->resetModified();
+ return true;
}
MapBlock* Database_LevelDB::loadBlock(v3s16 blockpos)
Database_LevelDB(ServerMap *map, std::string savedir);
virtual void beginSave();
virtual void endSave();
- virtual void saveBlock(MapBlock *block);
- virtual MapBlock* loadBlock(v3s16 blockpos);
+ virtual bool saveBlock(MapBlock *block);
+ virtual MapBlock *loadBlock(v3s16 blockpos);
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
virtual int Initialized(void);
~Database_LevelDB();
freeReplyObject(reply);
}
-void Database_Redis::saveBlock(MapBlock *block)
+bool Database_Redis::saveBlock(MapBlock *block)
{
DSTACK(__FUNCTION_NAME);
+
+ v3s16 p3d = block->getPos();
+
/*
Dummy blocks are not written
*/
if(block->isDummy())
{
- return;
+ errorstream << "WARNING: saveBlock: Not writing dummy block "
+ << PP(p3d) << std::endl;
+ return true;
}
// Format used for writing
u8 version = SER_FMT_VER_HIGHEST_WRITE;
- // Get destination
- v3s16 p3d = block->getPos();
/*
[0] u8 serialization version
std::string tmp1 = o.str();
std::string tmp2 = i64tos(getBlockAsInteger(p3d));
- redisReply *reply;
- reply = (redisReply*) redisCommand(ctx, "HSET %s %s %b", hash.c_str(), tmp2.c_str(), tmp1.c_str(), tmp1.size());
- if(!reply)
- throw FileNotGoodException(std::string("redis command 'HSET %s %s %b' failed: ") + ctx->errstr);
- if(reply->type == REDIS_REPLY_ERROR)
- throw FileNotGoodException("Failed to store block in Database");
- freeReplyObject(reply);
+ redisReply *reply = (redisReply *)redisCommand(ctx, "HSET %s %s %b",
+ hash.c_str(), tmp2.c_str(), tmp1.c_str(), tmp1.size());
+ if (!reply) {
+ errorstream << "WARNING: saveBlock: redis command 'HSET' failed on "
+ "block " << PP(p3d) << ": " << ctx->errstr << std::endl;
+ 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
block->resetModified();
+ freeReplyObject(reply);
+ return true;
}
MapBlock* Database_Redis::loadBlock(v3s16 blockpos)
Database_Redis(ServerMap *map, std::string savedir);
virtual void beginSave();
virtual void endSave();
- virtual void saveBlock(MapBlock *block);
- virtual MapBlock* loadBlock(v3s16 blockpos);
+ virtual bool saveBlock(MapBlock *block);
+ virtual MapBlock *loadBlock(v3s16 blockpos);
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
virtual int Initialized(void);
~Database_Redis();
infostream<<"ServerMap: SQLite3 database opened"<<std::endl;
}
-void Database_SQLite3::saveBlock(MapBlock *block)
+bool Database_SQLite3::saveBlock(MapBlock *block)
{
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())
{
- /*v3s16 p = block->getPos();
- infostream<<"Database_SQLite3::saveBlock(): WARNING: Not writing dummy block "
- <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
- return;
+ errorstream << "WARNING: saveBlock: Not writing dummy block "
+ << PP(p3d) << std::endl;
+ return true;
}
// Format used for writing
u8 version = SER_FMT_VER_HIGHEST_WRITE;
- // Get destination
- v3s16 p3d = block->getPos();
-
#if 0
v2s16 p2d(p3d.X, p3d.Z);
std::ostringstream o(std::ios_base::binary);
- o.write((char*)&version, 1);
+ 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)
- errorstream<<"WARNING: Block position failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
- if(sqlite3_bind_blob(m_database_write, 2, (void *)bytes, o.tellp(), NULL) != SQLITE_OK) // TODO this mught not be the right length
- errorstream<<"WARNING: Block data failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
- int written = sqlite3_step(m_database_write);
- if(written != SQLITE_DONE)
- errorstream<<"WARNING: Block failed to save ("<<p3d.X<<", "<<p3d.Y<<", "<<p3d.Z<<") "
- <<sqlite3_errmsg(m_database)<<std::endl;
- // Make ready for later reuse
- sqlite3_reset(m_database_write);
+
+ if (sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK) {
+ errorstream << "WARNING: saveBlock: Block position failed to bind: "
+ << PP(p3d) << ": " << sqlite3_errmsg(m_database) << std::endl;
+ sqlite3_reset(m_database_write);
+ return false;
+ }
+
+ if (sqlite3_bind_blob(m_database_write, 2, (void *)tmp.c_str(), tmp.size(), NULL) != SQLITE_OK) {
+ errorstream << "WARNING: saveBlock: Block data failed to bind: "
+ << 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
block->resetModified();
+ sqlite3_reset(m_database_write);
+ return true;
}
MapBlock* Database_SQLite3::loadBlock(v3s16 blockpos)
virtual void beginSave();
virtual void endSave();
- virtual void saveBlock(MapBlock *block);
- virtual MapBlock* loadBlock(v3s16 blockpos);
+ virtual bool saveBlock(MapBlock *block);
+ virtual MapBlock *loadBlock(v3s16 blockpos);
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
virtual int Initialized(void);
~Database_SQLite3();
#include "irr_v3d.h"
#include "irrlichttypes.h"
+#ifndef PP
+ #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
+#endif
+
class MapBlock;
class Database
{
public:
- virtual void beginSave()=0;
- virtual void endSave()=0;
+ virtual void beginSave() = 0;
+ virtual void endSave() = 0;
- virtual void saveBlock(MapBlock *block)=0;
- virtual MapBlock* loadBlock(v3s16 blockpos)=0;
+ virtual bool saveBlock(MapBlock *block) = 0;
+ virtual MapBlock *loadBlock(v3s16 blockpos) = 0;
s64 getBlockAsInteger(const v3s16 pos) 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 ~Database() {};
};
v3s16 p = block->getPos();
// Save if modified
- if(block->getModified() != MOD_STATE_CLEAN
- && save_before_unloading)
+ if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading)
{
modprofiler.add(block->getModifiedReason(), 1);
- saveBlock(block);
+ if (!saveBlock(block))
+ continue;
saved_blocks_count++;
}
}
#endif
-void ServerMap::beginSave() {
+void ServerMap::beginSave()
+{
dbase->beginSave();
}
-void ServerMap::endSave() {
+void ServerMap::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);
// Server implements this.
// 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.
// Returns true if sector now resides in memory
//bool deFlushSector(v2s16 p2d);
- void saveBlock(MapBlock *block);
+ bool saveBlock(MapBlock *block);
// 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);
MapBlock* loadBlock(v3s16 p);