#include <string.h>
#include <sqlite3.h>
+#include <algorithm>
#include <string>
#include "localdb.h"
#include "store.h"
+#include "util.h"
+using std::min;
using std::string;
/* Helper function to prepare a statement for execution in the current
rc = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, &tail);
if (rc != SQLITE_OK) {
ReportError(rc);
- throw IOException(string("Error preparing statement: ") + sql);
+ fatal(string("Error preparing statement: ") + sql);
}
return stmt;
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
- throw IOException("Error opening local database");
+ fatal("Error opening local database");
}
rc = sqlite3_exec(db, "begin", NULL, NULL, NULL);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
- throw IOException("Error starting transaction");
+ fatal("Error starting transaction");
}
sqlite3_extended_result_codes(db, 1);
+ if (snapshot_scheme == NULL)
+ snapshot_scheme = "";
+
/* Insert this snapshot into the database, and determine the integer key
* which will be used to identify it. */
sqlite3_stmt *stmt = Prepare("insert into "
"values (?, ?, julianday('now'), ?)");
sqlite3_bind_text(stmt, 1, snapshot_name, strlen(snapshot_name),
SQLITE_TRANSIENT);
- if (snapshot_scheme == NULL)
- sqlite3_bind_null(stmt, 2);
- else
- sqlite3_bind_text(stmt, 2, snapshot_scheme, strlen(snapshot_scheme),
- SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 2, snapshot_scheme, strlen(snapshot_scheme),
+ SQLITE_TRANSIENT);
sqlite3_bind_double(stmt, 3, intent);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
ReportError(rc);
sqlite3_close(db);
- throw IOException("Database execution error!");
+ fatal("Database execution error!");
}
snapshotid = sqlite3_last_insert_rowid(db);
if (snapshotid == 0) {
ReportError(rc);
sqlite3_close(db);
- throw IOException("Find snapshot id");
+ fatal("Find snapshot id");
}
/* Create a temporary table which will be used to keep track of the objects
if (rc != SQLITE_OK) {
ReportError(rc);
sqlite3_close(db);
- throw IOException("Database initialization");
+ fatal("Database initialization");
}
rc = sqlite3_exec(db,
"create unique index snapshot_refs_index "
if (rc != SQLITE_OK) {
ReportError(rc);
sqlite3_close(db);
- throw IOException("Database initialization");
+ fatal("Database initialization");
}
}
SQLITE_TRANSIENT);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
- throw IOException("Could not execute INSERT statement!");
+ fatal("Could not execute INSERT statement!");
}
sqlite3_finalize(stmt);
rc = sqlite3_step(stmt);
if (rc == SQLITE_DONE) {
- throw IOException("No segment found by id");
+ fatal("No segment found by id");
} else if (rc == SQLITE_ROW) {
result = sqlite3_column_int64(stmt, 0);
} else {
- throw IOException("Error executing find segment by id query");
+ fatal("Error executing find segment by id query");
}
sqlite3_finalize(stmt);
rc = sqlite3_step(stmt);
if (rc == SQLITE_DONE) {
- throw IOException("No segment found by id");
+ fatal("No segment found by id");
} else if (rc == SQLITE_ROW) {
result = (const char *)sqlite3_column_text(stmt, 0);
} else {
- throw IOException("Error executing find segment by id query");
+ fatal("Error executing find segment by id query");
}
sqlite3_finalize(stmt);
} else if (rc == SQLITE_ROW) {
ref = ObjectReference(IdToSegment(sqlite3_column_int64(stmt, 0)),
(const char *)sqlite3_column_text(stmt, 1));
- ref.set_range(0, size);
+ ref.set_range(0, size, true);
} else {
fprintf(stderr, "Could not execute SELECT statement!\n");
ReportError(rc);
if (!ref.is_normal())
return;
- stmt = Prepare("insert or ignore into snapshot_refs "
- "select segmentid, object, size from block_index "
+ int64_t old_size = 0;
+ stmt = Prepare("select size from snapshot_refs "
"where segmentid = ? and object = ?");
sqlite3_bind_int64(stmt, 1, SegmentToId(ref.get_segment()));
string obj = ref.get_sequence();
sqlite3_bind_text(stmt, 2, obj.c_str(), obj.size(), SQLITE_TRANSIENT);
-
rc = sqlite3_step(stmt);
- if (rc != SQLITE_DONE) {
- fprintf(stderr, "Could not execute INSERT statement!\n");
- ReportError(rc);
+ if (rc == SQLITE_ROW) {
+ old_size = sqlite3_column_int64(stmt, 0);
}
+ sqlite3_finalize(stmt);
+ int64_t block_size = 0;
+ stmt = Prepare("select size from block_index "
+ "where segmentid = ? and object = ?");
+ sqlite3_bind_int64(stmt, 1, SegmentToId(ref.get_segment()));
+ obj = ref.get_sequence();
+ sqlite3_bind_text(stmt, 2, obj.c_str(), obj.size(), SQLITE_TRANSIENT);
+ rc = sqlite3_step(stmt);
+ if (rc == SQLITE_ROW) {
+ block_size = sqlite3_column_int64(stmt, 0);
+ } else {
+ string refstr = ref.to_string();
+ fprintf(stderr, "No block found in block_index for %s\n",
+ refstr.c_str());
+ sqlite3_finalize(stmt);
+ return;
+ }
sqlite3_finalize(stmt);
+
+ int64_t new_size = old_size;
+ if (ref.has_range()) {
+ new_size += ref.get_range_length();
+ new_size = min(new_size, block_size);
+ } else {
+ new_size = block_size;
+ }
+
+ if (new_size != old_size) {
+ stmt = Prepare("insert or replace "
+ "into snapshot_refs(segmentid, object, size) "
+ "values (?, ?, ?)");
+ sqlite3_bind_int64(stmt, 1, SegmentToId(ref.get_segment()));
+ obj = ref.get_sequence();
+ sqlite3_bind_text(stmt, 2, obj.c_str(), obj.size(), SQLITE_TRANSIENT);
+ sqlite3_bind_int64(stmt, 3, new_size);
+
+ rc = sqlite3_step(stmt);
+ if (rc != SQLITE_DONE) {
+ fprintf(stderr, "Could not execute INSERT statement!\n");
+ ReportError(rc);
+ }
+
+ sqlite3_finalize(stmt);
+ }
}
void LocalDb::UseSegment(const std::string &segment, double utilization)
sqlite3_stmt *stmt;
int found = false;
- stmt = Prepare("select algorithm, signatures from subblock_signatures "
+ stmt = Prepare("select signatures, algorithm from subblock_signatures "
"where blockid = (select blockid from block_index "
" where segmentid = ? and object = ?)");
sqlite3_bind_int64(stmt, 1, SegmentToId(ref.get_segment()));
fprintf(stderr,
"Could not determine blockid in StoreChunkSignatures!\n");
ReportError(rc);
- throw IOException("Error getting blockid");
+ fatal("Error getting blockid");
}
int64_t blockid = sqlite3_column_int64(stmt, 0);
sqlite3_finalize(stmt);