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 "storage/browser/fileapi/file_system_usage_cache.h" | 5 #include "storage/browser/fileapi/file_system_usage_cache.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <utility> | 10 #include <utility> |
(...skipping 30 matching lines...) Expand all Loading... |
41 const int FileSystemUsageCache::kUsageFileHeaderSize = 4; | 41 const int FileSystemUsageCache::kUsageFileHeaderSize = 4; |
42 | 42 |
43 // Pickle::{Read,Write}Bool treat bool as int | 43 // Pickle::{Read,Write}Bool treat bool as int |
44 const int FileSystemUsageCache::kUsageFileSize = | 44 const int FileSystemUsageCache::kUsageFileSize = |
45 sizeof(base::Pickle::Header) + FileSystemUsageCache::kUsageFileHeaderSize + | 45 sizeof(base::Pickle::Header) + FileSystemUsageCache::kUsageFileHeaderSize + |
46 sizeof(int) + sizeof(int32_t) + sizeof(int64_t); // NOLINT | 46 sizeof(int) + sizeof(int32_t) + sizeof(int64_t); // NOLINT |
47 | 47 |
48 bool FileSystemUsageCache::GetUsage(const base::FilePath& usage_file_path, | 48 bool FileSystemUsageCache::GetUsage(const base::FilePath& usage_file_path, |
49 int64_t* usage_out) { | 49 int64_t* usage_out) { |
50 TRACE_EVENT0("FileSystem", "UsageCache::GetUsage"); | 50 TRACE_EVENT0("FileSystem", "UsageCache::GetUsage"); |
51 DCHECK(CalledOnValidThread()); | 51 DCHECK(CalledOnValidSequence()); |
52 DCHECK(usage_out); | 52 DCHECK(usage_out); |
53 bool is_valid = true; | 53 bool is_valid = true; |
54 uint32_t dirty = 0; | 54 uint32_t dirty = 0; |
55 int64_t usage = 0; | 55 int64_t usage = 0; |
56 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) | 56 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) |
57 return false; | 57 return false; |
58 *usage_out = usage; | 58 *usage_out = usage; |
59 return true; | 59 return true; |
60 } | 60 } |
61 | 61 |
62 bool FileSystemUsageCache::GetDirty(const base::FilePath& usage_file_path, | 62 bool FileSystemUsageCache::GetDirty(const base::FilePath& usage_file_path, |
63 uint32_t* dirty_out) { | 63 uint32_t* dirty_out) { |
64 TRACE_EVENT0("FileSystem", "UsageCache::GetDirty"); | 64 TRACE_EVENT0("FileSystem", "UsageCache::GetDirty"); |
65 DCHECK(CalledOnValidThread()); | 65 DCHECK(CalledOnValidSequence()); |
66 DCHECK(dirty_out); | 66 DCHECK(dirty_out); |
67 bool is_valid = true; | 67 bool is_valid = true; |
68 uint32_t dirty = 0; | 68 uint32_t dirty = 0; |
69 int64_t usage = 0; | 69 int64_t usage = 0; |
70 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) | 70 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) |
71 return false; | 71 return false; |
72 *dirty_out = dirty; | 72 *dirty_out = dirty; |
73 return true; | 73 return true; |
74 } | 74 } |
75 | 75 |
76 bool FileSystemUsageCache::IncrementDirty( | 76 bool FileSystemUsageCache::IncrementDirty( |
77 const base::FilePath& usage_file_path) { | 77 const base::FilePath& usage_file_path) { |
78 TRACE_EVENT0("FileSystem", "UsageCache::IncrementDirty"); | 78 TRACE_EVENT0("FileSystem", "UsageCache::IncrementDirty"); |
79 DCHECK(CalledOnValidThread()); | 79 DCHECK(CalledOnValidSequence()); |
80 bool is_valid = true; | 80 bool is_valid = true; |
81 uint32_t dirty = 0; | 81 uint32_t dirty = 0; |
82 int64_t usage = 0; | 82 int64_t usage = 0; |
83 bool new_handle = !HasCacheFileHandle(usage_file_path); | 83 bool new_handle = !HasCacheFileHandle(usage_file_path); |
84 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) | 84 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) |
85 return false; | 85 return false; |
86 | 86 |
87 bool success = Write(usage_file_path, is_valid, dirty + 1, usage); | 87 bool success = Write(usage_file_path, is_valid, dirty + 1, usage); |
88 if (success && dirty == 0 && new_handle) | 88 if (success && dirty == 0 && new_handle) |
89 FlushFile(usage_file_path); | 89 FlushFile(usage_file_path); |
90 return success; | 90 return success; |
91 } | 91 } |
92 | 92 |
93 bool FileSystemUsageCache::DecrementDirty( | 93 bool FileSystemUsageCache::DecrementDirty( |
94 const base::FilePath& usage_file_path) { | 94 const base::FilePath& usage_file_path) { |
95 TRACE_EVENT0("FileSystem", "UsageCache::DecrementDirty"); | 95 TRACE_EVENT0("FileSystem", "UsageCache::DecrementDirty"); |
96 DCHECK(CalledOnValidThread()); | 96 DCHECK(CalledOnValidSequence()); |
97 bool is_valid = true; | 97 bool is_valid = true; |
98 uint32_t dirty = 0; | 98 uint32_t dirty = 0; |
99 int64_t usage = 0; | 99 int64_t usage = 0; |
100 if (!Read(usage_file_path, &is_valid, &dirty, &usage) || dirty == 0) | 100 if (!Read(usage_file_path, &is_valid, &dirty, &usage) || dirty == 0) |
101 return false; | 101 return false; |
102 | 102 |
103 return Write(usage_file_path, is_valid, dirty - 1, usage); | 103 return Write(usage_file_path, is_valid, dirty - 1, usage); |
104 } | 104 } |
105 | 105 |
106 bool FileSystemUsageCache::Invalidate(const base::FilePath& usage_file_path) { | 106 bool FileSystemUsageCache::Invalidate(const base::FilePath& usage_file_path) { |
107 TRACE_EVENT0("FileSystem", "UsageCache::Invalidate"); | 107 TRACE_EVENT0("FileSystem", "UsageCache::Invalidate"); |
108 DCHECK(CalledOnValidThread()); | 108 DCHECK(CalledOnValidSequence()); |
109 bool is_valid = true; | 109 bool is_valid = true; |
110 uint32_t dirty = 0; | 110 uint32_t dirty = 0; |
111 int64_t usage = 0; | 111 int64_t usage = 0; |
112 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) | 112 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) |
113 return false; | 113 return false; |
114 | 114 |
115 return Write(usage_file_path, false, dirty, usage); | 115 return Write(usage_file_path, false, dirty, usage); |
116 } | 116 } |
117 | 117 |
118 bool FileSystemUsageCache::IsValid(const base::FilePath& usage_file_path) { | 118 bool FileSystemUsageCache::IsValid(const base::FilePath& usage_file_path) { |
119 TRACE_EVENT0("FileSystem", "UsageCache::IsValid"); | 119 TRACE_EVENT0("FileSystem", "UsageCache::IsValid"); |
120 DCHECK(CalledOnValidThread()); | 120 DCHECK(CalledOnValidSequence()); |
121 bool is_valid = true; | 121 bool is_valid = true; |
122 uint32_t dirty = 0; | 122 uint32_t dirty = 0; |
123 int64_t usage = 0; | 123 int64_t usage = 0; |
124 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) | 124 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) |
125 return false; | 125 return false; |
126 return is_valid; | 126 return is_valid; |
127 } | 127 } |
128 | 128 |
129 bool FileSystemUsageCache::AtomicUpdateUsageByDelta( | 129 bool FileSystemUsageCache::AtomicUpdateUsageByDelta( |
130 const base::FilePath& usage_file_path, | 130 const base::FilePath& usage_file_path, |
131 int64_t delta) { | 131 int64_t delta) { |
132 TRACE_EVENT0("FileSystem", "UsageCache::AtomicUpdateUsageByDelta"); | 132 TRACE_EVENT0("FileSystem", "UsageCache::AtomicUpdateUsageByDelta"); |
133 DCHECK(CalledOnValidThread()); | 133 DCHECK(CalledOnValidSequence()); |
134 bool is_valid = true; | 134 bool is_valid = true; |
135 uint32_t dirty = 0; | 135 uint32_t dirty = 0; |
136 int64_t usage = 0; | 136 int64_t usage = 0; |
137 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) | 137 if (!Read(usage_file_path, &is_valid, &dirty, &usage)) |
138 return false; | 138 return false; |
139 return Write(usage_file_path, is_valid, dirty, usage + delta); | 139 return Write(usage_file_path, is_valid, dirty, usage + delta); |
140 } | 140 } |
141 | 141 |
142 bool FileSystemUsageCache::UpdateUsage(const base::FilePath& usage_file_path, | 142 bool FileSystemUsageCache::UpdateUsage(const base::FilePath& usage_file_path, |
143 int64_t fs_usage) { | 143 int64_t fs_usage) { |
144 TRACE_EVENT0("FileSystem", "UsageCache::UpdateUsage"); | 144 TRACE_EVENT0("FileSystem", "UsageCache::UpdateUsage"); |
145 DCHECK(CalledOnValidThread()); | 145 DCHECK(CalledOnValidSequence()); |
146 return Write(usage_file_path, true, 0, fs_usage); | 146 return Write(usage_file_path, true, 0, fs_usage); |
147 } | 147 } |
148 | 148 |
149 bool FileSystemUsageCache::Exists(const base::FilePath& usage_file_path) { | 149 bool FileSystemUsageCache::Exists(const base::FilePath& usage_file_path) { |
150 TRACE_EVENT0("FileSystem", "UsageCache::Exists"); | 150 TRACE_EVENT0("FileSystem", "UsageCache::Exists"); |
151 DCHECK(CalledOnValidThread()); | 151 DCHECK(CalledOnValidSequence()); |
152 return base::PathExists(usage_file_path); | 152 return base::PathExists(usage_file_path); |
153 } | 153 } |
154 | 154 |
155 bool FileSystemUsageCache::Delete(const base::FilePath& usage_file_path) { | 155 bool FileSystemUsageCache::Delete(const base::FilePath& usage_file_path) { |
156 TRACE_EVENT0("FileSystem", "UsageCache::Delete"); | 156 TRACE_EVENT0("FileSystem", "UsageCache::Delete"); |
157 DCHECK(CalledOnValidThread()); | 157 DCHECK(CalledOnValidSequence()); |
158 CloseCacheFiles(); | 158 CloseCacheFiles(); |
159 return base::DeleteFile(usage_file_path, false); | 159 return base::DeleteFile(usage_file_path, false); |
160 } | 160 } |
161 | 161 |
162 void FileSystemUsageCache::CloseCacheFiles() { | 162 void FileSystemUsageCache::CloseCacheFiles() { |
163 TRACE_EVENT0("FileSystem", "UsageCache::CloseCacheFiles"); | 163 TRACE_EVENT0("FileSystem", "UsageCache::CloseCacheFiles"); |
164 DCHECK(CalledOnValidThread()); | 164 DCHECK(CalledOnValidSequence()); |
165 cache_files_.clear(); | 165 cache_files_.clear(); |
166 timer_.reset(); | 166 timer_.reset(); |
167 } | 167 } |
168 | 168 |
169 bool FileSystemUsageCache::Read(const base::FilePath& usage_file_path, | 169 bool FileSystemUsageCache::Read(const base::FilePath& usage_file_path, |
170 bool* is_valid, | 170 bool* is_valid, |
171 uint32_t* dirty_out, | 171 uint32_t* dirty_out, |
172 int64_t* usage_out) { | 172 int64_t* usage_out) { |
173 TRACE_EVENT0("FileSystem", "UsageCache::Read"); | 173 TRACE_EVENT0("FileSystem", "UsageCache::Read"); |
174 DCHECK(CalledOnValidThread()); | 174 DCHECK(CalledOnValidSequence()); |
175 DCHECK(is_valid); | 175 DCHECK(is_valid); |
176 DCHECK(dirty_out); | 176 DCHECK(dirty_out); |
177 DCHECK(usage_out); | 177 DCHECK(usage_out); |
178 char buffer[kUsageFileSize]; | 178 char buffer[kUsageFileSize]; |
179 const char *header; | 179 const char *header; |
180 if (usage_file_path.empty() || | 180 if (usage_file_path.empty() || |
181 !ReadBytes(usage_file_path, buffer, kUsageFileSize)) | 181 !ReadBytes(usage_file_path, buffer, kUsageFileSize)) |
182 return false; | 182 return false; |
183 base::Pickle read_pickle(buffer, kUsageFileSize); | 183 base::Pickle read_pickle(buffer, kUsageFileSize); |
184 base::PickleIterator iter(read_pickle); | 184 base::PickleIterator iter(read_pickle); |
(...skipping 15 matching lines...) Expand all Loading... |
200 *dirty_out = dirty; | 200 *dirty_out = dirty; |
201 *usage_out = usage; | 201 *usage_out = usage; |
202 return true; | 202 return true; |
203 } | 203 } |
204 | 204 |
205 bool FileSystemUsageCache::Write(const base::FilePath& usage_file_path, | 205 bool FileSystemUsageCache::Write(const base::FilePath& usage_file_path, |
206 bool is_valid, | 206 bool is_valid, |
207 int32_t dirty, | 207 int32_t dirty, |
208 int64_t usage) { | 208 int64_t usage) { |
209 TRACE_EVENT0("FileSystem", "UsageCache::Write"); | 209 TRACE_EVENT0("FileSystem", "UsageCache::Write"); |
210 DCHECK(CalledOnValidThread()); | 210 DCHECK(CalledOnValidSequence()); |
211 base::Pickle write_pickle; | 211 base::Pickle write_pickle; |
212 write_pickle.WriteBytes(kUsageFileHeader, kUsageFileHeaderSize); | 212 write_pickle.WriteBytes(kUsageFileHeader, kUsageFileHeaderSize); |
213 write_pickle.WriteBool(is_valid); | 213 write_pickle.WriteBool(is_valid); |
214 write_pickle.WriteUInt32(dirty); | 214 write_pickle.WriteUInt32(dirty); |
215 write_pickle.WriteInt64(usage); | 215 write_pickle.WriteInt64(usage); |
216 | 216 |
217 if (!WriteBytes(usage_file_path, | 217 if (!WriteBytes(usage_file_path, |
218 static_cast<const char*>(write_pickle.data()), | 218 static_cast<const char*>(write_pickle.data()), |
219 write_pickle.size())) { | 219 write_pickle.size())) { |
220 Delete(usage_file_path); | 220 Delete(usage_file_path); |
221 return false; | 221 return false; |
222 } | 222 } |
223 return true; | 223 return true; |
224 } | 224 } |
225 | 225 |
226 base::File* FileSystemUsageCache::GetFile(const base::FilePath& file_path) { | 226 base::File* FileSystemUsageCache::GetFile(const base::FilePath& file_path) { |
227 DCHECK(CalledOnValidThread()); | 227 DCHECK(CalledOnValidSequence()); |
228 if (cache_files_.size() >= kMaxHandleCacheSize) | 228 if (cache_files_.size() >= kMaxHandleCacheSize) |
229 CloseCacheFiles(); | 229 CloseCacheFiles(); |
230 ScheduleCloseTimer(); | 230 ScheduleCloseTimer(); |
231 | 231 |
232 auto& entry = cache_files_[file_path]; | 232 auto& entry = cache_files_[file_path]; |
233 if (entry) | 233 if (entry) |
234 return entry.get(); | 234 return entry.get(); |
235 | 235 |
236 // Because there are no null entries in cache_files_, the [] inserted a blank | 236 // Because there are no null entries in cache_files_, the [] inserted a blank |
237 // pointer, so let's populate the cache. | 237 // pointer, so let's populate the cache. |
238 entry = base::MakeUnique<base::File>(file_path, base::File::FLAG_OPEN_ALWAYS | | 238 entry = base::MakeUnique<base::File>(file_path, base::File::FLAG_OPEN_ALWAYS | |
239 base::File::FLAG_READ | | 239 base::File::FLAG_READ | |
240 base::File::FLAG_WRITE); | 240 base::File::FLAG_WRITE); |
241 | 241 |
242 if (!entry->IsValid()) { | 242 if (!entry->IsValid()) { |
243 cache_files_.erase(file_path); | 243 cache_files_.erase(file_path); |
244 return nullptr; | 244 return nullptr; |
245 } | 245 } |
246 | 246 |
247 return entry.get(); | 247 return entry.get(); |
248 } | 248 } |
249 | 249 |
250 bool FileSystemUsageCache::ReadBytes(const base::FilePath& file_path, | 250 bool FileSystemUsageCache::ReadBytes(const base::FilePath& file_path, |
251 char* buffer, | 251 char* buffer, |
252 int64_t buffer_size) { | 252 int64_t buffer_size) { |
253 DCHECK(CalledOnValidThread()); | 253 DCHECK(CalledOnValidSequence()); |
254 base::File* file = GetFile(file_path); | 254 base::File* file = GetFile(file_path); |
255 if (!file) | 255 if (!file) |
256 return false; | 256 return false; |
257 return file->Read(0, buffer, buffer_size) == buffer_size; | 257 return file->Read(0, buffer, buffer_size) == buffer_size; |
258 } | 258 } |
259 | 259 |
260 bool FileSystemUsageCache::WriteBytes(const base::FilePath& file_path, | 260 bool FileSystemUsageCache::WriteBytes(const base::FilePath& file_path, |
261 const char* buffer, | 261 const char* buffer, |
262 int64_t buffer_size) { | 262 int64_t buffer_size) { |
263 DCHECK(CalledOnValidThread()); | 263 DCHECK(CalledOnValidSequence()); |
264 base::File* file = GetFile(file_path); | 264 base::File* file = GetFile(file_path); |
265 if (!file) | 265 if (!file) |
266 return false; | 266 return false; |
267 return file->Write(0, buffer, buffer_size) == buffer_size; | 267 return file->Write(0, buffer, buffer_size) == buffer_size; |
268 } | 268 } |
269 | 269 |
270 bool FileSystemUsageCache::FlushFile(const base::FilePath& file_path) { | 270 bool FileSystemUsageCache::FlushFile(const base::FilePath& file_path) { |
271 TRACE_EVENT0("FileSystem", "UsageCache::FlushFile"); | 271 TRACE_EVENT0("FileSystem", "UsageCache::FlushFile"); |
272 DCHECK(CalledOnValidThread()); | 272 DCHECK(CalledOnValidSequence()); |
273 base::File* file = GetFile(file_path); | 273 base::File* file = GetFile(file_path); |
274 if (!file) | 274 if (!file) |
275 return false; | 275 return false; |
276 return file->Flush(); | 276 return file->Flush(); |
277 } | 277 } |
278 | 278 |
279 void FileSystemUsageCache::ScheduleCloseTimer() { | 279 void FileSystemUsageCache::ScheduleCloseTimer() { |
280 DCHECK(CalledOnValidThread()); | 280 DCHECK(CalledOnValidSequence()); |
281 if (!timer_) | 281 if (!timer_) |
282 timer_.reset(new TimedTaskHelper(task_runner_.get())); | 282 timer_.reset(new TimedTaskHelper(task_runner_.get())); |
283 | 283 |
284 if (timer_->IsRunning()) { | 284 if (timer_->IsRunning()) { |
285 timer_->Reset(); | 285 timer_->Reset(); |
286 return; | 286 return; |
287 } | 287 } |
288 | 288 |
289 timer_->Start(FROM_HERE, | 289 timer_->Start(FROM_HERE, |
290 base::TimeDelta::FromSeconds(kCloseDelaySeconds), | 290 base::TimeDelta::FromSeconds(kCloseDelaySeconds), |
291 base::Bind(&FileSystemUsageCache::CloseCacheFiles, | 291 base::Bind(&FileSystemUsageCache::CloseCacheFiles, |
292 weak_factory_.GetWeakPtr())); | 292 weak_factory_.GetWeakPtr())); |
293 } | 293 } |
294 | 294 |
295 bool FileSystemUsageCache::CalledOnValidThread() { | 295 bool FileSystemUsageCache::CalledOnValidSequence() { |
296 return !task_runner_.get() || task_runner_->RunsTasksOnCurrentThread(); | 296 return !task_runner_.get() || task_runner_->RunsTasksInCurrentSequence(); |
297 } | 297 } |
298 | 298 |
299 bool FileSystemUsageCache::HasCacheFileHandle(const base::FilePath& file_path) { | 299 bool FileSystemUsageCache::HasCacheFileHandle(const base::FilePath& file_path) { |
300 DCHECK(CalledOnValidThread()); | 300 DCHECK(CalledOnValidSequence()); |
301 DCHECK_LE(cache_files_.size(), kMaxHandleCacheSize); | 301 DCHECK_LE(cache_files_.size(), kMaxHandleCacheSize); |
302 return base::ContainsKey(cache_files_, file_path); | 302 return base::ContainsKey(cache_files_, file_path); |
303 } | 303 } |
304 | 304 |
305 } // namespace storage | 305 } // namespace storage |
OLD | NEW |