cumulus-util: In list-snapshot-sizes output, display backup intent values.
[cumulus.git] / localdb.cc
index c74e27d..7d93bb1 100644 (file)
 #include <string.h>
 #include <sqlite3.h>
 
+#include <algorithm>
 #include <string>
 
 #include "localdb.h"
 #include "store.h"
 
+using std::min;
 using std::string;
 
 /* Helper function to prepare a statement for execution in the current
@@ -83,6 +85,9 @@ void LocalDb::Open(const char *path, const char *snapshot_name,
 
     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 "
@@ -90,11 +95,8 @@ void LocalDb::Open(const char *path, const char *snapshot_name,
                                  "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);
@@ -293,7 +295,7 @@ ObjectReference LocalDb::FindObject(const string &checksum, int64_t size)
     } 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);
@@ -376,20 +378,61 @@ void LocalDb::UseObject(const ObjectReference& ref)
     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)
@@ -492,7 +535,7 @@ bool LocalDb::LoadChunkSignatures(ObjectReference ref,
     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()));