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 b0c59e037b0dc89c26df81b5d30e45f53644db80..26c0cb5196fa2f255d7ae091d031806f67d8296f 100644 |
--- a/content/browser/service_worker/service_worker_storage.cc |
+++ b/content/browser/service_worker/service_worker_storage.cc |
@@ -14,8 +14,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 +60,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; |
@@ -207,7 +208,8 @@ void ResponseComparer::OnReadDataComplete(int result) { |
ServiceWorkerStorage::InitialData::InitialData() |
: next_registration_id(kInvalidServiceWorkerRegistrationId), |
next_version_id(kInvalidServiceWorkerVersionId), |
- next_resource_id(kInvalidServiceWorkerResourceId) { |
+ next_resource_id(kInvalidServiceWorkerResourceId), |
+ migration_state(ServiceWorkerDatabase::DISKCACHE_UNKNOWN_STATE) { |
} |
ServiceWorkerStorage::InitialData::~InitialData() { |
@@ -928,6 +930,8 @@ ServiceWorkerStorage::ServiceWorkerStorage( |
disk_cache_thread_(disk_cache_thread), |
quota_manager_proxy_(quota_manager_proxy), |
special_storage_policy_(special_storage_policy), |
+ disk_cache_migration_state_( |
+ ServiceWorkerDatabase::DISKCACHE_UNKNOWN_STATE), |
is_purge_pending_(false), |
has_checked_for_stale_resources_(false), |
weak_factory_(this) { |
@@ -948,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; |
@@ -987,6 +998,7 @@ void ServiceWorkerStorage::DidReadInitialData( |
next_version_id_ = data->next_version_id; |
next_resource_id_ = data->next_resource_id; |
registered_origins_.swap(data->origins); |
+ disk_cache_migration_state_ = data->migration_state; |
state_ = INITIALIZED; |
} else { |
DVLOG(2) << "Failed to initialize: " |
@@ -1104,6 +1116,16 @@ void ServiceWorkerStorage::ReturnFoundRegistration( |
CompleteFindNow(registration, SERVICE_WORKER_OK, callback); |
} |
+void ServiceWorkerStorage::DidWriteDatabase( |
+ const base::Closure& continuation, |
+ ServiceWorkerDatabase::Status status) { |
+ if (status != ServiceWorkerDatabase::STATUS_OK) { |
+ ScheduleDeleteAndStartOver(); |
+ return; |
+ } |
+ continuation.Run(); |
+} |
+ |
void ServiceWorkerStorage::DidGetRegistrations( |
const GetRegistrationsCallback& callback, |
RegistrationList* registration_data_list, |
@@ -1407,10 +1429,11 @@ 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()) { |
@@ -1420,17 +1443,111 @@ ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() { |
return disk_cache_.get(); |
} |
+ switch (disk_cache_migration_state_) { |
michaeln
2015/06/12 20:47:58
if (migration_needed_)
start it; // when its do
nhiroki
2015/06/15 16:43:27
Done.
|
+ case ServiceWorkerDatabase::DISKCACHE_NOT_USED: { |
+ // Defer the start of initialization until a migration state is updated. |
+ disk_cache_->set_is_waiting_to_initialize(true); |
+ base::Closure continuation = |
+ base::Bind(&ServiceWorkerStorage::InitializeDiskCache, |
+ weak_factory_.GetWeakPtr()); |
+ PostTaskAndReplyWithResult( |
+ database_task_manager_->GetTaskRunner(), FROM_HERE, |
+ base::Bind(&ServiceWorkerDatabase::WriteDiskCacheMigrationState, |
+ base::Unretained(database_.get()), |
+ ServiceWorkerDatabase::DISKCACHE_MIGRATED), |
+ base::Bind(&ServiceWorkerStorage::DidWriteDatabase, |
+ weak_factory_.GetWeakPtr(), continuation)); |
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult( |
+ ServiceWorkerMetrics::MIGRATION_NOT_NECESSARY); |
+ break; |
+ } |
+ case ServiceWorkerDatabase::DISKCACHE_NEEDS_TO_MIGRATE: { |
+ // Defer the start of initialization until a migration is complete. |
+ disk_cache_->set_is_waiting_to_initialize(true); |
+ DCHECK(!disk_cache_migrator_); |
+ disk_cache_migrator_.reset(new ServiceWorkerDiskCacheMigrator( |
+ GetOldDiskCachePath(), GetDiskCachePath(), kMaxDiskCacheSize, |
+ disk_cache_thread_)); |
+ disk_cache_migrator_->Start( |
+ base::Bind(&ServiceWorkerStorage::DidMigrateDiskCache, |
+ weak_factory_.GetWeakPtr())); |
+ break; |
+ } |
+ case ServiceWorkerDatabase::DISKCACHE_NEEDS_TO_DELETE_OLD: { |
+ // A migration was complete, but an old diskcache still exists. |
+ base::Closure continuation = base::Bind(&base::DoNothing); |
+ BrowserThread::PostAfterStartupTask( |
+ FROM_HERE, database_task_manager_->GetTaskRunner(), |
+ base::Bind(&DeleteOldDiskCacheInDB, database_.get(), |
+ base::ThreadTaskRunnerHandle::Get(), GetOldDiskCachePath(), |
+ base::Bind(&ServiceWorkerStorage::DidWriteDatabase, |
+ weak_factory_.GetWeakPtr(), continuation))); |
+ |
+ // Don't have to wait for the completion of deleting the old diskcache. |
+ // Immediately continue to initialize. |
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult( |
+ ServiceWorkerMetrics::MIGRATION_NOT_NECESSARY); |
+ InitializeDiskCache(); |
+ break; |
+ } |
+ case ServiceWorkerDatabase::DISKCACHE_MIGRATED: { |
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult( |
+ ServiceWorkerMetrics::MIGRATION_NOT_NECESSARY); |
+ InitializeDiskCache(); |
+ break; |
+ } |
+ case ServiceWorkerDatabase::DISKCACHE_UNKNOWN_STATE: { |
+ NOTREACHED(); |
+ break; |
+ } |
+ } |
+ |
+ return disk_cache_.get(); |
+} |
+ |
+void ServiceWorkerStorage::DidMigrateDiskCache(ServiceWorkerStatusCode status) { |
+ disk_cache_migrator_.reset(); |
+ |
+ if (status != SERVICE_WORKER_OK) { |
+ LOG(ERROR) << "Failed to migrate the diskcache: " |
+ << ServiceWorkerStatusToString(status); |
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult( |
+ ServiceWorkerMetrics::MIGRATION_ERROR_FAILED); |
+ |
+ // Give up a migration and recreate the whole storage. |
+ ScheduleDeleteAndStartOver(); |
+ |
+ // Delete the old diskcache. |
+ disk_cache_thread_->PostTask( |
+ FROM_HERE, base::Bind(base::IgnoreResult(&base::DeleteFile), |
+ GetOldDiskCachePath(), true)); |
+ return; |
+ } |
+ |
+ // The migration was complete, but an old diskcache still exists. |
+ base::Closure continuation = base::Bind(&base::DoNothing); |
+ BrowserThread::PostAfterStartupTask( |
+ FROM_HERE, database_task_manager_->GetTaskRunner(), |
+ base::Bind(&DeleteOldDiskCacheInDB, database_.get(), |
+ base::ThreadTaskRunnerHandle::Get(), GetOldDiskCachePath(), |
+ base::Bind(&ServiceWorkerStorage::DidWriteDatabase, |
+ weak_factory_.GetWeakPtr(), continuation))); |
+ |
+ // Don't have to wait for the completion of deleting the old diskcache. |
+ // Immediately continue to initialize. |
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult( |
+ ServiceWorkerMetrics::MIGRATION_OK); |
+ InitializeDiskCache(); |
+} |
+ |
+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) { |
@@ -1588,11 +1705,44 @@ void ServiceWorkerStorage::ReadInitialDataFromDB( |
return; |
} |
+ status = database->ReadDiskCacheMigrationState(&data->migration_state); |
+ if (status != ServiceWorkerDatabase::STATUS_OK) { |
+ original_task_runner->PostTask( |
+ FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); |
+ return; |
+ } |
+ |
status = database->GetOriginsWithRegistrations(&data->origins); |
original_task_runner->PostTask( |
FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); |
} |
+void ServiceWorkerStorage::DeleteOldDiskCacheInDB( |
+ ServiceWorkerDatabase* database, |
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
+ const base::FilePath& disk_cache_path, |
+ const DatabaseStatusCallback& callback) { |
+ DCHECK(database); |
+ ServiceWorkerDatabase::Status status = database->WriteDiskCacheMigrationState( |
+ ServiceWorkerDatabase::DISKCACHE_NEEDS_TO_DELETE_OLD); |
+ if (status != ServiceWorkerDatabase::STATUS_OK) { |
+ original_task_runner->PostTask(FROM_HERE, base::Bind(callback, status)); |
+ return; |
+ } |
+ |
+ if (!base::DeleteFile(disk_cache_path, true)) { |
michaeln
2015/06/12 20:47:58
it would be good to defer this part till 'aftersta
nhiroki
2015/06/15 16:43:27
Done.
|
+ // Ignore a failure. A migration state has already been recorded in the |
+ // database and a retry happens on the next diskcache initialization. |
+ original_task_runner->PostTask( |
+ FROM_HERE, base::Bind(callback, ServiceWorkerDatabase::STATUS_OK)); |
+ return; |
+ } |
+ |
+ status = database->WriteDiskCacheMigrationState( |
+ ServiceWorkerDatabase::DISKCACHE_MIGRATED); |
+ original_task_runner->PostTask(FROM_HERE, base::Bind(callback, status)); |
+} |
+ |
void ServiceWorkerStorage::DeleteRegistrationFromDB( |
ServiceWorkerDatabase* database, |
scoped_refptr<base::SequencedTaskRunner> original_task_runner, |