12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SYNC_INTERNAL_API_PUBLIC_ENGINE_MODEL_SAFE_WORKER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SYNC_INTERNAL_API_PUBLIC_ENGINE_MODEL_SAFE_WORKER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/synchronization/lock.h" 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/base/sync_export.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/base/model_type.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/util/syncer_error.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DictionaryValue; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(akalin): Move the non-exported functions in this file to a 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// private header. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef base::Callback<enum SyncerError(void)> WorkCallback; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ModelSafeGroup { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GROUP_PASSIVE = 0, // Models that are just "passively" being synced; e.g. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changes to these models don't need to be pushed to a 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // native model. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GROUP_UI, // Models that live on UI thread and are being synced. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GROUP_DB, // Models that live on DB thread and are being synced. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GROUP_FILE, // Models that live on FILE thread and are being synced. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GROUP_HISTORY, // Models that live on history thread and are being 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // synced. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GROUP_PASSWORD, // Models that live on the password thread and are 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // being synced. On windows and linux, this runs on the 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DB thread. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MODEL_SAFE_GROUP_COUNT, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SYNC_EXPORT std::string ModelSafeGroupToString(ModelSafeGroup group); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// WorkerLoopDestructionObserver is notified when the thread where it works 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// is going to be destroyed. 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class WorkerLoopDestructionObserver { 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void OnWorkerLoopDestroyed(ModelSafeGroup group) = 0; 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The Syncer uses a ModelSafeWorker for all tasks that could potentially 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modify syncable entries (e.g under a WriteTransaction). The ModelSafeWorker 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// only knows how to do one thing, and that is take some work (in a fully 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pre-bound callback) and have it performed (as in Run()) from a thread which 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is guaranteed to be "model-safe", where "safe" refers to not allowing us to 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cause an embedding application model to fall out of sync with the 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// syncable::Directory due to a race. Each ModelSafeWorker is affiliated with 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// a thread and does actual work on that thread. On the destruction of that 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// thread, the affiliated worker is effectively disabled to do more 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// work and will notify its observer. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SYNC_EXPORT ModelSafeWorker 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : public base::RefCountedThreadSafe<ModelSafeWorker>, 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public base::MessageLoop::DestructionObserver { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Subclass should implement to observe destruction of the loop where 71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // it actually does work. Called on UI thread immediately after worker is 72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // created. 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void RegisterForLoopDestruction() = 0; 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Called on sync loop from SyncBackendRegistrar::ShutDown(). Post task to 76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // working loop to stop observing loop destruction and invoke 77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // |unregister_done_callback|. 78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) virtual void UnregisterForLoopDestruction( 79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Callback<void(ModelSafeGroup)> unregister_done_callback); 80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // If not stopped, call DoWorkAndWaitUntilDoneImpl() to do work. Otherwise 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // return CANNOT_DO_WORK. 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SyncerError DoWorkAndWaitUntilDone(const WorkCallback& work); 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Soft stop worker by setting stopped_ flag. Called when sync is disabled 86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // or browser is shutting down. Called on UI loop. 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void RequestStop(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ModelSafeGroup GetModelSafeGroup() = 0; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // MessageLoop::DestructionObserver implementation. 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void WillDestroyCurrentMessageLoop() OVERRIDE; 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) friend class base::RefCountedThreadSafe<ModelSafeWorker>; 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) explicit ModelSafeWorker(WorkerLoopDestructionObserver* observer); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ModelSafeWorker(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Any time the Syncer performs model modifications (e.g employing a 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // WriteTransaction), it should be done by this method to ensure it is done 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // from a model-safe thread. 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual SyncerError DoWorkAndWaitUntilDoneImpl(const WorkCallback& work) = 0; 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::WaitableEvent* work_done_or_stopped() { 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return &work_done_or_stopped_; 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Return true if the worker was stopped. Thread safe. 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool IsStopped(); 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Subclass should call this in RegisterForLoopDestruction() from the loop 113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // where work is done. 114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void SetWorkingLoopToCurrent(); 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void UnregisterForLoopDestructionAsync( 118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Callback<void(ModelSafeGroup)> unregister_done_callback); 119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Whether the worker should/can do more work. Set when sync is disabled or 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // when the worker's working thread is to be destroyed. 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Lock stopped_lock_; 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool stopped_; 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Signal set when work on native thread is finished or when native thread 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // is to be destroyed so no more work can be done. 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::WaitableEvent work_done_or_stopped_; 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Notified when working thread of the worker is to be destroyed. 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WorkerLoopDestructionObserver* observer_; 131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Remember working loop for posting task to unregister destruction 133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // observation from sync thread when shutting down sync. 1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Lock working_loop_lock_; 135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::MessageLoop* working_loop_; 1365b892326406927b709cdaf6c384d4ababf456332Ben Murdoch 1375b892326406927b709cdaf6c384d4ababf456332Ben Murdoch // Callback passed with UnregisterForLoopDestruction. Normally this 1385b892326406927b709cdaf6c384d4ababf456332Ben Murdoch // remains unset/unused and is stored only if |working_loop_| isn't 1395b892326406927b709cdaf6c384d4ababf456332Ben Murdoch // initialized by the time UnregisterForLoopDestruction is called. 1405b892326406927b709cdaf6c384d4ababf456332Ben Murdoch // It is safe to copy and thread safe. 1415b892326406927b709cdaf6c384d4ababf456332Ben Murdoch // See comments in model_safe_worker.cc for more details. 1425b892326406927b709cdaf6c384d4ababf456332Ben Murdoch base::Callback<void(ModelSafeGroup)> unregister_done_callback_; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A map that details which ModelSafeGroup each ModelType 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// belongs to. Routing info can change in response to the user enabling / 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// disabling sync for certain types, as well as model association completions. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<ModelType, ModelSafeGroup> ModelSafeRoutingInfo; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Caller takes ownership of return value. 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SYNC_EXPORT_PRIVATE base::DictionaryValue* ModelSafeRoutingInfoToValue( 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelSafeRoutingInfo& routing_info); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SYNC_EXPORT std::string ModelSafeRoutingInfoToString( 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelSafeRoutingInfo& routing_info); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SYNC_EXPORT ModelTypeSet GetRoutingInfoTypes( 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelSafeRoutingInfo& routing_info); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SYNC_EXPORT ModelSafeGroup GetGroupForModelType( 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelType type, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelSafeRoutingInfo& routes); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncer 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // SYNC_INTERNAL_API_PUBLIC_ENGINE_MODEL_SAFE_WORKER_H_ 167