diff options
-rw-r--r-- | net/disk_cache/flash/segment.cc | 21 | ||||
-rw-r--r-- | net/disk_cache/flash/segment.h | 41 | ||||
-rw-r--r-- | net/disk_cache/flash/segment_unittest.cc | 38 |
3 files changed, 34 insertions, 66 deletions
diff --git a/net/disk_cache/flash/segment.cc b/net/disk_cache/flash/segment.cc index b00b38a..191ccd7 100644 --- a/net/disk_cache/flash/segment.cc +++ b/net/disk_cache/flash/segment.cc @@ -44,7 +44,7 @@ bool Segment::Init() { DCHECK_LE(entry_count, kFlashMaxEntryCount); std::vector<int32> tmp(summary + 1, summary + 1 + entry_count); - header_offsets_.swap(tmp); + offsets_.swap(tmp); init_ = true; return true; } @@ -61,14 +61,9 @@ bool Segment::WriteData(const void* buffer, int32 size, int32* offset) { return true; } -bool Segment::WriteHeader(const void* header, int32 size, int32* offset) { - int32 my_offset; - if (!WriteData(header, size, &my_offset)) - return false; - if (offset) - *offset = my_offset; - header_offsets_.push_back(my_offset); - return true; +void Segment::StoreOffset(int32 offset) { + DCHECK(offsets_.size() < kFlashMaxEntryCount); + offsets_.push_back(offset); } bool Segment::ReadData(void* buffer, int32 size, int32 offset) const { @@ -81,12 +76,12 @@ bool Segment::Close() { if (read_only_) return true; - DCHECK(header_offsets_.size() <= kFlashMaxEntryCount); + DCHECK(offsets_.size() <= kFlashMaxEntryCount); int32 summary[kFlashMaxEntryCount + 1]; memset(summary, 0, kFlashSummarySize); - summary[0] = header_offsets_.size(); - std::copy(header_offsets_.begin(), header_offsets_.end(), summary + 1); + summary[0] = offsets_.size(); + std::copy(offsets_.begin(), offsets_.end(), summary + 1); if (!storage_->Write(summary, kFlashSummarySize, summary_offset_)) return false; @@ -95,7 +90,7 @@ bool Segment::Close() { } bool Segment::CanHold(int32 size) const { - return header_offsets_.size() < kFlashMaxEntryCount && + return offsets_.size() < kFlashMaxEntryCount && write_offset_ + size <= summary_offset_; } diff --git a/net/disk_cache/flash/segment.h b/net/disk_cache/flash/segment.h index 4a10c65..3c1fa67 100644 --- a/net/disk_cache/flash/segment.h +++ b/net/disk_cache/flash/segment.h @@ -40,22 +40,21 @@ class Storage; // mutating functions cannot be called on the object after that. // // Segment can only be used as a log, i.e. all writes are laid out sequentially -// on a segment. As a result, write APIs do not take an offset, but can return -// an offset of where the write took place. The entries living on a segment are -// expected to consist of data part and header part where the header holds -// enough information to identify all the data belonging to it. The difference -// between WriteData and WriteHeader is that writes issued with the latter have -// their offsets saved in the metadata, which can later be retrieved. Thus, it -// is up to the client to specify data layout and associate the header with -// data. For example the client may issue WriteData calls and save the offsets -// which then can be written using WriteHeader. Note that it is possible to -// write entries using just WriteHeader as well, for example if it is an entry -// of the format where header specifies the length of the following data. -// Before attempting to write an entry, the client should call CanHold to make -// sure that there is enough space in the segment. +// on a segment. As a result, WriteData() function does not take an offset, but +// can return an offset of where the write took place. +// +// Once the entries are written to the Segment and Close() called on it and the +// object destroyed, we should later be able to instantiate a read-only Segment +// object and recreate all the entries that were previously written to it. To +// achieve this, a tiny region of Segment is used for its metadata and Segment +// provides two calls for interacting with metadata: StoreOffset() and +// GetOffsets(). The former can be used to store an offset that was returned by +// WriteData() and the latter can be used to retrieve all the offsets that were +// stored in the Segment. Before attempting to write an entry, the client +// should call CanHold() to make sure that there is enough space in the segment. // // ReadData can be called over the range that was previously written with -// WriteData/WriteHeader. Reading from area that was not written will fail. +// WriteData. Reading from area that was not written will fail. class NET_EXPORT_PRIVATE Segment { public: @@ -67,7 +66,7 @@ class NET_EXPORT_PRIVATE Segment { Segment(int32 index, bool read_only, Storage* storage); ~Segment(); - const std::vector<int32>& header_offsets() const { return header_offsets_; } + std::vector<int32> GetOffsets() const { return offsets_; } // Performs segment initialization. Must be the first function called on the // segment and further calls should be made only if it is successful. @@ -78,17 +77,13 @@ class NET_EXPORT_PRIVATE Segment { // block for a long time. bool WriteData(const void* buffer, int32 size, int32* offset); - // Writes |header| of |size| bytes, returns false if fails and true if - // succeeds and sets the |offset|, if it is not NULL. Can block for a long - // time. The difference between this function and WriteData is that the - // offset of this write operation is saved in the segment metadata and can - // later be retrieved via |header_offsets|. - bool WriteHeader(const void* header, int32 size, int32* offset); - // Reads |size| bytes of data living at |offset| into |buffer|, returns true // on success and false on failure. bool ReadData(void* buffer, int32 size, int32 offset) const; + // Stores the offset in the metadata. + void StoreOffset(int32 offset); + // Closes the segment, returns true on success and false on failure. Closing // a segment makes it immutable. bool Close(); @@ -103,7 +98,7 @@ class NET_EXPORT_PRIVATE Segment { const int32 offset_; // Offset of the segment on |storage_|. const int32 summary_offset_; // Offset of the segment summary. int32 write_offset_; // Current write offset. - std::vector<int32> header_offsets_; + std::vector<int32> offsets_; DISALLOW_COPY_AND_ASSIGN(Segment); }; diff --git a/net/disk_cache/flash/segment_unittest.cc b/net/disk_cache/flash/segment_unittest.cc index bbbcc80..fb9fb33 100644 --- a/net/disk_cache/flash/segment_unittest.cc +++ b/net/disk_cache/flash/segment_unittest.cc @@ -77,30 +77,6 @@ TEST_F(FlashCacheTest, WriteDataReadData) { EXPECT_TRUE(segment->Close()); } -TEST_F(FlashCacheTest, WriteHeaderReadData) { - int32 index = rand() % num_segments_in_storage_; - scoped_ptr<disk_cache::Segment> segment( - new disk_cache::Segment(index, false, storage_.get())); - - EXPECT_TRUE(segment->Init()); - SmallEntry entry1; - EXPECT_TRUE(segment->CanHold(entry1.size)); - int32 offset; - EXPECT_TRUE(segment->WriteHeader(entry1.data, entry1.size, &offset)); - EXPECT_EQ(1u, segment->header_offsets().size()); - EXPECT_EQ(offset, segment->header_offsets().front()); - EXPECT_TRUE(segment->Close()); - - segment.reset(new disk_cache::Segment(index, true, storage_.get())); - EXPECT_TRUE(segment->Init()); - SmallEntry entry2; - EXPECT_EQ(1u, segment->header_offsets().size()); - offset = segment->header_offsets().front(); - EXPECT_TRUE(segment->ReadData(entry2.data, entry2.size, offset)); - EXPECT_EQ(entry1, entry2); - EXPECT_TRUE(segment->Close()); -} - TEST_F(FlashCacheTest, FillWithSmallEntries) { int32 index = rand() % num_segments_in_storage_; scoped_ptr<disk_cache::Segment> segment( @@ -109,14 +85,15 @@ TEST_F(FlashCacheTest, FillWithSmallEntries) { EXPECT_TRUE(segment->Init()); SmallEntry entry; int32 num_bytes_written = 0; + int32 offset; while (segment->CanHold(entry.size)) { - EXPECT_TRUE(segment->WriteHeader(entry.data, entry.size, NULL)); + EXPECT_TRUE(segment->WriteData(entry.data, entry.size, &offset)); + segment->StoreOffset(offset); num_bytes_written += entry.size; } int32 space_left = kSegmentFreeSpace - num_bytes_written; EXPECT_GE(space_left, entry.size); - EXPECT_EQ(segment->header_offsets().size(), - disk_cache::kFlashMaxEntryCount); + EXPECT_EQ(segment->GetOffsets().size(), disk_cache::kFlashMaxEntryCount); EXPECT_TRUE(segment->Close()); } @@ -128,13 +105,14 @@ TEST_F(FlashCacheTest, FillWithLargeEntries) { EXPECT_TRUE(segment->Init()); scoped_ptr<LargeEntry> entry(new LargeEntry); int32 num_bytes_written = 0; + int32 offset; while (segment->CanHold(entry->size)) { - EXPECT_TRUE(segment->WriteHeader(entry->data, entry->size, NULL)); + EXPECT_TRUE(segment->WriteData(entry->data, entry->size, &offset)); + segment->StoreOffset(offset); num_bytes_written += entry->size; } int32 space_left = kSegmentFreeSpace - num_bytes_written; EXPECT_LT(space_left, entry->size); - EXPECT_LT(segment->header_offsets().size(), - disk_cache::kFlashMaxEntryCount); + EXPECT_LT(segment->GetOffsets().size(), disk_cache::kFlashMaxEntryCount); EXPECT_TRUE(segment->Close()); } |