Home | History | Annotate | Download | only in engine
      1 // Copyright 2012 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 #ifndef SYNC_INTERNAL_API_PUBLIC_ENGINE_MODEL_SAFE_WORKER_H_
      6 #define SYNC_INTERNAL_API_PUBLIC_ENGINE_MODEL_SAFE_WORKER_H_
      7 
      8 #include <map>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/callback.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/message_loop/message_loop.h"
     15 #include "base/synchronization/lock.h"
     16 #include "base/synchronization/waitable_event.h"
     17 #include "sync/base/sync_export.h"
     18 #include "sync/internal_api/public/base/model_type.h"
     19 #include "sync/internal_api/public/util/syncer_error.h"
     20 
     21 namespace base {
     22 class DictionaryValue;
     23 }  // namespace
     24 
     25 namespace syncer {
     26 
     27 // TODO(akalin): Move the non-exported functions in this file to a
     28 // private header.
     29 
     30 typedef base::Callback<enum SyncerError(void)> WorkCallback;
     31 
     32 enum ModelSafeGroup {
     33   GROUP_PASSIVE = 0,   // Models that are just "passively" being synced; e.g.
     34                        // changes to these models don't need to be pushed to a
     35                        // native model.
     36   GROUP_UI,            // Models that live on UI thread and are being synced.
     37   GROUP_DB,            // Models that live on DB thread and are being synced.
     38   GROUP_FILE,          // Models that live on FILE thread and are being synced.
     39   GROUP_HISTORY,       // Models that live on history thread and are being
     40                        // synced.
     41   GROUP_PASSWORD,      // Models that live on the password thread and are
     42                        // being synced.  On windows and linux, this runs on the
     43                        // DB thread.
     44   MODEL_SAFE_GROUP_COUNT,
     45 };
     46 
     47 SYNC_EXPORT std::string ModelSafeGroupToString(ModelSafeGroup group);
     48 
     49 // WorkerLoopDestructionObserver is notified when the thread where it works
     50 // is going to be destroyed.
     51 class WorkerLoopDestructionObserver {
     52  public:
     53   virtual void OnWorkerLoopDestroyed(ModelSafeGroup group) = 0;
     54 };
     55 
     56 // The Syncer uses a ModelSafeWorker for all tasks that could potentially
     57 // modify syncable entries (e.g under a WriteTransaction). The ModelSafeWorker
     58 // only knows how to do one thing, and that is take some work (in a fully
     59 // pre-bound callback) and have it performed (as in Run()) from a thread which
     60 // is guaranteed to be "model-safe", where "safe" refers to not allowing us to
     61 // cause an embedding application model to fall out of sync with the
     62 // syncable::Directory due to a race. Each ModelSafeWorker is affiliated with
     63 // a thread and does actual work on that thread. On the destruction of that
     64 // thread, the affiliated worker is effectively disabled to do more
     65 // work and will notify its observer.
     66 class SYNC_EXPORT ModelSafeWorker
     67     : public base::RefCountedThreadSafe<ModelSafeWorker>,
     68       public base::MessageLoop::DestructionObserver {
     69  public:
     70   // Subclass should implement to observe destruction of the loop where
     71   // it actually does work. Called on UI thread immediately after worker is
     72   // created.
     73   virtual void RegisterForLoopDestruction() = 0;
     74 
     75   // Called on sync loop from SyncBackendRegistrar::ShutDown(). Post task to
     76   // working loop to stop observing loop destruction and invoke
     77   // |unregister_done_callback|.
     78   virtual void UnregisterForLoopDestruction(
     79       base::Callback<void(ModelSafeGroup)> unregister_done_callback);
     80 
     81   // If not stopped, call DoWorkAndWaitUntilDoneImpl() to do work. Otherwise
     82   // return CANNOT_DO_WORK.
     83   SyncerError DoWorkAndWaitUntilDone(const WorkCallback& work);
     84 
     85   // Soft stop worker by setting stopped_ flag. Called when sync is disabled
     86   // or browser is shutting down. Called on UI loop.
     87   virtual void RequestStop();
     88 
     89   virtual ModelSafeGroup GetModelSafeGroup() = 0;
     90 
     91   // MessageLoop::DestructionObserver implementation.
     92   virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
     93 
     94  protected:
     95   friend class base::RefCountedThreadSafe<ModelSafeWorker>;
     96 
     97   explicit ModelSafeWorker(WorkerLoopDestructionObserver* observer);
     98   virtual ~ModelSafeWorker();
     99 
    100   // Any time the Syncer performs model modifications (e.g employing a
    101   // WriteTransaction), it should be done by this method to ensure it is done
    102   // from a model-safe thread.
    103   virtual SyncerError DoWorkAndWaitUntilDoneImpl(const WorkCallback& work) = 0;
    104 
    105   base::WaitableEvent* work_done_or_stopped() {
    106     return &work_done_or_stopped_;
    107   }
    108 
    109   // Return true if the worker was stopped. Thread safe.
    110   bool IsStopped();
    111 
    112   // Subclass should call this in RegisterForLoopDestruction() from the loop
    113   // where work is done.
    114   void SetWorkingLoopToCurrent();
    115 
    116  private:
    117   void UnregisterForLoopDestructionAsync(
    118       base::Callback<void(ModelSafeGroup)> unregister_done_callback);
    119 
    120   // Whether the worker should/can do more work. Set when sync is disabled or
    121   // when the worker's working thread is to be destroyed.
    122   base::Lock stopped_lock_;
    123   bool stopped_;
    124 
    125   // Signal set when work on native thread is finished or when native thread
    126   // is to be destroyed so no more work can be done.
    127   base::WaitableEvent work_done_or_stopped_;
    128 
    129   // Notified when working thread of the worker is to be destroyed.
    130   WorkerLoopDestructionObserver* observer_;
    131 
    132   // Remember working loop for posting task to unregister destruction
    133   // observation from sync thread when shutting down sync.
    134   base::Lock working_loop_lock_;
    135   base::MessageLoop* working_loop_;
    136 
    137   // Callback passed with UnregisterForLoopDestruction. Normally this
    138   // remains unset/unused and is stored only if |working_loop_| isn't
    139   // initialized by the time UnregisterForLoopDestruction is called.
    140   // It is safe to copy and thread safe.
    141   // See comments in model_safe_worker.cc for more details.
    142   base::Callback<void(ModelSafeGroup)> unregister_done_callback_;
    143 };
    144 
    145 // A map that details which ModelSafeGroup each ModelType
    146 // belongs to.  Routing info can change in response to the user enabling /
    147 // disabling sync for certain types, as well as model association completions.
    148 typedef std::map<ModelType, ModelSafeGroup> ModelSafeRoutingInfo;
    149 
    150 // Caller takes ownership of return value.
    151 SYNC_EXPORT_PRIVATE base::DictionaryValue* ModelSafeRoutingInfoToValue(
    152     const ModelSafeRoutingInfo& routing_info);
    153 
    154 SYNC_EXPORT std::string ModelSafeRoutingInfoToString(
    155     const ModelSafeRoutingInfo& routing_info);
    156 
    157 SYNC_EXPORT ModelTypeSet GetRoutingInfoTypes(
    158     const ModelSafeRoutingInfo& routing_info);
    159 
    160 SYNC_EXPORT ModelSafeGroup GetGroupForModelType(
    161     const ModelType type,
    162     const ModelSafeRoutingInfo& routes);
    163 
    164 }  // namespace syncer
    165 
    166 #endif  // SYNC_INTERNAL_API_PUBLIC_ENGINE_MODEL_SAFE_WORKER_H_
    167