+
+ObjectReference LocalDb::FindObject(const string &checksum, int64_t size)
+{
+ int rc;
+ sqlite3_stmt *stmt;
+ ObjectReference ref;
+
+ stmt = Prepare("select segmentid, object from block_index "
+ "where checksum = ? and size = ? and expired is null");
+ sqlite3_bind_text(stmt, 1, checksum.c_str(), checksum.size(),
+ SQLITE_TRANSIENT);
+ sqlite3_bind_int64(stmt, 2, size);
+
+ rc = sqlite3_step(stmt);
+ if (rc == SQLITE_DONE) {
+ } else if (rc == SQLITE_ROW) {
+ ref = ObjectReference(IdToSegment(sqlite3_column_int64(stmt, 0)),
+ (const char *)sqlite3_column_text(stmt, 1));
+ } else {
+ fprintf(stderr, "Could not execute SELECT statement!\n");
+ ReportError(rc);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return ref;
+}
+
+bool LocalDb::IsOldObject(const string &checksum, int64_t size, double *age,
+ int *group)
+{
+ int rc;
+ sqlite3_stmt *stmt;
+ bool found = false;
+
+ stmt = Prepare("select segmentid, object, timestamp, expired "
+ "from block_index where checksum = ? and size = ?");
+ sqlite3_bind_text(stmt, 1, checksum.c_str(), checksum.size(),
+ SQLITE_TRANSIENT);
+ sqlite3_bind_int64(stmt, 2, size);
+
+ rc = sqlite3_step(stmt);
+ if (rc == SQLITE_DONE) {
+ found = false;
+ } else if (rc == SQLITE_ROW) {
+ found = true;
+ *age = sqlite3_column_double(stmt, 2);
+ *group = sqlite3_column_int(stmt, 3);
+ } else {
+ fprintf(stderr, "Could not execute SELECT statement!\n");
+ ReportError(rc);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return found;
+}
+
+/* Does this object still exist in the database (and not expired)? */
+bool LocalDb::IsAvailable(const ObjectReference &ref)
+{
+ int rc;
+ sqlite3_stmt *stmt;
+ bool found = false;
+
+ // Special objects (such as the zero object) aren't stored in segments, and
+ // so are always available.
+ if (!ref.is_normal())
+ return true;
+
+ stmt = Prepare("select count(*) from block_index "
+ "where segmentid = ? and object = ? and expired is null");
+ sqlite3_bind_int64(stmt, 1, SegmentToId(ref.get_segment()));
+ sqlite3_bind_text(stmt, 2, ref.get_sequence().c_str(),
+ ref.get_sequence().size(), SQLITE_TRANSIENT);
+
+ rc = sqlite3_step(stmt);
+ if (rc == SQLITE_DONE) {
+ found = false;
+ } else if (rc == SQLITE_ROW) {
+ if (sqlite3_column_int(stmt, 0) > 0)
+ found = true;
+ } else {
+ fprintf(stderr, "Could not execute SELECT statement!\n");
+ ReportError(rc);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return found;
+}
+
+void LocalDb::UseObject(const ObjectReference& ref)
+{
+ int rc;
+ sqlite3_stmt *stmt;
+
+ if (!ref.is_normal())
+ return;
+
+ stmt = Prepare("insert or ignore into snapshot_refs "
+ "select segmentid, object, size from block_index "
+ "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);
+ }
+
+ sqlite3_finalize(stmt);
+}
+
+void LocalDb::SetSegmentChecksum(const std::string &segment,
+ const std::string &path,
+ const std::string &checksum)
+{
+ int rc;
+ sqlite3_stmt *stmt;
+
+ stmt = Prepare("update segments set path = ?, checksum = ?, "
+ "size = (select sum(size) from block_index "
+ " where segmentid = ?) "
+ "where segmentid = ?");
+ sqlite3_bind_text(stmt, 1, path.c_str(), path.size(),
+ SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 2, checksum.c_str(), checksum.size(),
+ SQLITE_TRANSIENT);
+ sqlite3_bind_int64(stmt, 3, SegmentToId(segment));
+ sqlite3_bind_int64(stmt, 4, SegmentToId(segment));
+
+ rc = sqlite3_step(stmt);
+ if (rc != SQLITE_DONE) {
+ fprintf(stderr, "Could not update segment checksum in database!\n");
+ ReportError(rc);
+ }
+
+ sqlite3_finalize(stmt);
+}
+
+bool LocalDb::GetSegmentChecksum(const string &segment,
+ string *seg_path,
+ string *seg_checksum)
+{
+ int rc;
+ sqlite3_stmt *stmt;
+ ObjectReference ref;
+ int found = false;
+
+ stmt = Prepare("select path, checksum from segments where segment = ?");
+ sqlite3_bind_text(stmt, 1, segment.c_str(), segment.size(),
+ SQLITE_TRANSIENT);
+
+ rc = sqlite3_step(stmt);
+ if (rc == SQLITE_DONE) {
+ } else if (rc == SQLITE_ROW) {
+ found = true;
+ const char *val;
+
+ val = (const char *)sqlite3_column_text(stmt, 0);
+ if (val == NULL)
+ found = false;
+ else
+ *seg_path = val;
+
+ val = (const char *)sqlite3_column_text(stmt, 1);
+ if (val == NULL)
+ found = false;
+ else
+ *seg_checksum = val;
+ } else {
+ fprintf(stderr, "Could not execute SELECT statement!\n");
+ ReportError(rc);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return found;
+}