rollback.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  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 "rollback.h"
  17. #include <fstream>
  18. #include <list>
  19. #include <sstream>
  20. #include "log.h"
  21. #include "mapnode.h"
  22. #include "gamedef.h"
  23. #include "nodedef.h"
  24. #include "util/serialize.h"
  25. #include "util/string.h"
  26. #include "util/numeric.h"
  27. #include "inventorymanager.h" // deserializing InventoryLocations
  28. #include "sqlite3.h"
  29. #include "filesys.h"
  30. #define POINTS_PER_NODE (16.0)
  31. #define SQLRES(f, good) \
  32. if ((f) != (good)) {\
  33. throw FileNotGoodException(std::string("RollbackManager: " \
  34. "SQLite3 error (" __FILE__ ":" TOSTRING(__LINE__) \
  35. "): ") + sqlite3_errmsg(db)); \
  36. }
  37. #define SQLOK(f) SQLRES(f, SQLITE_OK)
  38. #define SQLOK_ERRSTREAM(s, m) \
  39. if ((s) != SQLITE_OK) { \
  40. errorstream << "RollbackManager: " << (m) << ": " \
  41. << sqlite3_errmsg(db) << std::endl; \
  42. }
  43. #define FINALIZE_STATEMENT(statement) \
  44. SQLOK_ERRSTREAM(sqlite3_finalize(statement), "Failed to finalize " #statement)
  45. class ItemStackRow : public ItemStack {
  46. public:
  47. ItemStackRow & operator = (const ItemStack & other)
  48. {
  49. *static_cast<ItemStack *>(this) = other;
  50. return *this;
  51. }
  52. int id;
  53. };
  54. struct ActionRow {
  55. int id;
  56. int actor;
  57. time_t timestamp;
  58. int type;
  59. std::string location, list;
  60. int index, add;
  61. ItemStackRow stack;
  62. int nodeMeta;
  63. int x, y, z;
  64. int oldNode;
  65. int oldParam1, oldParam2;
  66. std::string oldMeta;
  67. int newNode;
  68. int newParam1, newParam2;
  69. std::string newMeta;
  70. int guessed;
  71. };
  72. struct Entity {
  73. int id;
  74. std::string name;
  75. };
  76. RollbackManager::RollbackManager(const std::string & world_path,
  77. IGameDef * gamedef_) :
  78. gamedef(gamedef_)
  79. {
  80. verbosestream << "RollbackManager::RollbackManager(" << world_path
  81. << ")" << std::endl;
  82. std::string txt_filename = world_path + DIR_DELIM "rollback.txt";
  83. std::string migrating_flag = txt_filename + ".migrating";
  84. database_path = world_path + DIR_DELIM "rollback.sqlite";
  85. bool created = initDatabase();
  86. if (fs::PathExists(txt_filename) && (created ||
  87. fs::PathExists(migrating_flag))) {
  88. std::ofstream of(migrating_flag.c_str());
  89. of.close();
  90. migrate(txt_filename);
  91. fs::DeleteSingleFileOrEmptyDirectory(migrating_flag);
  92. }
  93. }
  94. RollbackManager::~RollbackManager()
  95. {
  96. flush();
  97. FINALIZE_STATEMENT(stmt_insert);
  98. FINALIZE_STATEMENT(stmt_replace);
  99. FINALIZE_STATEMENT(stmt_select);
  100. FINALIZE_STATEMENT(stmt_select_range);
  101. FINALIZE_STATEMENT(stmt_select_withActor);
  102. FINALIZE_STATEMENT(stmt_knownActor_select);
  103. FINALIZE_STATEMENT(stmt_knownActor_insert);
  104. FINALIZE_STATEMENT(stmt_knownNode_select);
  105. FINALIZE_STATEMENT(stmt_knownNode_insert);
  106. SQLOK_ERRSTREAM(sqlite3_close(db), "Could not close db");
  107. }
  108. void RollbackManager::registerNewActor(const int id, const std::string &name)
  109. {
  110. Entity actor = {id, name};
  111. knownActors.push_back(actor);
  112. }
  113. void RollbackManager::registerNewNode(const int id, const std::string &name)
  114. {
  115. Entity node = {id, name};
  116. knownNodes.push_back(node);
  117. }
  118. int RollbackManager::getActorId(const std::string &name)
  119. {
  120. for (std::vector<Entity>::const_iterator iter = knownActors.begin();
  121. iter != knownActors.end(); ++iter) {
  122. if (iter->name == name) {
  123. return iter->id;
  124. }
  125. }
  126. SQLOK(sqlite3_bind_text(stmt_knownActor_insert, 1, name.c_str(), name.size(), NULL));
  127. SQLRES(sqlite3_step(stmt_knownActor_insert), SQLITE_DONE);
  128. SQLOK(sqlite3_reset(stmt_knownActor_insert));
  129. int id = sqlite3_last_insert_rowid(db);
  130. registerNewActor(id, name);
  131. return id;
  132. }
  133. int RollbackManager::getNodeId(const std::string &name)
  134. {
  135. for (std::vector<Entity>::const_iterator iter = knownNodes.begin();
  136. iter != knownNodes.end(); ++iter) {
  137. if (iter->name == name) {
  138. return iter->id;
  139. }
  140. }
  141. SQLOK(sqlite3_bind_text(stmt_knownNode_insert, 1, name.c_str(), name.size(), NULL));
  142. SQLRES(sqlite3_step(stmt_knownNode_insert), SQLITE_DONE);
  143. SQLOK(sqlite3_reset(stmt_knownNode_insert));
  144. int id = sqlite3_last_insert_rowid(db);
  145. registerNewNode(id, name);
  146. return id;
  147. }
  148. const char * RollbackManager::getActorName(const int id)
  149. {
  150. for (std::vector<Entity>::const_iterator iter = knownActors.begin();
  151. iter != knownActors.end(); ++iter) {
  152. if (iter->id == id) {
  153. return iter->name.c_str();
  154. }
  155. }
  156. return "";
  157. }
  158. const char * RollbackManager::getNodeName(const int id)
  159. {
  160. for (std::vector<Entity>::const_iterator iter = knownNodes.begin();
  161. iter != knownNodes.end(); ++iter) {
  162. if (iter->id == id) {
  163. return iter->name.c_str();
  164. }
  165. }
  166. return "";
  167. }
  168. bool RollbackManager::createTables()
  169. {
  170. SQLOK(sqlite3_exec(db,
  171. "CREATE TABLE IF NOT EXISTS `actor` (\n"
  172. " `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
  173. " `name` TEXT NOT NULL\n"
  174. ");\n"
  175. "CREATE TABLE IF NOT EXISTS `node` (\n"
  176. " `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
  177. " `name` TEXT NOT NULL\n"
  178. ");\n"
  179. "CREATE TABLE IF NOT EXISTS `action` (\n"
  180. " `id` INTEGER PRIMARY KEY AUTOINCREMENT,\n"
  181. " `actor` INTEGER NOT NULL,\n"
  182. " `timestamp` TIMESTAMP NOT NULL,\n"
  183. " `type` INTEGER NOT NULL,\n"
  184. " `list` TEXT,\n"
  185. " `index` INTEGER,\n"
  186. " `add` INTEGER,\n"
  187. " `stackNode` INTEGER,\n"
  188. " `stackQuantity` INTEGER,\n"
  189. " `nodeMeta` INTEGER,\n"
  190. " `x` INT,\n"
  191. " `y` INT,\n"
  192. " `z` INT,\n"
  193. " `oldNode` INTEGER,\n"
  194. " `oldParam1` INTEGER,\n"
  195. " `oldParam2` INTEGER,\n"
  196. " `oldMeta` TEXT,\n"
  197. " `newNode` INTEGER,\n"
  198. " `newParam1` INTEGER,\n"
  199. " `newParam2` INTEGER,\n"
  200. " `newMeta` TEXT,\n"
  201. " `guessedActor` INTEGER,\n"
  202. " FOREIGN KEY (`actor`) REFERENCES `actor`(`id`),\n"
  203. " FOREIGN KEY (`stackNode`) REFERENCES `node`(`id`),\n"
  204. " FOREIGN KEY (`oldNode`) REFERENCES `node`(`id`),\n"
  205. " FOREIGN KEY (`newNode`) REFERENCES `node`(`id`)\n"
  206. ");\n"
  207. "CREATE INDEX IF NOT EXISTS `actionIndex` ON `action`(`x`,`y`,`z`,`timestamp`,`actor`);\n",
  208. NULL, NULL, NULL));
  209. verbosestream << "SQL Rollback: SQLite3 database structure was created" << std::endl;
  210. return true;
  211. }
  212. bool RollbackManager::initDatabase()
  213. {
  214. verbosestream << "RollbackManager: Database connection setup" << std::endl;
  215. bool needs_create = !fs::PathExists(database_path);
  216. SQLOK(sqlite3_open_v2(database_path.c_str(), &db,
  217. SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL));
  218. if (needs_create) {
  219. createTables();
  220. }
  221. SQLOK(sqlite3_prepare_v2(db,
  222. "INSERT INTO `action` (\n"
  223. " `actor`, `timestamp`, `type`,\n"
  224. " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodeMeta`,\n"
  225. " `x`, `y`, `z`,\n"
  226. " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`,\n"
  227. " `newNode`, `newParam1`, `newParam2`, `newMeta`,\n"
  228. " `guessedActor`\n"
  229. ") VALUES (\n"
  230. " ?, ?, ?,\n"
  231. " ?, ?, ?, ?, ?, ?,\n"
  232. " ?, ?, ?,\n"
  233. " ?, ?, ?, ?,\n"
  234. " ?, ?, ?, ?,\n"
  235. " ?"
  236. ");",
  237. -1, &stmt_insert, NULL));
  238. SQLOK(sqlite3_prepare_v2(db,
  239. "REPLACE INTO `action` (\n"
  240. " `actor`, `timestamp`, `type`,\n"
  241. " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodeMeta`,\n"
  242. " `x`, `y`, `z`,\n"
  243. " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`,\n"
  244. " `newNode`, `newParam1`, `newParam2`, `newMeta`,\n"
  245. " `guessedActor`, `id`\n"
  246. ") VALUES (\n"
  247. " ?, ?, ?,\n"
  248. " ?, ?, ?, ?, ?, ?,\n"
  249. " ?, ?, ?,\n"
  250. " ?, ?, ?, ?,\n"
  251. " ?, ?, ?, ?,\n"
  252. " ?, ?\n"
  253. ");",
  254. -1, &stmt_replace, NULL));
  255. SQLOK(sqlite3_prepare_v2(db,
  256. "SELECT\n"
  257. " `actor`, `timestamp`, `type`,\n"
  258. " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodemeta`,\n"
  259. " `x`, `y`, `z`,\n"
  260. " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`,\n"
  261. " `newNode`, `newParam1`, `newParam2`, `newMeta`,\n"
  262. " `guessedActor`\n"
  263. " FROM `action`\n"
  264. " WHERE `timestamp` >= ?\n"
  265. " ORDER BY `timestamp` DESC, `id` DESC",
  266. -1, &stmt_select, NULL));
  267. SQLOK(sqlite3_prepare_v2(db,
  268. "SELECT\n"
  269. " `actor`, `timestamp`, `type`,\n"
  270. " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodemeta`,\n"
  271. " `x`, `y`, `z`,\n"
  272. " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`,\n"
  273. " `newNode`, `newParam1`, `newParam2`, `newMeta`,\n"
  274. " `guessedActor`\n"
  275. "FROM `action`\n"
  276. "WHERE `timestamp` >= ?\n"
  277. " AND `x` IS NOT NULL\n"
  278. " AND `y` IS NOT NULL\n"
  279. " AND `z` IS NOT NULL\n"
  280. " AND `x` BETWEEN ? AND ?\n"
  281. " AND `y` BETWEEN ? AND ?\n"
  282. " AND `z` BETWEEN ? AND ?\n"
  283. "ORDER BY `timestamp` DESC, `id` DESC\n"
  284. "LIMIT 0,?",
  285. -1, &stmt_select_range, NULL));
  286. SQLOK(sqlite3_prepare_v2(db,
  287. "SELECT\n"
  288. " `actor`, `timestamp`, `type`,\n"
  289. " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodemeta`,\n"
  290. " `x`, `y`, `z`,\n"
  291. " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`,\n"
  292. " `newNode`, `newParam1`, `newParam2`, `newMeta`,\n"
  293. " `guessedActor`\n"
  294. "FROM `action`\n"
  295. "WHERE `timestamp` >= ?\n"
  296. " AND `actor` = ?\n"
  297. "ORDER BY `timestamp` DESC, `id` DESC\n",
  298. -1, &stmt_select_withActor, NULL));
  299. SQLOK(sqlite3_prepare_v2(db, "SELECT `id`, `name` FROM `actor`",
  300. -1, &stmt_knownActor_select, NULL));
  301. SQLOK(sqlite3_prepare_v2(db, "INSERT INTO `actor` (`name`) VALUES (?)",
  302. -1, &stmt_knownActor_insert, NULL));
  303. SQLOK(sqlite3_prepare_v2(db, "SELECT `id`, `name` FROM `node`",
  304. -1, &stmt_knownNode_select, NULL));
  305. SQLOK(sqlite3_prepare_v2(db, "INSERT INTO `node` (`name`) VALUES (?)",
  306. -1, &stmt_knownNode_insert, NULL));
  307. verbosestream << "SQL prepared statements setup correctly" << std::endl;
  308. while (sqlite3_step(stmt_knownActor_select) == SQLITE_ROW) {
  309. registerNewActor(
  310. sqlite3_column_int(stmt_knownActor_select, 0),
  311. reinterpret_cast<const char *>(sqlite3_column_text(stmt_knownActor_select, 1))
  312. );
  313. }
  314. SQLOK(sqlite3_reset(stmt_knownActor_select));
  315. while (sqlite3_step(stmt_knownNode_select) == SQLITE_ROW) {
  316. registerNewNode(
  317. sqlite3_column_int(stmt_knownNode_select, 0),
  318. reinterpret_cast<const char *>(sqlite3_column_text(stmt_knownNode_select, 1))
  319. );
  320. }
  321. SQLOK(sqlite3_reset(stmt_knownNode_select));
  322. return needs_create;
  323. }
  324. bool RollbackManager::registerRow(const ActionRow & row)
  325. {
  326. sqlite3_stmt * stmt_do = (row.id) ? stmt_replace : stmt_insert;
  327. bool nodeMeta = false;
  328. SQLOK(sqlite3_bind_int (stmt_do, 1, row.actor));
  329. SQLOK(sqlite3_bind_int64(stmt_do, 2, row.timestamp));
  330. SQLOK(sqlite3_bind_int (stmt_do, 3, row.type));
  331. if (row.type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) {
  332. const std::string & loc = row.location;
  333. nodeMeta = (loc.substr(0, 9) == "nodemeta:");
  334. SQLOK(sqlite3_bind_text(stmt_do, 4, row.list.c_str(), row.list.size(), NULL));
  335. SQLOK(sqlite3_bind_int (stmt_do, 5, row.index));
  336. SQLOK(sqlite3_bind_int (stmt_do, 6, row.add));
  337. SQLOK(sqlite3_bind_int (stmt_do, 7, row.stack.id));
  338. SQLOK(sqlite3_bind_int (stmt_do, 8, row.stack.count));
  339. SQLOK(sqlite3_bind_int (stmt_do, 9, (int) nodeMeta));
  340. if (nodeMeta) {
  341. std::string::size_type p1, p2;
  342. p1 = loc.find(':') + 1;
  343. p2 = loc.find(',');
  344. std::string x = loc.substr(p1, p2 - p1);
  345. p1 = p2 + 1;
  346. p2 = loc.find(',', p1);
  347. std::string y = loc.substr(p1, p2 - p1);
  348. std::string z = loc.substr(p2 + 1);
  349. SQLOK(sqlite3_bind_int(stmt_do, 10, atoi(x.c_str())));
  350. SQLOK(sqlite3_bind_int(stmt_do, 11, atoi(y.c_str())));
  351. SQLOK(sqlite3_bind_int(stmt_do, 12, atoi(z.c_str())));
  352. }
  353. } else {
  354. SQLOK(sqlite3_bind_null(stmt_do, 4));
  355. SQLOK(sqlite3_bind_null(stmt_do, 5));
  356. SQLOK(sqlite3_bind_null(stmt_do, 6));
  357. SQLOK(sqlite3_bind_null(stmt_do, 7));
  358. SQLOK(sqlite3_bind_null(stmt_do, 8));
  359. SQLOK(sqlite3_bind_null(stmt_do, 9));
  360. }
  361. if (row.type == RollbackAction::TYPE_SET_NODE) {
  362. SQLOK(sqlite3_bind_int (stmt_do, 10, row.x));
  363. SQLOK(sqlite3_bind_int (stmt_do, 11, row.y));
  364. SQLOK(sqlite3_bind_int (stmt_do, 12, row.z));
  365. SQLOK(sqlite3_bind_int (stmt_do, 13, row.oldNode));
  366. SQLOK(sqlite3_bind_int (stmt_do, 14, row.oldParam1));
  367. SQLOK(sqlite3_bind_int (stmt_do, 15, row.oldParam2));
  368. SQLOK(sqlite3_bind_text(stmt_do, 16, row.oldMeta.c_str(), row.oldMeta.size(), NULL));
  369. SQLOK(sqlite3_bind_int (stmt_do, 17, row.newNode));
  370. SQLOK(sqlite3_bind_int (stmt_do, 18, row.newParam1));
  371. SQLOK(sqlite3_bind_int (stmt_do, 19, row.newParam2));
  372. SQLOK(sqlite3_bind_text(stmt_do, 20, row.newMeta.c_str(), row.newMeta.size(), NULL));
  373. SQLOK(sqlite3_bind_int (stmt_do, 21, row.guessed ? 1 : 0));
  374. } else {
  375. if (!nodeMeta) {
  376. SQLOK(sqlite3_bind_null(stmt_do, 10));
  377. SQLOK(sqlite3_bind_null(stmt_do, 11));
  378. SQLOK(sqlite3_bind_null(stmt_do, 12));
  379. }
  380. SQLOK(sqlite3_bind_null(stmt_do, 13));
  381. SQLOK(sqlite3_bind_null(stmt_do, 14));
  382. SQLOK(sqlite3_bind_null(stmt_do, 15));
  383. SQLOK(sqlite3_bind_null(stmt_do, 16));
  384. SQLOK(sqlite3_bind_null(stmt_do, 17));
  385. SQLOK(sqlite3_bind_null(stmt_do, 18));
  386. SQLOK(sqlite3_bind_null(stmt_do, 19));
  387. SQLOK(sqlite3_bind_null(stmt_do, 20));
  388. SQLOK(sqlite3_bind_null(stmt_do, 21));
  389. }
  390. if (row.id) {
  391. SQLOK(sqlite3_bind_int(stmt_do, 22, row.id));
  392. }
  393. int written = sqlite3_step(stmt_do);
  394. SQLOK(sqlite3_reset(stmt_do));
  395. return written == SQLITE_DONE;
  396. }
  397. const std::list<ActionRow> RollbackManager::actionRowsFromSelect(sqlite3_stmt* stmt)
  398. {
  399. std::list<ActionRow> rows;
  400. const unsigned char * text;
  401. size_t size;
  402. while (sqlite3_step(stmt) == SQLITE_ROW) {
  403. ActionRow row;
  404. row.actor = sqlite3_column_int (stmt, 0);
  405. row.timestamp = sqlite3_column_int64(stmt, 1);
  406. row.type = sqlite3_column_int (stmt, 2);
  407. if (row.type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) {
  408. text = sqlite3_column_text (stmt, 3);
  409. size = sqlite3_column_bytes(stmt, 3);
  410. row.list = std::string(reinterpret_cast<const char*>(text), size);
  411. row.index = sqlite3_column_int(stmt, 4);
  412. row.add = sqlite3_column_int(stmt, 5);
  413. row.stack.id = sqlite3_column_int(stmt, 6);
  414. row.stack.count = sqlite3_column_int(stmt, 7);
  415. row.nodeMeta = sqlite3_column_int(stmt, 8);
  416. }
  417. if (row.type == RollbackAction::TYPE_SET_NODE || row.nodeMeta) {
  418. row.x = sqlite3_column_int(stmt, 9);
  419. row.y = sqlite3_column_int(stmt, 10);
  420. row.z = sqlite3_column_int(stmt, 11);
  421. }
  422. if (row.type == RollbackAction::TYPE_SET_NODE) {
  423. row.oldNode = sqlite3_column_int(stmt, 12);
  424. row.oldParam1 = sqlite3_column_int(stmt, 13);
  425. row.oldParam2 = sqlite3_column_int(stmt, 14);
  426. text = sqlite3_column_text (stmt, 15);
  427. size = sqlite3_column_bytes(stmt, 15);
  428. row.oldMeta = std::string(reinterpret_cast<const char*>(text), size);
  429. row.newNode = sqlite3_column_int(stmt, 16);
  430. row.newParam1 = sqlite3_column_int(stmt, 17);
  431. row.newParam2 = sqlite3_column_int(stmt, 18);
  432. text = sqlite3_column_text(stmt, 19);
  433. size = sqlite3_column_bytes(stmt, 19);
  434. row.newMeta = std::string(reinterpret_cast<const char*>(text), size);
  435. row.guessed = sqlite3_column_int(stmt, 20);
  436. }
  437. if (row.nodeMeta) {
  438. row.location = "nodemeta:";
  439. row.location += itos(row.x);
  440. row.location += ',';
  441. row.location += itos(row.y);
  442. row.location += ',';
  443. row.location += itos(row.z);
  444. } else {
  445. row.location = getActorName(row.actor);
  446. }
  447. rows.push_back(row);
  448. }
  449. SQLOK(sqlite3_reset(stmt));
  450. return rows;
  451. }
  452. ActionRow RollbackManager::actionRowFromRollbackAction(const RollbackAction & action)
  453. {
  454. ActionRow row;
  455. row.id = 0;
  456. row.actor = getActorId(action.actor);
  457. row.timestamp = action.unix_time;
  458. row.type = action.type;
  459. if (row.type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) {
  460. row.location = action.inventory_location;
  461. row.list = action.inventory_list;
  462. row.index = action.inventory_index;
  463. row.add = action.inventory_add;
  464. row.stack = action.inventory_stack;
  465. row.stack.id = getNodeId(row.stack.name);
  466. } else {
  467. row.x = action.p.X;
  468. row.y = action.p.Y;
  469. row.z = action.p.Z;
  470. row.oldNode = getNodeId(action.n_old.name);
  471. row.oldParam1 = action.n_old.param1;
  472. row.oldParam2 = action.n_old.param2;
  473. row.oldMeta = action.n_old.meta;
  474. row.newNode = getNodeId(action.n_new.name);
  475. row.newParam1 = action.n_new.param1;
  476. row.newParam2 = action.n_new.param2;
  477. row.newMeta = action.n_new.meta;
  478. row.guessed = action.actor_is_guess;
  479. }
  480. return row;
  481. }
  482. const std::list<RollbackAction> RollbackManager::rollbackActionsFromActionRows(
  483. const std::list<ActionRow> & rows)
  484. {
  485. std::list<RollbackAction> actions;
  486. for (const ActionRow &row : rows) {
  487. RollbackAction action;
  488. action.actor = (row.actor) ? getActorName(row.actor) : "";
  489. action.unix_time = row.timestamp;
  490. action.type = static_cast<RollbackAction::Type>(row.type);
  491. switch (action.type) {
  492. case RollbackAction::TYPE_MODIFY_INVENTORY_STACK:
  493. action.inventory_location = row.location;
  494. action.inventory_list = row.list;
  495. action.inventory_index = row.index;
  496. action.inventory_add = row.add;
  497. action.inventory_stack = row.stack;
  498. if (action.inventory_stack.name.empty()) {
  499. action.inventory_stack.name = getNodeName(row.stack.id);
  500. }
  501. break;
  502. case RollbackAction::TYPE_SET_NODE:
  503. action.p = v3s16(row.x, row.y, row.z);
  504. action.n_old.name = getNodeName(row.oldNode);
  505. action.n_old.param1 = row.oldParam1;
  506. action.n_old.param2 = row.oldParam2;
  507. action.n_old.meta = row.oldMeta;
  508. action.n_new.name = getNodeName(row.newNode);
  509. action.n_new.param1 = row.newParam1;
  510. action.n_new.param2 = row.newParam2;
  511. action.n_new.meta = row.newMeta;
  512. break;
  513. default:
  514. throw ("W.T.F.");
  515. break;
  516. }
  517. actions.push_back(action);
  518. }
  519. return actions;
  520. }
  521. const std::list<ActionRow> RollbackManager::getRowsSince(time_t firstTime, const std::string & actor)
  522. {
  523. sqlite3_stmt *stmt_stmt = actor.empty() ? stmt_select : stmt_select_withActor;
  524. sqlite3_bind_int64(stmt_stmt, 1, firstTime);
  525. if (!actor.empty()) {
  526. sqlite3_bind_int(stmt_stmt, 2, getActorId(actor));
  527. }
  528. const std::list<ActionRow> & rows = actionRowsFromSelect(stmt_stmt);
  529. sqlite3_reset(stmt_stmt);
  530. return rows;
  531. }
  532. const std::list<ActionRow> RollbackManager::getRowsSince_range(
  533. time_t start_time, v3s16 p, int range, int limit)
  534. {
  535. sqlite3_bind_int64(stmt_select_range, 1, start_time);
  536. sqlite3_bind_int (stmt_select_range, 2, static_cast<int>(p.X - range));
  537. sqlite3_bind_int (stmt_select_range, 3, static_cast<int>(p.X + range));
  538. sqlite3_bind_int (stmt_select_range, 4, static_cast<int>(p.Y - range));
  539. sqlite3_bind_int (stmt_select_range, 5, static_cast<int>(p.Y + range));
  540. sqlite3_bind_int (stmt_select_range, 6, static_cast<int>(p.Z - range));
  541. sqlite3_bind_int (stmt_select_range, 7, static_cast<int>(p.Z + range));
  542. sqlite3_bind_int (stmt_select_range, 8, limit);
  543. const std::list<ActionRow> & rows = actionRowsFromSelect(stmt_select_range);
  544. sqlite3_reset(stmt_select_range);
  545. return rows;
  546. }
  547. const std::list<RollbackAction> RollbackManager::getActionsSince_range(
  548. time_t start_time, v3s16 p, int range, int limit)
  549. {
  550. return rollbackActionsFromActionRows(getRowsSince_range(start_time, p, range, limit));
  551. }
  552. const std::list<RollbackAction> RollbackManager::getActionsSince(
  553. time_t start_time, const std::string & actor)
  554. {
  555. return rollbackActionsFromActionRows(getRowsSince(start_time, actor));
  556. }
  557. void RollbackManager::migrate(const std::string & file_path)
  558. {
  559. std::cout << "Migrating from rollback.txt to rollback.sqlite." << std::endl;
  560. std::ifstream fh(file_path.c_str(), std::ios::in | std::ios::ate);
  561. if (!fh.good()) {
  562. throw FileNotGoodException("Unable to open rollback.txt");
  563. }
  564. std::streampos file_size = fh.tellg();
  565. if (file_size < 10) {
  566. errorstream << "Empty rollback log." << std::endl;
  567. return;
  568. }
  569. fh.seekg(0);
  570. sqlite3_stmt *stmt_begin;
  571. sqlite3_stmt *stmt_commit;
  572. SQLOK(sqlite3_prepare_v2(db, "BEGIN", -1, &stmt_begin, NULL));
  573. SQLOK(sqlite3_prepare_v2(db, "COMMIT", -1, &stmt_commit, NULL));
  574. std::string bit;
  575. int i = 0;
  576. time_t start = time(0);
  577. time_t t = start;
  578. SQLRES(sqlite3_step(stmt_begin), SQLITE_DONE);
  579. sqlite3_reset(stmt_begin);
  580. do {
  581. ActionRow row;
  582. row.id = 0;
  583. // Get the timestamp
  584. std::getline(fh, bit, ' ');
  585. bit = trim(bit);
  586. if (!atoi(bit.c_str())) {
  587. std::getline(fh, bit);
  588. continue;
  589. }
  590. row.timestamp = atoi(bit.c_str());
  591. // Get the actor
  592. row.actor = getActorId(deSerializeJsonString(fh));
  593. // Get the action type
  594. std::getline(fh, bit, '[');
  595. std::getline(fh, bit, ' ');
  596. if (bit == "modify_inventory_stack") {
  597. row.type = RollbackAction::TYPE_MODIFY_INVENTORY_STACK;
  598. row.location = trim(deSerializeJsonString(fh));
  599. std::getline(fh, bit, ' ');
  600. row.list = trim(deSerializeJsonString(fh));
  601. std::getline(fh, bit, ' ');
  602. std::getline(fh, bit, ' ');
  603. row.index = atoi(trim(bit).c_str());
  604. std::getline(fh, bit, ' ');
  605. row.add = (int)(trim(bit) == "add");
  606. row.stack.deSerialize(deSerializeJsonString(fh));
  607. row.stack.id = getNodeId(row.stack.name);
  608. std::getline(fh, bit);
  609. } else if (bit == "set_node") {
  610. row.type = RollbackAction::TYPE_SET_NODE;
  611. std::getline(fh, bit, '(');
  612. std::getline(fh, bit, ',');
  613. row.x = atoi(trim(bit).c_str());
  614. std::getline(fh, bit, ',');
  615. row.y = atoi(trim(bit).c_str());
  616. std::getline(fh, bit, ')');
  617. row.z = atoi(trim(bit).c_str());
  618. std::getline(fh, bit, ' ');
  619. row.oldNode = getNodeId(trim(deSerializeJsonString(fh)));
  620. std::getline(fh, bit, ' ');
  621. std::getline(fh, bit, ' ');
  622. row.oldParam1 = atoi(trim(bit).c_str());
  623. std::getline(fh, bit, ' ');
  624. row.oldParam2 = atoi(trim(bit).c_str());
  625. row.oldMeta = trim(deSerializeJsonString(fh));
  626. std::getline(fh, bit, ' ');
  627. row.newNode = getNodeId(trim(deSerializeJsonString(fh)));
  628. std::getline(fh, bit, ' ');
  629. std::getline(fh, bit, ' ');
  630. row.newParam1 = atoi(trim(bit).c_str());
  631. std::getline(fh, bit, ' ');
  632. row.newParam2 = atoi(trim(bit).c_str());
  633. row.newMeta = trim(deSerializeJsonString(fh));
  634. std::getline(fh, bit, ' ');
  635. std::getline(fh, bit, ' ');
  636. std::getline(fh, bit);
  637. row.guessed = (int)(trim(bit) == "actor_is_guess");
  638. } else {
  639. errorstream << "Unrecognized rollback action type \""
  640. << bit << "\"!" << std::endl;
  641. continue;
  642. }
  643. registerRow(row);
  644. ++i;
  645. if (time(0) - t >= 1) {
  646. SQLRES(sqlite3_step(stmt_commit), SQLITE_DONE);
  647. sqlite3_reset(stmt_commit);
  648. t = time(0);
  649. std::cout
  650. << " Done: " << static_cast<int>((static_cast<float>(fh.tellg()) / static_cast<float>(file_size)) * 100) << "%"
  651. << " Speed: " << i / (t - start) << "/second \r" << std::flush;
  652. SQLRES(sqlite3_step(stmt_begin), SQLITE_DONE);
  653. sqlite3_reset(stmt_begin);
  654. }
  655. } while (fh.good());
  656. SQLRES(sqlite3_step(stmt_commit), SQLITE_DONE);
  657. sqlite3_reset(stmt_commit);
  658. SQLOK(sqlite3_finalize(stmt_begin));
  659. SQLOK(sqlite3_finalize(stmt_commit));
  660. std::cout
  661. << " Done: 100% " << std::endl
  662. << "Now you can delete the old rollback.txt file." << std::endl;
  663. }
  664. // Get nearness factor for subject's action for this action
  665. // Return value: 0 = impossible, >0 = factor
  666. float RollbackManager::getSuspectNearness(bool is_guess, v3s16 suspect_p,
  667. time_t suspect_t, v3s16 action_p, time_t action_t)
  668. {
  669. // Suspect cannot cause things in the past
  670. if (action_t < suspect_t) {
  671. return 0; // 0 = cannot be
  672. }
  673. // Start from 100
  674. int f = 100;
  675. // Distance (1 node = -x points)
  676. f -= POINTS_PER_NODE * intToFloat(suspect_p, 1).getDistanceFrom(intToFloat(action_p, 1));
  677. // Time (1 second = -x points)
  678. f -= 1 * (action_t - suspect_t);
  679. // If is a guess, halve the points
  680. if (is_guess) {
  681. f *= 0.5;
  682. }
  683. // Limit to 0
  684. if (f < 0) {
  685. f = 0;
  686. }
  687. return f;
  688. }
  689. void RollbackManager::reportAction(const RollbackAction &action_)
  690. {
  691. // Ignore if not important
  692. if (!action_.isImportant(gamedef)) {
  693. return;
  694. }
  695. RollbackAction action = action_;
  696. action.unix_time = time(0);
  697. // Figure out actor
  698. action.actor = current_actor;
  699. action.actor_is_guess = current_actor_is_guess;
  700. if (action.actor.empty()) { // If actor is not known, find out suspect or cancel
  701. v3s16 p;
  702. if (!action.getPosition(&p)) {
  703. return;
  704. }
  705. action.actor = getSuspect(p, 83, 1);
  706. if (action.actor.empty()) {
  707. return;
  708. }
  709. action.actor_is_guess = true;
  710. }
  711. addAction(action);
  712. }
  713. std::string RollbackManager::getActor()
  714. {
  715. return current_actor;
  716. }
  717. bool RollbackManager::isActorGuess()
  718. {
  719. return current_actor_is_guess;
  720. }
  721. void RollbackManager::setActor(const std::string & actor, bool is_guess)
  722. {
  723. current_actor = actor;
  724. current_actor_is_guess = is_guess;
  725. }
  726. std::string RollbackManager::getSuspect(v3s16 p, float nearness_shortcut,
  727. float min_nearness)
  728. {
  729. if (!current_actor.empty()) {
  730. return current_actor;
  731. }
  732. int cur_time = time(0);
  733. time_t first_time = cur_time - (100 - min_nearness);
  734. RollbackAction likely_suspect;
  735. float likely_suspect_nearness = 0;
  736. for (std::list<RollbackAction>::const_reverse_iterator
  737. i = action_latest_buffer.rbegin();
  738. i != action_latest_buffer.rend(); ++i) {
  739. if (i->unix_time < first_time) {
  740. break;
  741. }
  742. if (i->actor.empty()) {
  743. continue;
  744. }
  745. // Find position of suspect or continue
  746. v3s16 suspect_p;
  747. if (!i->getPosition(&suspect_p)) {
  748. continue;
  749. }
  750. float f = getSuspectNearness(i->actor_is_guess, suspect_p,
  751. i->unix_time, p, cur_time);
  752. if (f >= min_nearness && f > likely_suspect_nearness) {
  753. likely_suspect_nearness = f;
  754. likely_suspect = *i;
  755. if (likely_suspect_nearness >= nearness_shortcut) {
  756. break;
  757. }
  758. }
  759. }
  760. // No likely suspect was found
  761. if (likely_suspect_nearness == 0) {
  762. return "";
  763. }
  764. // Likely suspect was found
  765. return likely_suspect.actor;
  766. }
  767. void RollbackManager::flush()
  768. {
  769. sqlite3_exec(db, "BEGIN", NULL, NULL, NULL);
  770. std::list<RollbackAction>::const_iterator iter;
  771. for (iter = action_todisk_buffer.begin();
  772. iter != action_todisk_buffer.end();
  773. ++iter) {
  774. if (iter->actor.empty()) {
  775. continue;
  776. }
  777. registerRow(actionRowFromRollbackAction(*iter));
  778. }
  779. sqlite3_exec(db, "COMMIT", NULL, NULL, NULL);
  780. action_todisk_buffer.clear();
  781. }
  782. void RollbackManager::addAction(const RollbackAction & action)
  783. {
  784. action_todisk_buffer.push_back(action);
  785. action_latest_buffer.push_back(action);
  786. // Flush to disk sometimes
  787. if (action_todisk_buffer.size() >= 500) {
  788. flush();
  789. }
  790. }
  791. std::list<RollbackAction> RollbackManager::getEntriesSince(time_t first_time)
  792. {
  793. flush();
  794. return getActionsSince(first_time);
  795. }
  796. std::list<RollbackAction> RollbackManager::getNodeActors(v3s16 pos, int range,
  797. time_t seconds, int limit)
  798. {
  799. flush();
  800. time_t cur_time = time(0);
  801. time_t first_time = cur_time - seconds;
  802. return getActionsSince_range(first_time, pos, range, limit);
  803. }
  804. std::list<RollbackAction> RollbackManager::getRevertActions(
  805. const std::string &actor_filter,
  806. time_t seconds)
  807. {
  808. time_t cur_time = time(0);
  809. time_t first_time = cur_time - seconds;
  810. flush();
  811. return getActionsSince(first_time, actor_filter);
  812. }