database-leveldb.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "config.h"
  17. #if USE_LEVELDB
  18. #include "database-leveldb.h"
  19. #include "log.h"
  20. #include "filesys.h"
  21. #include "exceptions.h"
  22. #include "remoteplayer.h"
  23. #include "irrlicht_changes/printing.h"
  24. #include "server/player_sao.h"
  25. #include "util/serialize.h"
  26. #include "util/string.h"
  27. #include "leveldb/db.h"
  28. #define ENSURE_STATUS_OK(s) \
  29. if (!(s).ok()) { \
  30. throw DatabaseException(std::string("LevelDB error: ") + \
  31. (s).ToString()); \
  32. }
  33. Database_LevelDB::Database_LevelDB(const std::string &savedir)
  34. {
  35. leveldb::Options options;
  36. options.create_if_missing = true;
  37. leveldb::DB *db;
  38. leveldb::Status status = leveldb::DB::Open(options,
  39. savedir + DIR_DELIM + "map.db", &db);
  40. ENSURE_STATUS_OK(status);
  41. m_database.reset(db);
  42. }
  43. bool Database_LevelDB::saveBlock(const v3s16 &pos, std::string_view data)
  44. {
  45. leveldb::Slice data_s(data.data(), data.size());
  46. leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
  47. i64tos(getBlockAsInteger(pos)), data_s);
  48. if (!status.ok()) {
  49. warningstream << "saveBlock: LevelDB error saving block "
  50. << pos << ": " << status.ToString() << std::endl;
  51. return false;
  52. }
  53. return true;
  54. }
  55. void Database_LevelDB::loadBlock(const v3s16 &pos, std::string *block)
  56. {
  57. leveldb::Status status = m_database->Get(leveldb::ReadOptions(),
  58. i64tos(getBlockAsInteger(pos)), block);
  59. if (!status.ok())
  60. block->clear();
  61. }
  62. bool Database_LevelDB::deleteBlock(const v3s16 &pos)
  63. {
  64. leveldb::Status status = m_database->Delete(leveldb::WriteOptions(),
  65. i64tos(getBlockAsInteger(pos)));
  66. if (!status.ok()) {
  67. warningstream << "deleteBlock: LevelDB error deleting block "
  68. << pos << ": " << status.ToString() << std::endl;
  69. return false;
  70. }
  71. return true;
  72. }
  73. void Database_LevelDB::listAllLoadableBlocks(std::vector<v3s16> &dst)
  74. {
  75. std::unique_ptr<leveldb::Iterator> it(m_database->NewIterator(leveldb::ReadOptions()));
  76. for (it->SeekToFirst(); it->Valid(); it->Next()) {
  77. dst.push_back(getIntegerAsBlock(stoi64(it->key().ToString())));
  78. }
  79. ENSURE_STATUS_OK(it->status()); // Check for any errors found during the scan
  80. }
  81. PlayerDatabaseLevelDB::PlayerDatabaseLevelDB(const std::string &savedir)
  82. {
  83. leveldb::Options options;
  84. options.create_if_missing = true;
  85. leveldb::DB *db;
  86. leveldb::Status status = leveldb::DB::Open(options,
  87. savedir + DIR_DELIM + "players.db", &db);
  88. ENSURE_STATUS_OK(status);
  89. m_database.reset(db);
  90. }
  91. void PlayerDatabaseLevelDB::savePlayer(RemotePlayer *player)
  92. {
  93. /*
  94. u8 version = 1
  95. u16 hp
  96. v3f position
  97. f32 pitch
  98. f32 yaw
  99. u16 breath
  100. u32 attribute_count
  101. for each attribute {
  102. std::string name
  103. std::string (long) value
  104. }
  105. std::string (long) serialized_inventory
  106. */
  107. std::ostringstream os(std::ios_base::binary);
  108. writeU8(os, 1);
  109. PlayerSAO *sao = player->getPlayerSAO();
  110. sanity_check(sao);
  111. writeU16(os, sao->getHP());
  112. writeV3F32(os, sao->getBasePosition());
  113. writeF32(os, sao->getLookPitch());
  114. writeF32(os, sao->getRotation().Y);
  115. writeU16(os, sao->getBreath());
  116. const auto &stringvars = sao->getMeta().getStrings();
  117. writeU32(os, stringvars.size());
  118. for (const auto &it : stringvars) {
  119. os << serializeString16(it.first);
  120. os << serializeString32(it.second);
  121. }
  122. player->inventory.serialize(os);
  123. leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
  124. player->getName(), os.str());
  125. ENSURE_STATUS_OK(status);
  126. player->onSuccessfulSave();
  127. }
  128. bool PlayerDatabaseLevelDB::removePlayer(const std::string &name)
  129. {
  130. leveldb::Status s = m_database->Delete(leveldb::WriteOptions(), name);
  131. return s.ok();
  132. }
  133. bool PlayerDatabaseLevelDB::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
  134. {
  135. std::string raw;
  136. leveldb::Status s = m_database->Get(leveldb::ReadOptions(),
  137. player->getName(), &raw);
  138. if (!s.ok())
  139. return false;
  140. std::istringstream is(raw, std::ios_base::binary);
  141. if (readU8(is) > 1)
  142. return false;
  143. sao->setHPRaw(readU16(is));
  144. sao->setBasePosition(readV3F32(is));
  145. sao->setLookPitch(readF32(is));
  146. sao->setPlayerYaw(readF32(is));
  147. sao->setBreath(readU16(is), false);
  148. u32 attribute_count = readU32(is);
  149. for (u32 i = 0; i < attribute_count; i++) {
  150. std::string name = deSerializeString16(is);
  151. std::string value = deSerializeString32(is);
  152. sao->getMeta().setString(name, value);
  153. }
  154. sao->getMeta().setModified(false);
  155. // This should always be last.
  156. try {
  157. player->inventory.deSerialize(is);
  158. } catch (SerializationError &e) {
  159. errorstream << "Failed to deserialize player inventory. player_name="
  160. << player->getName() << " " << e.what() << std::endl;
  161. }
  162. return true;
  163. }
  164. void PlayerDatabaseLevelDB::listPlayers(std::vector<std::string> &res)
  165. {
  166. std::unique_ptr<leveldb::Iterator> it(m_database->NewIterator(leveldb::ReadOptions()));
  167. res.clear();
  168. for (it->SeekToFirst(); it->Valid(); it->Next()) {
  169. res.push_back(it->key().ToString());
  170. }
  171. }
  172. AuthDatabaseLevelDB::AuthDatabaseLevelDB(const std::string &savedir)
  173. {
  174. leveldb::Options options;
  175. options.create_if_missing = true;
  176. leveldb::DB *db;
  177. leveldb::Status status = leveldb::DB::Open(options,
  178. savedir + DIR_DELIM + "auth.db", &db);
  179. ENSURE_STATUS_OK(status);
  180. m_database.reset(db);
  181. }
  182. bool AuthDatabaseLevelDB::getAuth(const std::string &name, AuthEntry &res)
  183. {
  184. std::string raw;
  185. leveldb::Status s = m_database->Get(leveldb::ReadOptions(), name, &raw);
  186. if (!s.ok())
  187. return false;
  188. std::istringstream is(raw, std::ios_base::binary);
  189. /*
  190. u8 version = 1
  191. std::string password
  192. u16 number of privileges
  193. for each privilege {
  194. std::string privilege
  195. }
  196. s64 last_login
  197. */
  198. if (readU8(is) > 1)
  199. return false;
  200. res.id = 1;
  201. res.name = name;
  202. res.password = deSerializeString16(is);
  203. u16 privilege_count = readU16(is);
  204. res.privileges.clear();
  205. res.privileges.reserve(privilege_count);
  206. for (u16 i = 0; i < privilege_count; i++) {
  207. res.privileges.push_back(deSerializeString16(is));
  208. }
  209. res.last_login = readS64(is);
  210. return true;
  211. }
  212. bool AuthDatabaseLevelDB::saveAuth(const AuthEntry &authEntry)
  213. {
  214. std::ostringstream os(std::ios_base::binary);
  215. writeU8(os, 1);
  216. os << serializeString16(authEntry.password);
  217. size_t privilege_count = authEntry.privileges.size();
  218. FATAL_ERROR_IF(privilege_count > U16_MAX,
  219. "Unsupported number of privileges");
  220. writeU16(os, privilege_count);
  221. for (const std::string &privilege : authEntry.privileges) {
  222. os << serializeString16(privilege);
  223. }
  224. writeS64(os, authEntry.last_login);
  225. leveldb::Status s = m_database->Put(leveldb::WriteOptions(),
  226. authEntry.name, os.str());
  227. return s.ok();
  228. }
  229. bool AuthDatabaseLevelDB::createAuth(AuthEntry &authEntry)
  230. {
  231. return saveAuth(authEntry);
  232. }
  233. bool AuthDatabaseLevelDB::deleteAuth(const std::string &name)
  234. {
  235. leveldb::Status s = m_database->Delete(leveldb::WriteOptions(), name);
  236. return s.ok();
  237. }
  238. void AuthDatabaseLevelDB::listNames(std::vector<std::string> &res)
  239. {
  240. std::unique_ptr<leveldb::Iterator> it(m_database->NewIterator(leveldb::ReadOptions()));
  241. res.clear();
  242. for (it->SeekToFirst(); it->Valid(); it->Next()) {
  243. res.emplace_back(it->key().ToString());
  244. }
  245. }
  246. void AuthDatabaseLevelDB::reload()
  247. {
  248. // No-op for LevelDB.
  249. }
  250. #endif // USE_LEVELDB