6 #include "server/database.h"
7 #include "server/server_map.h"
12 // print SQLite3 error message for failed block SQL statement
13 static void print_error(sqlite3 *db, MapBlock *block, const char *action)
15 printf("Database error with %s block at (%d, %d, %d): %s\n", action, block->pos.x, block->pos.y, block->pos.z, sqlite3_errmsg(db));
18 // prepare a SQLite3 block statement and bind the position
19 static sqlite3_stmt *prepare_statement(sqlite3 *db, MapBlock *block, const char *action, const char *sql)
23 if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
24 print_error(db, block, action);
28 size_t psize = sizeof(s32) * 3;
29 s32 *pos = malloc(psize);
30 pos[0] = htobe32(block->pos.x);
31 pos[1] = htobe32(block->pos.y);
32 pos[2] = htobe32(block->pos.z);
34 sqlite3_bind_blob(stmt, 1, pos, psize, &free);
41 // open and initialize SQLite3 database at path
42 sqlite3 *database_open(const char *path)
47 if (sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL) != SQLITE_OK) {
48 printf("Failed to open database: %s\n", sqlite3_errmsg(db));
49 } else if (sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS map (pos BLOB PRIMARY KEY, generated INT, size INT, data BLOB, mgsb_size INT, mgsb_data BLOB);", NULL, NULL, &err) != SQLITE_OK) {
50 printf("Failed to initialize database: %s\n", err);
57 // load a block from map database (initializes state, mgs buffer and data), returns false on failure
58 bool database_load_block(sqlite3 *db, MapBlock *block)
62 if (! (stmt = prepare_statement(db, block, "loading", "SELECT generated, size, data, mgsb_size, mgsb_data FROM map WHERE pos=?")))
65 int rc = sqlite3_step(stmt);
66 bool found = rc == SQLITE_ROW;
69 MapBlockExtraData *extra = block->extra;
71 extra->state = sqlite3_column_int(stmt, 0) ? MBS_READY : MBS_CREATED;
72 extra->size = sqlite3_column_int64(stmt, 1);
73 extra->data = malloc(extra->size);
74 memcpy(extra->data, sqlite3_column_blob(stmt, 2), extra->size);
76 MapgenStageBuffer decompressed_mgsb;
77 my_decompress(sqlite3_column_blob(stmt, 4), sqlite3_column_int64(stmt, 3), &decompressed_mgsb, sizeof(MapgenStageBuffer));
79 ITERATE_MAPBLOCK extra->mgs_buffer[x][y][z] = be32toh(decompressed_mgsb[x][y][z]);
81 if (! map_deserialize_block(block, extra->data, extra->size))
82 printf("Error with deserializing block at (%d, %d, %d)\n", block->pos.x, block->pos.y, block->pos.z);
83 } else if (rc != SQLITE_DONE) {
84 print_error(db, block, "loading");
87 sqlite3_finalize(stmt);
91 // save a block to database
92 void database_save_block(sqlite3 *db, MapBlock *block)
96 if (! (stmt = prepare_statement(db, block, "saving", "REPLACE INTO map (pos, generated, size, data, mgsb_size, mgsb_data) VALUES(?1, ?2, ?3, ?4, ?5, ?6)")))
99 MapBlockExtraData *extra = block->extra;
101 MapgenStageBuffer uncompressed_mgsb;
102 ITERATE_MAPBLOCK uncompressed_mgsb[x][y][z] = htobe32(extra->mgs_buffer[x][y][z]);
107 my_compress(&uncompressed_mgsb, sizeof(MapgenStageBuffer), &mgsb_data, &mgsb_size);
109 sqlite3_bind_int(stmt, 2, extra->state > MBS_CREATED);
110 sqlite3_bind_int64(stmt, 3, extra->size);
111 sqlite3_bind_blob(stmt, 4, extra->data, extra->size, SQLITE_TRANSIENT);
112 sqlite3_bind_int64(stmt, 5, mgsb_size);
113 sqlite3_bind_blob(stmt, 6, mgsb_data, mgsb_size, &free);
115 if (sqlite3_step(stmt) != SQLITE_DONE)
116 print_error(db, block, "saving");
118 sqlite3_finalize(stmt);