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.
24 #include "database-leveldb.h"
28 #include "exceptions.h"
29 #include "remoteplayer.h"
30 #include "server/player_sao.h"
31 #include "util/serialize.h"
32 #include "util/string.h"
34 #include "leveldb/db.h"
37 #define ENSURE_STATUS_OK(s) \
39 throw DatabaseException(std::string("LevelDB error: ") + \
44 Database_LevelDB::Database_LevelDB(const std::string &savedir)
46 leveldb::Options options;
47 options.create_if_missing = true;
48 leveldb::Status status = leveldb::DB::Open(options,
49 savedir + DIR_DELIM + "map.db", &m_database);
50 ENSURE_STATUS_OK(status);
53 Database_LevelDB::~Database_LevelDB()
58 bool Database_LevelDB::saveBlock(const v3s16 &pos, const std::string &data)
60 leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
61 i64tos(getBlockAsInteger(pos)), data);
63 warningstream << "saveBlock: LevelDB error saving block "
64 << PP(pos) << ": " << status.ToString() << std::endl;
71 void Database_LevelDB::loadBlock(const v3s16 &pos, std::string *block)
73 leveldb::Status status = m_database->Get(leveldb::ReadOptions(),
74 i64tos(getBlockAsInteger(pos)), block);
80 bool Database_LevelDB::deleteBlock(const v3s16 &pos)
82 leveldb::Status status = m_database->Delete(leveldb::WriteOptions(),
83 i64tos(getBlockAsInteger(pos)));
85 warningstream << "deleteBlock: LevelDB error deleting block "
86 << PP(pos) << ": " << status.ToString() << std::endl;
93 void Database_LevelDB::listAllLoadableBlocks(std::vector<v3s16> &dst)
95 leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions());
96 for (it->SeekToFirst(); it->Valid(); it->Next()) {
97 dst.push_back(getIntegerAsBlock(stoi64(it->key().ToString())));
99 ENSURE_STATUS_OK(it->status()); // Check for any errors found during the scan
103 PlayerDatabaseLevelDB::PlayerDatabaseLevelDB(const std::string &savedir)
105 leveldb::Options options;
106 options.create_if_missing = true;
107 leveldb::Status status = leveldb::DB::Open(options,
108 savedir + DIR_DELIM + "players.db", &m_database);
109 ENSURE_STATUS_OK(status);
112 PlayerDatabaseLevelDB::~PlayerDatabaseLevelDB()
117 void PlayerDatabaseLevelDB::savePlayer(RemotePlayer *player)
129 std::string (long) value
131 std::string (long) serialized_inventory
134 std::ostringstream os(std::ios_base::binary);
137 PlayerSAO *sao = player->getPlayerSAO();
139 writeU16(os, sao->getHP());
140 writeV3F32(os, sao->getBasePosition());
141 writeF32(os, sao->getLookPitch());
142 writeF32(os, sao->getRotation().Y);
143 writeU16(os, sao->getBreath());
145 const auto &stringvars = sao->getMeta().getStrings();
146 writeU32(os, stringvars.size());
147 for (const auto &it : stringvars) {
148 os << serializeString16(it.first);
149 os << serializeString32(it.second);
152 player->inventory.serialize(os);
154 leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
155 player->getName(), os.str());
156 ENSURE_STATUS_OK(status);
157 player->onSuccessfulSave();
160 bool PlayerDatabaseLevelDB::removePlayer(const std::string &name)
162 leveldb::Status s = m_database->Delete(leveldb::WriteOptions(), name);
166 bool PlayerDatabaseLevelDB::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
169 leveldb::Status s = m_database->Get(leveldb::ReadOptions(),
170 player->getName(), &raw);
173 std::istringstream is(raw, std::ios_base::binary);
178 sao->setHPRaw(readU16(is));
179 sao->setBasePosition(readV3F32(is));
180 sao->setLookPitch(readF32(is));
181 sao->setPlayerYaw(readF32(is));
182 sao->setBreath(readU16(is), false);
184 u32 attribute_count = readU32(is);
185 for (u32 i = 0; i < attribute_count; i++) {
186 std::string name = deSerializeString16(is);
187 std::string value = deSerializeString32(is);
188 sao->getMeta().setString(name, value);
190 sao->getMeta().setModified(false);
192 // This should always be last.
194 player->inventory.deSerialize(is);
195 } catch (SerializationError &e) {
196 errorstream << "Failed to deserialize player inventory. player_name="
197 << player->getName() << " " << e.what() << std::endl;
203 void PlayerDatabaseLevelDB::listPlayers(std::vector<std::string> &res)
205 leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions());
207 for (it->SeekToFirst(); it->Valid(); it->Next()) {
208 res.push_back(it->key().ToString());
213 AuthDatabaseLevelDB::AuthDatabaseLevelDB(const std::string &savedir)
215 leveldb::Options options;
216 options.create_if_missing = true;
217 leveldb::Status status = leveldb::DB::Open(options,
218 savedir + DIR_DELIM + "auth.db", &m_database);
219 ENSURE_STATUS_OK(status);
222 AuthDatabaseLevelDB::~AuthDatabaseLevelDB()
227 bool AuthDatabaseLevelDB::getAuth(const std::string &name, AuthEntry &res)
230 leveldb::Status s = m_database->Get(leveldb::ReadOptions(), name, &raw);
233 std::istringstream is(raw, std::ios_base::binary);
238 u16 number of privileges
240 std::string privilege
250 res.password = deSerializeString16(is);
252 u16 privilege_count = readU16(is);
253 res.privileges.clear();
254 res.privileges.reserve(privilege_count);
255 for (u16 i = 0; i < privilege_count; i++) {
256 res.privileges.push_back(deSerializeString16(is));
259 res.last_login = readS64(is);
263 bool AuthDatabaseLevelDB::saveAuth(const AuthEntry &authEntry)
265 std::ostringstream os(std::ios_base::binary);
267 os << serializeString16(authEntry.password);
269 size_t privilege_count = authEntry.privileges.size();
270 FATAL_ERROR_IF(privilege_count > U16_MAX,
271 "Unsupported number of privileges");
272 writeU16(os, privilege_count);
273 for (const std::string &privilege : authEntry.privileges) {
274 os << serializeString16(privilege);
277 writeS64(os, authEntry.last_login);
278 leveldb::Status s = m_database->Put(leveldb::WriteOptions(),
279 authEntry.name, os.str());
283 bool AuthDatabaseLevelDB::createAuth(AuthEntry &authEntry)
285 return saveAuth(authEntry);
288 bool AuthDatabaseLevelDB::deleteAuth(const std::string &name)
290 leveldb::Status s = m_database->Delete(leveldb::WriteOptions(), name);
294 void AuthDatabaseLevelDB::listNames(std::vector<std::string> &res)
296 leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions());
298 for (it->SeekToFirst(); it->Valid(); it->Next()) {
299 res.emplace_back(it->key().ToString());
304 void AuthDatabaseLevelDB::reload()
306 // No-op for LevelDB.
309 #endif // USE_LEVELDB