Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: chrome/browser/chromeos/drive/file_cache.cc

Issue 17249004: drive: Use ResourceMetadataStorage from FileCache (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/file_util.h" 9 #include "base/file_util.h"
10 #include "base/files/file_enumerator.h" 10 #include "base/files/file_enumerator.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/sys_info.h" 14 #include "base/sys_info.h"
15 #include "base/task_runner_util.h" 15 #include "base/task_runner_util.h"
16 #include "chrome/browser/chromeos/drive/drive.pb.h" 16 #include "chrome/browser/chromeos/drive/drive.pb.h"
17 #include "chrome/browser/chromeos/drive/file_cache_metadata.h" 17 #include "chrome/browser/chromeos/drive/file_cache_metadata.h"
18 #include "chrome/browser/chromeos/drive/file_system_util.h" 18 #include "chrome/browser/chromeos/drive/file_system_util.h"
19 #include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
19 #include "chrome/browser/google_apis/task_util.h" 20 #include "chrome/browser/google_apis/task_util.h"
20 #include "chromeos/chromeos_constants.h" 21 #include "chromeos/chromeos_constants.h"
21 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
22 23
23 using content::BrowserThread; 24 using content::BrowserThread;
24 25
25 namespace drive { 26 namespace drive {
26 namespace internal { 27 namespace internal {
27 namespace { 28 namespace {
28 29
29 // Name of the cache metadata DB. 30 // Name of the cache metadata DB.
30 const base::FilePath::CharType* kCacheMetadataDBName = 31 const base::FilePath::CharType kCacheMetadataDBName[] =
31 FILE_PATH_LITERAL("cache_metadata.db"); 32 FILE_PATH_LITERAL("cache_metadata.db");
32 33
33 typedef std::map<std::string, FileCacheEntry> CacheMap; 34 typedef std::map<std::string, FileCacheEntry> CacheMap;
34 35
35 // Returns true if |md5| matches the one in |cache_entry| with some 36 // Returns true if |md5| matches the one in |cache_entry| with some
36 // exceptions. See the function definition for details. 37 // exceptions. See the function definition for details.
37 bool CheckIfMd5Matches(const std::string& md5, 38 bool CheckIfMd5Matches(const std::string& md5,
38 const FileCacheEntry& cache_entry) { 39 const FileCacheEntry& cache_entry) {
39 if (cache_entry.is_dirty()) { 40 if (cache_entry.is_dirty()) {
40 // If the entry is dirty, its MD5 may have been replaced by "local" 41 // If the entry is dirty, its MD5 may have been replaced by "local"
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 void RunGetCacheEntryCallback(const GetCacheEntryCallback& callback, 153 void RunGetCacheEntryCallback(const GetCacheEntryCallback& callback,
153 FileCacheEntry* cache_entry, 154 FileCacheEntry* cache_entry,
154 bool success) { 155 bool success) {
155 DCHECK(cache_entry); 156 DCHECK(cache_entry);
156 DCHECK(!callback.is_null()); 157 DCHECK(!callback.is_null());
157 callback.Run(success, *cache_entry); 158 callback.Run(success, *cache_entry);
158 } 159 }
159 160
160 } // namespace 161 } // namespace
161 162
162 FileCache::FileCache(const base::FilePath& metadata_directory, 163 FileCache::FileCache(ResourceMetadataStorage* storage,
163 const base::FilePath& cache_file_directory, 164 const base::FilePath& cache_file_directory,
164 base::SequencedTaskRunner* blocking_task_runner, 165 base::SequencedTaskRunner* blocking_task_runner,
165 FreeDiskSpaceGetterInterface* free_disk_space_getter) 166 FreeDiskSpaceGetterInterface* free_disk_space_getter)
166 : metadata_directory_(metadata_directory), 167 : cache_file_directory_(cache_file_directory),
167 cache_file_directory_(cache_file_directory),
168 blocking_task_runner_(blocking_task_runner), 168 blocking_task_runner_(blocking_task_runner),
169 storage_(storage),
169 free_disk_space_getter_(free_disk_space_getter), 170 free_disk_space_getter_(free_disk_space_getter),
170 weak_ptr_factory_(this) { 171 weak_ptr_factory_(this) {
171 DCHECK(blocking_task_runner_.get()); 172 DCHECK(blocking_task_runner_.get());
172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
173 } 174 }
174 175
175 FileCache::~FileCache() { 176 FileCache::~FileCache() {
176 // Must be on the sequenced worker pool, as |metadata_| must be deleted on 177 // Must be on the sequenced worker pool, as |metadata_| must be deleted on
177 // the sequenced worker pool. 178 // the sequenced worker pool.
178 AssertOnSequencedWorkerPool(); 179 AssertOnSequencedWorkerPool();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 cache_entry), 223 cache_entry),
223 base::Bind( 224 base::Bind(
224 &RunGetCacheEntryCallback, callback, base::Owned(cache_entry))); 225 &RunGetCacheEntryCallback, callback, base::Owned(cache_entry)));
225 } 226 }
226 227
227 bool FileCache::GetCacheEntry(const std::string& resource_id, 228 bool FileCache::GetCacheEntry(const std::string& resource_id,
228 const std::string& md5, 229 const std::string& md5,
229 FileCacheEntry* entry) { 230 FileCacheEntry* entry) {
230 DCHECK(entry); 231 DCHECK(entry);
231 AssertOnSequencedWorkerPool(); 232 AssertOnSequencedWorkerPool();
232 return metadata_->GetCacheEntry(resource_id, entry) && 233 return storage_->GetCacheEntry(resource_id, entry) &&
233 CheckIfMd5Matches(md5, *entry); 234 CheckIfMd5Matches(md5, *entry);
234 } 235 }
235 236
236 void FileCache::IterateOnUIThread( 237 void FileCache::IterateOnUIThread(
237 const CacheIterateCallback& iteration_callback, 238 const CacheIterateCallback& iteration_callback,
238 const base::Closure& completion_callback) { 239 const base::Closure& completion_callback) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
240 DCHECK(!iteration_callback.is_null()); 241 DCHECK(!iteration_callback.is_null());
241 DCHECK(!completion_callback.is_null()); 242 DCHECK(!completion_callback.is_null());
242 243
243 blocking_task_runner_->PostTaskAndReply( 244 blocking_task_runner_->PostTaskAndReply(
244 FROM_HERE, 245 FROM_HERE,
245 base::Bind(&FileCache::Iterate, 246 base::Bind(&FileCache::Iterate,
246 base::Unretained(this), 247 base::Unretained(this),
247 google_apis::CreateRelayCallback(iteration_callback)), 248 google_apis::CreateRelayCallback(iteration_callback)),
248 completion_callback); 249 completion_callback);
249 } 250 }
250 251
251 void FileCache::Iterate(const CacheIterateCallback& iteration_callback) { 252 void FileCache::Iterate(const CacheIterateCallback& iteration_callback) {
252 AssertOnSequencedWorkerPool(); 253 AssertOnSequencedWorkerPool();
253 DCHECK(!iteration_callback.is_null()); 254 DCHECK(!iteration_callback.is_null());
254 255
255 scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator(); 256 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
257 storage_->GetCacheEntryIterator();
256 for (; !it->IsAtEnd(); it->Advance()) 258 for (; !it->IsAtEnd(); it->Advance())
257 iteration_callback.Run(it->GetKey(), it->GetValue()); 259 iteration_callback.Run(it->GetID(), it->GetValue());
258 DCHECK(!it->HasError()); 260 DCHECK(!it->HasError());
259 } 261 }
260 262
261 void FileCache::FreeDiskSpaceIfNeededForOnUIThread( 263 void FileCache::FreeDiskSpaceIfNeededForOnUIThread(
262 int64 num_bytes, 264 int64 num_bytes,
263 const InitializeCacheCallback& callback) { 265 const InitializeCacheCallback& callback) {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
265 DCHECK(!callback.is_null()); 267 DCHECK(!callback.is_null());
266 268
267 base::PostTaskAndReplyWithResult( 269 base::PostTaskAndReplyWithResult(
268 blocking_task_runner_.get(), 270 blocking_task_runner_.get(),
269 FROM_HERE, 271 FROM_HERE,
270 base::Bind(&FileCache::FreeDiskSpaceIfNeededFor, 272 base::Bind(&FileCache::FreeDiskSpaceIfNeededFor,
271 base::Unretained(this), 273 base::Unretained(this),
272 num_bytes), 274 num_bytes),
273 callback); 275 callback);
274 } 276 }
275 277
276 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { 278 bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) {
277 AssertOnSequencedWorkerPool(); 279 AssertOnSequencedWorkerPool();
278 280
279 // Do nothing and return if we have enough space. 281 // Do nothing and return if we have enough space.
280 if (HasEnoughSpaceFor(num_bytes, cache_file_directory_)) 282 if (HasEnoughSpaceFor(num_bytes, cache_file_directory_))
281 return true; 283 return true;
282 284
283 // Otherwise, try to free up the disk space. 285 // Otherwise, try to free up the disk space.
284 DVLOG(1) << "Freeing up disk space for " << num_bytes; 286 DVLOG(1) << "Freeing up disk space for " << num_bytes;
285 287
286 // Remove all entries unless specially marked. 288 // Remove all entries unless specially marked.
287 scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator(); 289 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
290 storage_->GetCacheEntryIterator();
288 for (; !it->IsAtEnd(); it->Advance()) { 291 for (; !it->IsAtEnd(); it->Advance()) {
289 const FileCacheEntry& entry = it->GetValue(); 292 const FileCacheEntry& entry = it->GetValue();
290 if (!entry.is_pinned() && 293 if (!entry.is_pinned() &&
291 !entry.is_dirty() && 294 !entry.is_dirty() &&
292 !mounted_files_.count(it->GetKey())) 295 !mounted_files_.count(it->GetID()))
293 metadata_->RemoveCacheEntry(it->GetKey()); 296 storage_->RemoveCacheEntry(it->GetID());
294 } 297 }
295 DCHECK(!it->HasError()); 298 DCHECK(!it->HasError());
296 299
297 // Remove all files which have no corresponding cache entries. 300 // Remove all files which have no corresponding cache entries.
298 base::FileEnumerator enumerator(cache_file_directory_, 301 base::FileEnumerator enumerator(cache_file_directory_,
299 false, // not recursive 302 false, // not recursive
300 base::FileEnumerator::FILES); 303 base::FileEnumerator::FILES);
301 std::string resource_id; 304 std::string resource_id;
302 std::string md5; 305 std::string md5;
303 FileCacheEntry entry; 306 FileCacheEntry entry;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 blocking_task_runner_.get(), 388 blocking_task_runner_.get(),
386 FROM_HERE, 389 FROM_HERE,
387 base::Bind(&FileCache::Pin, base::Unretained(this), resource_id), 390 base::Bind(&FileCache::Pin, base::Unretained(this), resource_id),
388 callback); 391 callback);
389 } 392 }
390 393
391 FileError FileCache::Pin(const std::string& resource_id) { 394 FileError FileCache::Pin(const std::string& resource_id) {
392 AssertOnSequencedWorkerPool(); 395 AssertOnSequencedWorkerPool();
393 396
394 FileCacheEntry cache_entry; 397 FileCacheEntry cache_entry;
395 metadata_->GetCacheEntry(resource_id, &cache_entry); 398 storage_->GetCacheEntry(resource_id, &cache_entry);
396 cache_entry.set_is_pinned(true); 399 cache_entry.set_is_pinned(true);
397 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 400 storage_->PutCacheEntry(resource_id, cache_entry);
398 return FILE_ERROR_OK; 401 return FILE_ERROR_OK;
399 } 402 }
400 403
401 void FileCache::UnpinOnUIThread(const std::string& resource_id, 404 void FileCache::UnpinOnUIThread(const std::string& resource_id,
402 const FileOperationCallback& callback) { 405 const FileOperationCallback& callback) {
403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 406 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
404 DCHECK(!callback.is_null()); 407 DCHECK(!callback.is_null());
405 408
406 base::PostTaskAndReplyWithResult( 409 base::PostTaskAndReplyWithResult(
407 blocking_task_runner_.get(), 410 blocking_task_runner_.get(),
408 FROM_HERE, 411 FROM_HERE,
409 base::Bind(&FileCache::Unpin, base::Unretained(this), resource_id), 412 base::Bind(&FileCache::Unpin, base::Unretained(this), resource_id),
410 callback); 413 callback);
411 } 414 }
412 415
413 FileError FileCache::Unpin(const std::string& resource_id) { 416 FileError FileCache::Unpin(const std::string& resource_id) {
414 AssertOnSequencedWorkerPool(); 417 AssertOnSequencedWorkerPool();
415 418
416 // Unpinning a file means its entry must exist in cache. 419 // Unpinning a file means its entry must exist in cache.
417 FileCacheEntry cache_entry; 420 FileCacheEntry cache_entry;
418 if (!metadata_->GetCacheEntry(resource_id, &cache_entry)) 421 if (!storage_->GetCacheEntry(resource_id, &cache_entry))
419 return FILE_ERROR_NOT_FOUND; 422 return FILE_ERROR_NOT_FOUND;
420 423
421 // Now that file operations have completed, update metadata. 424 // Now that file operations have completed, update metadata.
422 if (cache_entry.is_present()) { 425 if (cache_entry.is_present()) {
423 cache_entry.set_is_pinned(false); 426 cache_entry.set_is_pinned(false);
424 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 427 storage_->PutCacheEntry(resource_id, cache_entry);
425 } else { 428 } else {
426 // Remove the existing entry if we are unpinning a non-present file. 429 // Remove the existing entry if we are unpinning a non-present file.
427 metadata_->RemoveCacheEntry(resource_id); 430 storage_->RemoveCacheEntry(resource_id);
428 } 431 }
429 432
430 // Now it's a chance to free up space if needed. 433 // Now it's a chance to free up space if needed.
431 FreeDiskSpaceIfNeededFor(0); 434 FreeDiskSpaceIfNeededFor(0);
432 435
433 return FILE_ERROR_OK; 436 return FILE_ERROR_OK;
434 } 437 }
435 438
436 void FileCache::MarkAsMountedOnUIThread( 439 void FileCache::MarkAsMountedOnUIThread(
437 const std::string& resource_id, 440 const std::string& resource_id,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 AssertOnSequencedWorkerPool(); 487 AssertOnSequencedWorkerPool();
485 488
486 // If file has already been marked dirty in previous instance of chrome, we 489 // If file has already been marked dirty in previous instance of chrome, we
487 // would have lost the md5 info during cache initialization, because the file 490 // would have lost the md5 info during cache initialization, because the file
488 // would have been renamed to .local extension. 491 // would have been renamed to .local extension.
489 // So, search for entry in cache without comparing md5. 492 // So, search for entry in cache without comparing md5.
490 493
491 // Marking a file dirty means its entry and actual file blob must exist in 494 // Marking a file dirty means its entry and actual file blob must exist in
492 // cache. 495 // cache.
493 FileCacheEntry cache_entry; 496 FileCacheEntry cache_entry;
494 if (!metadata_->GetCacheEntry(resource_id, &cache_entry) || 497 if (!storage_->GetCacheEntry(resource_id, &cache_entry) ||
495 !cache_entry.is_present()) { 498 !cache_entry.is_present()) {
496 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: res_id=" 499 LOG(WARNING) << "Can't mark dirty a file that wasn't cached: res_id="
497 << resource_id 500 << resource_id
498 << ", md5=" << md5; 501 << ", md5=" << md5;
499 return FILE_ERROR_NOT_FOUND; 502 return FILE_ERROR_NOT_FOUND;
500 } 503 }
501 504
502 if (cache_entry.is_dirty()) 505 if (cache_entry.is_dirty())
503 return FILE_ERROR_OK; 506 return FILE_ERROR_OK;
504 507
505 // Get the current path of the file in cache. 508 // Get the current path of the file in cache.
506 base::FilePath source_path = GetCacheFilePath(resource_id, md5, 509 base::FilePath source_path = GetCacheFilePath(resource_id, md5,
507 CACHED_FILE_FROM_SERVER); 510 CACHED_FILE_FROM_SERVER);
508 // Determine destination path. 511 // Determine destination path.
509 base::FilePath cache_file_path = GetCacheFilePath( 512 base::FilePath cache_file_path = GetCacheFilePath(
510 resource_id, md5, CACHED_FILE_LOCALLY_MODIFIED); 513 resource_id, md5, CACHED_FILE_LOCALLY_MODIFIED);
511 514
512 if (!MoveFile(source_path, cache_file_path)) 515 if (!MoveFile(source_path, cache_file_path))
513 return FILE_ERROR_FAILED; 516 return FILE_ERROR_FAILED;
514 517
515 // Now that file operations have completed, update metadata. 518 // Now that file operations have completed, update metadata.
516 cache_entry.set_md5(md5); 519 cache_entry.set_md5(md5);
517 cache_entry.set_is_dirty(true); 520 cache_entry.set_is_dirty(true);
518 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 521 storage_->PutCacheEntry(resource_id, cache_entry);
519 return FILE_ERROR_OK; 522 return FILE_ERROR_OK;
520 } 523 }
521 524
522 FileError FileCache::ClearDirty(const std::string& resource_id, 525 FileError FileCache::ClearDirty(const std::string& resource_id,
523 const std::string& md5) { 526 const std::string& md5) {
524 AssertOnSequencedWorkerPool(); 527 AssertOnSequencedWorkerPool();
525 528
526 // |md5| is the new .<md5> extension to rename the file to. 529 // |md5| is the new .<md5> extension to rename the file to.
527 // So, search for entry in cache without comparing md5. 530 // So, search for entry in cache without comparing md5.
528 FileCacheEntry cache_entry; 531 FileCacheEntry cache_entry;
529 532
530 // Clearing a dirty file means its entry and actual file blob must exist in 533 // Clearing a dirty file means its entry and actual file blob must exist in
531 // cache. 534 // cache.
532 if (!metadata_->GetCacheEntry(resource_id, &cache_entry) || 535 if (!storage_->GetCacheEntry(resource_id, &cache_entry) ||
533 !cache_entry.is_present()) { 536 !cache_entry.is_present()) {
534 LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: " 537 LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: "
535 << "res_id=" << resource_id 538 << "res_id=" << resource_id
536 << ", md5=" << md5; 539 << ", md5=" << md5;
537 return FILE_ERROR_NOT_FOUND; 540 return FILE_ERROR_NOT_FOUND;
538 } 541 }
539 542
540 // If a file is not dirty (it should have been marked dirty via 543 // If a file is not dirty (it should have been marked dirty via
541 // MarkDirtyInCache), clearing its dirty state is an invalid operation. 544 // MarkDirtyInCache), clearing its dirty state is an invalid operation.
542 if (!cache_entry.is_dirty()) { 545 if (!cache_entry.is_dirty()) {
543 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: res_id=" 546 LOG(WARNING) << "Can't clear dirty state of a non-dirty file: res_id="
544 << resource_id 547 << resource_id
545 << ", md5=" << md5; 548 << ", md5=" << md5;
546 return FILE_ERROR_INVALID_OPERATION; 549 return FILE_ERROR_INVALID_OPERATION;
547 } 550 }
548 551
549 base::FilePath source_path = GetCacheFilePath(resource_id, md5, 552 base::FilePath source_path = GetCacheFilePath(resource_id, md5,
550 CACHED_FILE_LOCALLY_MODIFIED); 553 CACHED_FILE_LOCALLY_MODIFIED);
551 base::FilePath dest_path = GetCacheFilePath(resource_id, md5, 554 base::FilePath dest_path = GetCacheFilePath(resource_id, md5,
552 CACHED_FILE_FROM_SERVER); 555 CACHED_FILE_FROM_SERVER);
553 if (!MoveFile(source_path, dest_path)) 556 if (!MoveFile(source_path, dest_path))
554 return FILE_ERROR_FAILED; 557 return FILE_ERROR_FAILED;
555 558
556 // Now that file operations have completed, update metadata. 559 // Now that file operations have completed, update metadata.
557 cache_entry.set_md5(md5); 560 cache_entry.set_md5(md5);
558 cache_entry.set_is_dirty(false); 561 cache_entry.set_is_dirty(false);
559 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 562 storage_->PutCacheEntry(resource_id, cache_entry);
560 return FILE_ERROR_OK; 563 return FILE_ERROR_OK;
561 } 564 }
562 565
563 void FileCache::RemoveOnUIThread(const std::string& resource_id, 566 void FileCache::RemoveOnUIThread(const std::string& resource_id,
564 const FileOperationCallback& callback) { 567 const FileOperationCallback& callback) {
565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 568 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
566 DCHECK(!callback.is_null()); 569 DCHECK(!callback.is_null());
567 570
568 base::PostTaskAndReplyWithResult( 571 base::PostTaskAndReplyWithResult(
569 blocking_task_runner_.get(), 572 blocking_task_runner_.get(),
570 FROM_HERE, 573 FROM_HERE,
571 base::Bind(&FileCache::Remove, base::Unretained(this), resource_id), 574 base::Bind(&FileCache::Remove, base::Unretained(this), resource_id),
572 callback); 575 callback);
573 } 576 }
574 577
575 FileError FileCache::Remove(const std::string& resource_id) { 578 FileError FileCache::Remove(const std::string& resource_id) {
576 AssertOnSequencedWorkerPool(); 579 AssertOnSequencedWorkerPool();
577 580
578 // MD5 is not passed into RemoveCacheEntry because we would delete all 581 // MD5 is not passed into RemoveCacheEntry because we would delete all
579 // cache files corresponding to <resource_id> regardless of the md5. 582 // cache files corresponding to <resource_id> regardless of the md5.
580 // So, search for entry in cache without taking md5 into account. 583 // So, search for entry in cache without taking md5 into account.
581 FileCacheEntry cache_entry; 584 FileCacheEntry cache_entry;
582 585
583 // If entry doesn't exist, nothing to do. 586 // If entry doesn't exist, nothing to do.
584 if (!metadata_->GetCacheEntry(resource_id, &cache_entry)) 587 if (!storage_->GetCacheEntry(resource_id, &cache_entry))
585 return FILE_ERROR_OK; 588 return FILE_ERROR_OK;
586 589
587 // Cannot delete a dirty or mounted file. 590 // Cannot delete a dirty or mounted file.
588 if (cache_entry.is_dirty() || mounted_files_.count(resource_id)) 591 if (cache_entry.is_dirty() || mounted_files_.count(resource_id))
589 return FILE_ERROR_IN_USE; 592 return FILE_ERROR_IN_USE;
590 593
591 // Delete files that match "<resource_id>.*" unless modified locally. 594 // Delete files that match "<resource_id>.*" unless modified locally.
592 base::FilePath path_to_delete = GetCacheFilePath(resource_id, util::kWildCard, 595 base::FilePath path_to_delete = GetCacheFilePath(resource_id, util::kWildCard,
593 CACHED_FILE_FROM_SERVER); 596 CACHED_FILE_FROM_SERVER);
594 base::FilePath path_to_keep = GetCacheFilePath(resource_id, std::string(), 597 base::FilePath path_to_keep = GetCacheFilePath(resource_id, std::string(),
595 CACHED_FILE_LOCALLY_MODIFIED); 598 CACHED_FILE_LOCALLY_MODIFIED);
596 DeleteFilesSelectively(path_to_delete, path_to_keep); 599 DeleteFilesSelectively(path_to_delete, path_to_keep);
597 600
598 // Now that all file operations have completed, remove from metadata. 601 // Now that all file operations have completed, remove from metadata.
599 metadata_->RemoveCacheEntry(resource_id); 602 storage_->RemoveCacheEntry(resource_id);
600 603
601 return FILE_ERROR_OK; 604 return FILE_ERROR_OK;
602 } 605 }
603 606
604 void FileCache::ClearAllOnUIThread(const InitializeCacheCallback& callback) { 607 void FileCache::ClearAllOnUIThread(const InitializeCacheCallback& callback) {
605 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 608 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
606 DCHECK(!callback.is_null()); 609 DCHECK(!callback.is_null());
607 610
608 base::PostTaskAndReplyWithResult( 611 base::PostTaskAndReplyWithResult(
609 blocking_task_runner_.get(), 612 blocking_task_runner_.get(),
610 FROM_HERE, 613 FROM_HERE,
611 base::Bind(&FileCache::ClearAll, base::Unretained(this)), 614 base::Bind(&FileCache::ClearAll, base::Unretained(this)),
612 callback); 615 callback);
613 } 616 }
614 617
615 bool FileCache::Initialize() { 618 bool FileCache::Initialize() {
616 AssertOnSequencedWorkerPool(); 619 AssertOnSequencedWorkerPool();
617 620
618 metadata_.reset(new FileCacheMetadata(blocking_task_runner_.get())); 621 if (!ImportOldDB(storage_->directory_path().Append(kCacheMetadataDBName)) &&
619 622 !storage_->opened_existing_db()) {
620 const base::FilePath db_path = 623 CacheMap cache_map;
621 metadata_directory_.Append(kCacheMetadataDBName); 624 ScanCacheDirectory(cache_file_directory_, &cache_map);
622 switch (metadata_->Initialize(db_path)) { 625 for (CacheMap::const_iterator it = cache_map.begin();
623 case FileCacheMetadata::INITIALIZE_FAILED: 626 it != cache_map.end(); ++it) {
624 return false; 627 storage_->PutCacheEntry(it->first, it->second);
625
626 case FileCacheMetadata::INITIALIZE_OPENED: // Do nothing.
627 break;
628
629 case FileCacheMetadata::INITIALIZE_CREATED: {
630 CacheMap cache_map;
631 ScanCacheDirectory(cache_file_directory_, &cache_map);
632 for (CacheMap::const_iterator it = cache_map.begin();
633 it != cache_map.end(); ++it) {
634 metadata_->AddOrUpdateCacheEntry(it->first, it->second);
635 }
636 break;
637 } 628 }
638 } 629 }
639 return true; 630 return true;
640 } 631 }
641 632
642 void FileCache::Destroy() { 633 void FileCache::Destroy() {
643 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 634 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
644 635
645 // Invalidate the weak pointer. 636 // Invalidate the weak pointer.
646 weak_ptr_factory_.InvalidateWeakPtrs(); 637 weak_ptr_factory_.InvalidateWeakPtrs();
(...skipping 21 matching lines...) Expand all
668 if (file_operation_type == FILE_OPERATION_COPY) { 659 if (file_operation_type == FILE_OPERATION_COPY) {
669 if (!file_util::GetFileSize(source_path, &file_size)) { 660 if (!file_util::GetFileSize(source_path, &file_size)) {
670 LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); 661 LOG(WARNING) << "Couldn't get file size for: " << source_path.value();
671 return FILE_ERROR_FAILED; 662 return FILE_ERROR_FAILED;
672 } 663 }
673 } 664 }
674 if (!FreeDiskSpaceIfNeededFor(file_size)) 665 if (!FreeDiskSpaceIfNeededFor(file_size))
675 return FILE_ERROR_NO_SPACE; 666 return FILE_ERROR_NO_SPACE;
676 667
677 FileCacheEntry cache_entry; 668 FileCacheEntry cache_entry;
678 metadata_->GetCacheEntry(resource_id, &cache_entry); 669 storage_->GetCacheEntry(resource_id, &cache_entry);
679 670
680 // If file is dirty or mounted, return error. 671 // If file is dirty or mounted, return error.
681 if (cache_entry.is_dirty() || mounted_files_.count(resource_id)) 672 if (cache_entry.is_dirty() || mounted_files_.count(resource_id))
682 return FILE_ERROR_IN_USE; 673 return FILE_ERROR_IN_USE;
683 674
684 base::FilePath dest_path = GetCacheFilePath(resource_id, md5, 675 base::FilePath dest_path = GetCacheFilePath(resource_id, md5,
685 CACHED_FILE_FROM_SERVER); 676 CACHED_FILE_FROM_SERVER);
686 bool success = false; 677 bool success = false;
687 switch (file_operation_type) { 678 switch (file_operation_type) {
688 case FILE_OPERATION_MOVE: 679 case FILE_OPERATION_MOVE:
(...skipping 26 matching lines...) Expand all
715 } 706 }
716 707
717 // Delete files that match |stale_filenames_pattern| except for |dest_path|. 708 // Delete files that match |stale_filenames_pattern| except for |dest_path|.
718 DeleteFilesSelectively(stale_filenames_pattern, dest_path); 709 DeleteFilesSelectively(stale_filenames_pattern, dest_path);
719 710
720 if (success) { 711 if (success) {
721 // Now that file operations have completed, update metadata. 712 // Now that file operations have completed, update metadata.
722 cache_entry.set_md5(md5); 713 cache_entry.set_md5(md5);
723 cache_entry.set_is_present(true); 714 cache_entry.set_is_present(true);
724 cache_entry.set_is_dirty(false); 715 cache_entry.set_is_dirty(false);
725 metadata_->AddOrUpdateCacheEntry(resource_id, cache_entry); 716 storage_->PutCacheEntry(resource_id, cache_entry);
726 } 717 }
727 718
728 return success ? FILE_ERROR_OK : FILE_ERROR_FAILED; 719 return success ? FILE_ERROR_OK : FILE_ERROR_FAILED;
729 } 720 }
730 721
731 FileError FileCache::MarkAsMounted(const std::string& resource_id, 722 FileError FileCache::MarkAsMounted(const std::string& resource_id,
732 base::FilePath* cache_file_path) { 723 base::FilePath* cache_file_path) {
733 AssertOnSequencedWorkerPool(); 724 AssertOnSequencedWorkerPool();
734 DCHECK(cache_file_path); 725 DCHECK(cache_file_path);
735 726
736 // Get cache entry associated with the resource_id and md5 727 // Get cache entry associated with the resource_id and md5
737 FileCacheEntry cache_entry; 728 FileCacheEntry cache_entry;
738 if (!metadata_->GetCacheEntry(resource_id, &cache_entry)) 729 if (!storage_->GetCacheEntry(resource_id, &cache_entry))
739 return FILE_ERROR_NOT_FOUND; 730 return FILE_ERROR_NOT_FOUND;
740 731
741 if (mounted_files_.count(resource_id)) 732 if (mounted_files_.count(resource_id))
742 return FILE_ERROR_INVALID_OPERATION; 733 return FILE_ERROR_INVALID_OPERATION;
743 734
744 // Ensure the file is readable to cros_disks. See crbug.com/236994. 735 // Ensure the file is readable to cros_disks. See crbug.com/236994.
745 base::FilePath path = GetCacheFilePath( 736 base::FilePath path = GetCacheFilePath(
746 resource_id, cache_entry.md5(), CACHED_FILE_FROM_SERVER); 737 resource_id, cache_entry.md5(), CACHED_FILE_FROM_SERVER);
747 file_util::SetPosixFilePermissions( 738 file_util::SetPosixFilePermissions(
748 path, 739 path,
(...skipping 27 matching lines...) Expand all
776 return FILE_ERROR_INVALID_OPERATION; 767 return FILE_ERROR_INVALID_OPERATION;
777 768
778 mounted_files_.erase(it); 769 mounted_files_.erase(it);
779 return FILE_ERROR_OK; 770 return FILE_ERROR_OK;
780 } 771 }
781 772
782 bool FileCache::ClearAll() { 773 bool FileCache::ClearAll() {
783 AssertOnSequencedWorkerPool(); 774 AssertOnSequencedWorkerPool();
784 775
785 // Remove entries on the metadata. 776 // Remove entries on the metadata.
786 scoped_ptr<FileCacheMetadata::Iterator> it = metadata_->GetIterator(); 777 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
778 storage_->GetCacheEntryIterator();
787 for (; !it->IsAtEnd(); it->Advance()) 779 for (; !it->IsAtEnd(); it->Advance())
788 metadata_->RemoveCacheEntry(it->GetKey()); 780 storage_->RemoveCacheEntry(it->GetID());
789 781
790 if (it->HasError()) 782 if (it->HasError())
791 return false; 783 return false;
792 784
793 // Remove files. 785 // Remove files.
794 base::FileEnumerator enumerator(cache_file_directory_, 786 base::FileEnumerator enumerator(cache_file_directory_,
795 false, // not recursive 787 false, // not recursive
796 base::FileEnumerator::FILES); 788 base::FileEnumerator::FILES);
797 for (base::FilePath file = enumerator.Next(); !file.empty(); 789 for (base::FilePath file = enumerator.Next(); !file.empty();
798 file = enumerator.Next()) 790 file = enumerator.Next())
799 file_util::Delete(file, false /* recursive */); 791 file_util::Delete(file, false /* recursive */);
800 792
801 return true; 793 return true;
802 } 794 }
803 795
804 bool FileCache::HasEnoughSpaceFor(int64 num_bytes, 796 bool FileCache::HasEnoughSpaceFor(int64 num_bytes,
805 const base::FilePath& path) { 797 const base::FilePath& path) {
806 int64 free_space = 0; 798 int64 free_space = 0;
807 if (free_disk_space_getter_) 799 if (free_disk_space_getter_)
808 free_space = free_disk_space_getter_->AmountOfFreeDiskSpace(); 800 free_space = free_disk_space_getter_->AmountOfFreeDiskSpace();
809 else 801 else
810 free_space = base::SysInfo::AmountOfFreeDiskSpace(path); 802 free_space = base::SysInfo::AmountOfFreeDiskSpace(path);
811 803
812 // Subtract this as if this portion does not exist. 804 // Subtract this as if this portion does not exist.
813 free_space -= kMinFreeSpace; 805 free_space -= kMinFreeSpace;
814 return (free_space >= num_bytes); 806 return (free_space >= num_bytes);
815 } 807 }
816 808
817 void FileCache::ImportOldDB(const base::FilePath& old_db_path) { 809 bool FileCache::ImportOldDB(const base::FilePath& old_db_path) {
818 if (!file_util::PathExists(old_db_path)) // Old DB is not there, do nothing. 810 if (!file_util::PathExists(old_db_path)) // Old DB is not there, do nothing.
819 return; 811 return false;
820 812
821 // Copy all entries stored in the old DB. 813 // Copy all entries stored in the old DB.
822 FileCacheMetadata old_data(blocking_task_runner_); 814 FileCacheMetadata old_data(blocking_task_runner_);
823 if (old_data.Initialize(old_db_path)) { 815 if (old_data.Initialize(old_db_path)) {
824 scoped_ptr<FileCacheMetadata::Iterator> it = old_data.GetIterator(); 816 scoped_ptr<FileCacheMetadata::Iterator> it = old_data.GetIterator();
825 for (; !it->IsAtEnd(); it->Advance()) { 817 for (; !it->IsAtEnd(); it->Advance()) {
826 FileCacheEntry entry; 818 FileCacheEntry entry;
827 if (metadata_->GetCacheEntry(it->GetKey(), &entry)) 819 if (storage_->GetCacheEntry(it->GetKey(), &entry))
828 continue; // Do not overwrite. 820 continue; // Do not overwrite.
829 821
830 metadata_->AddOrUpdateCacheEntry(it->GetKey(), it->GetValue()); 822 storage_->PutCacheEntry(it->GetKey(), it->GetValue());
831 } 823 }
832 } 824 }
kinaba 2013/06/21 07:32:50 When old_data.Initialize() failed, shouldn't we re
hashimoto 2013/06/21 08:23:41 Amazingly good catch. Done as you suggested.
833 825
834 // Delete old DB. 826 // Delete old DB.
835 file_util::Delete(old_db_path, true /* recursive */ ); 827 file_util::Delete(old_db_path, true /* recursive */ );
828 return true;
836 } 829 }
837 830
838 } // namespace internal 831 } // namespace internal
839 } // namespace drive 832 } // namespace drive
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/drive/file_cache.h ('k') | chrome/browser/chromeos/drive/file_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698