From d1a16f24cfb360a0a6e60fc76ea87d7c4cf24618 Mon Sep 17 00:00:00 2001 From: JacobF Date: Fri, 2 Sep 2011 19:07:14 -0400 Subject: [PATCH] Initial sqlite3 maps. * The map will reside in world/map.sqlite * It will load from the sectors folder but will not save there --- src/map.cpp | 251 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/map.h | 35 ++++++++ 2 files changed, 277 insertions(+), 9 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 27a491428..41c4e17d2 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -29,12 +29,21 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen.h" #include "nodemetadata.h" -extern "C" { - #include "sqlite3.h" -} /* SQLite format specification: - Initially only replaces sectors/ and sectors2/ + + If map.sqlite does not exist in the save dir + or the block was not found in the database + the map will try to load from sectors folder. + In either case, map.sqlite will be created + and all future saves will save there. + + Structure of map.sqlite: + Tables: + blocks + (PK) INT pos + BLOB data */ /* @@ -1408,6 +1417,8 @@ void Map::timerUpdate(float dtime, float unload_timeout, core::list blocks; sector->getBlocks(blocks); + + beginSave(); for(core::list::Iterator i = blocks.begin(); i != blocks.end(); i++) { @@ -1440,6 +1451,7 @@ void Map::timerUpdate(float dtime, float unload_timeout, all_blocks_deleted = false; } } + endSave(); if(all_blocks_deleted) { @@ -1873,7 +1885,10 @@ void Map::nodeMetadataStep(float dtime, ServerMap::ServerMap(std::string savedir): Map(dout_server), m_seed(0), - m_map_metadata_changed(true) + m_map_metadata_changed(true), + m_database(NULL), + m_database_read(NULL), + m_database_write(NULL) { dstream<<__FUNCTION_NAME<::Iterator i = m_sectors.getIterator(); for(; i.atEnd() == false; i++) { @@ -2876,6 +2971,8 @@ void ServerMap::save(bool only_changed) core::list blocks; sector->getBlocks(blocks); core::list::Iterator j; + + //sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL); for(j=blocks.begin(); j!=blocks.end(); j++) { MapBlock *block = *j; @@ -2894,8 +2991,10 @@ void ServerMap::save(bool only_changed) <getPos().Z<<")" <getPos(); + +#if 0 v2s16 p2d(p3d.X, p3d.Z); std::string sectordir = getSectorDir(p2d); @@ -3182,11 +3295,16 @@ void ServerMap::saveBlock(MapBlock *block) std::ofstream o(fullpath.c_str(), std::ios_base::binary); if(o.good() == false) throw FileNotGoodException("Cannot open block data"); - +#endif /* [0] u8 serialization version [1] data */ + + verifyDatabase(); + + std::ostringstream o(std::ios_base::binary); + o.write((char*)&version, 1); // Write basic data @@ -3194,7 +3312,23 @@ void ServerMap::saveBlock(MapBlock *block) // Write extra data stored on disk block->serializeDiskExtra(o, version); - + + // Write block to database + + std::string tmp = o.str(); + const char *bytes = tmp.c_str(); + + if(sqlite3_bind_int(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK) + dstream<<"WARNING: Block position failed to bind: "<resetModified(); } @@ -3275,12 +3409,111 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto } } +void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load) +{ + DSTACK(__FUNCTION_NAME); + + try { + std::istringstream is(*blob, std::ios_base::binary); + + u8 version = SER_FMT_VER_INVALID; + is.read((char*)&version, 1); + + if(is.fail()) + throw SerializationError("ServerMap::loadBlock(): Failed" + " to read MapBlock version"); + + /*u32 block_size = MapBlock::serializedLength(version); + SharedBuffer data(block_size); + is.read((char*)*data, block_size);*/ + + // This will always return a sector because we're the server + //MapSector *sector = emergeSector(p2d); + + MapBlock *block = NULL; + bool created_new = false; + block = sector->getBlockNoCreateNoEx(p3d.Y); + if(block == NULL) + { + block = sector->createBlankBlockNoInsert(p3d.Y); + created_new = true; + } + + // Read basic data + block->deSerialize(is, version); + + // Read extra data stored on disk + block->deSerializeDiskExtra(is, version); + + // If it's a new block, insert it to the map + if(created_new) + sector->insertBlock(block); + + /* + Save blocks loaded in old format in new format + */ + + if(version < SER_FMT_VER_HIGHEST || save_after_load) + { + saveBlock(block); + } + + // We just loaded it from, so it's up-to-date. + block->resetModified(); + + } + catch(SerializationError &e) + { + dstream<<"WARNING: Invalid block data in database " + <<" (SerializationError). " + <<"what()="< #include #include +#include #include "common_irrlicht.h" #include "mapnode.h" @@ -31,6 +32,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "constants.h" #include "voxel.h" +extern "C" { + #include "sqlite3.h" +} + class MapSector; class ServerMapSector; class ClientMapSector; @@ -220,6 +225,10 @@ public: //core::aabbox3d getDisplayedBlockArea(); //bool updateChangedVisibleArea(); + + // Call these before and after saving of many blocks + virtual void beginSave() {return;}; + virtual void endSave() {return;}; virtual void save(bool only_changed){assert(0);}; @@ -361,6 +370,23 @@ public: v3s16 getBlockPos(std::string sectordir, std::string blockfile); static std::string getBlockFilename(v3s16 p); + /* + Database functions + */ + // Create the database structure + void createDatabase(); + // Verify we can read/write to the database + void verifyDatabase(); + // Get an integer suitable for a block + static int getBlockAsInteger(const v3s16 pos); + + // Returns true if the database file does not exist + bool loadFromFolders(); + + // Call these before and after saving of blocks + void beginSave(); + void endSave(); + void save(bool only_changed); //void loadAll(); @@ -391,6 +417,8 @@ public: // 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); + // Database version + void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false); // For debug printing virtual void PrintInfo(std::ostream &out); @@ -419,6 +447,13 @@ private: This is reset to false when written on disk. */ bool m_map_metadata_changed; + + /* + SQLite database and statements + */ + sqlite3 *m_database; + sqlite3_stmt *m_database_read; + sqlite3_stmt *m_database_write; }; /*