From d38558b79c81f446698c272a85f1a2782667bce3 Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Fri, 14 Dec 2007 11:51:41 -0800 Subject: [PATCH] Fix a bug in computing the size of a segment that led to utilization > 1.0. The old code for computing the size of a segment (to be stored in the segments table) could leave off the last object to be written to the segment. This could cause the computed segment utilization to be greater than 1.0, which should be impossible. Fix the size calculation so that it should always include all data written to the segment. As a bonus, this also correctly computes the size of metadata-log segments, even though the metadata objects don't appear in the block_index table (which was previously used for computing the segment size, but is no longer). --- localdb.cc | 9 ++++----- localdb.h | 2 +- store.cc | 5 ++++- store.h | 1 + 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/localdb.cc b/localdb.cc index 17337f0..50c15e9 100644 --- a/localdb.cc +++ b/localdb.cc @@ -359,20 +359,19 @@ void LocalDb::UseObject(const ObjectReference& ref) void LocalDb::SetSegmentChecksum(const std::string &segment, const std::string &path, - const std::string &checksum) + const std::string &checksum, + int size) { int rc; sqlite3_stmt *stmt; - stmt = Prepare("update segments set path = ?, checksum = ?, " - "size = (select sum(size) from block_index " - " where segmentid = ?) " + stmt = Prepare("update segments set path = ?, checksum = ?, size = ? " "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, 3, size); sqlite3_bind_int64(stmt, 4, SegmentToId(segment)); rc = sqlite3_step(stmt); diff --git a/localdb.h b/localdb.h index 69fb330..a89923f 100644 --- a/localdb.h +++ b/localdb.h @@ -33,7 +33,7 @@ public: void UseObject(const ObjectReference& ref); void SetSegmentChecksum(const std::string &segment, const std::string &path, - const std::string &checksum); + const std::string &checksum, int size); bool GetSegmentChecksum(const std::string &segment, std::string *seg_path, std::string *seg_checksum); private: diff --git a/store.cc b/store.cc index a156a57..1ea2439 100644 --- a/store.cc +++ b/store.cc @@ -232,6 +232,7 @@ ObjectReference TarSegmentStore::write_object(const char *data, size_t len, segment->fullname = path + "/" + segment->basename; segment->file = new Tarfile(segment->fullname, segment->name); segment->count = 0; + segment->size = 0; segments[group] = segment; } else { @@ -244,6 +245,7 @@ ObjectReference TarSegmentStore::write_object(const char *data, size_t len, segment->file->write_object(id, data, len); segment->count++; + segment->size += len; group_sizes[group] += len; @@ -282,7 +284,8 @@ void TarSegmentStore::close_segment(const string &group) SHA1Checksum segment_checksum; if (segment_checksum.process_file(segment->fullname.c_str())) { string checksum = segment_checksum.checksum_str(); - db->SetSegmentChecksum(segment->name, segment->basename, checksum); + db->SetSegmentChecksum(segment->name, segment->basename, checksum, + segment->size); } } diff --git a/store.h b/store.h index 956a1b5..d447031 100644 --- a/store.h +++ b/store.h @@ -115,6 +115,7 @@ private: Tarfile *file; std::string name; // UUID int count; // Objects written to this segment + int size; // Combined size of objects written std::string basename; // Name of segment without directory std::string fullname; // Full path to stored segment }; -- 2.20.1