summaryrefslogtreecommitdiffstats
path: root/net/disk_cache/flash/log_store.h
blob: e53b83e16259dccffe46f4afb33258fe91f74377 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_DISK_CACHE_FLASH_LOG_STORE_H_
#define NET_DISK_CACHE_FLASH_LOG_STORE_H_

#include <set>
#include <vector>

#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "net/base/net_export.h"
#include "net/disk_cache/flash/storage.h"

namespace disk_cache {

class Segment;

// This class implements a general purpose store for storing and retrieving
// entries consisting of arbitrary binary data.  The store has log semantics,
// i.e. it's not possible to overwrite data in place.  In order to update an
// entry, a new version must be written.  Only one entry can be written to at
// any given time, while concurrent reading of multiple entries is supported.
class NET_EXPORT_PRIVATE LogStore {
 public:
  LogStore(const base::FilePath& path, int32 size);
  ~LogStore();

  // Performs initialization.  Must be the first function called and further
  // calls should be made only if it is successful.
  bool Init();

  // Closes the store.  Should be the last function called before destruction.
  bool Close();

  // Creates an entry of |size| bytes.  The id of the created entry is stored in
  // |entry_id|.
  bool CreateEntry(int32 size, int32* entry_id);

  // Deletes |entry_id|; the client should keep track of |size| and provide it
  // here.  Only inactive (i.e. not currently open or being created) entries can
  // be deleted.
  void DeleteEntry(int32 entry_id, int32 size);

  // Appends data to the end of the last created entry.
  bool WriteData(const void* buffer, int32 size);

  // Opens an entry with id |entry_id|.
  bool OpenEntry(int32 entry_id);

  // Reads |size| bytes starting from |offset| into |buffer|, where |offset| is
  // relative to the entry's content, from an entry identified by |entry_id|.
  bool ReadData(int32 entry_id, void* buffer, int32 size, int32 offset) const;

  // Closes an entry that was either opened with OpenEntry or created with
  // CreateEntry.
  void CloseEntry(int32 id);

 private:
  FRIEND_TEST_ALL_PREFIXES(FlashCacheTest, LogStoreReadFromClosedSegment);
  FRIEND_TEST_ALL_PREFIXES(FlashCacheTest, LogStoreSegmentSelectionIsFifo);
  FRIEND_TEST_ALL_PREFIXES(FlashCacheTest, LogStoreInUseSegmentIsSkipped);
  FRIEND_TEST_ALL_PREFIXES(FlashCacheTest, LogStoreReadFromCurrentAfterClose);

  int32 GetNextSegmentIndex();
  bool InUse(int32 segment_index) const;

  Storage storage_;

  int32 num_segments_;

  // Currently open segments, either for reading or writing.  There can only be
  // one segment open for writing, and multiple open for reading.
  std::vector<Segment*> open_segments_;

  // The index of the segment currently being written to.  It's an index to
  // |open_segments_| vector.
  int32 write_index_;

  // Ids of entries currently open, either CreatEntry'ed or OpenEntry'ed.
  std::set<int32> open_entries_;

  // Id of the entry that is currently being written to, -1 if there is no entry
  // currently being written to.
  int32 current_entry_id_;

  // Number of bytes left to be written to the entry identified by
  // |current_entry_id_|.  Its value makes sense iff |current_entry_id_| is not
  // -1.
  int32 current_entry_num_bytes_left_to_write_;

  bool init_;  // Init was called.
  bool closed_;  // Close was called.

  DISALLOW_COPY_AND_ASSIGN(LogStore);
};

}  // namespace disk_cache

#endif  // NET_DISK_CACHE_FLASH_LOG_STORE_H_