3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 SQLite format specification:
22 - Initially only replaces sectors/ and sectors2/
24 If map.sqlite does not exist in the save dir
25 or the block was not found in the database
26 the map will try to load from sectors folder.
27 In either case, map.sqlite will be created
28 and all future saves will save there.
30 Structure of map.sqlite:
38 #include "database-sqlite3.h"
41 #include "mapsector.h"
43 #include "serialization.h"
48 Database_SQLite3::Database_SQLite3(ServerMap *map, std::string savedir)
51 m_database_read = NULL;
52 m_database_write = NULL;
53 m_database_list = NULL;
58 int Database_SQLite3::Initialized(void)
60 return m_database ? 1 : 0;
63 void Database_SQLite3::beginSave() {
65 if(sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL) != SQLITE_OK)
66 infostream<<"WARNING: beginSave() failed, saving might be slow.";
69 void Database_SQLite3::endSave() {
71 if(sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK)
72 infostream<<"WARNING: endSave() failed, map might not have saved.";
75 void Database_SQLite3::createDirs(std::string path)
77 if(fs::CreateAllDirs(path) == false)
79 infostream<<DTIME<<"Database_SQLite3: Failed to create directory "
80 <<"\""<<path<<"\""<<std::endl;
81 throw BaseException("Database_SQLite3 failed to create directory");
85 void Database_SQLite3::verifyDatabase() {
90 std::string dbp = m_savedir + DIR_DELIM + "map.sqlite";
91 bool needs_create = false;
95 Open the database connection
98 createDirs(m_savedir); // ?
100 if(!fs::PathExists(dbp))
103 d = sqlite3_open_v2(dbp.c_str(), &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
105 infostream<<"WARNING: SQLite3 database failed to open: "<<sqlite3_errmsg(m_database)<<std::endl;
106 throw FileNotGoodException("Cannot open database file");
112 d = sqlite3_prepare(m_database, "SELECT `data` FROM `blocks` WHERE `pos`=? LIMIT 1", -1, &m_database_read, NULL);
114 infostream<<"WARNING: SQLite3 database read statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
115 throw FileNotGoodException("Cannot prepare read statement");
118 d = sqlite3_prepare(m_database, "REPLACE INTO `blocks` VALUES(?, ?)", -1, &m_database_write, NULL);
120 infostream<<"WARNING: SQLite3 database write statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
121 throw FileNotGoodException("Cannot prepare write statement");
124 d = sqlite3_prepare(m_database, "SELECT `pos` FROM `blocks`", -1, &m_database_list, NULL);
126 infostream<<"WARNING: SQLite3 database list statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
127 throw FileNotGoodException("Cannot prepare read statement");
130 infostream<<"ServerMap: SQLite3 database opened"<<std::endl;
134 void Database_SQLite3::saveBlock(MapBlock *block)
136 DSTACK(__FUNCTION_NAME);
138 Dummy blocks are not written
142 /*v3s16 p = block->getPos();
143 infostream<<"Database_SQLite3::saveBlock(): WARNING: Not writing dummy block "
144 <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
148 // Format used for writing
149 u8 version = SER_FMT_VER_HIGHEST_WRITE;
151 v3s16 p3d = block->getPos();
155 v2s16 p2d(p3d.X, p3d.Z);
156 std::string sectordir = getSectorDir(p2d);
158 createDirs(sectordir);
160 std::string fullpath = sectordir+DIR_DELIM+getBlockFilename(p3d);
161 std::ofstream o(fullpath.c_str(), std::ios_base::binary);
162 if(o.good() == false)
163 throw FileNotGoodException("Cannot open block data");
166 [0] u8 serialization version
172 std::ostringstream o(std::ios_base::binary);
174 o.write((char*)&version, 1);
177 block->serialize(o, version, true);
179 // Write block to database
181 std::string tmp = o.str();
182 const char *bytes = tmp.c_str();
184 if(sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK)
185 infostream<<"WARNING: Block position failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
186 if(sqlite3_bind_blob(m_database_write, 2, (void *)bytes, o.tellp(), NULL) != SQLITE_OK) // TODO this mught not be the right length
187 infostream<<"WARNING: Block data failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
188 int written = sqlite3_step(m_database_write);
189 if(written != SQLITE_DONE)
190 infostream<<"WARNING: Block failed to save ("<<p3d.X<<", "<<p3d.Y<<", "<<p3d.Z<<") "
191 <<sqlite3_errmsg(m_database)<<std::endl;
192 // Make ready for later reuse
193 sqlite3_reset(m_database_write);
195 // We just wrote it to the disk so clear modified flag
196 block->resetModified();
199 MapBlock* Database_SQLite3::loadBlock(v3s16 blockpos)
201 v2s16 p2d(blockpos.X, blockpos.Z);
204 if(sqlite3_bind_int64(m_database_read, 1, getBlockAsInteger(blockpos)) != SQLITE_OK)
205 infostream<<"WARNING: Could not bind block position for load: "
206 <<sqlite3_errmsg(m_database)<<std::endl;
207 if(sqlite3_step(m_database_read) == SQLITE_ROW) {
209 Make sure sector is loaded
211 MapSector *sector = srvmap->createSector(p2d);
216 const char * data = (const char *)sqlite3_column_blob(m_database_read, 0);
217 size_t len = sqlite3_column_bytes(m_database_read, 0);
219 std::string datastr(data, len);
221 // srvmap->loadBlock(&datastr, blockpos, sector, false);
224 std::istringstream is(datastr, std::ios_base::binary);
226 u8 version = SER_FMT_VER_INVALID;
227 is.read((char*)&version, 1);
230 throw SerializationError("ServerMap::loadBlock(): Failed"
231 " to read MapBlock version");
233 MapBlock *block = NULL;
234 bool created_new = false;
235 block = sector->getBlockNoCreateNoEx(blockpos.Y);
238 block = sector->createBlankBlockNoInsert(blockpos.Y);
243 block->deSerialize(is, version, true);
245 // If it's a new block, insert it to the map
247 sector->insertBlock(block);
250 Save blocks loaded in old format in new format
253 //if(version < SER_FMT_VER_HIGHEST || save_after_load)
254 // Only save if asked to; no need to update version
255 //if(save_after_load)
258 // We just loaded it from, so it's up-to-date.
259 block->resetModified();
262 catch(SerializationError &e)
264 errorstream<<"Invalid block data in database"
265 <<" ("<<blockpos.X<<","<<blockpos.Y<<","<<blockpos.Z<<")"
266 <<" (SerializationError): "<<e.what()<<std::endl;
268 // TODO: Block should be marked as invalid in memory so that it is
269 // not touched but the game can run
271 if(g_settings->getBool("ignore_world_load_errors")){
272 errorstream<<"Ignoring block load error. Duck and cover! "
273 <<"(ignore_world_load_errors)"<<std::endl;
275 throw SerializationError("Invalid block data in database");
281 sqlite3_step(m_database_read);
282 // We should never get more than 1 row, so ok to reset
283 sqlite3_reset(m_database_read);
285 return srvmap->getBlockNoCreateNoEx(blockpos); // should not be using this here
287 sqlite3_reset(m_database_read);
291 void Database_SQLite3::createDatabase()
295 e = sqlite3_exec(m_database,
296 "CREATE TABLE IF NOT EXISTS `blocks` ("
297 "`pos` INT NOT NULL PRIMARY KEY,"
301 if(e == SQLITE_ABORT)
302 throw FileNotGoodException("Could not create sqlite3 database structure");
304 infostream<<"ServerMap: SQLite3 database structure was created";
308 void Database_SQLite3::listAllLoadableBlocks(std::list<v3s16> &dst)
312 while(sqlite3_step(m_database_list) == SQLITE_ROW)
314 sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0);
315 v3s16 p = getIntegerAsBlock(block_i);
316 //dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
321 Database_SQLite3::~Database_SQLite3()
324 sqlite3_finalize(m_database_read);
326 sqlite3_finalize(m_database_write);
328 sqlite3_close(m_database);