Home | History | Annotate | Download | only in flash
      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