OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/logging.h" | 5 #include "base/logging.h" |
6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "net/disk_cache/flash/format.h" | 8 #include "net/disk_cache/flash/format.h" |
9 #include "net/disk_cache/flash/log_structured_store.h" | 9 #include "net/disk_cache/flash/log_store.h" |
10 #include "net/disk_cache/flash/segment.h" | 10 #include "net/disk_cache/flash/segment.h" |
11 #include "net/disk_cache/flash/storage.h" | 11 #include "net/disk_cache/flash/storage.h" |
12 | 12 |
13 namespace disk_cache { | 13 namespace disk_cache { |
14 | 14 |
15 LogStructuredStore::LogStructuredStore(Storage* storage) | 15 LogStore::LogStore(Storage* storage) |
16 : storage_(storage), | 16 : storage_(storage), |
17 num_segments_(storage->size() / kFlashSegmentSize), | 17 num_segments_(storage->size() / kFlashSegmentSize), |
18 open_segments_(num_segments_), | 18 open_segments_(num_segments_), |
19 write_index_(0), | 19 write_index_(0), |
20 current_entry_id_(-1), | 20 current_entry_id_(-1), |
21 current_entry_num_bytes_left_to_write_(0), | 21 current_entry_num_bytes_left_to_write_(0), |
22 init_(false), | 22 init_(false), |
23 closed_(false) { | 23 closed_(false) { |
24 DCHECK(storage->size() % kFlashSegmentSize == 0); | 24 DCHECK(storage->size() % kFlashSegmentSize == 0); |
25 } | 25 } |
26 | 26 |
27 LogStructuredStore::~LogStructuredStore() { | 27 LogStore::~LogStore() { |
28 DCHECK(!init_ || closed_); | 28 DCHECK(!init_ || closed_); |
29 STLDeleteElements(&open_segments_); | 29 STLDeleteElements(&open_segments_); |
30 } | 30 } |
31 | 31 |
32 bool LogStructuredStore::Init() { | 32 bool LogStore::Init() { |
33 DCHECK(!init_); | 33 DCHECK(!init_); |
34 // TODO(agayev): Once we start persisting segment metadata to disk, we will | 34 // TODO(agayev): Once we start persisting segment metadata to disk, we will |
35 // start from where we left off during the last shutdown. | 35 // start from where we left off during the last shutdown. |
36 scoped_ptr<Segment> segment(new Segment(write_index_, false, storage_)); | 36 scoped_ptr<Segment> segment(new Segment(write_index_, false, storage_)); |
37 if (!segment->Init()) | 37 if (!segment->Init()) |
38 return false; | 38 return false; |
39 | 39 |
40 segment->AddUser(); | 40 segment->AddUser(); |
41 open_segments_[write_index_] = segment.release(); | 41 open_segments_[write_index_] = segment.release(); |
42 init_ = true; | 42 init_ = true; |
43 return true; | 43 return true; |
44 } | 44 } |
45 | 45 |
46 bool LogStructuredStore::Close() { | 46 bool LogStore::Close() { |
47 DCHECK(init_ && !closed_); | 47 DCHECK(init_ && !closed_); |
48 open_segments_[write_index_]->ReleaseUser(); | 48 open_segments_[write_index_]->ReleaseUser(); |
49 if (!open_segments_[write_index_]->Close()) | 49 if (!open_segments_[write_index_]->Close()) |
50 return false; | 50 return false; |
51 closed_ = true; | 51 closed_ = true; |
52 return true; | 52 return true; |
53 // TODO(agayev): persist metadata to disk. | 53 // TODO(agayev): persist metadata to disk. |
54 } | 54 } |
55 | 55 |
56 bool LogStructuredStore::CreateEntry(int32 size, int32* id) { | 56 bool LogStore::CreateEntry(int32 size, int32* id) { |
57 DCHECK(init_ && !closed_); | 57 DCHECK(init_ && !closed_); |
58 DCHECK(current_entry_id_ == -1 && size <= disk_cache::kFlashSegmentFreeSpace); | 58 DCHECK(current_entry_id_ == -1 && size <= disk_cache::kFlashSegmentFreeSpace); |
59 | 59 |
60 // TODO(agayev): Avoid large entries from leaving the segments almost empty. | 60 // TODO(agayev): Avoid large entries from leaving the segments almost empty. |
61 if (!open_segments_[write_index_]->CanHold(size)) { | 61 if (!open_segments_[write_index_]->CanHold(size)) { |
62 if (!open_segments_[write_index_]->Close()) | 62 if (!open_segments_[write_index_]->Close()) |
63 return false; | 63 return false; |
64 | 64 |
65 open_segments_[write_index_]->ReleaseUser(); | 65 open_segments_[write_index_]->ReleaseUser(); |
66 if (open_segments_[write_index_]->HasNoUsers()) { | 66 if (open_segments_[write_index_]->HasNoUsers()) { |
(...skipping 11 matching lines...) Expand all Loading... |
78 } | 78 } |
79 | 79 |
80 *id = open_segments_[write_index_]->write_offset(); | 80 *id = open_segments_[write_index_]->write_offset(); |
81 open_segments_[write_index_]->StoreOffset(*id); | 81 open_segments_[write_index_]->StoreOffset(*id); |
82 current_entry_id_ = *id; | 82 current_entry_id_ = *id; |
83 current_entry_num_bytes_left_to_write_ = size; | 83 current_entry_num_bytes_left_to_write_ = size; |
84 open_entries_.insert(current_entry_id_); | 84 open_entries_.insert(current_entry_id_); |
85 return true; | 85 return true; |
86 } | 86 } |
87 | 87 |
88 bool LogStructuredStore::WriteData(const void* buffer, int32 size) { | 88 bool LogStore::WriteData(const void* buffer, int32 size) { |
89 DCHECK(init_ && !closed_); | 89 DCHECK(init_ && !closed_); |
90 DCHECK(current_entry_id_ != -1 && | 90 DCHECK(current_entry_id_ != -1 && |
91 size <= current_entry_num_bytes_left_to_write_); | 91 size <= current_entry_num_bytes_left_to_write_); |
92 if (open_segments_[write_index_]->WriteData(buffer, size)) { | 92 if (open_segments_[write_index_]->WriteData(buffer, size)) { |
93 current_entry_num_bytes_left_to_write_ -= size; | 93 current_entry_num_bytes_left_to_write_ -= size; |
94 return true; | 94 return true; |
95 } | 95 } |
96 return false; | 96 return false; |
97 } | 97 } |
98 | 98 |
99 bool LogStructuredStore::OpenEntry(int32 id) { | 99 bool LogStore::OpenEntry(int32 id) { |
100 DCHECK(init_ && !closed_); | 100 DCHECK(init_ && !closed_); |
101 if (open_entries_.find(id) != open_entries_.end()) | 101 if (open_entries_.find(id) != open_entries_.end()) |
102 return false; | 102 return false; |
103 | 103 |
104 // Segment is already open. | 104 // Segment is already open. |
105 int32 index = id / disk_cache::kFlashSegmentSize; | 105 int32 index = id / disk_cache::kFlashSegmentSize; |
106 if (open_segments_[index]) { | 106 if (open_segments_[index]) { |
107 if (!open_segments_[index]->HaveOffset(id)) | 107 if (!open_segments_[index]->HaveOffset(id)) |
108 return false; | 108 return false; |
109 open_segments_[index]->AddUser(); | 109 open_segments_[index]->AddUser(); |
110 open_entries_.insert(id); | 110 open_entries_.insert(id); |
111 return true; | 111 return true; |
112 } | 112 } |
113 | 113 |
114 // Segment is not open. | 114 // Segment is not open. |
115 scoped_ptr<Segment> segment(new Segment(index, true, storage_)); | 115 scoped_ptr<Segment> segment(new Segment(index, true, storage_)); |
116 if (!segment->Init() || !segment->HaveOffset(id)) | 116 if (!segment->Init() || !segment->HaveOffset(id)) |
117 return false; | 117 return false; |
118 | 118 |
119 segment->AddUser(); | 119 segment->AddUser(); |
120 open_segments_[index] = segment.release(); | 120 open_segments_[index] = segment.release(); |
121 open_entries_.insert(id); | 121 open_entries_.insert(id); |
122 return true; | 122 return true; |
123 } | 123 } |
124 | 124 |
125 bool LogStructuredStore::ReadData(int32 id, void* buffer, int32 size, | 125 bool LogStore::ReadData(int32 id, void* buffer, int32 size, |
126 int32 offset) const { | 126 int32 offset) const { |
127 DCHECK(init_ && !closed_); | 127 DCHECK(init_ && !closed_); |
128 DCHECK(open_entries_.find(id) != open_entries_.end()); | 128 DCHECK(open_entries_.find(id) != open_entries_.end()); |
129 | 129 |
130 int32 index = id / disk_cache::kFlashSegmentSize; | 130 int32 index = id / disk_cache::kFlashSegmentSize; |
131 DCHECK(open_segments_[index] && open_segments_[index]->HaveOffset(id)); | 131 DCHECK(open_segments_[index] && open_segments_[index]->HaveOffset(id)); |
132 return open_segments_[index]->ReadData(buffer, size, id + offset); | 132 return open_segments_[index]->ReadData(buffer, size, id + offset); |
133 } | 133 } |
134 | 134 |
135 void LogStructuredStore::CloseEntry(int32 id) { | 135 void LogStore::CloseEntry(int32 id) { |
136 DCHECK(init_ && !closed_); | 136 DCHECK(init_ && !closed_); |
137 std::set<int32>::iterator entry_iter = open_entries_.find(id); | 137 std::set<int32>::iterator entry_iter = open_entries_.find(id); |
138 DCHECK(entry_iter != open_entries_.end()); | 138 DCHECK(entry_iter != open_entries_.end()); |
139 | 139 |
140 if (current_entry_id_ != -1) { | 140 if (current_entry_id_ != -1) { |
141 DCHECK(id == current_entry_id_ && !current_entry_num_bytes_left_to_write_); | 141 DCHECK(id == current_entry_id_ && !current_entry_num_bytes_left_to_write_); |
142 open_entries_.erase(entry_iter); | 142 open_entries_.erase(entry_iter); |
143 current_entry_id_ = -1; | 143 current_entry_id_ = -1; |
144 return; | 144 return; |
145 } | 145 } |
146 | 146 |
147 int32 index = id / disk_cache::kFlashSegmentSize; | 147 int32 index = id / disk_cache::kFlashSegmentSize; |
148 DCHECK(open_segments_[index]); | 148 DCHECK(open_segments_[index]); |
149 open_entries_.erase(entry_iter); | 149 open_entries_.erase(entry_iter); |
150 | 150 |
151 open_segments_[index]->ReleaseUser(); | 151 open_segments_[index]->ReleaseUser(); |
152 if (open_segments_[index]->HasNoUsers()) { | 152 if (open_segments_[index]->HasNoUsers()) { |
153 delete open_segments_[index]; | 153 delete open_segments_[index]; |
154 open_segments_[index] = NULL; | 154 open_segments_[index] = NULL; |
155 } | 155 } |
156 } | 156 } |
157 | 157 |
158 int32 LogStructuredStore::GetNextSegmentIndex() { | 158 int32 LogStore::GetNextSegmentIndex() { |
159 DCHECK(init_ && !closed_); | 159 DCHECK(init_ && !closed_); |
160 int32 next_index = (write_index_ + 1) % num_segments_; | 160 int32 next_index = (write_index_ + 1) % num_segments_; |
161 | 161 |
162 while (InUse(next_index)) { | 162 while (InUse(next_index)) { |
163 next_index = (next_index + 1) % num_segments_; | 163 next_index = (next_index + 1) % num_segments_; |
164 DCHECK_NE(next_index, write_index_); | 164 DCHECK_NE(next_index, write_index_); |
165 } | 165 } |
166 return next_index; | 166 return next_index; |
167 } | 167 } |
168 | 168 |
169 bool LogStructuredStore::InUse(int32 index) const { | 169 bool LogStore::InUse(int32 index) const { |
170 DCHECK(init_ && !closed_); | 170 DCHECK(init_ && !closed_); |
171 DCHECK(index >= 0 && index < num_segments_); | 171 DCHECK(index >= 0 && index < num_segments_); |
172 return open_segments_[index] != NULL; | 172 return open_segments_[index] != NULL; |
173 } | 173 } |
174 | 174 |
175 } // namespace disk_cache | 175 } // namespace disk_cache |
OLD | NEW |