]> git.sesse.net Git - nageru/blob - db.cpp
Cache file descriptors when reading frames, for better readahead and fewer syscalls.
[nageru] / db.cpp
1 #include "db.h"
2
3 #include <string>
4
5 using namespace std;
6
7 DB::DB(const std::string &filename)
8 {
9         int ret = sqlite3_open(filename.c_str(), &db);
10         if (ret != SQLITE_OK) {
11                 fprintf(stderr, "%s: %s\n", filename.c_str(), sqlite3_errmsg(db));
12                 exit(1);
13         }
14
15         sqlite3_exec(db, R"(
16                 CREATE TABLE IF NOT EXISTS state (state BLOB);
17         )", nullptr, nullptr, nullptr);  // Ignore errors.
18
19         sqlite3_exec(db, "PRAGMA journal_mode=WAL", nullptr, nullptr, nullptr);  // Ignore errors.
20         sqlite3_exec(db, "PRAGMA synchronous=NORMAL", nullptr, nullptr, nullptr);  // Ignore errors.
21 }
22
23 StateProto DB::get_state()
24 {
25         StateProto state;
26
27         sqlite3_stmt *stmt;
28         int ret = sqlite3_prepare(db, "SELECT state FROM state", -1, &stmt, 0);
29         if (ret != SQLITE_OK) {
30                 fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
31                 exit(1);
32         }
33
34         ret = sqlite3_step(stmt);
35         if (ret == SQLITE_ROW) {
36                 bool ok = state.ParseFromArray(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
37                 if (!ok) {
38                         fprintf(stderr, "State in database is corrupted!\n");
39                         exit(1);
40                 }
41         } else if (ret != SQLITE_DONE) {
42                 fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
43                 exit(1);
44         }
45
46         ret = sqlite3_finalize(stmt);
47         if (ret != SQLITE_OK) {
48                 fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
49                 exit(1);
50         }
51
52         return state;
53 }
54
55 void DB::store_state(const StateProto &state)
56 {
57         string serialized;
58         state.SerializeToString(&serialized);
59
60         int ret = sqlite3_exec(db, "BEGIN", nullptr, nullptr, nullptr);
61         if (ret != SQLITE_OK) {
62                 fprintf(stderr, "BEGIN: %s\n", sqlite3_errmsg(db));
63                 exit(1);
64         }
65
66         ret = sqlite3_exec(db, "DELETE FROM state", nullptr, nullptr, nullptr);
67         if (ret != SQLITE_OK) {
68                 fprintf(stderr, "DELETE: %s\n", sqlite3_errmsg(db));
69                 exit(1);
70         }
71
72         sqlite3_stmt *stmt;
73         ret = sqlite3_prepare(db, "INSERT INTO state VALUES (?)", -1, &stmt, 0);
74         if (ret != SQLITE_OK) {
75                 fprintf(stderr, "INSERT prepare: %s\n", sqlite3_errmsg(db));
76                 exit(1);
77         }
78
79         sqlite3_bind_blob(stmt, 1, serialized.data(), serialized.size(), SQLITE_STATIC);
80
81         ret = sqlite3_step(stmt);
82         if (ret == SQLITE_ROW) {
83                 fprintf(stderr, "INSERT step: %s\n", sqlite3_errmsg(db));
84                 exit(1);
85         }
86
87         ret = sqlite3_finalize(stmt);
88         if (ret != SQLITE_OK) {
89                 fprintf(stderr, "INSERT finalize: %s\n", sqlite3_errmsg(db));
90                 exit(1);
91         }
92
93         ret = sqlite3_exec(db, "COMMIT", nullptr, nullptr, nullptr);
94         if (ret != SQLITE_OK) {
95                 fprintf(stderr, "COMMIT: %s\n", sqlite3_errmsg(db));
96                 exit(1);
97         }
98 }