1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_DISK_CACHE_FLASH_SEGMENT_H_ 6 #define NET_DISK_CACHE_FLASH_SEGMENT_H_ 7 8 #include <vector> 9 10 #include "base/basictypes.h" 11 #include "base/gtest_prod_util.h" 12 #include "net/base/net_export.h" 13 14 namespace disk_cache { 15 16 class Storage; 17 18 // The underlying storage represented by Storage class, is divided into fixed 19 // size logical segments, represented by this class. Since segment size is 20 // fixed, the storage size should be a multiple of segment size. The picture 21 // below describes the relation between storage and segments: 22 // 23 // |-----------+-----------+-----+-------------+-----------| 24 // | segment 0 | segment 1 | ... | segment n-1 | segment n | 25 // |-----------+-----------+-----+-------------+-----------| 26 // 27 // |-------------------------------------------------------| 28 // | storage | 29 // |-------------------------------------------------------| 30 // 31 // A segment is constructed by taking its index within the storage, a flag 32 // indicating whether it is a read-only segment and a pointer to the storage on 33 // which it resides. It provides an API for reading/writing entries residing on 34 // it. Init() function must be called right after the construction of a segment 35 // and one should proceed to calling other functions only if Init() has 36 // succeeded. After a successful initialization, one may proceed to call 37 // non-mutating functions; mutating functions can be called if the segment is 38 // not read-only. Finally, Close() function must be called right before the 39 // destruction. Calling Close() makes the segment immutable, which means 40 // mutating functions cannot be called on the object after that. 41 // 42 // Segment can only be used as a log, i.e. all writes are laid out sequentially 43 // on a segment. As a result, WriteData() function does not take an offset. 44 // Current write offset can be learned by calling write_offset(). 45 // 46 // Once the entries are written to the Segment and Close() called on it and the 47 // object destroyed, we should later be able to instantiate a read-only Segment 48 // object and recreate all the entries that were previously written to it. To 49 // achieve this, a tiny region of Segment is used for its metadata and Segment 50 // provides two calls for interacting with metadata: StoreOffset() and 51 // GetOffsets(). The former can be used to store an offset that was returned by 52 // write_offset() and the latter can be used to retrieve all the offsets that 53 // were stored in the Segment. Before attempting to write an entry, the client 54 // should call CanHold() to make sure that there is enough space in the segment. 55 // 56 // ReadData can be called over the range that was previously written with 57 // WriteData. Reading from area that was not written will fail. 58 59 class NET_EXPORT_PRIVATE Segment { 60 public: 61 // |index| is the index of this segment on |storage|. If the storage size is 62 // X and the segment size is Y, where X >> Y and X % Y == 0, then the valid 63 // values for the index are integers within the range [0, X/Y). Thus, if 64 // |index| is given value Z, then it covers bytes on storage starting at the 65 // offset Z*Y and ending at the offset Z*Y+Y-1. 66 Segment(int32 index, bool read_only, Storage* storage); 67 ~Segment(); 68 69 int32 index() const { return index_; } 70 int32 write_offset() const { return write_offset_; } 71 72 bool HaveOffset(int32 offset) const; 73 std::vector<int32> GetOffsets() const { return offsets_; } 74 75 // Manage the number of users of this segment. 76 void AddUser(); 77 void ReleaseUser(); 78 bool HasNoUsers() const; 79 80 // Performs segment initialization. Must be the first function called on the 81 // segment and further calls should be made only if it is successful. 82 bool Init(); 83 84 // Writes |size| bytes of data from |buffer| to segment, returns false if 85 // fails and true if succeeds. Can block for a long time. 86 bool WriteData(const void* buffer, int32 size); 87 88 // Reads |size| bytes of data living at |offset| into |buffer| returns true on 89 // success and false on failure. 90 bool ReadData(void* buffer, int32 size, int32 offset) const; 91 92 // Stores the offset in the metadata. 93 void StoreOffset(int32 offset); 94 95 // Closes the segment, returns true on success and false on failure. Closing 96 // a segment makes it immutable. 97 bool Close(); 98 99 // Returns true if segment can accommodate an entry of |size| bytes. 100 bool CanHold(int32 size) const; 101 102 private: 103 int32 index_; 104 int32 num_users_; 105 bool read_only_; // Indicates whether the segment can be written to. 106 bool init_; // Indicates whether segment was initialized. 107 Storage* storage_; // Storage on which the segment resides. 108 const int32 offset_; // Offset of the segment on |storage_|. 109 const int32 summary_offset_; // Offset of the segment summary. 110 int32 write_offset_; // Current write offset. 111 std::vector<int32> offsets_; 112 113 DISALLOW_COPY_AND_ASSIGN(Segment); 114 }; 115 116 } // namespace disk_cache 117 118 #endif // NET_DISK_CACHE_FLASH_SEGMENT_H_ 119