]> git.proxmox.com Git - pve-cluster.git/blob - data/src/database.c
d1c15a75b40d5a47a1261009017a0cb043d1c053
[pve-cluster.git] / data / src / database.c
1 /*
2 Copyright (C) 2010 - 2020 Proxmox Server Solutions GmbH
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Affero General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Affero General Public License for more details.
13
14 You should have received a copy of the GNU Affero General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 Author: Dietmar Maurer <dietmar@proxmox.com>
18
19 */
20
21 #define G_LOG_DOMAIN "database"
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif /* HAVE_CONFIG_H */
26
27 #include <stdlib.h>
28 #include <inttypes.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <glib.h>
33 #include <dirent.h>
34 #include <sys/stat.h>
35 #include <errno.h>
36
37 #include <sqlite3.h>
38
39 #include "cfs-utils.h"
40 #include "status.h"
41 #include "memdb.h"
42
43 struct db_backend {
44 sqlite3 *db;
45 sqlite3_stmt *stmt_insert_entry;
46 sqlite3_stmt *stmt_update_entry;
47 sqlite3_stmt *stmt_replace_entry;
48 sqlite3_stmt *stmt_delete_entry;
49 sqlite3_stmt *stmt_begin;
50 sqlite3_stmt *stmt_commit;
51 sqlite3_stmt *stmt_rollback;
52 sqlite3_stmt *stmt_load_all;
53 };
54
55 #define VERSIONFILENAME "__version__"
56
57 /* colume type "INTEGER PRIMARY KEY" is a special case, because sqlite
58 * uses the internal ROWID. So only real interger are allowed, and
59 * there is no need to add an additionl check
60 */
61 static const char *sql_create_db =
62 "CREATE TABLE IF NOT EXISTS tree ("
63 " inode INTEGER PRIMARY KEY NOT NULL,"
64 " parent INTEGER NOT NULL CHECK(typeof(parent)=='integer'),"
65 " version INTEGER NOT NULL CHECK(typeof(version)=='integer'),"
66 " writer INTEGER NOT NULL CHECK(typeof(writer)=='integer'),"
67 " mtime INTEGER NOT NULL CHECK(typeof(mtime)=='integer'),"
68 " type INTEGER NOT NULL CHECK(typeof(type)=='integer'),"
69 " name TEXT NOT NULL,"
70 " data BLOB);";
71
72 static const char *sql_load_all =
73 "SELECT inode, parent, version, writer, mtime, type, name, data FROM tree;";
74
75 static char *sql_insert_entry =
76 "INSERT INTO tree ("
77 "inode, parent, version, writer, mtime, type, name, data) "
78 "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8);";
79
80 static char *sql_update_entry =
81 "UPDATE tree SET parent = ?2, version = ?3, writer = ?4, mtime = ?5, "
82 "type = ?6, name = ?7, data = ?8 WHERE inode = ?1;";
83
84 static char *sql_replace_entry =
85 "REPLACE INTO tree (inode, parent, version, writer, mtime, type, "
86 "name, data) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8);";
87
88 static char *sql_delete_entry =
89 "DELETE FROM tree WHERE inode = ?1;";
90
91 static char *sql_begin = "BEGIN TRANSACTION;";
92 static char *sql_commit = "COMMIT TRANSACTION;";
93 static char *sql_rollback = "ROLLBACK TRANSACTION;";
94
95 static sqlite3 *bdb_create(
96 const char *filename)
97 {
98 int rc;
99 sqlite3 *db = NULL;
100
101 int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
102 rc = sqlite3_open_v2(filename, &db, flags, NULL);
103 if (rc != SQLITE_OK) {
104 cfs_critical("splite3_open_v2 failed: %d\n", rc);
105 sqlite3_close(db);
106 return NULL;
107 }
108
109 if (chmod(filename, 0600) == -1) {
110 cfs_critical("chmod failed: %s", strerror(errno));
111 return NULL;
112 }
113
114 /* use WAL mode - to allow concurrent reads */
115 rc = sqlite3_exec(db, "PRAGMA journal_mode=WAL;", NULL, NULL, NULL);
116 if (rc != SQLITE_OK) {
117 cfs_critical("unable to set WAL mode: %s\n", sqlite3_errmsg(db));
118 sqlite3_close(db);
119 return NULL;
120 }
121
122 /* NORMAL is good enough when using WAL */
123 rc = sqlite3_exec(db, "PRAGMA synchronous=NORMAL", NULL, NULL, NULL);
124 if (rc != SQLITE_OK) {
125 cfs_critical("unable to set synchronous mode: %s\n", sqlite3_errmsg(db));
126 sqlite3_close(db);
127 return NULL;
128 }
129
130 sqlite3_busy_timeout(db, 10000); /* 10 seconds */
131
132 rc = sqlite3_exec(db, sql_create_db, NULL, NULL, NULL);
133 if (rc != SQLITE_OK) {
134 cfs_critical("init database failed: %s\n", sqlite3_errmsg(db));
135 sqlite3_close(db);
136 return NULL;
137 }
138
139 return db;
140 }
141
142 static int backend_write_inode(
143 sqlite3 *db,
144 sqlite3_stmt *stmt,
145 guint64 inode,
146 guint64 parent,
147 guint64 version,
148 guint32 writer,
149 guint32 mtime,
150 guint32 size,
151 char type,
152 char *name,
153 gpointer value)
154 {
155 int rc;
156
157 cfs_debug("enter backend_write_inode %016" PRIX64 " '%s', size %"PRIu32"", inode, name, size);
158
159 if ((rc = sqlite3_bind_int64(stmt, 1, inode)) != SQLITE_OK) {
160 cfs_critical("sqlite3_bind failed: %s\n", sqlite3_errmsg(db));
161 return rc;
162 }
163 if ((rc = sqlite3_bind_int64(stmt, 2, parent)) != SQLITE_OK) {
164 cfs_critical("sqlite3_bind failed: %s\n", sqlite3_errmsg(db));
165 return rc;
166 }
167 if ((rc = sqlite3_bind_int64(stmt, 3, version)) != SQLITE_OK) {
168 cfs_critical("sqlite3_bind failed: %s\n", sqlite3_errmsg(db));
169 return rc;
170 }
171 if ((rc = sqlite3_bind_int64(stmt, 4, writer)) != SQLITE_OK) {
172 cfs_critical("sqlite3_bind failed: %s\n", sqlite3_errmsg(db));
173 return rc;
174 }
175 if ((rc = sqlite3_bind_int64(stmt, 5, mtime)) != SQLITE_OK) {
176 cfs_critical("sqlite3_bind failed: %s\n", sqlite3_errmsg(db));
177 return rc;
178 }
179 if ((rc = sqlite3_bind_int64(stmt, 6, type)) != SQLITE_OK) {
180 cfs_critical("sqlite3_bind failed: %s\n", sqlite3_errmsg(db));
181 return rc;
182 }
183 if ((rc = sqlite3_bind_text(stmt, 7, name, -1, SQLITE_STATIC)) != SQLITE_OK) {
184 cfs_critical("sqlite3_bind failed: %s\n", sqlite3_errmsg(db));
185 return rc;
186 }
187 if ((rc = sqlite3_bind_blob(stmt, 8, value, size, SQLITE_STATIC)) != SQLITE_OK) {
188 cfs_critical("sqlite3_bind failed: %s\n", sqlite3_errmsg(db));
189 return rc;
190 }
191
192 if ((rc = sqlite3_step(stmt)) != SQLITE_DONE) {
193 cfs_critical("sqlite3_step failed: %s\n", sqlite3_errmsg(db));
194 sqlite3_reset(stmt);
195 return rc;
196 }
197
198 sqlite3_reset(stmt);
199
200 return SQLITE_OK;
201 }
202
203 static int bdb_backend_delete_inode(
204 db_backend_t *bdb,
205 guint64 inode)
206 {
207 int rc;
208
209 cfs_debug("enter dbd_backend_delete_inode");
210
211 sqlite3_stmt *stmt = bdb->stmt_delete_entry;
212
213 if ((rc = sqlite3_bind_int64(stmt, 1, inode)) != SQLITE_OK) {
214 cfs_critical("delete_inode/sqlite3_bind failed: %s\n", sqlite3_errmsg(bdb->db));
215 return rc;
216 }
217
218 if ((rc = sqlite3_step(stmt)) != SQLITE_DONE) {
219 cfs_critical("delete_inode failed: %s\n", sqlite3_errmsg(bdb->db));
220 sqlite3_reset(stmt);
221 return rc;
222 }
223
224 sqlite3_reset(stmt);
225
226 return SQLITE_OK;
227 }
228
229 int bdb_backend_write(
230 db_backend_t *bdb,
231 guint64 inode,
232 guint64 parent,
233 guint64 version,
234 guint32 writer,
235 guint32 mtime,
236 guint32 size,
237 char type,
238 char *name,
239 gpointer value,
240 guint64 delete_inode)
241 {
242 g_return_val_if_fail(bdb != NULL, SQLITE_PERM);
243 g_return_val_if_fail(inode == 0 || (name != NULL && name[0]), SQLITE_PERM);
244 g_return_val_if_fail(type == DT_REG || type == DT_DIR, SQLITE_PERM);
245 int rc;
246
247 gboolean need_txn = (inode != 0 || delete_inode != 0);
248
249 if (need_txn) {
250 rc = sqlite3_step(bdb->stmt_begin);
251 sqlite3_reset(bdb->stmt_begin);
252 if (rc != SQLITE_DONE) {
253 cfs_critical("begin transaction failed: %s\n", sqlite3_errmsg(bdb->db));
254 return rc;
255 }
256 }
257
258 if (delete_inode != 0) {
259 if ((rc = bdb_backend_delete_inode(bdb, delete_inode)) != SQLITE_OK)
260 goto rollback;
261 }
262
263 if (inode != 0) {
264
265 sqlite3_stmt *stmt = (inode > version) ?
266 bdb->stmt_insert_entry : bdb->stmt_replace_entry;
267
268 rc = backend_write_inode(bdb->db, stmt, inode, parent, version,
269 writer, mtime, size, type, name, value);
270 if (rc != SQLITE_OK)
271 goto rollback;
272
273 if (sqlite3_changes(bdb->db) != 1) {
274 cfs_critical("no such inode %016" PRIX64, inode);
275 goto rollback;
276 }
277 }
278
279 rc = backend_write_inode(bdb->db, bdb->stmt_replace_entry, 0, 0, version,
280 writer, mtime, 0, DT_REG, VERSIONFILENAME, NULL);
281
282 if (rc != SQLITE_OK)
283 goto rollback;
284
285
286 if (need_txn) {
287 rc = sqlite3_step(bdb->stmt_commit);
288 sqlite3_reset(bdb->stmt_commit);
289 if (rc != SQLITE_DONE) {
290 cfs_critical("commit transaction failed: %s\n", sqlite3_errmsg(bdb->db));
291 goto rollback;
292 }
293 }
294
295 return SQLITE_OK;
296
297 rollback:
298
299 if (!need_txn)
300 return rc;
301
302 int rbrc = sqlite3_step(bdb->stmt_rollback);
303 sqlite3_reset(bdb->stmt_rollback);
304 if (rbrc != SQLITE_DONE) {
305 cfs_critical("rollback transaction failed: %s\n", sqlite3_errmsg(bdb->db));
306 return rc;
307 }
308
309 return rc;
310 }
311
312 static gboolean bdb_backend_load_index(
313 db_backend_t *bdb,
314 memdb_tree_entry_t *root,
315 GHashTable *index)
316 {
317 g_return_val_if_fail(bdb != NULL, FALSE);
318 g_return_val_if_fail(root != NULL, FALSE);
319 g_return_val_if_fail(index != NULL, FALSE);
320 g_return_val_if_fail(root->version == 0, FALSE);
321 g_return_val_if_fail(g_hash_table_size(index) == 1, FALSE);
322
323 sqlite3_stmt *stmt = bdb->stmt_load_all;
324
325 int rc;
326 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
327
328 memdb_tree_entry_t *te;
329
330 guint64 inode = sqlite3_column_int64(stmt, 0);
331 const char *name = (const char *)sqlite3_column_text(stmt, 6);
332 int namelen = sqlite3_column_bytes(stmt, 6);
333 if (name == NULL || namelen == 0) {
334 cfs_critical("inode has no name (inode = %016" PRIX64 ")", inode);
335 goto fail;
336 }
337 te = g_malloc0(sizeof(memdb_tree_entry_t) + namelen + 1);
338 strcpy(te->name, name);
339
340 te->inode = inode;
341 te->parent = sqlite3_column_int64(stmt, 1);
342 te->version = sqlite3_column_int64(stmt, 2);
343 te->writer = sqlite3_column_int64(stmt, 3) & 0x0ffffffff;
344 te->mtime = sqlite3_column_int64(stmt, 4) & 0x0ffffffff;
345 te->type = sqlite3_column_int64(stmt, 5) & 255;
346
347 gconstpointer value = sqlite3_column_blob(stmt, 7);
348
349 int size = sqlite3_column_bytes(stmt, 7);
350 te->size = size;
351
352 if (te->type == DT_REG) {
353 if (size > 0)
354 te->data.value = g_memdup2(value, size);
355 } else if (te->type == DT_DIR) {
356 if (size) {
357 cfs_critical("directory inode contains data (inode = %016" PRIX64 ")",
358 te->inode);
359 g_free(te);
360 goto fail;
361 }
362 te->data.entries = NULL;
363 } else {
364 cfs_critical("inode has unknown type (inode = %016" PRIX64 ", type = %d)",
365 te->inode, te->type);
366 g_free(te);
367 goto fail;
368 }
369
370 cfs_debug("name %s (inode = %016" PRIX64 ", parent = %016" PRIX64 ")",
371 te->name, te->inode, te->parent);
372
373 if (te->inode == 0) {
374 if (!strcmp(te->name, VERSIONFILENAME)) {
375 root->version = te->version;
376 root->writer = te->writer;
377 root->mtime = te->mtime;
378 memdb_tree_entry_free(te);
379 } else {
380 cfs_critical("root inode has unexpected name '%s'", te->name);
381 memdb_tree_entry_free(te);
382 goto fail;
383 }
384 } else {
385 memdb_tree_entry_t *pte;
386
387 if (!(pte = g_hash_table_lookup(index, &te->parent))) {
388 /* allocate placeholder (type == 0)
389 * this is simply replaced if we find a real inode later
390 */
391 pte = g_malloc0(sizeof(memdb_tree_entry_t));
392 pte->inode = te->parent;
393 pte->data.entries = g_hash_table_new(g_str_hash, g_str_equal);
394 g_hash_table_replace(index, &pte->inode, pte);
395
396 } else if (!(pte->type == DT_DIR || pte->type == 0)) {
397 cfs_critical("parent is not a directory "
398 "(inode = %016" PRIX64 ", parent = %016" PRIX64 ", name = '%s')",
399 te->inode, te->parent, te->name);
400 memdb_tree_entry_free(te);
401 goto fail;
402 }
403
404 if (te->type == DT_DIR) {
405 memdb_tree_entry_t *tmpte;
406 /* test if there is a placeholder entry */
407 if ((tmpte = g_hash_table_lookup(index, &te->inode))) {
408 if (tmpte->type != 0) {
409 cfs_critical("found strange placeholder for "
410 "(inode = %016" PRIX64 ", parent = %016" PRIX64 ", name = '%s', type = '%d')",
411 te->inode, te->parent, te->name, tmpte->type);
412 memdb_tree_entry_free(te);
413 goto fail;
414 }
415 /* copy entries from placeholder */
416 te->data.entries = tmpte->data.entries;
417 tmpte->data.entries = NULL;
418 } else {
419 te->data.entries = g_hash_table_new(g_str_hash, g_str_equal);
420 }
421 }
422
423 memdb_tree_entry_t *existing;
424 if ((existing = g_hash_table_lookup(pte->data.entries, te->name))) {
425 cfs_critical(
426 "found entry with duplicate name '%s' - "
427 "A:(inode = 0x%016"PRIX64", parent = 0x%016"PRIX64", v./mtime = 0x%"PRIX64"/0x%"PRIi32")"
428 " vs. "
429 "B:(inode = 0x%016"PRIX64", parent = 0x%016"PRIX64", v./mtime = 0x%"PRIX64"/0x%"PRIi32")",
430 te->name,
431 existing->inode, existing->parent, existing->version, existing->mtime,
432 te->inode, te->parent, te->version, te->mtime
433 );
434 goto fail;
435 }
436
437 g_hash_table_replace(pte->data.entries, te->name, te);
438 g_hash_table_replace(index, &te->inode, te);
439 }
440 }
441 if (rc != SQLITE_DONE) {
442 cfs_critical("select returned error: %s", sqlite3_errmsg(bdb->db));
443 goto fail;
444 }
445
446 /* check if all inodes have parents (there must be no placeholders) */
447 GHashTableIter iter;
448 gpointer key, value;
449 g_hash_table_iter_init (&iter, index);
450 while (g_hash_table_iter_next (&iter, &key, &value)) {
451 memdb_tree_entry_t *te = (memdb_tree_entry_t *)value;
452 if (te->type == 0) {
453 cfs_critical("missing directory inode (inode = %016" PRIX64 ")", te->inode);
454 goto fail;
455 }
456 }
457
458 sqlite3_reset(stmt);
459
460 return TRUE;
461
462 fail:
463 sqlite3_reset(stmt);
464
465 cfs_critical("DB load failed");
466
467 return FALSE;
468 }
469
470 gboolean bdb_backend_commit_update(
471 memdb_t *memdb,
472 memdb_index_t *master,
473 memdb_index_t *slave,
474 GList *inodes)
475 {
476 g_return_val_if_fail(memdb != NULL, FALSE);
477 g_return_val_if_fail(memdb->bdb != NULL, FALSE);
478 g_return_val_if_fail(master != NULL, FALSE);
479 g_return_val_if_fail(slave != NULL, FALSE);
480
481 cfs_debug("enter bdb_backend_commit_update");
482
483 memdb_tree_entry_t *root = NULL;
484 GHashTable *index = NULL;
485
486 db_backend_t *bdb = (db_backend_t *)memdb->bdb;
487 gboolean result = FALSE;
488
489 int rc;
490
491 rc = sqlite3_step(bdb->stmt_begin);
492 sqlite3_reset(bdb->stmt_begin);
493 if (rc != SQLITE_DONE) {
494 cfs_critical("begin transaction failed: %s\n", sqlite3_errmsg(bdb->db));
495 return rc;
496 }
497
498 g_mutex_lock (&memdb->mutex);
499
500 /* first, delete anything not found in master index) */
501
502 int i = 0;
503 int j = 0;
504
505 for (i = 0; i < master->size; i++) {
506 guint64 inode = master->entries[i].inode;
507 guint64 slave_inode;
508 while (j < slave->size && (slave_inode = slave->entries[j].inode) <= inode) {
509
510 if (slave_inode < inode) {
511 if (bdb_backend_delete_inode(bdb, slave_inode) != SQLITE_OK)
512 goto abort;
513
514 cfs_debug("deleted inode %016" PRIX64, slave_inode);
515 }
516 j++;
517 }
518 if (j >= slave->size)
519 break;
520 }
521
522 while (j < slave->size) {
523 guint64 slave_inode = slave->entries[j].inode;
524
525 if (bdb_backend_delete_inode(bdb, slave_inode) != SQLITE_OK)
526 goto abort;
527
528 cfs_debug("deleted inode %016" PRIX64, slave_inode);
529
530 j++;
531 }
532
533 /* now add all updates */
534
535 GList *l = inodes;
536 while (l) {
537 memdb_tree_entry_t *te = (memdb_tree_entry_t *)l->data;
538
539 tree_entry_debug(te);
540
541 if (backend_write_inode(
542 bdb->db, bdb->stmt_replace_entry, te->inode, te->parent, te->version,
543 te->writer, te->mtime, te->size, te->type,
544 te->inode ? te->name : VERSIONFILENAME, te->data.value) != SQLITE_OK) {
545 goto abort;
546 }
547
548 l = g_list_next(l);
549 }
550
551 /* now try to reload */
552 root = memdb_tree_entry_new("");
553 root->data.entries = g_hash_table_new(g_str_hash, g_str_equal);
554 root->type = DT_DIR;
555
556 index = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL,
557 (GDestroyNotify)memdb_tree_entry_free);
558
559 g_hash_table_replace(index, &root->inode, root);
560
561 if (!bdb_backend_load_index(bdb, root, index))
562 goto abort;
563
564 if (!memdb->root->version) {
565 cfs_critical("new index has version 0 - internal error");
566 goto abort;
567 }
568
569 memdb_index_t *new_idx = memdb_encode_index(index, root);
570 if (!new_idx) {
571 cfs_critical("cant encode new index - internal error");
572 goto abort;
573 }
574
575 int idx_equal = (new_idx->bytes == master->bytes &&
576 (memcmp(master, new_idx, new_idx->bytes) == 0));
577
578 g_free (new_idx);
579
580 if (!idx_equal) {
581 cfs_critical("new index does not match master index - internal error");
582 goto abort;
583 }
584
585 rc = sqlite3_step(bdb->stmt_commit);
586 sqlite3_reset(bdb->stmt_commit);
587 if (rc != SQLITE_DONE) {
588 cfs_critical("commit transaction failed: %s\n", sqlite3_errmsg(bdb->db));
589 goto abort;
590 }
591
592 g_hash_table_destroy(memdb->index);
593 memdb->index = index;
594 memdb->root = root;
595 index = NULL;
596 root = NULL;
597
598 record_memdb_reload();
599
600 if (!memdb_recreate_vmlist(memdb)) {
601 cfs_critical("memdb_recreate_vmlist failed");
602 memdb->errors = 1;
603 result = FALSE;
604 goto ret;
605 }
606
607 memdb_update_locks(memdb);
608
609 result = TRUE;
610
611 ret:
612 g_mutex_unlock (&memdb->mutex);
613
614 if (index)
615 g_hash_table_destroy(index);
616
617 cfs_debug("leave bdb_backend_commit_update (%d)", result);
618
619 return result;
620
621 abort:
622
623 memdb->errors = 1;
624
625 rc = sqlite3_step(bdb->stmt_rollback);
626 sqlite3_reset(bdb->stmt_rollback);
627 if (rc != SQLITE_DONE)
628 cfs_critical("rollback transaction failed: %s\n", sqlite3_errmsg(bdb->db));
629
630 result = FALSE;
631
632 goto ret;
633 }
634
635 void bdb_backend_close(db_backend_t *bdb)
636 {
637 g_return_if_fail(bdb != NULL);
638
639 sqlite3_finalize(bdb->stmt_insert_entry);
640 sqlite3_finalize(bdb->stmt_replace_entry);
641 sqlite3_finalize(bdb->stmt_update_entry);
642 sqlite3_finalize(bdb->stmt_delete_entry);
643 sqlite3_finalize(bdb->stmt_begin);
644 sqlite3_finalize(bdb->stmt_commit);
645 sqlite3_finalize(bdb->stmt_rollback);
646 sqlite3_finalize(bdb->stmt_load_all);
647
648 int rc;
649 if ((rc = sqlite3_close(bdb->db)) != SQLITE_OK) {
650 cfs_critical("sqlite3_close failed: %d\n", rc);
651 }
652
653 sqlite3_shutdown();
654
655 g_free(bdb);
656 }
657
658 db_backend_t *bdb_backend_open(
659 const char *filename,
660 memdb_tree_entry_t *root,
661 GHashTable *index)
662 {
663 g_return_val_if_fail(filename != NULL, NULL);
664 g_return_val_if_fail(root != NULL, NULL);
665 g_return_val_if_fail(index != NULL, NULL);
666
667 db_backend_t *bdb = g_new0(db_backend_t, 1);
668 g_return_val_if_fail(bdb != NULL, NULL);
669
670 int rc;
671
672 sqlite3_initialize();
673
674 if (!(bdb->db = bdb_create(filename)))
675 goto fail;
676
677 // tell the query planner that the prepared statement will be retained for a long time and
678 // probably reused many times
679 const unsigned int flags = SQLITE_PREPARE_PERSISTENT;
680
681 rc = sqlite3_prepare_v3(bdb->db, sql_insert_entry, -1, flags, &bdb->stmt_insert_entry, NULL);
682 if (rc != SQLITE_OK) {
683 cfs_critical("sqlite3_prepare 'sql_insert_entry' failed: %s\n",
684 sqlite3_errmsg(bdb->db));
685 goto fail;
686 }
687 rc = sqlite3_prepare_v3(bdb->db, sql_update_entry, -1, flags, &bdb->stmt_update_entry, NULL);
688 if (rc != SQLITE_OK) {
689 cfs_critical("sqlite3_prepare 'sql_update_entry' failed: %s\n",
690 sqlite3_errmsg(bdb->db));
691 goto fail;
692 }
693 rc = sqlite3_prepare_v3(bdb->db, sql_replace_entry, -1, flags, &bdb->stmt_replace_entry, NULL);
694 if (rc != SQLITE_OK) {
695 cfs_critical("sqlite3_prepare 'sql_replace_entry' failed: %s\n",
696 sqlite3_errmsg(bdb->db));
697 goto fail;
698 }
699 rc = sqlite3_prepare_v3(bdb->db, sql_delete_entry, -1, flags, &bdb->stmt_delete_entry, NULL);
700 if (rc != SQLITE_OK) {
701 cfs_critical("sqlite3_prepare 'sql_delete_entry' failed: %s\n",
702 sqlite3_errmsg(bdb->db));
703 goto fail;
704 }
705 rc = sqlite3_prepare_v3(bdb->db, sql_begin, -1, flags, &bdb->stmt_begin, NULL);
706 if (rc != SQLITE_OK) {
707 cfs_critical("sqlite3_prepare 'sql_begin' failed: %s\n",
708 sqlite3_errmsg(bdb->db));
709 goto fail;
710 }
711 rc = sqlite3_prepare_v3(bdb->db, sql_commit, -1, flags, &bdb->stmt_commit, NULL);
712 if (rc != SQLITE_OK) {
713 cfs_critical("sqlite3_prepare 'sql_commit' failed: %s\n",
714 sqlite3_errmsg(bdb->db));
715 goto fail;
716 }
717 rc = sqlite3_prepare_v3(bdb->db, sql_rollback, -1, flags, &bdb->stmt_rollback, NULL);
718 if (rc != SQLITE_OK) {
719 cfs_critical("sqlite3_prepare 'sql_rollback' failed: %s\n",
720 sqlite3_errmsg(bdb->db));
721 goto fail;
722 }
723 rc = sqlite3_prepare_v3(bdb->db, sql_load_all, -1, flags, &bdb->stmt_load_all, NULL);
724 if (rc != SQLITE_OK) {
725 cfs_critical("sqlite3_prepare 'sql_load_all' failed: %s\n",
726 sqlite3_errmsg(bdb->db));
727 goto fail;
728 }
729
730 if (!bdb_backend_load_index(bdb, root, index))
731 goto fail;
732
733 if (!root->version) {
734 root->version++;
735
736 guint32 mtime = time(NULL);
737
738 if (bdb_backend_write(bdb, 0, 0, root->version, 0, mtime,
739 0, DT_REG, NULL, NULL, 0) != SQLITE_OK)
740 goto fail;
741 }
742
743 return bdb;
744
745 fail:
746 bdb_backend_close(bdb);
747
748 return NULL;
749 }