| 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 "chrome/browser/chromeos/drive/file_cache.h" | 5 #include "chrome/browser/chromeos/drive/file_cache.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 67 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
| 68 } | 68 } |
| 69 | 69 |
| 70 bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const { | 70 bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const { |
| 71 return cache_file_directory_.IsParent(path); | 71 return cache_file_directory_.IsParent(path); |
| 72 } | 72 } |
| 73 | 73 |
| 74 bool FileCache::GetCacheEntry(const std::string& id, FileCacheEntry* entry) { | 74 bool FileCache::GetCacheEntry(const std::string& id, FileCacheEntry* entry) { |
| 75 DCHECK(entry); | 75 DCHECK(entry); |
| 76 AssertOnSequencedWorkerPool(); | 76 AssertOnSequencedWorkerPool(); |
| 77 return storage_->GetCacheEntry(id, entry); | 77 return storage_->GetCacheEntry(id, entry) == FILE_ERROR_OK; |
| 78 } | 78 } |
| 79 | 79 |
| 80 scoped_ptr<FileCache::Iterator> FileCache::GetIterator() { | 80 scoped_ptr<FileCache::Iterator> FileCache::GetIterator() { |
| 81 AssertOnSequencedWorkerPool(); | 81 AssertOnSequencedWorkerPool(); |
| 82 return storage_->GetCacheEntryIterator(); | 82 return storage_->GetCacheEntryIterator(); |
| 83 } | 83 } |
| 84 | 84 |
| 85 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { | 85 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { |
| 86 AssertOnSequencedWorkerPool(); | 86 AssertOnSequencedWorkerPool(); |
| 87 | 87 |
| 88 // Do nothing and return if we have enough space. | 88 // Do nothing and return if we have enough space. |
| 89 if (HasEnoughSpaceFor(num_bytes, cache_file_directory_)) | 89 if (HasEnoughSpaceFor(num_bytes, cache_file_directory_)) |
| 90 return true; | 90 return true; |
| 91 | 91 |
| 92 // Otherwise, try to free up the disk space. | 92 // Otherwise, try to free up the disk space. |
| 93 DVLOG(1) << "Freeing up disk space for " << num_bytes; | 93 DVLOG(1) << "Freeing up disk space for " << num_bytes; |
| 94 | 94 |
| 95 // Remove all entries unless specially marked. | 95 // Remove all entries unless specially marked. |
| 96 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = | 96 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = |
| 97 storage_->GetCacheEntryIterator(); | 97 storage_->GetCacheEntryIterator(); |
| 98 for (; !it->IsAtEnd(); it->Advance()) { | 98 for (; !it->IsAtEnd(); it->Advance()) { |
| 99 const FileCacheEntry& entry = it->GetValue(); | 99 const FileCacheEntry& entry = it->GetValue(); |
| 100 if (!entry.is_pinned() && | 100 if (!entry.is_pinned() && |
| 101 !entry.is_dirty() && | 101 !entry.is_dirty() && |
| 102 !mounted_files_.count(it->GetID())) | 102 !mounted_files_.count(it->GetID())) |
| 103 storage_->RemoveCacheEntry(it->GetID()); | 103 storage_->RemoveCacheEntry(it->GetID()); |
| 104 } | 104 } |
| 105 DCHECK(!it->HasError()); | 105 if (it->HasError()) |
| 106 return false; |
| 106 | 107 |
| 107 // Remove all files which have no corresponding cache entries. | 108 // Remove all files which have no corresponding cache entries. |
| 108 base::FileEnumerator enumerator(cache_file_directory_, | 109 base::FileEnumerator enumerator(cache_file_directory_, |
| 109 false, // not recursive | 110 false, // not recursive |
| 110 base::FileEnumerator::FILES); | 111 base::FileEnumerator::FILES); |
| 111 FileCacheEntry entry; | 112 FileCacheEntry entry; |
| 112 for (base::FilePath current = enumerator.Next(); !current.empty(); | 113 for (base::FilePath current = enumerator.Next(); !current.empty(); |
| 113 current = enumerator.Next()) { | 114 current = enumerator.Next()) { |
| 114 std::string id = GetIdFromPath(current); | 115 std::string id = GetIdFromPath(current); |
| 115 if (!storage_->GetCacheEntry(id, &entry)) | 116 FileError error = storage_->GetCacheEntry(id, &entry); |
| 117 if (error == FILE_ERROR_NOT_FOUND) |
| 116 base::DeleteFile(current, false /* recursive */); | 118 base::DeleteFile(current, false /* recursive */); |
| 119 else if (error != FILE_ERROR_OK) |
| 120 return false; |
| 117 } | 121 } |
| 118 | 122 |
| 119 // Check the disk space again. | 123 // Check the disk space again. |
| 120 return HasEnoughSpaceFor(num_bytes, cache_file_directory_); | 124 return HasEnoughSpaceFor(num_bytes, cache_file_directory_); |
| 121 } | 125 } |
| 122 | 126 |
| 123 FileError FileCache::GetFile(const std::string& id, | 127 FileError FileCache::GetFile(const std::string& id, |
| 124 base::FilePath* cache_file_path) { | 128 base::FilePath* cache_file_path) { |
| 125 AssertOnSequencedWorkerPool(); | 129 AssertOnSequencedWorkerPool(); |
| 126 DCHECK(cache_file_path); | 130 DCHECK(cache_file_path); |
| 127 | 131 |
| 128 FileCacheEntry cache_entry; | 132 FileCacheEntry cache_entry; |
| 129 if (!storage_->GetCacheEntry(id, &cache_entry) || | 133 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 130 !cache_entry.is_present()) | 134 if (error != FILE_ERROR_OK) |
| 135 return error; |
| 136 if (!cache_entry.is_present()) |
| 131 return FILE_ERROR_NOT_FOUND; | 137 return FILE_ERROR_NOT_FOUND; |
| 132 | 138 |
| 133 *cache_file_path = GetCacheFilePath(id); | 139 *cache_file_path = GetCacheFilePath(id); |
| 134 return FILE_ERROR_OK; | 140 return FILE_ERROR_OK; |
| 135 } | 141 } |
| 136 | 142 |
| 137 FileError FileCache::Store(const std::string& id, | 143 FileError FileCache::Store(const std::string& id, |
| 138 const std::string& md5, | 144 const std::string& md5, |
| 139 const base::FilePath& source_path, | 145 const base::FilePath& source_path, |
| 140 FileOperationType file_operation_type) { | 146 FileOperationType file_operation_type) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 170 if (!success) { | 176 if (!success) { |
| 171 LOG(ERROR) << "Failed to store: " | 177 LOG(ERROR) << "Failed to store: " |
| 172 << "source_path = " << source_path.value() << ", " | 178 << "source_path = " << source_path.value() << ", " |
| 173 << "dest_path = " << dest_path.value() << ", " | 179 << "dest_path = " << dest_path.value() << ", " |
| 174 << "file_operation_type = " << file_operation_type; | 180 << "file_operation_type = " << file_operation_type; |
| 175 return FILE_ERROR_FAILED; | 181 return FILE_ERROR_FAILED; |
| 176 } | 182 } |
| 177 | 183 |
| 178 // Now that file operations have completed, update metadata. | 184 // Now that file operations have completed, update metadata. |
| 179 FileCacheEntry cache_entry; | 185 FileCacheEntry cache_entry; |
| 180 storage_->GetCacheEntry(id, &cache_entry); | 186 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 187 if (error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND) |
| 188 return error; |
| 181 cache_entry.set_md5(md5); | 189 cache_entry.set_md5(md5); |
| 182 cache_entry.set_is_present(true); | 190 cache_entry.set_is_present(true); |
| 183 if (md5.empty()) | 191 if (md5.empty()) |
| 184 cache_entry.set_is_dirty(true); | 192 cache_entry.set_is_dirty(true); |
| 185 return storage_->PutCacheEntry(id, cache_entry) ? | 193 return storage_->PutCacheEntry(id, cache_entry); |
| 186 FILE_ERROR_OK : FILE_ERROR_FAILED; | |
| 187 } | 194 } |
| 188 | 195 |
| 189 FileError FileCache::Pin(const std::string& id) { | 196 FileError FileCache::Pin(const std::string& id) { |
| 190 AssertOnSequencedWorkerPool(); | 197 AssertOnSequencedWorkerPool(); |
| 191 | 198 |
| 192 FileCacheEntry cache_entry; | 199 FileCacheEntry cache_entry; |
| 193 storage_->GetCacheEntry(id, &cache_entry); | 200 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 201 if (error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND) |
| 202 return error; |
| 194 cache_entry.set_is_pinned(true); | 203 cache_entry.set_is_pinned(true); |
| 195 return storage_->PutCacheEntry(id, cache_entry) ? | 204 return storage_->PutCacheEntry(id, cache_entry); |
| 196 FILE_ERROR_OK : FILE_ERROR_FAILED; | |
| 197 } | 205 } |
| 198 | 206 |
| 199 FileError FileCache::Unpin(const std::string& id) { | 207 FileError FileCache::Unpin(const std::string& id) { |
| 200 AssertOnSequencedWorkerPool(); | 208 AssertOnSequencedWorkerPool(); |
| 201 | 209 |
| 202 // Unpinning a file means its entry must exist in cache. | 210 // Unpinning a file means its entry must exist in cache. |
| 203 FileCacheEntry cache_entry; | 211 FileCacheEntry cache_entry; |
| 204 if (!storage_->GetCacheEntry(id, &cache_entry)) | 212 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 205 return FILE_ERROR_NOT_FOUND; | 213 if (error != FILE_ERROR_OK) |
| 214 return error; |
| 206 | 215 |
| 207 // Now that file operations have completed, update metadata. | 216 // Now that file operations have completed, update metadata. |
| 208 if (cache_entry.is_present()) { | 217 if (cache_entry.is_present()) { |
| 209 cache_entry.set_is_pinned(false); | 218 cache_entry.set_is_pinned(false); |
| 210 if (!storage_->PutCacheEntry(id, cache_entry)) | 219 error = storage_->PutCacheEntry(id, cache_entry); |
| 211 return FILE_ERROR_FAILED; | 220 if (error != FILE_ERROR_OK) |
| 221 return error; |
| 212 } else { | 222 } else { |
| 213 // Remove the existing entry if we are unpinning a non-present file. | 223 // Remove the existing entry if we are unpinning a non-present file. |
| 214 if (!storage_->RemoveCacheEntry(id)) | 224 error = storage_->RemoveCacheEntry(id); |
| 215 return FILE_ERROR_FAILED; | 225 if (error != FILE_ERROR_OK) |
| 226 return error; |
| 216 } | 227 } |
| 217 | 228 |
| 218 // Now it's a chance to free up space if needed. | 229 // Now it's a chance to free up space if needed. |
| 219 FreeDiskSpaceIfNeededFor(0); | 230 FreeDiskSpaceIfNeededFor(0); |
| 220 | 231 |
| 221 return FILE_ERROR_OK; | 232 return FILE_ERROR_OK; |
| 222 } | 233 } |
| 223 | 234 |
| 224 FileError FileCache::MarkAsMounted(const std::string& id, | 235 FileError FileCache::MarkAsMounted(const std::string& id, |
| 225 base::FilePath* cache_file_path) { | 236 base::FilePath* cache_file_path) { |
| 226 AssertOnSequencedWorkerPool(); | 237 AssertOnSequencedWorkerPool(); |
| 227 DCHECK(cache_file_path); | 238 DCHECK(cache_file_path); |
| 228 | 239 |
| 229 // Get cache entry associated with the id and md5 | 240 // Get cache entry associated with the id and md5 |
| 230 FileCacheEntry cache_entry; | 241 FileCacheEntry cache_entry; |
| 231 if (!storage_->GetCacheEntry(id, &cache_entry)) | 242 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 232 return FILE_ERROR_NOT_FOUND; | 243 if (error != FILE_ERROR_OK) |
| 244 return error; |
| 233 | 245 |
| 234 if (mounted_files_.count(id)) | 246 if (mounted_files_.count(id)) |
| 235 return FILE_ERROR_INVALID_OPERATION; | 247 return FILE_ERROR_INVALID_OPERATION; |
| 236 | 248 |
| 237 // Ensure the file is readable to cros_disks. See crbug.com/236994. | 249 // Ensure the file is readable to cros_disks. See crbug.com/236994. |
| 238 base::FilePath path = GetCacheFilePath(id); | 250 base::FilePath path = GetCacheFilePath(id); |
| 239 if (!base::SetPosixFilePermissions( | 251 if (!base::SetPosixFilePermissions( |
| 240 path, | 252 path, |
| 241 base::FILE_PERMISSION_READ_BY_USER | | 253 base::FILE_PERMISSION_READ_BY_USER | |
| 242 base::FILE_PERMISSION_WRITE_BY_USER | | 254 base::FILE_PERMISSION_WRITE_BY_USER | |
| 243 base::FILE_PERMISSION_READ_BY_GROUP | | 255 base::FILE_PERMISSION_READ_BY_GROUP | |
| 244 base::FILE_PERMISSION_READ_BY_OTHERS)) | 256 base::FILE_PERMISSION_READ_BY_OTHERS)) |
| 245 return FILE_ERROR_FAILED; | 257 return FILE_ERROR_FAILED; |
| 246 | 258 |
| 247 mounted_files_.insert(id); | 259 mounted_files_.insert(id); |
| 248 | 260 |
| 249 *cache_file_path = path; | 261 *cache_file_path = path; |
| 250 return FILE_ERROR_OK; | 262 return FILE_ERROR_OK; |
| 251 } | 263 } |
| 252 | 264 |
| 253 FileError FileCache::OpenForWrite( | 265 FileError FileCache::OpenForWrite( |
| 254 const std::string& id, | 266 const std::string& id, |
| 255 scoped_ptr<base::ScopedClosureRunner>* file_closer) { | 267 scoped_ptr<base::ScopedClosureRunner>* file_closer) { |
| 256 AssertOnSequencedWorkerPool(); | 268 AssertOnSequencedWorkerPool(); |
| 257 | 269 |
| 258 // Marking a file dirty means its entry and actual file blob must exist in | 270 // Marking a file dirty means its entry and actual file blob must exist in |
| 259 // cache. | 271 // cache. |
| 260 FileCacheEntry cache_entry; | 272 FileCacheEntry cache_entry; |
| 261 if (!storage_->GetCacheEntry(id, &cache_entry) || | 273 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 262 !cache_entry.is_present()) { | 274 if (error != FILE_ERROR_OK) |
| 275 return error; |
| 276 if (!cache_entry.is_present()) { |
| 263 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: " << id; | 277 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: " << id; |
| 264 return FILE_ERROR_NOT_FOUND; | 278 return FILE_ERROR_NOT_FOUND; |
| 265 } | 279 } |
| 266 | 280 |
| 267 cache_entry.set_is_dirty(true); | 281 cache_entry.set_is_dirty(true); |
| 268 cache_entry.clear_md5(); | 282 cache_entry.clear_md5(); |
| 269 if (!storage_->PutCacheEntry(id, cache_entry)) | 283 error = storage_->PutCacheEntry(id, cache_entry); |
| 270 return FILE_ERROR_FAILED; | 284 if (error != FILE_ERROR_OK) |
| 285 return error; |
| 271 | 286 |
| 272 write_opened_files_[id]++; | 287 write_opened_files_[id]++; |
| 273 file_closer->reset(new base::ScopedClosureRunner( | 288 file_closer->reset(new base::ScopedClosureRunner( |
| 274 base::Bind(&google_apis::RunTaskOnThread, | 289 base::Bind(&google_apis::RunTaskOnThread, |
| 275 blocking_task_runner_, | 290 blocking_task_runner_, |
| 276 base::Bind(&FileCache::CloseForWrite, | 291 base::Bind(&FileCache::CloseForWrite, |
| 277 weak_ptr_factory_.GetWeakPtr(), | 292 weak_ptr_factory_.GetWeakPtr(), |
| 278 id)))); | 293 id)))); |
| 279 return FILE_ERROR_OK; | 294 return FILE_ERROR_OK; |
| 280 } | 295 } |
| 281 | 296 |
| 282 bool FileCache::IsOpenedForWrite(const std::string& id) { | 297 bool FileCache::IsOpenedForWrite(const std::string& id) { |
| 283 AssertOnSequencedWorkerPool(); | 298 AssertOnSequencedWorkerPool(); |
| 284 return write_opened_files_.count(id); | 299 return write_opened_files_.count(id); |
| 285 } | 300 } |
| 286 | 301 |
| 287 FileError FileCache::UpdateMd5(const std::string& id) { | 302 FileError FileCache::UpdateMd5(const std::string& id) { |
| 288 AssertOnSequencedWorkerPool(); | 303 AssertOnSequencedWorkerPool(); |
| 289 | 304 |
| 290 if (IsOpenedForWrite(id)) | 305 if (IsOpenedForWrite(id)) |
| 291 return FILE_ERROR_IN_USE; | 306 return FILE_ERROR_IN_USE; |
| 292 | 307 |
| 293 FileCacheEntry cache_entry; | 308 FileCacheEntry cache_entry; |
| 294 if (!storage_->GetCacheEntry(id, &cache_entry) || | 309 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 295 !cache_entry.is_present()) | 310 if (error != FILE_ERROR_OK) |
| 311 return error; |
| 312 if (!cache_entry.is_present()) |
| 296 return FILE_ERROR_NOT_FOUND; | 313 return FILE_ERROR_NOT_FOUND; |
| 297 | 314 |
| 298 const std::string& md5 = util::GetMd5Digest(GetCacheFilePath(id)); | 315 const std::string& md5 = util::GetMd5Digest(GetCacheFilePath(id)); |
| 299 if (md5.empty()) | 316 if (md5.empty()) |
| 300 return FILE_ERROR_NOT_FOUND; | 317 return FILE_ERROR_NOT_FOUND; |
| 301 | 318 |
| 302 cache_entry.set_md5(md5); | 319 cache_entry.set_md5(md5); |
| 303 return storage_->PutCacheEntry(id, cache_entry) ? | 320 return storage_->PutCacheEntry(id, cache_entry); |
| 304 FILE_ERROR_OK : FILE_ERROR_FAILED; | |
| 305 } | 321 } |
| 306 | 322 |
| 307 FileError FileCache::ClearDirty(const std::string& id) { | 323 FileError FileCache::ClearDirty(const std::string& id) { |
| 308 AssertOnSequencedWorkerPool(); | 324 AssertOnSequencedWorkerPool(); |
| 309 | 325 |
| 310 if (IsOpenedForWrite(id)) | 326 if (IsOpenedForWrite(id)) |
| 311 return FILE_ERROR_IN_USE; | 327 return FILE_ERROR_IN_USE; |
| 312 | 328 |
| 313 // Clearing a dirty file means its entry and actual file blob must exist in | 329 // Clearing a dirty file means its entry and actual file blob must exist in |
| 314 // cache. | 330 // cache. |
| 315 FileCacheEntry cache_entry; | 331 FileCacheEntry cache_entry; |
| 316 if (!storage_->GetCacheEntry(id, &cache_entry) || | 332 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 317 !cache_entry.is_present()) { | 333 if (error != FILE_ERROR_OK) |
| 334 return error; |
| 335 if (!cache_entry.is_present()) { |
| 318 LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: " | 336 LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: " |
| 319 << id; | 337 << id; |
| 320 return FILE_ERROR_NOT_FOUND; | 338 return FILE_ERROR_NOT_FOUND; |
| 321 } | 339 } |
| 322 | 340 |
| 323 // If a file is not dirty (it should have been marked dirty via OpenForWrite), | 341 // If a file is not dirty (it should have been marked dirty via OpenForWrite), |
| 324 // clearing its dirty state is an invalid operation. | 342 // clearing its dirty state is an invalid operation. |
| 325 if (!cache_entry.is_dirty()) { | 343 if (!cache_entry.is_dirty()) { |
| 326 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: " << id; | 344 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: " << id; |
| 327 return FILE_ERROR_INVALID_OPERATION; | 345 return FILE_ERROR_INVALID_OPERATION; |
| 328 } | 346 } |
| 329 | 347 |
| 330 cache_entry.set_is_dirty(false); | 348 cache_entry.set_is_dirty(false); |
| 331 return storage_->PutCacheEntry(id, cache_entry) ? | 349 return storage_->PutCacheEntry(id, cache_entry); |
| 332 FILE_ERROR_OK : FILE_ERROR_FAILED; | |
| 333 } | 350 } |
| 334 | 351 |
| 335 FileError FileCache::Remove(const std::string& id) { | 352 FileError FileCache::Remove(const std::string& id) { |
| 336 AssertOnSequencedWorkerPool(); | 353 AssertOnSequencedWorkerPool(); |
| 337 | 354 |
| 338 FileCacheEntry cache_entry; | 355 FileCacheEntry cache_entry; |
| 339 | 356 |
| 340 // If entry doesn't exist, nothing to do. | 357 // If entry doesn't exist, nothing to do. |
| 341 if (!storage_->GetCacheEntry(id, &cache_entry)) | 358 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 359 if (error == FILE_ERROR_NOT_FOUND) |
| 342 return FILE_ERROR_OK; | 360 return FILE_ERROR_OK; |
| 361 if (error != FILE_ERROR_OK) |
| 362 return error; |
| 343 | 363 |
| 344 // Cannot delete a mounted file. | 364 // Cannot delete a mounted file. |
| 345 if (mounted_files_.count(id)) | 365 if (mounted_files_.count(id)) |
| 346 return FILE_ERROR_IN_USE; | 366 return FILE_ERROR_IN_USE; |
| 347 | 367 |
| 348 // Delete the file. | 368 // Delete the file. |
| 349 base::FilePath path = GetCacheFilePath(id); | 369 base::FilePath path = GetCacheFilePath(id); |
| 350 if (!base::DeleteFile(path, false /* recursive */)) | 370 if (!base::DeleteFile(path, false /* recursive */)) |
| 351 return FILE_ERROR_FAILED; | 371 return FILE_ERROR_FAILED; |
| 352 | 372 |
| 353 // Now that all file operations have completed, remove from metadata. | 373 // Now that all file operations have completed, remove from metadata. |
| 354 return storage_->RemoveCacheEntry(id) ? FILE_ERROR_OK : FILE_ERROR_FAILED; | 374 return storage_->RemoveCacheEntry(id); |
| 355 } | 375 } |
| 356 | 376 |
| 357 bool FileCache::ClearAll() { | 377 bool FileCache::ClearAll() { |
| 358 AssertOnSequencedWorkerPool(); | 378 AssertOnSequencedWorkerPool(); |
| 359 | 379 |
| 360 // Remove entries on the metadata. | 380 // Remove entries on the metadata. |
| 361 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = | 381 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = |
| 362 storage_->GetCacheEntryIterator(); | 382 storage_->GetCacheEntryIterator(); |
| 363 for (; !it->IsAtEnd(); it->Advance()) { | 383 for (; !it->IsAtEnd(); it->Advance()) { |
| 364 if (!storage_->RemoveCacheEntry(it->GetID())) | 384 if (storage_->RemoveCacheEntry(it->GetID()) != FILE_ERROR_OK) |
| 365 return false; | 385 return false; |
| 366 } | 386 } |
| 367 | 387 |
| 368 if (it->HasError()) | 388 if (it->HasError()) |
| 369 return false; | 389 return false; |
| 370 | 390 |
| 371 // Remove files. | 391 // Remove files. |
| 372 base::FileEnumerator enumerator(cache_file_directory_, | 392 base::FileEnumerator enumerator(cache_file_directory_, |
| 373 false, // not recursive | 393 false, // not recursive |
| 374 base::FileEnumerator::FILES); | 394 base::FileEnumerator::FILES); |
| 375 for (base::FilePath file = enumerator.Next(); !file.empty(); | 395 for (base::FilePath file = enumerator.Next(); !file.empty(); |
| 376 file = enumerator.Next()) | 396 file = enumerator.Next()) |
| 377 base::DeleteFile(file, false /* recursive */); | 397 base::DeleteFile(file, false /* recursive */); |
| 378 | 398 |
| 379 return true; | 399 return true; |
| 380 } | 400 } |
| 381 | 401 |
| 382 bool FileCache::Initialize() { | 402 bool FileCache::Initialize() { |
| 383 AssertOnSequencedWorkerPool(); | 403 AssertOnSequencedWorkerPool(); |
| 384 | 404 |
| 385 // Older versions do not clear MD5 when marking entries dirty. | 405 // Older versions do not clear MD5 when marking entries dirty. |
| 386 // Clear MD5 of all dirty entries to deal with old data. | 406 // Clear MD5 of all dirty entries to deal with old data. |
| 387 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = | 407 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = |
| 388 storage_->GetCacheEntryIterator(); | 408 storage_->GetCacheEntryIterator(); |
| 389 for (; !it->IsAtEnd(); it->Advance()) { | 409 for (; !it->IsAtEnd(); it->Advance()) { |
| 390 if (it->GetValue().is_dirty()) { | 410 if (it->GetValue().is_dirty()) { |
| 391 FileCacheEntry new_entry(it->GetValue()); | 411 FileCacheEntry new_entry(it->GetValue()); |
| 392 new_entry.clear_md5(); | 412 new_entry.clear_md5(); |
| 393 if (!storage_->PutCacheEntry(it->GetID(), new_entry)) | 413 if (storage_->PutCacheEntry(it->GetID(), new_entry) != FILE_ERROR_OK) |
| 394 return false; | 414 return false; |
| 395 } | 415 } |
| 396 } | 416 } |
| 417 if (it->HasError()) |
| 418 return false; |
| 397 | 419 |
| 398 if (!RenameCacheFilesToNewFormat()) | 420 if (!RenameCacheFilesToNewFormat()) |
| 399 return false; | 421 return false; |
| 400 return true; | 422 return true; |
| 401 } | 423 } |
| 402 | 424 |
| 403 void FileCache::Destroy() { | 425 void FileCache::Destroy() { |
| 404 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 405 | 427 |
| 406 // Destroy myself on the blocking pool. | 428 // Destroy myself on the blocking pool. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 422 recovered_cache_info) { | 444 recovered_cache_info) { |
| 423 int file_number = 1; | 445 int file_number = 1; |
| 424 | 446 |
| 425 base::FileEnumerator enumerator(cache_file_directory_, | 447 base::FileEnumerator enumerator(cache_file_directory_, |
| 426 false, // not recursive | 448 false, // not recursive |
| 427 base::FileEnumerator::FILES); | 449 base::FileEnumerator::FILES); |
| 428 for (base::FilePath current = enumerator.Next(); !current.empty(); | 450 for (base::FilePath current = enumerator.Next(); !current.empty(); |
| 429 current = enumerator.Next()) { | 451 current = enumerator.Next()) { |
| 430 const std::string& id = GetIdFromPath(current); | 452 const std::string& id = GetIdFromPath(current); |
| 431 FileCacheEntry entry; | 453 FileCacheEntry entry; |
| 432 if (storage_->GetCacheEntry(id, &entry)) { | 454 FileError error = storage_->GetCacheEntry(id, &entry); |
| 455 if (error == FILE_ERROR_OK) { |
| 433 // This file is managed by FileCache, no need to recover it. | 456 // This file is managed by FileCache, no need to recover it. |
| 434 continue; | 457 continue; |
| 435 } | 458 } |
| 459 if (error != FILE_ERROR_NOT_FOUND) |
| 460 return false; |
| 436 | 461 |
| 437 // If a cache entry which is non-dirty and has matching MD5 is found in | 462 // If a cache entry which is non-dirty and has matching MD5 is found in |
| 438 // |recovered_cache_entries|, it means the current file is already uploaded | 463 // |recovered_cache_entries|, it means the current file is already uploaded |
| 439 // to the server. Just delete it instead of recovering it. | 464 // to the server. Just delete it instead of recovering it. |
| 440 ResourceMetadataStorage::RecoveredCacheInfoMap::const_iterator it = | 465 ResourceMetadataStorage::RecoveredCacheInfoMap::const_iterator it = |
| 441 recovered_cache_info.find(id); | 466 recovered_cache_info.find(id); |
| 442 if (it != recovered_cache_info.end()) { | 467 if (it != recovered_cache_info.end()) { |
| 443 // Due to the DB corruption, cache info might be recovered from old | 468 // Due to the DB corruption, cache info might be recovered from old |
| 444 // revision. Perform MD5 check even when is_dirty is false just in case. | 469 // revision. Perform MD5 check even when is_dirty is false just in case. |
| 445 if (!it->second.is_dirty && | 470 if (!it->second.is_dirty && |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 } | 535 } |
| 511 | 536 |
| 512 FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) { | 537 FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) { |
| 513 AssertOnSequencedWorkerPool(); | 538 AssertOnSequencedWorkerPool(); |
| 514 DCHECK(IsUnderFileCacheDirectory(file_path)); | 539 DCHECK(IsUnderFileCacheDirectory(file_path)); |
| 515 | 540 |
| 516 std::string id = GetIdFromPath(file_path); | 541 std::string id = GetIdFromPath(file_path); |
| 517 | 542 |
| 518 // Get cache entry associated with the id and md5 | 543 // Get cache entry associated with the id and md5 |
| 519 FileCacheEntry cache_entry; | 544 FileCacheEntry cache_entry; |
| 520 if (!storage_->GetCacheEntry(id, &cache_entry)) | 545 FileError error = storage_->GetCacheEntry(id, &cache_entry); |
| 521 return FILE_ERROR_NOT_FOUND; | 546 if (error != FILE_ERROR_OK) |
| 547 return error; |
| 522 | 548 |
| 523 std::set<std::string>::iterator it = mounted_files_.find(id); | 549 std::set<std::string>::iterator it = mounted_files_.find(id); |
| 524 if (it == mounted_files_.end()) | 550 if (it == mounted_files_.end()) |
| 525 return FILE_ERROR_INVALID_OPERATION; | 551 return FILE_ERROR_INVALID_OPERATION; |
| 526 | 552 |
| 527 mounted_files_.erase(it); | 553 mounted_files_.erase(it); |
| 528 return FILE_ERROR_OK; | 554 return FILE_ERROR_OK; |
| 529 } | 555 } |
| 530 | 556 |
| 531 bool FileCache::HasEnoughSpaceFor(int64 num_bytes, | 557 bool FileCache::HasEnoughSpaceFor(int64 num_bytes, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 return; | 596 return; |
| 571 | 597 |
| 572 DCHECK_LT(0, it->second); | 598 DCHECK_LT(0, it->second); |
| 573 --it->second; | 599 --it->second; |
| 574 if (it->second == 0) | 600 if (it->second == 0) |
| 575 write_opened_files_.erase(it); | 601 write_opened_files_.erase(it); |
| 576 } | 602 } |
| 577 | 603 |
| 578 } // namespace internal | 604 } // namespace internal |
| 579 } // namespace drive | 605 } // namespace drive |
| OLD | NEW |