Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(466)

Side by Side Diff: chrome/browser/sync/engine/syncer_thread.h

Issue 214033: Use chrome/base synchronization primitives and threads instead of... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/sync/engine/syncapi.cc ('k') | chrome/browser/sync/engine/syncer_thread.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // A class to run the syncer on a thread. 5 // A class to run the syncer on a thread.
6 6 // This is the default implementation of SyncerThread whose Stop implementation
7 // does not support a timeout, but is greatly simplified.
7 #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_ 8 #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
8 #define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_ 9 #define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
9 10
10 #include <list> 11 #include <list>
11 #include <map> 12 #include <map>
12 #include <queue> 13 #include <queue>
13 #include <vector> 14 #include <vector>
14 15
15 #include "base/basictypes.h" 16 #include "base/basictypes.h"
17 #include "base/condition_variable.h"
18 #include "base/ref_counted.h"
16 #include "base/scoped_ptr.h" 19 #include "base/scoped_ptr.h"
20 #include "base/thread.h"
21 #include "base/time.h"
22 #include "base/waitable_event.h"
17 #include "chrome/browser/sync/engine/all_status.h" 23 #include "chrome/browser/sync/engine/all_status.h"
18 #include "chrome/browser/sync/engine/client_command_channel.h" 24 #include "chrome/browser/sync/engine/client_command_channel.h"
19 #include "chrome/browser/sync/util/event_sys-inl.h" 25 #include "chrome/browser/sync/util/event_sys-inl.h"
20 #include "chrome/browser/sync/util/pthread_helpers.h"
21 #include "testing/gtest/include/gtest/gtest_prod.h" // For FRIEND_TEST 26 #include "testing/gtest/include/gtest/gtest_prod.h" // For FRIEND_TEST
22 27
23 class EventListenerHookup; 28 class EventListenerHookup;
24 29
25 namespace syncable { 30 namespace syncable {
26 class DirectoryManager; 31 class DirectoryManager;
27 struct DirectoryManagerEvent; 32 struct DirectoryManagerEvent;
28 } 33 }
29 34
30 namespace browser_sync { 35 namespace browser_sync {
31 36
32 class ModelSafeWorker; 37 class ModelSafeWorker;
33 class ServerConnectionManager; 38 class ServerConnectionManager;
34 class Syncer; 39 class Syncer;
35 class TalkMediator; 40 class TalkMediator;
36 class URLFactory; 41 class URLFactory;
37 struct ServerConnectionEvent; 42 struct ServerConnectionEvent;
38 struct SyncerEvent; 43 struct SyncerEvent;
39 struct SyncerShutdownEvent; 44 struct SyncerShutdownEvent;
40 struct TalkMediatorEvent; 45 struct TalkMediatorEvent;
41 46
42 class SyncerThread { 47 class SyncerThreadFactory {
48 public:
49 // Creates a SyncerThread based on the default (or user-overridden)
50 // implementation. The thread does not start running until you call Start(),
51 // which will cause it to check-and-wait for certain conditions to be met
52 // (such as valid connection with Server established, syncable::Directory has
53 // been opened) before performing an intial sync with a server. It uses
54 // |connection_manager| to detect valid connections, and |mgr| to detect the
55 // opening of a Directory, which will cause it to create a Syncer object for
56 // said Directory, and assign |model_safe_worker| to it. |connection_manager|
57 // and |mgr| should outlive the SyncerThread. You must stop the thread by
58 // calling Stop before destroying the object. Stopping will first tear down
59 // the Syncer object, allowing it to finish work in progress, before joining
60 // the Stop-calling thread with the internal thread.
61 static SyncerThread* Create(ClientCommandChannel* command_channel,
62 syncable::DirectoryManager* mgr,
63 ServerConnectionManager* connection_manager, AllStatus* all_status,
64 ModelSafeWorker* model_safe_worker);
65 private:
66 DISALLOW_IMPLICIT_CONSTRUCTORS(SyncerThreadFactory);
67 };
68
69 class SyncerThread : public base::RefCountedThreadSafe<SyncerThread> {
43 FRIEND_TEST(SyncerThreadTest, CalculateSyncWaitTime); 70 FRIEND_TEST(SyncerThreadTest, CalculateSyncWaitTime);
44 FRIEND_TEST(SyncerThreadTest, CalculatePollingWaitTime); 71 FRIEND_TEST(SyncerThreadTest, CalculatePollingWaitTime);
45 72 FRIEND_TEST(SyncerThreadWithSyncerTest, Polling);
46 public: 73 FRIEND_TEST(SyncerThreadWithSyncerTest, Nudge);
47 friend class SyncerThreadTest; 74 friend class SyncerThreadWithSyncerTest;
48 75 friend class SyncerThreadFactory;
76 public:
49 enum NudgeSource { 77 enum NudgeSource {
50 kUnknown = 0, 78 kUnknown = 0,
51 kNotification, 79 kNotification,
52 kLocal, 80 kLocal,
53 kContinuation 81 kContinuation
54 }; 82 };
55
56 // Server can overwrite these values via client commands. 83 // Server can overwrite these values via client commands.
57 // Standard short poll. This is used when XMPP is off. 84 // Standard short poll. This is used when XMPP is off.
58 static const int kDefaultShortPollIntervalSeconds = 60; 85 static const int kDefaultShortPollIntervalSeconds = 60;
59 // Long poll is used when XMPP is on. 86 // Long poll is used when XMPP is on.
60 static const int kDefaultLongPollIntervalSeconds = 3600; 87 static const int kDefaultLongPollIntervalSeconds = 3600;
61 // 30 minutes by default. If exponential backoff kicks in, this is the 88 // 30 minutes by default. If exponential backoff kicks in, this is the
62 // longest possible poll interval. 89 // longest possible poll interval.
63 static const int kDefaultMaxPollIntervalMs = 30 * 60 * 1000; 90 static const int kDefaultMaxPollIntervalMs = 30 * 60 * 1000;
64 91
92 virtual ~SyncerThread();
93
94 virtual void WatchConnectionManager(ServerConnectionManager* conn_mgr);
95
96 // Starts a syncer thread.
97 // Returns true if it creates a thread or if there's currently a thread
98 // running and false otherwise.
99 virtual bool Start();
100
101 // Stop processing. |max_wait| doesn't do anything in this version.
102 virtual bool Stop(int max_wait);
103
104 // Nudges the syncer to sync with a delay specified. This API is for access
105 // from the SyncerThread's controller and will cause a mutex lock.
106 virtual bool NudgeSyncer(int milliseconds_from_now, NudgeSource source);
107
108 // Registers this thread to watch talk mediator events.
109 virtual void WatchTalkMediator(TalkMediator* talk_mediator);
110
111 virtual void WatchClientCommands(ClientCommandChannel* channel);
112
113 virtual SyncerEventChannel* channel();
114
115 protected:
116 SyncerThread(); // Necessary for temporary pthreads-based PIMPL impl.
65 SyncerThread(ClientCommandChannel* command_channel, 117 SyncerThread(ClientCommandChannel* command_channel,
66 syncable::DirectoryManager* mgr, 118 syncable::DirectoryManager* mgr,
67 ServerConnectionManager* connection_manager, AllStatus* all_status, 119 ServerConnectionManager* connection_manager, AllStatus* all_status,
68 ModelSafeWorker* model_safe_worker); 120 ModelSafeWorker* model_safe_worker);
69 ~SyncerThread(); 121 virtual void ThreadMain();
122 void ThreadMainLoop();
70 123
71 void WatchConnectionManager(ServerConnectionManager* conn_mgr); 124 virtual void SetConnected(bool connected) {
72 // Creates and starts a syncer thread. 125 DCHECK(!thread_.IsRunning());
73 // Returns true if it creates a thread or if there's currently a thread 126 vault_.connected_ = connected;
74 // running and false otherwise. 127 }
75 bool Start();
76 128
77 // Stop processing. A max wait of at least 2*server RTT time is recommended. 129 virtual void SetSyncerPollingInterval(base::TimeDelta interval) {
78 // returns true if we stopped, false otherwise. 130 // TODO(timsteele): Use TimeDelta internally.
79 bool Stop(int max_wait); 131 syncer_polling_interval_ = static_cast<int>(interval.InSeconds());
132 }
133 virtual void SetSyncerShortPollInterval(base::TimeDelta interval) {
134 // TODO(timsteele): Use TimeDelta internally.
135 syncer_short_poll_interval_seconds_ =
136 static_cast<int>(interval.InSeconds());
137 }
80 138
81 // Nudges the syncer to sync with a delay specified. This API is for access 139 // Needed to emulate the behavior of pthread_create, which synchronously
82 // from the SyncerThread's controller and will cause a mutex lock. 140 // started the thread and set the value of thread_running_ to true.
83 bool NudgeSyncer(int milliseconds_from_now, NudgeSource source); 141 // We can't quite match that because we asynchronously post the task,
142 // which opens a window for Stop to get called before the task actually
143 // makes it. To prevent this, we block Start() until we're sure it's ok.
144 base::WaitableEvent thread_main_started_;
84 145
85 // Registers this thread to watch talk mediator events. 146 // Handle of the running thread.
86 void WatchTalkMediator(TalkMediator* talk_mediator); 147 base::Thread thread_;
87 148
88 void WatchClientCommands(ClientCommandChannel* channel); 149 typedef std::pair<base::TimeTicks, NudgeSource> NudgeObject;
89 150
90 SyncerEventChannel* channel(); 151 struct IsTimeTicksGreater {
152 inline bool operator() (const NudgeObject& lhs, const NudgeObject& rhs) {
153 return lhs.first > rhs.first;
154 }
155 };
156
157 typedef std::priority_queue<NudgeObject, std::vector<NudgeObject>,
158 IsTimeTicksGreater> NudgeQueue;
159
160 // Fields that are modified / accessed by multiple threads go in this struct
161 // for clarity and explicitness.
162 struct ProtectedFields {
163 // False when we want to stop the thread.
164 bool stop_syncer_thread_;
165
166 Syncer* syncer_;
167
168 // State of the server connection.
169 bool connected_;
170
171 // A queue of all scheduled nudges. One insertion for every call to
172 // NudgeQueue().
173 NudgeQueue nudge_queue_;
174
175 ProtectedFields()
176 : stop_syncer_thread_(false), syncer_(NULL), connected_(false) {}
177 } vault_;
178
179 // Gets signaled whenever a thread outside of the syncer thread changes a
180 // protected field in the vault_.
181 ConditionVariable vault_field_changed_;
182
183 // Used to lock everything in |vault_|.
184 Lock lock_;
91 185
92 private: 186 private:
93 // A few members to gate the rate at which we nudge the syncer. 187 // A few members to gate the rate at which we nudge the syncer.
94 enum { 188 enum {
95 kNudgeRateLimitCount = 6, 189 kNudgeRateLimitCount = 6,
96 kNudgeRateLimitTime = 180, 190 kNudgeRateLimitTime = 180,
97 }; 191 };
98 192
99 // A queue of all scheduled nudges. One insertion for every call to
100 // NudgeQueue().
101 typedef std::pair<timespec, NudgeSource> NudgeObject;
102
103 struct IsTimeSpecGreater {
104 inline bool operator() (const NudgeObject& lhs, const NudgeObject& rhs) {
105 return lhs.first.tv_sec == rhs.first.tv_sec ?
106 lhs.first.tv_nsec > rhs.first.tv_nsec :
107 lhs.first.tv_sec > rhs.first.tv_sec;
108 }
109 };
110
111 typedef std::priority_queue<NudgeObject, std::vector<NudgeObject>,
112 IsTimeSpecGreater> NudgeQueue;
113
114 // Threshold multipler for how long before user should be considered idle. 193 // Threshold multipler for how long before user should be considered idle.
115 static const int kPollBackoffThresholdMultiplier = 10; 194 static const int kPollBackoffThresholdMultiplier = 10;
116 195
117 friend void* RunSyncerThread(void* syncer_thread); 196 friend void* RunSyncerThread(void* syncer_thread);
118 void* Run(); 197 void* Run();
119 void HandleDirectoryManagerEvent( 198 void HandleDirectoryManagerEvent(
120 const syncable::DirectoryManagerEvent& event); 199 const syncable::DirectoryManagerEvent& event);
121 void HandleSyncerEvent(const SyncerEvent& event); 200 void HandleSyncerEvent(const SyncerEvent& event);
122 void HandleClientCommand(ClientCommandChannel::EventType event); 201 void HandleClientCommand(ClientCommandChannel::EventType event);
123 202
124 void HandleServerConnectionEvent(const ServerConnectionEvent& event); 203 void HandleServerConnectionEvent(const ServerConnectionEvent& event);
125 204
126 void HandleTalkMediatorEvent(const TalkMediatorEvent& event); 205 void HandleTalkMediatorEvent(const TalkMediatorEvent& event);
127 206
128 void* ThreadMain();
129 void ThreadMainLoop();
130
131 void SyncMain(Syncer* syncer); 207 void SyncMain(Syncer* syncer);
132 208
133 // Calculates the next sync wait time in seconds. last_poll_wait is the time 209 // Calculates the next sync wait time in seconds. last_poll_wait is the time
134 // duration of the previous polling timeout which was used. 210 // duration of the previous polling timeout which was used.
135 // user_idle_milliseconds is updated by this method, and is a report of the 211 // user_idle_milliseconds is updated by this method, and is a report of the
136 // full amount of time since the last period of activity for the user. The 212 // full amount of time since the last period of activity for the user. The
137 // continue_sync_cycle parameter is used to determine whether or not we are 213 // continue_sync_cycle parameter is used to determine whether or not we are
138 // calculating a polling wait time that is a continuation of an sync cycle 214 // calculating a polling wait time that is a continuation of an sync cycle
139 // which terminated while the syncer still had work to do. 215 // which terminated while the syncer still had work to do.
140 int CalculatePollingWaitTime( 216 virtual int CalculatePollingWaitTime(
141 const AllStatus::Status& status, 217 const AllStatus::Status& status,
142 int last_poll_wait, // in s 218 int last_poll_wait, // in s
143 int* user_idle_milliseconds, 219 int* user_idle_milliseconds,
144 bool* continue_sync_cycle); 220 bool* continue_sync_cycle);
145 // Helper to above function, considers effect of user idle time. 221 // Helper to above function, considers effect of user idle time.
146 int CalculateSyncWaitTime(int last_wait, int user_idle_ms); 222 virtual int CalculateSyncWaitTime(int last_wait, int user_idle_ms);
147 223
148 // Sets the source value of the controlled syncer's updates_source value. 224 // Sets the source value of the controlled syncer's updates_source value.
149 // The initial sync boolean is updated if read as a sentinel. The following 225 // The initial sync boolean is updated if read as a sentinel. The following
150 // two methods work in concert to achieve this goal. 226 // two methods work in concert to achieve this goal.
151 void UpdateNudgeSource(const timespec& now, bool* continue_sync_cycle, 227 void UpdateNudgeSource(bool* continue_sync_cycle,
152 bool* initial_sync); 228 bool* initial_sync);
153 void SetUpdatesSource(bool nudged, NudgeSource nudge_source, 229 void SetUpdatesSource(bool nudged, NudgeSource nudge_source,
154 bool* initial_sync); 230 bool* initial_sync);
155 231
156 // For unit tests only. 232 // For unit tests only.
157 void DisableIdleDetection() { disable_idle_detection_ = true; } 233 virtual void DisableIdleDetection() { disable_idle_detection_ = true; }
158
159 // False when we want to stop the thread.
160 bool stop_syncer_thread_;
161
162 // We use one mutex for all members except the channel.
163 PThreadMutex mutex_;
164 typedef PThreadScopedLock<PThreadMutex> MutexLock;
165
166 // Handle of the running thread.
167 pthread_t thread_;
168 bool thread_running_;
169
170 // Gets signaled whenever a thread outside of the syncer thread changes a
171 // member variable.
172 PThreadCondVar changed_;
173
174 // State of the server connection.
175 bool connected_;
176 234
177 // State of the notification framework is tracked by these values. 235 // State of the notification framework is tracked by these values.
178 bool p2p_authenticated_; 236 bool p2p_authenticated_;
179 bool p2p_subscribed_; 237 bool p2p_subscribed_;
180 238
181 scoped_ptr<EventListenerHookup> client_command_hookup_; 239 scoped_ptr<EventListenerHookup> client_command_hookup_;
182 scoped_ptr<EventListenerHookup> conn_mgr_hookup_; 240 scoped_ptr<EventListenerHookup> conn_mgr_hookup_;
183 const AllStatus* allstatus_; 241 const AllStatus* allstatus_;
184 242
185 Syncer* syncer_;
186
187 syncable::DirectoryManager* dirman_; 243 syncable::DirectoryManager* dirman_;
188 ServerConnectionManager* scm_; 244 ServerConnectionManager* scm_;
189 245
190 // Modifiable versions of kDefaultLongPollIntervalSeconds which can be 246 // Modifiable versions of kDefaultLongPollIntervalSeconds which can be
191 // updated by the server. 247 // updated by the server.
192 int syncer_short_poll_interval_seconds_; 248 int syncer_short_poll_interval_seconds_;
193 int syncer_long_poll_interval_seconds_; 249 int syncer_long_poll_interval_seconds_;
194 250
195 // The time we wait between polls in seconds. This is used as lower bound on 251 // The time we wait between polls in seconds. This is used as lower bound on
196 // our wait time. Updated once per loop from the command line flag. 252 // our wait time. Updated once per loop from the command line flag.
197 int syncer_polling_interval_; 253 int syncer_polling_interval_;
198 254
199 // The upper bound on the nominal wait between polls in seconds. Note that 255 // The upper bound on the nominal wait between polls in seconds. Note that
200 // this bounds the "nominal" poll interval, while the the actual interval 256 // this bounds the "nominal" poll interval, while the the actual interval
201 // also takes previous failures into account. 257 // also takes previous failures into account.
202 int syncer_max_interval_; 258 int syncer_max_interval_;
203 259
204 scoped_ptr<SyncerEventChannel> syncer_event_channel_; 260 scoped_ptr<SyncerEventChannel> syncer_event_channel_;
205 261
206 // This causes syncer to start syncing ASAP. If the rate of requests is too 262 // This causes syncer to start syncing ASAP. If the rate of requests is too
207 // high the request will be silently dropped. mutex_ should be held when 263 // high the request will be silently dropped. mutex_ should be held when
208 // this is called. 264 // this is called.
209 void NudgeSyncImpl(int milliseconds_from_now, NudgeSource source); 265 void NudgeSyncImpl(int milliseconds_from_now, NudgeSource source);
210 266
211 NudgeQueue nudge_queue_;
212
213 scoped_ptr<EventListenerHookup> talk_mediator_hookup_; 267 scoped_ptr<EventListenerHookup> talk_mediator_hookup_;
214 ClientCommandChannel* const command_channel_; 268 ClientCommandChannel* const command_channel_;
215 scoped_ptr<EventListenerHookup> directory_manager_hookup_; 269 scoped_ptr<EventListenerHookup> directory_manager_hookup_;
216 scoped_ptr<EventListenerHookup> syncer_events_; 270 scoped_ptr<EventListenerHookup> syncer_events_;
217 271
218 // Handles any tasks that will result in model changes (modifications of 272 // Handles any tasks that will result in model changes (modifications of
219 // syncable::Entries). Pass this to the syncer created and managed by |this|. 273 // syncable::Entries). Pass this to the syncer created and managed by |this|.
220 // Only non-null in syncapi case. 274 // Only non-null in syncapi case.
221 scoped_ptr<ModelSafeWorker> model_safe_worker_; 275 scoped_ptr<ModelSafeWorker> model_safe_worker_;
222 276
223 // Useful for unit tests 277 // Useful for unit tests
224 bool disable_idle_detection_; 278 bool disable_idle_detection_;
225 279
226 DISALLOW_COPY_AND_ASSIGN(SyncerThread); 280 DISALLOW_COPY_AND_ASSIGN(SyncerThread);
227 }; 281 };
228 282
229 } // namespace browser_sync 283 } // namespace browser_sync
230 284
231 #endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_ 285 #endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/syncapi.cc ('k') | chrome/browser/sync/engine/syncer_thread.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698