using std::string;
-void LocalDb::Open(const char *path)
+void LocalDb::Open(const char *path, const char *snapshot_name)
{
int rc;
+ snapshot = snapshot_name;
+
rc = sqlite3_open(path, &db);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return ref;
}
+
+void LocalDb::UseObject(const ObjectReference& ref)
+{
+ int rc;
+ sqlite3_stmt *stmt;
+ static const char s[] =
+ "insert into snapshot_contents "
+ "select blockid, ? as snapshot from block_index "
+ "where segment = ? and object = ?";
+ const char *tail;
+
+ rc = sqlite3_prepare_v2(db, s, strlen(s), &stmt, &tail);
+ if (rc != SQLITE_OK) {
+ return;
+ }
+
+ sqlite3_bind_text(stmt, 1, snapshot.c_str(), snapshot.size(),
+ SQLITE_TRANSIENT);
+ string seg = ref.get_segment();
+ sqlite3_bind_text(stmt, 2, seg.c_str(), seg.size(), SQLITE_TRANSIENT);
+ string obj = ref.get_sequence();
+ sqlite3_bind_text(stmt, 3, obj.c_str(), obj.size(), SQLITE_TRANSIENT);
+
+ rc = sqlite3_step(stmt);
+ if (rc != SQLITE_DONE) {
+ fprintf(stderr, "Could not execute INSERT statement!\n");
+ }
+
+ sqlite3_finalize(stmt);
+}
class LocalDb {
public:
- void Open(const char *path);
+ void Open(const char *path, const char *snapshot_name);
void Close();
void StoreObject(const ObjectReference& ref,
const std::string &checksum, int64_t size);
ObjectReference FindObject(const std::string &checksum, int64_t size);
+ void UseObject(const ObjectReference& ref);
private:
+ std::string snapshot;
sqlite3 *db;
};
db->StoreObject(ref, block_csum, bytes);
delete o;
}
+
object_list.push_back(ref.to_string());
segment_list.insert(ref.get_segment());
+ db->UseObject(ref);
size += bytes;
}
tss = new TarSegmentStore(backup_dest);
- string database_path = backup_dest + "/localdb.sqlite";
- db = new LocalDb;
- db->Open(database_path.c_str());
-
/* Write a backup descriptor file, which says which segments are needed and
* where to start to restore this snapshot. The filename is based on the
* current time. */
string desc_filename = backup_dest + "/" + desc_buf + ".lbs";
std::ofstream descriptor(desc_filename.c_str());
+ /* Open the local database which tracks all objects that are stored
+ * remotely, for efficient incrementals. Provide it with the name of this
+ * snapshot. */
+ string database_path = backup_dest + "/localdb.sqlite";
+ db = new LocalDb;
+ db->Open(database_path.c_str(), desc_buf);
+
try {
scanfile(".");
} catch (IOException e) {
--
-- The index is stored in an SQLite3 database. This is its schema.
--- Index of all blocks which have been stored in one snapshot, by checksum.
+-- Index of all blocks which have been stored in a snapshot, by checksum.
create table block_index (
blockid integer primary key,
segment text,
size integer
);
create index block_content_index on block_index(checksum);
+create index block_name_index on block_index(segment, object);
+
+-- Index tracking which blocks are used by which snapshots.
+create table snapshot_contents (
+ blockid integer,
+ snapshot text
+);