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

Side by Side Diff: chrome/browser/sync/engine/net/server_connection_manager.cc

Issue 7731002: sync: make ServerConnectionManager explicitly NonThreadSafe (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: dcheck Created 9 years, 4 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 #include "chrome/browser/sync/engine/net/server_connection_manager.h" 5 #include "chrome/browser/sync/engine/net/server_connection_manager.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 8
9 #include <ostream> 9 #include <ostream>
10 #include <string> 10 #include <string>
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 int bytes_read = buffer_.length(); 125 int bytes_read = buffer_.length();
126 CHECK(length <= bytes_read); 126 CHECK(length <= bytes_read);
127 out_buffer->assign(buffer_); 127 out_buffer->assign(buffer_);
128 return bytes_read; 128 return bytes_read;
129 } 129 }
130 130
131 ScopedServerStatusWatcher::ScopedServerStatusWatcher( 131 ScopedServerStatusWatcher::ScopedServerStatusWatcher(
132 ServerConnectionManager* conn_mgr, HttpResponse* response) 132 ServerConnectionManager* conn_mgr, HttpResponse* response)
133 : conn_mgr_(conn_mgr), 133 : conn_mgr_(conn_mgr),
134 response_(response), 134 response_(response),
135 reset_count_(conn_mgr->reset_count_),
136 server_reachable_(conn_mgr->server_reachable_) { 135 server_reachable_(conn_mgr->server_reachable_) {
137 response->server_status = conn_mgr->server_status_; 136 response->server_status = conn_mgr->server_status_;
138 } 137 }
139 138
140 ScopedServerStatusWatcher::~ScopedServerStatusWatcher() { 139 ScopedServerStatusWatcher::~ScopedServerStatusWatcher() {
141 // Don't update the status of the connection if it has been reset.
142 // TODO(timsteele): Do we need this? Is this used by multiple threads?
143 if (reset_count_ != conn_mgr_->reset_count_)
144 return;
145 if (conn_mgr_->server_status_ != response_->server_status) { 140 if (conn_mgr_->server_status_ != response_->server_status) {
146 conn_mgr_->server_status_ = response_->server_status; 141 conn_mgr_->server_status_ = response_->server_status;
147 conn_mgr_->NotifyStatusChanged(); 142 conn_mgr_->NotifyStatusChanged();
148 return; 143 return;
149 } 144 }
150 // Notify if we've gone on or offline. 145 // Notify if we've gone on or offline.
151 if (server_reachable_ != conn_mgr_->server_reachable_) 146 if (server_reachable_ != conn_mgr_->server_reachable_)
152 conn_mgr_->NotifyStatusChanged(); 147 conn_mgr_->NotifyStatusChanged();
153 } 148 }
154 149
155 ServerConnectionManager::ServerConnectionManager( 150 ServerConnectionManager::ServerConnectionManager(
156 const string& server, 151 const string& server,
157 int port, 152 int port,
158 bool use_ssl, 153 bool use_ssl,
159 const string& user_agent) 154 const string& user_agent)
160 : sync_server_(server), 155 : sync_server_(server),
161 sync_server_port_(port), 156 sync_server_port_(port),
162 user_agent_(user_agent), 157 user_agent_(user_agent),
163 use_ssl_(use_ssl), 158 use_ssl_(use_ssl),
164 proto_sync_path_(kSyncServerSyncPath), 159 proto_sync_path_(kSyncServerSyncPath),
165 get_time_path_(kSyncServerGetTimePath), 160 get_time_path_(kSyncServerGetTimePath),
166 error_count_(0), 161 error_count_(0),
167 listeners_(new ObserverListThreadSafe<ServerConnectionEventListener>()),
168 server_status_(HttpResponse::NONE), 162 server_status_(HttpResponse::NONE),
169 server_reachable_(false), 163 server_reachable_(false) {
170 reset_count_(0),
171 terminate_all_io_(false) {
172 } 164 }
173 165
174 ServerConnectionManager::~ServerConnectionManager() { 166 ServerConnectionManager::~ServerConnectionManager() {
175 } 167 }
176 168
177 void ServerConnectionManager::NotifyStatusChanged() { 169 void ServerConnectionManager::NotifyStatusChanged() {
178 listeners_->Notify(&ServerConnectionEventListener::OnServerConnectionEvent, 170 DCHECK(CalledOnValidThread());
179 ServerConnectionEvent(server_status_, server_reachable_)); 171 FOR_EACH_OBSERVER(ServerConnectionEventListener, listeners_,
172 OnServerConnectionEvent(
173 ServerConnectionEvent(server_status_, server_reachable_)));
180 } 174 }
181 175
182 bool ServerConnectionManager::PostBufferWithCachedAuth( 176 bool ServerConnectionManager::PostBufferWithCachedAuth(
183 const PostBufferParams* params, ScopedServerStatusWatcher* watcher) { 177 const PostBufferParams* params, ScopedServerStatusWatcher* watcher) {
178 DCHECK(CalledOnValidThread());
184 string path = 179 string path =
185 MakeSyncServerPath(proto_sync_path(), MakeSyncQueryString(client_id_)); 180 MakeSyncServerPath(proto_sync_path(), MakeSyncQueryString(client_id_));
186 return PostBufferToPath(params, path, auth_token(), watcher); 181 return PostBufferToPath(params, path, auth_token(), watcher);
187 } 182 }
188 183
189 bool ServerConnectionManager::PostBufferToPath(const PostBufferParams* params, 184 bool ServerConnectionManager::PostBufferToPath(const PostBufferParams* params,
190 const string& path, const string& auth_token, 185 const string& path, const string& auth_token,
191 ScopedServerStatusWatcher* watcher) { 186 ScopedServerStatusWatcher* watcher) {
187 DCHECK(CalledOnValidThread());
192 DCHECK(watcher != NULL); 188 DCHECK(watcher != NULL);
193 189
194 if (auth_token.empty()) { 190 if (auth_token.empty()) {
195 params->response->server_status = HttpResponse::SYNC_AUTH_ERROR; 191 params->response->server_status = HttpResponse::SYNC_AUTH_ERROR;
196 return false; 192 return false;
197 } 193 }
198 194
199 scoped_ptr<Post> post(MakePost()); 195 scoped_ptr<Post> post(MakePost());
200 post->set_timing_info(params->timing_info); 196 post->set_timing_info(params->timing_info);
201 bool ok = post->Init(path.c_str(), auth_token, params->buffer_in, 197 bool ok = post->Init(path.c_str(), auth_token, params->buffer_in,
(...skipping 10 matching lines...) Expand all
212 208
213 if (post->ReadBufferResponse(params->buffer_out, params->response, true)) { 209 if (post->ReadBufferResponse(params->buffer_out, params->response, true)) {
214 params->response->server_status = HttpResponse::SERVER_CONNECTION_OK; 210 params->response->server_status = HttpResponse::SERVER_CONNECTION_OK;
215 server_reachable_ = true; 211 server_reachable_ = true;
216 return true; 212 return true;
217 } 213 }
218 return false; 214 return false;
219 } 215 }
220 216
221 bool ServerConnectionManager::CheckTime(int32* out_time) { 217 bool ServerConnectionManager::CheckTime(int32* out_time) {
218 DCHECK(CalledOnValidThread());
222 // Verify that the server really is reachable by checking the time. We need 219 // Verify that the server really is reachable by checking the time. We need
223 // to do this because of wifi interstitials that intercept messages from the 220 // to do this because of wifi interstitials that intercept messages from the
224 // client and return HTTP OK instead of a redirect. 221 // client and return HTTP OK instead of a redirect.
225 HttpResponse response; 222 HttpResponse response;
226 ScopedServerStatusWatcher watcher(this, &response); 223 ScopedServerStatusWatcher watcher(this, &response);
227 string post_body = "command=get_time"; 224 string post_body = "command=get_time";
228 225
229 // We only retry the CheckTime call if we were reset during the CheckTime 226 for (int i = 0 ; i < 3; i++) {
230 // attempt. We only try 3 times in case we're in a reset loop elsewhere.
231 base::subtle::AtomicWord start_reset_count = reset_count_ - 1;
232 for (int i = 0 ; i < 3 && start_reset_count != reset_count_ ; i++) {
233 start_reset_count = reset_count_;
234 scoped_ptr<Post> post(MakePost()); 227 scoped_ptr<Post> post(MakePost());
235 228
236 // Note that the server's get_time path doesn't require authentication. 229 // Note that the server's get_time path doesn't require authentication.
237 string get_time_path = 230 string get_time_path =
238 MakeSyncServerPath(kSyncServerGetTimePath, post_body); 231 MakeSyncServerPath(kSyncServerGetTimePath, post_body);
239 VLOG(1) << "Requesting get_time from:" << get_time_path; 232 VLOG(1) << "Requesting get_time from:" << get_time_path;
240 233
241 string blank_post_body; 234 string blank_post_body;
242 bool ok = post->Init(get_time_path.c_str(), blank_post_body, 235 bool ok = post->Init(get_time_path.c_str(), blank_post_body,
243 blank_post_body, &response); 236 blank_post_body, &response);
(...skipping 13 matching lines...) Expand all
257 } 250 }
258 *out_time = atoi(time_response.c_str()); 251 *out_time = atoi(time_response.c_str());
259 VLOG(1) << "Server was reachable."; 252 VLOG(1) << "Server was reachable.";
260 return true; 253 return true;
261 } 254 }
262 IncrementErrorCount(); 255 IncrementErrorCount();
263 return false; 256 return false;
264 } 257 }
265 258
266 bool ServerConnectionManager::IsServerReachable() { 259 bool ServerConnectionManager::IsServerReachable() {
260 DCHECK(CalledOnValidThread());
267 int32 time; 261 int32 time;
268 return CheckTime(&time); 262 return CheckTime(&time);
269 } 263 }
270 264
271 bool ServerConnectionManager::IsUserAuthenticated() { 265 bool ServerConnectionManager::IsUserAuthenticated() {
266 DCHECK(CalledOnValidThread());
272 return IsGoodReplyFromServer(server_status_); 267 return IsGoodReplyFromServer(server_status_);
273 } 268 }
274 269
275 bool ServerConnectionManager::CheckServerReachable() { 270 bool ServerConnectionManager::CheckServerReachable() {
271 DCHECK(CalledOnValidThread());
276 const bool server_is_reachable = IsServerReachable(); 272 const bool server_is_reachable = IsServerReachable();
277 if (server_reachable_ != server_is_reachable) { 273 if (server_reachable_ != server_is_reachable) {
278 server_reachable_ = server_is_reachable; 274 server_reachable_ = server_is_reachable;
279 NotifyStatusChanged(); 275 NotifyStatusChanged();
280 } 276 }
281 return server_is_reachable; 277 return server_is_reachable;
282 } 278 }
283 279
284 void ServerConnectionManager::kill() {
285 {
286 base::AutoLock lock(terminate_all_io_mutex_);
287 terminate_all_io_ = true;
288 }
289 }
290
291 void ServerConnectionManager::ResetConnection() {
292 base::subtle::NoBarrier_AtomicIncrement(&reset_count_, 1);
293 }
294
295 bool ServerConnectionManager::IncrementErrorCount() { 280 bool ServerConnectionManager::IncrementErrorCount() {
296 error_count_mutex_.Acquire(); 281 DCHECK(CalledOnValidThread());
297 error_count_++; 282 error_count_++;
298 283
299 if (error_count_ > kMaxConnectionErrorsBeforeReset) { 284 if (error_count_ > kMaxConnectionErrorsBeforeReset) {
300 error_count_ = 0; 285 error_count_ = 0;
301 286
302 // Be careful with this mutex because calling out to other methods can
303 // result in being called back. Unlock it here to prevent any potential
304 // double-acquisitions.
305 error_count_mutex_.Release();
306
307 if (!IsServerReachable()) { 287 if (!IsServerReachable()) {
308 LOG(WARNING) << "Too many connection failures, server is not reachable. " 288 LOG(WARNING) << "Too many connection failures, server is not reachable. "
309 << "Resetting connections."; 289 << "Resetting connections.";
310 ResetConnection();
311 } else { 290 } else {
312 LOG(WARNING) << "Multiple connection failures while server is reachable."; 291 LOG(WARNING) << "Multiple connection failures while server is reachable.";
313 } 292 }
314 return false; 293 return false;
315 } 294 }
316 295
317 error_count_mutex_.Release();
318 return true; 296 return true;
319 } 297 }
320 298
321 void ServerConnectionManager::SetServerParameters(const string& server_url, 299 void ServerConnectionManager::SetServerParameters(const string& server_url,
322 int port, 300 int port,
323 bool use_ssl) { 301 bool use_ssl) {
324 { 302 DCHECK(CalledOnValidThread());
325 base::AutoLock lock(server_parameters_mutex_); 303 sync_server_ = server_url;
326 sync_server_ = server_url; 304 sync_server_port_ = port;
327 sync_server_port_ = port; 305 use_ssl_ = use_ssl;
328 use_ssl_ = use_ssl;
329 }
330 } 306 }
331 307
332 // Returns the current server parameters in server_url and port. 308 // Returns the current server parameters in server_url and port.
333 void ServerConnectionManager::GetServerParameters(string* server_url, 309 void ServerConnectionManager::GetServerParameters(string* server_url,
334 int* port, 310 int* port,
335 bool* use_ssl) const { 311 bool* use_ssl) const {
336 base::AutoLock lock(server_parameters_mutex_);
337 if (server_url != NULL) 312 if (server_url != NULL)
338 *server_url = sync_server_; 313 *server_url = sync_server_;
339 if (port != NULL) 314 if (port != NULL)
340 *port = sync_server_port_; 315 *port = sync_server_port_;
341 if (use_ssl != NULL) 316 if (use_ssl != NULL)
342 *use_ssl = use_ssl_; 317 *use_ssl = use_ssl_;
343 } 318 }
344 319
345 std::string ServerConnectionManager::GetServerHost() const { 320 std::string ServerConnectionManager::GetServerHost() const {
346 string server_url; 321 string server_url;
347 int port; 322 int port;
348 bool use_ssl; 323 bool use_ssl;
349 GetServerParameters(&server_url, &port, &use_ssl); 324 GetServerParameters(&server_url, &port, &use_ssl);
350 // For unit tests. 325 // For unit tests.
351 if (server_url.empty()) 326 if (server_url.empty())
352 return std::string(); 327 return std::string();
353 // We just want the hostname, so we don't need to switch on use_ssl. 328 // We just want the hostname, so we don't need to switch on use_ssl.
354 server_url = "http://" + server_url; 329 server_url = "http://" + server_url;
355 GURL gurl(server_url); 330 GURL gurl(server_url);
356 DCHECK(gurl.is_valid()) << gurl; 331 DCHECK(gurl.is_valid()) << gurl;
357 return gurl.host(); 332 return gurl.host();
358 } 333 }
359 334
360 void ServerConnectionManager::AddListener( 335 void ServerConnectionManager::AddListener(
361 ServerConnectionEventListener* listener) { 336 ServerConnectionEventListener* listener) {
362 listeners_->AddObserver(listener); 337 DCHECK(CalledOnValidThread());
338 listeners_.AddObserver(listener);
363 } 339 }
364 340
365 void ServerConnectionManager::RemoveListener( 341 void ServerConnectionManager::RemoveListener(
366 ServerConnectionEventListener* listener) { 342 ServerConnectionEventListener* listener) {
367 listeners_->RemoveObserver(listener); 343 DCHECK(CalledOnValidThread());
344 listeners_.RemoveObserver(listener);
368 } 345 }
369 346
370 ServerConnectionManager::Post* ServerConnectionManager::MakePost() { 347 ServerConnectionManager::Post* ServerConnectionManager::MakePost() {
371 return NULL; // For testing. 348 return NULL; // For testing.
372 } 349 }
373 350
374 bool FillMessageWithShareDetails(sync_pb::ClientToServerMessage* csm, 351 bool FillMessageWithShareDetails(sync_pb::ClientToServerMessage* csm,
375 syncable::DirectoryManager* manager, 352 syncable::DirectoryManager* manager,
376 const std::string& share) { 353 const std::string& share) {
377 syncable::ScopedDirLookup dir(manager, share); 354 syncable::ScopedDirLookup dir(manager, share);
378 if (!dir.good()) { 355 if (!dir.good()) {
379 VLOG(1) << "Dir lookup failed"; 356 VLOG(1) << "Dir lookup failed";
380 return false; 357 return false;
381 } 358 }
382 string birthday = dir->store_birthday(); 359 string birthday = dir->store_birthday();
383 if (!birthday.empty()) 360 if (!birthday.empty())
384 csm->set_store_birthday(birthday); 361 csm->set_store_birthday(birthday);
385 csm->set_share(share); 362 csm->set_share(share);
386 return true; 363 return true;
387 } 364 }
388 365
389 std::ostream& operator << (std::ostream& s, const struct HttpResponse& hr) { 366 std::ostream& operator << (std::ostream& s, const struct HttpResponse& hr) {
390 s << " Response Code (bogus on error): " << hr.response_code; 367 s << " Response Code (bogus on error): " << hr.response_code;
391 s << " Content-Length (bogus on error): " << hr.content_length; 368 s << " Content-Length (bogus on error): " << hr.content_length;
392 s << " Server Status: " << hr.server_status; 369 s << " Server Status: " << hr.server_status;
393 return s; 370 return s;
394 } 371 }
395 372
396 } // namespace browser_sync 373 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/net/server_connection_manager.h ('k') | chrome/browser/sync/internal_api/sync_manager.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698