Home | History | Annotate | Download | only in sync_file_system
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/sync_file_system/sync_task_manager.h"
      6 
      7 #include "base/debug/trace_event.h"
      8 #include "base/location.h"
      9 #include "chrome/browser/sync_file_system/sync_file_metadata.h"
     10 
     11 using fileapi::FileSystemURL;
     12 
     13 namespace sync_file_system {
     14 
     15 class SyncTaskManager::TaskToken {
     16  public:
     17   explicit TaskToken(const base::WeakPtr<SyncTaskManager>& manager)
     18       : manager_(manager) {
     19   }
     20 
     21   void UpdateTask(const tracked_objects::Location& location) {
     22     location_ = location;
     23     DVLOG(2) << "Token updated: " << location_.ToString();
     24   }
     25 
     26   const tracked_objects::Location& location() const { return location_; }
     27 
     28   ~TaskToken() {
     29     // All task on Client must hold TaskToken instance to ensure
     30     // no other tasks are running. Also, as soon as a task finishes to work,
     31     // it must return the token to TaskManager.
     32     // Destroying a token with valid |client| indicates the token was
     33     // dropped by a task without returning.
     34     if (manager_.get() && manager_->client_.get()) {
     35       NOTREACHED()
     36           << "Unexpected TaskToken deletion from: " << location_.ToString();
     37 
     38       // Reinitializes the token.
     39       manager_->NotifyTaskDone(
     40           make_scoped_ptr(new TaskToken(manager_)),
     41           SyncStatusCallback(),
     42           SYNC_STATUS_OK);
     43     }
     44   }
     45 
     46  private:
     47   base::WeakPtr<SyncTaskManager> manager_;
     48   tracked_objects::Location location_;
     49 
     50   DISALLOW_COPY_AND_ASSIGN(TaskToken);
     51 };
     52 
     53 SyncTaskManager::SyncTaskManager(
     54     base::WeakPtr<Client> client)
     55     : client_(client),
     56       last_operation_status_(SYNC_STATUS_OK) {
     57 }
     58 
     59 SyncTaskManager::~SyncTaskManager() {
     60   client_.reset();
     61   token_.reset();
     62 }
     63 
     64 void SyncTaskManager::Initialize(SyncStatusCode status) {
     65   DCHECK(!token_);
     66   NotifyTaskDone(make_scoped_ptr(new TaskToken(AsWeakPtr())),
     67                  SyncStatusCallback(),
     68                  status);
     69 }
     70 
     71 void SyncTaskManager::ScheduleTask(
     72     const Task& task,
     73     const SyncStatusCallback& callback) {
     74   scoped_ptr<TaskToken> token(GetToken(FROM_HERE));
     75   if (!token) {
     76     pending_tasks_.push_back(base::Bind(
     77         &SyncTaskManager::ScheduleTask, AsWeakPtr(), task, callback));
     78     return;
     79   }
     80   task.Run(CreateCompletionCallback(token.Pass(), callback));
     81 }
     82 
     83 void SyncTaskManager::ScheduleTaskIfIdle(const Task& task) {
     84   scoped_ptr<TaskToken> token(GetToken(FROM_HERE));
     85   if (!token)
     86     return;
     87   task.Run(CreateCompletionCallback(token.Pass(), SyncStatusCallback()));
     88 }
     89 
     90 void SyncTaskManager::NotifyTaskDone(
     91     scoped_ptr<TaskToken> token,
     92     const SyncStatusCallback& callback,
     93     SyncStatusCode status) {
     94   DCHECK(token);
     95   last_operation_status_ = status;
     96   token_ = token.Pass();
     97   TRACE_EVENT_ASYNC_END0("Sync FileSystem", "GetToken", this);
     98 
     99   DVLOG(3) << "NotifyTaskDone: " << "finished with status=" << status
    100            << " (" << SyncStatusCodeToString(status) << ")"
    101            << " " << token_->location().ToString();
    102 
    103   client_->NotifyLastOperationStatus(last_operation_status_);
    104 
    105   if (!callback.is_null())
    106     callback.Run(status);
    107 
    108   if (!pending_tasks_.empty()) {
    109     base::Closure closure = pending_tasks_.front();
    110     pending_tasks_.pop_front();
    111     closure.Run();
    112     return;
    113   }
    114 
    115   client_->MaybeScheduleNextTask();
    116 }
    117 
    118 scoped_ptr<SyncTaskManager::TaskToken> SyncTaskManager::GetToken(
    119     const tracked_objects::Location& from_here) {
    120   if (!token_)
    121     return scoped_ptr<TaskToken>();
    122   TRACE_EVENT_ASYNC_BEGIN1("Sync FileSystem", "GetToken", this,
    123                            "where", from_here.ToString());
    124   token_->UpdateTask(from_here);
    125   return token_.Pass();
    126 }
    127 
    128 SyncStatusCallback SyncTaskManager::CreateCompletionCallback(
    129     scoped_ptr<TaskToken> token,
    130     const SyncStatusCallback& callback) {
    131   DCHECK(token);
    132   return base::Bind(&SyncTaskManager::NotifyTaskDone,
    133                     AsWeakPtr(), base::Passed(&token), callback);
    134 }
    135 
    136 }  // namespace sync_file_system
    137