Keep an index of old stored blocks, using sqlite3.
[cumulus.git] / localdb.cc
1 /* LBS: An LFS-inspired filesystem backup system
2  * Copyright (C) 2007  Michael Vrable
3  *
4  * When creating backup snapshots, maintain a local database of data blocks and
5  * checksums, in addition to the data contents (which may be stored remotely).
6  * This database is consulted when attempting to build incremental snapshots,
7  * as it says which objects can be reused.
8  *
9  * The database is implemented as an SQLite3 database, but this implementation
10  * detail is kept internal to this file, so that the storage format may be
11  * changed later. */
12
13 #include <assert.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <sqlite3.h>
17
18 #include <string>
19
20 #include "localdb.h"
21 #include "store.h"
22
23 using std::string;
24
25 void LocalDb::Open(const char *path)
26 {
27     int rc;
28
29     rc = sqlite3_open(path, &db);
30     if (rc) {
31         fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
32         sqlite3_close(db);
33         throw IOException("Error opening local database");
34     }
35
36     rc = sqlite3_exec(db, "begin", NULL, NULL, NULL);
37     if (rc) {
38         fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
39         sqlite3_close(db);
40         throw IOException("Error starting transaction");
41     }
42 }
43
44 void LocalDb::Close()
45 {
46     int rc;
47     rc = sqlite3_exec(db, "commit", NULL, NULL, NULL);
48     if (rc != SQLITE_OK) {
49         fprintf(stderr, "Can't commit database!\n");
50     }
51     sqlite3_close(db);
52 }
53
54 void LocalDb::StoreObject(const ObjectReference& ref,
55                           const string &checksum, int64_t size)
56 {
57     int rc;
58     sqlite3_stmt *stmt;
59     static const char s[] =
60         "insert into block_index(segment, object, checksum, size) "
61         "values (?, ?, ?, ?)";
62     const char *tail;
63
64     rc = sqlite3_prepare_v2(db, s, strlen(s), &stmt, &tail);
65     if (rc != SQLITE_OK) {
66         return;
67     }
68
69     string seg = ref.get_segment();
70     sqlite3_bind_text(stmt, 1, seg.c_str(), seg.size(), SQLITE_TRANSIENT);
71     string obj = ref.get_sequence();
72     sqlite3_bind_text(stmt, 2, obj.c_str(), obj.size(), SQLITE_TRANSIENT);
73     sqlite3_bind_text(stmt, 3, checksum.c_str(), checksum.size(),
74                       SQLITE_TRANSIENT);
75     sqlite3_bind_int64(stmt, 4, size);
76
77     rc = sqlite3_step(stmt);
78     if (rc != SQLITE_DONE) {
79         fprintf(stderr, "Could not execute INSERT statement!\n");
80     }
81
82     sqlite3_finalize(stmt);
83 }