| Index: chrome/browser/sync_file_system/local/local_file_sync_context.cc
|
| diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context.cc b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
|
| index 227ce74a0bde8414ea6a9c274b659aaaa4e5741f..8e45cf2e24a32d9ca3f3e38c2e2634b3a063f0ee 100644
|
| --- a/chrome/browser/sync_file_system/local/local_file_sync_context.cc
|
| +++ b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
|
| @@ -5,6 +5,7 @@
|
| #include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
|
|
|
| #include "base/bind.h"
|
| +#include "base/file_util.h"
|
| #include "base/location.h"
|
| #include "base/platform_file.h"
|
| #include "base/single_thread_task_runner.h"
|
| @@ -21,6 +22,7 @@
|
| #include "webkit/browser/fileapi/file_system_file_util.h"
|
| #include "webkit/browser/fileapi/file_system_operation_context.h"
|
| #include "webkit/browser/fileapi/file_system_operation_runner.h"
|
| +#include "webkit/common/blob/scoped_file.h"
|
| #include "webkit/common/fileapi/file_system_util.h"
|
|
|
| using fileapi::FileSystemContext;
|
| @@ -37,12 +39,16 @@ const int kMaxConcurrentSyncableOperation = 3;
|
| const int kNotifyChangesDurationInSec = 1;
|
| const int kMaxURLsToFetchForLocalSync = 5;
|
|
|
| +const base::FilePath::CharType kSnapshotDir[] = FILE_PATH_LITERAL("snapshots");
|
| +
|
| } // namespace
|
|
|
| LocalFileSyncContext::LocalFileSyncContext(
|
| + const base::FilePath& base_path,
|
| base::SingleThreadTaskRunner* ui_task_runner,
|
| base::SingleThreadTaskRunner* io_task_runner)
|
| - : ui_task_runner_(ui_task_runner),
|
| + : local_base_path_(base_path.Append(FILE_PATH_LITERAL("local"))),
|
| + ui_task_runner_(ui_task_runner),
|
| io_task_runner_(io_task_runner),
|
| shutdown_on_ui_(false),
|
| mock_notify_changes_duration_in_sec_(-1) {
|
| @@ -159,6 +165,12 @@ void LocalFileSyncContext::CommitChangeStatusForURL(
|
| backend->change_tracker()->RemoveMirrorAndCommitChangesForURL(url);
|
| }
|
|
|
| + // We've been keeping it in writing mode, so clear the writing counter
|
| + // to unblock sync activities.
|
| + io_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&LocalFileSyncContext::EndWritingOnIOThread,
|
| + this, url));
|
| +
|
| // Call the completion callback on UI thread.
|
| ui_task_runner_->PostTask(FROM_HERE, done_callback);
|
| }
|
| @@ -167,8 +179,8 @@ void LocalFileSyncContext::ClearSyncFlagForURL(const FileSystemURL& url) {
|
| // This is initially called on UI thread and to be relayed to IO thread.
|
| io_task_runner_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&LocalFileSyncContext::EnableWritingOnIOThread,
|
| - this, url, true /* may_have_updates */));
|
| + base::Bind(&LocalFileSyncContext::ClearSyncFlagOnIOThread,
|
| + this, url, false /* keep_url_in_writing */));
|
| }
|
|
|
| void LocalFileSyncContext::PrepareForSync(
|
| @@ -552,6 +564,10 @@ SyncStatusCode LocalFileSyncContext::InitializeChangeTrackerOnFileThread(
|
| iter != urls.end(); ++iter) {
|
| origins_with_changes->insert(iter->origin());
|
| }
|
| +
|
| + // Creates snapshot directory.
|
| + file_util::CreateDirectory(local_base_path_.Append(kSnapshotDir));
|
| +
|
| return status;
|
| }
|
|
|
| @@ -635,13 +651,14 @@ void LocalFileSyncContext::TryPrepareForLocalSync(
|
| DCHECK(urls);
|
|
|
| if (shutdown_on_ui_) {
|
| - callback.Run(SYNC_STATUS_ABORT, LocalFileSyncInfo());
|
| + callback.Run(SYNC_STATUS_ABORT, LocalFileSyncInfo(),
|
| + scoped_ptr<webkit_blob::ScopedFile>());
|
| return;
|
| }
|
|
|
| if (urls->empty()) {
|
| - callback.Run(SYNC_STATUS_NO_CHANGE_TO_SYNC,
|
| - LocalFileSyncInfo());
|
| + callback.Run(SYNC_STATUS_NO_CHANGE_TO_SYNC, LocalFileSyncInfo(),
|
| + scoped_ptr<webkit_blob::ScopedFile>());
|
| return;
|
| }
|
|
|
| @@ -650,9 +667,8 @@ void LocalFileSyncContext::TryPrepareForLocalSync(
|
| std::deque<FileSystemURL>* remaining = new std::deque<FileSystemURL>;
|
| remaining->swap(*urls);
|
|
|
| - // TODO(kinuko): Call PrepareForSync with SYNC_SNAPSHOT when it becomes ready.
|
| PrepareForSync(
|
| - file_system_context, url, SYNC_EXCLUSIVE,
|
| + file_system_context, url, SYNC_SNAPSHOT,
|
| base::Bind(&LocalFileSyncContext::DidTryPrepareForLocalSync,
|
| this, make_scoped_refptr(file_system_context),
|
| base::Owned(remaining), callback));
|
| @@ -663,10 +679,11 @@ void LocalFileSyncContext::DidTryPrepareForLocalSync(
|
| std::deque<FileSystemURL>* remaining_urls,
|
| const LocalFileSyncInfoCallback& callback,
|
| SyncStatusCode status,
|
| - const LocalFileSyncInfo& sync_file_info) {
|
| + const LocalFileSyncInfo& sync_file_info,
|
| + scoped_ptr<webkit_blob::ScopedFile> snapshot) {
|
| DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| if (status != SYNC_STATUS_FILE_BUSY) {
|
| - callback.Run(status, sync_file_info);
|
| + callback.Run(status, sync_file_info, snapshot.Pass());
|
| return;
|
| }
|
| // Recursively call TryPrepareForLocalSync with remaining_urls.
|
| @@ -685,7 +702,8 @@ void LocalFileSyncContext::DidGetWritingStatusForSync(
|
| RunsTasksOnCurrentThread()) {
|
| DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| if (shutdown_on_ui_) {
|
| - callback.Run(SYNC_STATUS_ABORT, LocalFileSyncInfo());
|
| + callback.Run(SYNC_STATUS_ABORT, LocalFileSyncInfo(),
|
| + scoped_ptr<webkit_blob::ScopedFile>());
|
| return;
|
| }
|
| file_system_context->default_file_task_runner()->PostTask(
|
| @@ -715,9 +733,21 @@ void LocalFileSyncContext::DidGetWritingStatusForSync(
|
| url,
|
| &file_info,
|
| &platform_path);
|
| +
|
| + scoped_ptr<webkit_blob::ScopedFile> snapshot;
|
| if (file_error == base::PLATFORM_FILE_OK && sync_mode == SYNC_SNAPSHOT) {
|
| - // TODO(kinuko): creates a snapshot file.
|
| + base::FilePath snapshot_path;
|
| + file_util::CreateTemporaryFileInDir(local_base_path_.Append(kSnapshotDir),
|
| + &snapshot_path);
|
| + if (base::CopyFile(platform_path, snapshot_path)) {
|
| + platform_path = snapshot_path;
|
| + snapshot.reset(new webkit_blob::ScopedFile(
|
| + snapshot_path,
|
| + webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
|
| + file_system_context->default_file_task_runner()));
|
| + }
|
| }
|
| +
|
| if (status == SYNC_STATUS_OK &&
|
| file_error != base::PLATFORM_FILE_OK &&
|
| file_error != base::PLATFORM_FILE_ERROR_NOT_FOUND)
|
| @@ -731,7 +761,6 @@ void LocalFileSyncContext::DidGetWritingStatusForSync(
|
| else if (file_info.is_directory)
|
| file_type = SYNC_FILE_TYPE_DIRECTORY;
|
|
|
| - // TODO(kinuko): returns the snapshot file path if snapshot is available.
|
| LocalFileSyncInfo sync_file_info;
|
| sync_file_info.url = url;
|
| sync_file_info.local_file_path = platform_path;
|
| @@ -749,21 +778,24 @@ void LocalFileSyncContext::DidGetWritingStatusForSync(
|
| }
|
|
|
| // 'Unlock' the file if sync_mode is not SYNC_EXCLUSIVE.
|
| + // (But keep it in writing status so that no other sync starts on
|
| + // the same URL)
|
| if (sync_mode != SYNC_EXCLUSIVE) {
|
| io_task_runner_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&LocalFileSyncContext::EnableWritingOnIOThread,
|
| - this, url, false /* may_have_updates */));
|
| + base::Bind(&LocalFileSyncContext::ClearSyncFlagOnIOThread,
|
| + this, url, true /* keep_url_in_writing */));
|
| }
|
| }
|
|
|
| ui_task_runner_->PostTask(FROM_HERE,
|
| - base::Bind(callback, status, sync_file_info));
|
| + base::Bind(callback, status, sync_file_info,
|
| + base::Passed(&snapshot)));
|
| }
|
|
|
| -void LocalFileSyncContext::EnableWritingOnIOThread(
|
| +void LocalFileSyncContext::ClearSyncFlagOnIOThread(
|
| const FileSystemURL& url,
|
| - bool may_have_updates) {
|
| + bool keep_url_in_writing) {
|
| DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
|
| if (!sync_status()) {
|
| // The service might have been shut down.
|
| @@ -771,14 +803,27 @@ void LocalFileSyncContext::EnableWritingOnIOThread(
|
| }
|
| sync_status()->EndSyncing(url);
|
|
|
| - if (!may_have_updates)
|
| + if (keep_url_in_writing) {
|
| + // The caller will hold shared lock on this one.
|
| + sync_status()->StartWriting(url);
|
| return;
|
| + }
|
|
|
| // Since a sync has finished the number of changes must have been updated.
|
| origins_with_pending_changes_.insert(url.origin());
|
| ScheduleNotifyChangesUpdatedOnIOThread();
|
| }
|
|
|
| +void LocalFileSyncContext::EndWritingOnIOThread(
|
| + const FileSystemURL& url) {
|
| + DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
|
| + if (!sync_status()) {
|
| + // The service might have been shut down.
|
| + return;
|
| + }
|
| + sync_status()->EndWriting(url);
|
| +}
|
| +
|
| void LocalFileSyncContext::DidApplyRemoteChange(
|
| const FileSystemURL& url,
|
| const SyncStatusCallback& callback_on_ui,
|
| @@ -788,7 +833,7 @@ void LocalFileSyncContext::DidApplyRemoteChange(
|
| FROM_HERE,
|
| base::Bind(callback_on_ui,
|
| PlatformFileErrorToSyncStatusCode(file_error)));
|
| - EnableWritingOnIOThread(url, true /* may_have_updates */);
|
| + ClearSyncFlagOnIOThread(url, false /* keep_url_in_writing */);
|
| }
|
|
|
| void LocalFileSyncContext::DidGetFileMetadata(
|
|
|