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