1 // Copyright (c) 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.
5 #include "sync/internal_api/public/engine/model_safe_worker.h"
8 #include "base/json/json_writer.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/values.h"
14 base::DictionaryValue
* ModelSafeRoutingInfoToValue(
15 const ModelSafeRoutingInfo
& routing_info
) {
16 base::DictionaryValue
* dict
= new base::DictionaryValue();
17 for (ModelSafeRoutingInfo::const_iterator it
= routing_info
.begin();
18 it
!= routing_info
.end(); ++it
) {
19 dict
->SetString(ModelTypeToString(it
->first
),
20 ModelSafeGroupToString(it
->second
));
25 std::string
ModelSafeRoutingInfoToString(
26 const ModelSafeRoutingInfo
& routing_info
) {
27 scoped_ptr
<base::DictionaryValue
> dict(
28 ModelSafeRoutingInfoToValue(routing_info
));
30 base::JSONWriter::Write(dict
.get(), &json
);
34 ModelTypeSet
GetRoutingInfoTypes(const ModelSafeRoutingInfo
& routing_info
) {
36 for (ModelSafeRoutingInfo::const_iterator it
= routing_info
.begin();
37 it
!= routing_info
.end(); ++it
) {
43 ModelSafeGroup
GetGroupForModelType(const ModelType type
,
44 const ModelSafeRoutingInfo
& routes
) {
45 ModelSafeRoutingInfo::const_iterator it
= routes
.find(type
);
46 if (it
== routes
.end()) {
47 if (type
!= UNSPECIFIED
&& type
!= TOP_LEVEL_FOLDER
)
48 DVLOG(1) << "Entry does not belong to active ModelSafeGroup!";
54 std::string
ModelSafeGroupToString(ModelSafeGroup group
) {
63 return "GROUP_HISTORY";
65 return "GROUP_PASSIVE";
67 return "GROUP_PASSWORD";
74 ModelSafeWorker::ModelSafeWorker(WorkerLoopDestructionObserver
* observer
)
76 work_done_or_stopped_(false, false),
79 working_loop_set_wait_(true, false) {}
81 ModelSafeWorker::~ModelSafeWorker() {}
83 void ModelSafeWorker::RequestStop() {
84 base::AutoLock
al(stopped_lock_
);
86 // Set stop flag but don't signal work_done_or_stopped_ to unblock sync loop
87 // because the worker may be working and depending on sync command object
88 // living on sync thread. his prevents any *further* tasks from being posted
89 // to worker threads (see DoWorkAndWaitUntilDone below), but note that one
90 // may already be posted.
94 SyncerError
ModelSafeWorker::DoWorkAndWaitUntilDone(const WorkCallback
& work
) {
96 base::AutoLock
al(stopped_lock_
);
98 return CANNOT_DO_WORK
;
100 CHECK(!work_done_or_stopped_
.IsSignaled());
103 return DoWorkAndWaitUntilDoneImpl(work
);
106 bool ModelSafeWorker::IsStopped() {
107 base::AutoLock
al(stopped_lock_
);
111 void ModelSafeWorker::WillDestroyCurrentMessageLoop() {
113 base::AutoLock
al(stopped_lock_
);
116 // Must signal to unblock syncer if it's waiting for a posted task to
117 // finish. At this point, all pending tasks posted to the loop have been
118 // destroyed (see MessageLoop::~MessageLoop). So syncer will be blocked
119 // indefinitely without signaling here.
120 work_done_or_stopped_
.Signal();
122 DVLOG(1) << ModelSafeGroupToString(GetModelSafeGroup())
123 << " worker stops on destruction of its working thread.";
127 base::AutoLock
l(working_loop_lock_
);
128 working_loop_
= NULL
;
132 observer_
->OnWorkerLoopDestroyed(GetModelSafeGroup());
135 void ModelSafeWorker::SetWorkingLoopToCurrent() {
136 base::AutoLock
l(working_loop_lock_
);
137 DCHECK(!working_loop_
);
138 working_loop_
= base::MessageLoop::current();
139 working_loop_set_wait_
.Signal();
142 void ModelSafeWorker::UnregisterForLoopDestruction(
143 base::Callback
<void(ModelSafeGroup
)> unregister_done_callback
) {
144 // Ok to wait until |working_loop_| is set because this is called on sync
146 working_loop_set_wait_
.Wait();
149 base::AutoLock
l(working_loop_lock_
);
150 if (working_loop_
!= NULL
) {
151 // Should be called on sync loop.
152 DCHECK_NE(base::MessageLoop::current(), working_loop_
);
153 working_loop_
->PostTask(
155 base::Bind(&ModelSafeWorker::UnregisterForLoopDestructionAsync
,
156 this, unregister_done_callback
));
161 void ModelSafeWorker::UnregisterForLoopDestructionAsync(
162 base::Callback
<void(ModelSafeGroup
)> unregister_done_callback
) {
164 base::AutoLock
l(working_loop_lock_
);
167 DCHECK_EQ(base::MessageLoop::current(), working_loop_
);
171 base::MessageLoop::current()->RemoveDestructionObserver(this);
172 unregister_done_callback
.Run(GetModelSafeGroup());
175 } // namespace syncer