]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/mapdb.c
Save MapBlocks in SQLite3 database; Redesign MapBlock loading & sending code
[dragonblocks_alpha.git] / src / mapdb.c
1 #include <stdio.h>
2 #include <endian.h>
3 #include <stdlib.h>
4 #include "mapdb.h"
5 #include "servermap.h"
6
7 static void print_error(sqlite3 *db, MapBlock *block, const char *action)
8 {
9         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));
10 }
11
12 sqlite3 *open_mapdb(const char *path)
13 {
14         sqlite3 *db;
15         char *err;
16
17         if (sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL) != SQLITE_OK) {
18                 printf("Failed to open database: %s\n", sqlite3_errmsg(db));
19         } else if (sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS blocks (pos BLOB PRIMARY KEY, data BLOB NOT NULL);", NULL, NULL, &err) != SQLITE_OK) {
20                 printf("Failed to initialize database: %s\n", err);
21                 sqlite3_free(err);
22         }
23
24         return db;
25 }
26
27 static sqlite3_stmt *prepare_statement(sqlite3 *db, MapBlock *block, const char *action, const char *sql)
28 {
29         sqlite3_stmt *stmt;
30
31         if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
32                 print_error(db, block, action);
33                 return NULL;
34         }
35
36         size_t psize = sizeof(s32) * 3;
37         s32 *pos = malloc(psize);
38         pos[0] = htobe32(block->pos.x);
39         pos[1] = htobe32(block->pos.y);
40         pos[2] = htobe32(block->pos.z);
41
42         sqlite3_bind_blob(stmt, 1, pos, psize, &free);
43
44         return stmt;
45 }
46
47 bool load_block(sqlite3 *db, MapBlock *block)
48 {
49         sqlite3_stmt *stmt;
50
51         if (! (stmt = prepare_statement(db, block, "loading", "SELECT data FROM blocks WHERE pos=?")))
52                 return false;
53
54         int rc = sqlite3_step(stmt);
55         bool found = rc == SQLITE_ROW;
56
57         if (found) {
58                 const char *data = sqlite3_column_blob(stmt, 0);
59                 map_deserialize_block(block, data + sizeof(MapBlockHeader), be64toh(*(MapBlockHeader *) data));
60         } else if (rc != SQLITE_DONE) {
61                 print_error(db, block, "loading");
62         }
63
64         sqlite3_finalize(stmt);
65         return found;
66 }
67
68 void save_block(sqlite3 *db, MapBlock *block)
69 {
70         sqlite3_stmt *stmt;
71
72         if (! (stmt = prepare_statement(db, block, "saving", "REPLACE INTO blocks (pos, data) VALUES(?1, ?2)")))
73                 return;
74
75         MapBlockExtraData *extra = block->extra;
76
77         sqlite3_bind_blob(stmt, 2, extra->data, extra->size, SQLITE_TRANSIENT);
78
79         if (sqlite3_step(stmt) != SQLITE_DONE)
80                 print_error(db, block, "saving");
81
82         sqlite3_finalize(stmt);
83 }