| 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 |