15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NET_DISK_CACHE_FLASH_SEGMENT_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NET_DISK_CACHE_FLASH_SEGMENT_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace disk_cache {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Storage;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The underlying storage represented by Storage class, is divided into fixed
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// size logical segments, represented by this class.  Since segment size is
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fixed, the storage size should be a multiple of segment size.  The picture
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// below describes the relation between storage and segments:
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   |-----------+-----------+-----+-------------+-----------|
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   | segment 0 | segment 1 | ... | segment n-1 | segment n |
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   |-----------+-----------+-----+-------------+-----------|
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   |-------------------------------------------------------|
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   |                       storage                         |
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   |-------------------------------------------------------|
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A segment is constructed by taking its index within the storage, a flag
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// indicating whether it is a read-only segment and a pointer to the storage on
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which it resides.  It provides an API for reading/writing entries residing on
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it.  Init() function must be called right after the construction of a segment
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and one should proceed to calling other functions only if Init() has
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// succeeded.  After a successful initialization, one may proceed to call
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// non-mutating functions; mutating functions can be called if the segment is
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not read-only.  Finally, Close() function must be called right before the
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destruction.  Calling Close() makes the segment immutable, which means
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mutating functions cannot be called on the object after that.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Segment can only be used as a log, i.e. all writes are laid out sequentially
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// on a segment.  As a result, WriteData() function does not take an offset.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Current write offset can be learned by calling write_offset().
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Once the entries are written to the Segment and Close() called on it and the
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object destroyed, we should later be able to instantiate a read-only Segment
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object and recreate all the entries that were previously written to it.  To
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// achieve this, a tiny region of Segment is used for its metadata and Segment
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// provides two calls for interacting with metadata: StoreOffset() and
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetOffsets().  The former can be used to store an offset that was returned by
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// write_offset() and the latter can be used to retrieve all the offsets that
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// were stored in the Segment.  Before attempting to write an entry, the client
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// should call CanHold() to make sure that there is enough space in the segment.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ReadData can be called over the range that was previously written with
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteData.  Reading from area that was not written will fail.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class NET_EXPORT_PRIVATE Segment {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |index| is the index of this segment on |storage|.  If the storage size is
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X and the segment size is Y, where X >> Y and X % Y == 0, then the valid
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // values for the index are integers within the range [0, X/Y).  Thus, if
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |index| is given value Z, then it covers bytes on storage starting at the
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // offset Z*Y and ending at the offset Z*Y+Y-1.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Segment(int32 index, bool read_only, Storage* storage);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~Segment();
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 index() const { return index_; }
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 write_offset() const { return write_offset_; }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool HaveOffset(int32 offset) const;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int32> GetOffsets() const { return offsets_; }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Manage the number of users of this segment.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddUser();
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ReleaseUser();
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool HasNoUsers() const;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Performs segment initialization.  Must be the first function called on the
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // segment and further calls should be made only if it is successful.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Init();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Writes |size| bytes of data from |buffer| to segment, returns false if
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // fails and true if succeeds.  Can block for a long time.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool WriteData(const void* buffer, int32 size);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Reads |size| bytes of data living at |offset| into |buffer| returns true on
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // success and false on failure.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ReadData(void* buffer, int32 size, int32 offset) const;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stores the offset in the metadata.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StoreOffset(int32 offset);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Closes the segment, returns true on success and false on failure.  Closing
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a segment makes it immutable.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Close();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if segment can accommodate an entry of |size| bytes.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CanHold(int32 size) const;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 index_;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 num_users_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool read_only_;  // Indicates whether the segment can be written to.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool init_;  // Indicates whether segment was initialized.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Storage* storage_;  // Storage on which the segment resides.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int32 offset_;  // Offset of the segment on |storage_|.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int32 summary_offset_;  // Offset of the segment summary.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 write_offset_;  // Current write offset.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int32> offsets_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Segment);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace disk_cache
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // NET_DISK_CACHE_FLASH_SEGMENT_H_
119