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

Unified Diff: content/browser/service_worker/service_worker_storage.cc

Issue 1152543002: ServiceWorker: Migrate the script cache backend from BlockFile to Simple (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: incorporate falken@'s comments Created 5 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/service_worker/service_worker_storage.cc
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index 4f714195ce0ea688daffbebcf25093034b944c16..840eecebe29897b4bd29ef2a7bd0248b374bf454 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -4,6 +4,7 @@
#include "content/browser/service_worker/service_worker_storage.h"
+#include "base/barrier_closure.h"
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/message_loop/message_loop.h"
@@ -14,8 +15,8 @@
#include "base/trace_event/trace_event.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
+#include "content/browser/service_worker/service_worker_disk_cache_migrator.h"
#include "content/browser/service_worker/service_worker_info.h"
-#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
@@ -60,7 +61,8 @@ void CompleteFindSoon(
const base::FilePath::CharType kDatabaseName[] =
FILE_PATH_LITERAL("Database");
const base::FilePath::CharType kDiskCacheName[] =
- FILE_PATH_LITERAL("Cache");
+ FILE_PATH_LITERAL("ScriptCache");
+const base::FilePath::CharType kOldDiskCacheName[] = FILE_PATH_LITERAL("Cache");
const int kMaxMemDiskCacheSize = 10 * 1024 * 1024;
const int kMaxDiskCacheSize = 250 * 1024 * 1024;
@@ -929,6 +931,7 @@ ServiceWorkerStorage::ServiceWorkerStorage(
disk_cache_thread_(disk_cache_thread),
quota_manager_proxy_(quota_manager_proxy),
special_storage_policy_(special_storage_policy),
+ needs_disk_cache_migration_(false),
is_purge_pending_(false),
has_checked_for_stale_resources_(false),
weak_factory_(this) {
@@ -949,6 +952,13 @@ base::FilePath ServiceWorkerStorage::GetDiskCachePath() {
.Append(kDiskCacheName);
}
+base::FilePath ServiceWorkerStorage::GetOldDiskCachePath() {
+ if (path_.empty())
+ return base::FilePath();
+ return path_.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
+ .Append(kOldDiskCacheName);
+}
+
bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
if (!context_)
return false;
@@ -969,9 +979,8 @@ bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
state_ = INITIALIZING;
database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&ReadInitialDataFromDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
+ base::Bind(&ReadInitialDataFromDB, database_.get(),
+ base::ThreadTaskRunnerHandle::Get(), GetOldDiskCachePath(),
base::Bind(&ServiceWorkerStorage::DidReadInitialData,
weak_factory_.GetWeakPtr())));
return false;
@@ -979,6 +988,7 @@ bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
void ServiceWorkerStorage::DidReadInitialData(
InitialData* data,
+ bool needs_disk_cache_migration,
ServiceWorkerDatabase::Status status) {
DCHECK(data);
DCHECK_EQ(INITIALIZING, state_);
@@ -989,6 +999,7 @@ void ServiceWorkerStorage::DidReadInitialData(
next_resource_id_ = data->next_resource_id;
registered_origins_.swap(data->origins);
state_ = INITIALIZED;
+ needs_disk_cache_migration_ = needs_disk_cache_migration;
michaeln 2015/06/08 21:36:33 Curiosity: I wish we didn't have to migrate at all
nhiroki 2015/06/09 15:41:56 Yeah... it's definitely simpler and easier to achi
} else {
DVLOG(2) << "Failed to initialize: "
<< ServiceWorkerDatabase::StatusToString(status);
@@ -1368,30 +1379,160 @@ ServiceWorkerStorage::FindInstallingRegistrationForId(
}
ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() {
+ DCHECK_EQ(INITIALIZED, state_);
if (disk_cache_)
return disk_cache_.get();
- disk_cache_ = ServiceWorkerDiskCache::CreateWithBlockFileBackend();
+ disk_cache_ = ServiceWorkerDiskCache::CreateWithSimpleBackend();
- base::FilePath path = GetDiskCachePath();
- if (path.empty()) {
+ if (GetDiskCachePath().empty()) {
int rv = disk_cache_->InitWithMemBackend(kMaxMemDiskCacheSize,
net::CompletionCallback());
DCHECK_EQ(net::OK, rv);
return disk_cache_.get();
}
+ if (needs_disk_cache_migration_) {
+ // Defer the start of initialization until the migration is complete.
+ disk_cache_->set_is_waiting_to_initialize(true);
+ PrepareDiskCacheForMigration();
+ return disk_cache_.get();
+ }
+
+ // DiskCache has already been migrated.
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult(
+ ServiceWorkerMetrics::MIGRATION_NOT_NECESSARY);
+ InitializeDiskCache();
+
+ return disk_cache_.get();
+}
+
+void ServiceWorkerStorage::PrepareDiskCacheForMigration() {
+ scoped_ptr<ServiceWorkerDiskCache> src_disk_cache =
+ ServiceWorkerDiskCache::CreateWithBlockFileBackend();
+ ServiceWorkerDiskCache* src_disk_cache_ptr = src_disk_cache.get();
+ scoped_ptr<ServiceWorkerDiskCache> dest_disk_cache =
+ ServiceWorkerDiskCache::CreateWithSimpleBackend();
+ ServiceWorkerDiskCache* dest_disk_cache_ptr = dest_disk_cache.get();
+ bool* is_failed = new bool(false);
+
+ // This closure is called when both diskcaches are initialized.
+ base::Closure barrier_closure = base::BarrierClosure(
+ 2, base::Bind(
+ &ServiceWorkerStorage::DidPrepareDiskCacheForMigration,
+ weak_factory_.GetWeakPtr(), base::Passed(src_disk_cache.Pass()),
+ base::Passed(dest_disk_cache.Pass()), base::Owned(is_failed)));
+
+ // Initialize the src DiskCache.
+ net::CompletionCallback src_callback =
+ base::Bind(&ServiceWorkerStorage::DidInitializeDiskCacheForMigration,
+ weak_factory_.GetWeakPtr(), is_failed, barrier_closure);
+ int result = src_disk_cache_ptr->InitWithDiskBackend(
+ GetOldDiskCachePath(), kMaxDiskCacheSize, false /* force */,
+ disk_cache_thread_, src_callback);
+ if (result != net::ERR_IO_PENDING)
+ src_callback.Run(result);
+
+ // Initialize the dest DiskCache.
michaeln 2015/06/08 21:36:33 Since a migration attempt can be started multiple
nhiroki 2015/06/09 15:41:56 Done.
+ net::CompletionCallback dest_callback =
+ base::Bind(&ServiceWorkerStorage::DidInitializeDiskCacheForMigration,
+ weak_factory_.GetWeakPtr(), is_failed, barrier_closure);
+ result = dest_disk_cache_ptr->InitWithDiskBackend(
+ GetDiskCachePath(), kMaxDiskCacheSize, false /* force */,
+ disk_cache_thread_, dest_callback);
+ if (result != net::ERR_IO_PENDING)
+ dest_callback.Run(result);
+}
+
+void ServiceWorkerStorage::DidInitializeDiskCacheForMigration(
+ bool* is_failed,
+ const base::Closure& barrier_closure,
+ int result) {
+ if (result != net::OK)
+ *is_failed = true;
+ barrier_closure.Run();
+}
+
+void ServiceWorkerStorage::DidPrepareDiskCacheForMigration(
+ scoped_ptr<ServiceWorkerDiskCache> src_disk_cache,
+ scoped_ptr<ServiceWorkerDiskCache> dest_disk_cache,
+ bool* is_failed) {
+ if (*is_failed) {
+ LOG(ERROR) << "Failed to initialize the diskcache.";
+ src_disk_cache.reset();
+ dest_disk_cache.reset();
+ AbortDiskCacheMigration(ServiceWorkerMetrics::MIGRATION_ERROR_INITIALIZE);
+ return;
+ }
+
+ // Start migrating resources stored in the src DiskCache.
+ scoped_ptr<ServiceWorkerDiskCacheMigrator> migrator(
+ new ServiceWorkerDiskCacheMigrator(src_disk_cache.get(),
+ dest_disk_cache.get()));
+ ServiceWorkerDiskCacheMigrator* migrator_ptr = migrator.get();
+ migrator_ptr->Start(base::Bind(
michaeln 2015/06/08 21:36:33 The migrator will continue to run even after Servi
nhiroki 2015/06/09 15:41:56 I changed the storage to own the migrator. When th
+ &ServiceWorkerStorage::DidMigrateDiskCache, weak_factory_.GetWeakPtr(),
+ base::Passed(migrator.Pass()), base::Passed(src_disk_cache.Pass()),
+ base::Passed(dest_disk_cache.Pass())));
michaeln 2015/06/08 21:36:33 having ownership of src and dst bound into the clo
nhiroki 2015/06/09 15:41:57 Moved the initialization code from storage to migr
+}
+
+void ServiceWorkerStorage::DidMigrateDiskCache(
+ scoped_ptr<ServiceWorkerDiskCacheMigrator> migrator,
+ scoped_ptr<ServiceWorkerDiskCache> src_disk_cache,
+ scoped_ptr<ServiceWorkerDiskCache> dest_disk_cache,
+ ServiceWorkerStatusCode status) {
+ migrator.reset();
+ src_disk_cache.reset();
+ dest_disk_cache.reset();
+
+ if (status != SERVICE_WORKER_OK) {
+ LOG(ERROR) << "Failed to migrate the diskcache: "
+ << ServiceWorkerStatusToString(status);
+ AbortDiskCacheMigration(ServiceWorkerMetrics::MIGRATION_ERROR_FAILED);
+ return;
+ }
+
+ // Delete the old DiskCache directory.
+ PostTaskAndReplyWithResult(
+ disk_cache_thread_.get(), FROM_HERE,
+ base::Bind(&base::DeleteFile, GetOldDiskCachePath(), true),
+ base::Bind(&ServiceWorkerStorage::DidDeleteOldDiskCache,
+ weak_factory_.GetWeakPtr()));
+}
+
+void ServiceWorkerStorage::DidDeleteOldDiskCache(bool deleted) {
+ if (!deleted) {
+ LOG(ERROR) << "Failed to delete the old diskcache directory";
+ AbortDiskCacheMigration(
michaeln 2015/06/08 21:36:33 Seems unfortunate to let this error prevent migrat
nhiroki 2015/06/09 15:41:57 Changed this sequence. The latest patchset records
+ ServiceWorkerMetrics::MIGRATION_ERROR_DELETE_DISK_CACHE);
+ return;
+ }
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult(
+ ServiceWorkerMetrics::MIGRATION_OK);
+ InitializeDiskCache();
+}
+
+void ServiceWorkerStorage::AbortDiskCacheMigration(
michaeln 2015/06/08 21:36:33 This method doesn't actually abort anything, it ha
nhiroki 2015/06/09 15:41:57 (This function is gone)
+ ServiceWorkerMetrics::DiskCacheMigrationResult result) {
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult(result);
+
+ // Give up initialization and recreate the whole storage.
+ ScheduleDeleteAndStartOver();
+
+ // Delete the old disk directory because DeleteAndStartOver doesn't.
+ disk_cache_thread_->PostTask(FROM_HERE,
+ base::Bind(base::IgnoreResult(&base::DeleteFile),
+ GetOldDiskCachePath(), true));
+}
+
+void ServiceWorkerStorage::InitializeDiskCache() {
+ disk_cache_->set_is_waiting_to_initialize(false);
int rv = disk_cache_->InitWithDiskBackend(
- path,
- kMaxDiskCacheSize,
- false,
- disk_cache_thread_,
+ GetDiskCachePath(), kMaxDiskCacheSize, false, disk_cache_thread_,
base::Bind(&ServiceWorkerStorage::OnDiskCacheInitialized,
weak_factory_.GetWeakPtr()));
if (rv != net::ERR_IO_PENDING)
OnDiskCacheInitialized(rv);
-
- return disk_cache_.get();
}
void ServiceWorkerStorage::OnDiskCacheInitialized(int rv) {
@@ -1534,6 +1675,7 @@ void ServiceWorkerStorage::CollectStaleResourcesFromDB(
void ServiceWorkerStorage::ReadInitialDataFromDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+ const base::FilePath& old_disk_cache_path,
const InitializeCallback& callback) {
DCHECK(database);
scoped_ptr<ServiceWorkerStorage::InitialData> data(
@@ -1545,13 +1687,19 @@ void ServiceWorkerStorage::ReadInitialDataFromDB(
&data->next_resource_id);
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, base::Owned(data.release()), status));
+ FROM_HERE, base::Bind(callback, base::Owned(data.release()),
+ false /* needs_disk_cache_migration */, status));
return;
}
+ bool needs_disk_cache_migration = false;
+ if (!old_disk_cache_path.empty())
+ needs_disk_cache_migration = base::DirectoryExists(old_disk_cache_path);
michaeln 2015/06/08 21:36:33 I'm wondering about pathological cases where migra
nhiroki 2015/06/09 15:41:57 Added INITDATA_DISKCACHE_VERSION field in the data
+
status = database->GetOriginsWithRegistrations(&data->origins);
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, base::Owned(data.release()), status));
+ FROM_HERE, base::Bind(callback, base::Owned(data.release()),
+ needs_disk_cache_migration, status));
}
void ServiceWorkerStorage::DeleteRegistrationFromDB(

Powered by Google App Engine
This is Rietveld 408576698