diff options
-rw-r--r-- | chrome/browser/sync/engine/model_safe_worker.h | 5 | ||||
-rw-r--r-- | chrome/browser/sync/engine/syncer_thread_unittest.cc | 4 | ||||
-rwxr-xr-x | chrome/browser/sync/engine/syncer_unittest.cc | 4 | ||||
-rw-r--r-- | chrome/browser/sync/glue/database_model_worker.cc | 36 | ||||
-rw-r--r-- | chrome/browser/sync/glue/database_model_worker.h | 33 | ||||
-rw-r--r-- | chrome/browser/sync/glue/database_model_worker_unittest.cc | 90 | ||||
-rw-r--r-- | chrome/browser/sync/glue/sync_backend_host.cc | 16 | ||||
-rw-r--r-- | chrome/browser/sync/glue/sync_backend_host.h | 9 | ||||
-rw-r--r-- | chrome/browser/sync/glue/ui_model_worker_unittest.cc | 9 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 2 | ||||
-rwxr-xr-x | chrome/chrome_tests.gypi | 1 |
11 files changed, 185 insertions, 24 deletions
diff --git a/chrome/browser/sync/engine/model_safe_worker.h b/chrome/browser/sync/engine/model_safe_worker.h index c68218c..84a6a2f 100644 --- a/chrome/browser/sync/engine/model_safe_worker.h +++ b/chrome/browser/sync/engine/model_safe_worker.h @@ -8,6 +8,7 @@ #include <map> #include <vector> +#include "base/ref_counted.h" #include "chrome/browser/sync/syncable/model_type.h" #include "chrome/browser/sync/util/closure.h" #include "chrome/browser/sync/util/sync_types.h" @@ -30,7 +31,7 @@ enum ModelSafeGroup { // is guaranteed to be "model-safe", where "safe" refers to not allowing us to // cause an embedding application model to fall out of sync with the // syncable::Directory due to a race. -class ModelSafeWorker { +class ModelSafeWorker : public base::RefCountedThreadSafe<ModelSafeWorker> { public: ModelSafeWorker() { } virtual ~ModelSafeWorker() { } @@ -47,6 +48,8 @@ class ModelSafeWorker { } private: + friend class base::RefCountedThreadSafe<ModelSafeWorker>; + DISALLOW_COPY_AND_ASSIGN(ModelSafeWorker); }; diff --git a/chrome/browser/sync/engine/syncer_thread_unittest.cc b/chrome/browser/sync/engine/syncer_thread_unittest.cc index 314237a..f676cd6 100644 --- a/chrome/browser/sync/engine/syncer_thread_unittest.cc +++ b/chrome/browser/sync/engine/syncer_thread_unittest.cc @@ -35,7 +35,7 @@ class SyncerThreadWithSyncerTest : public testing::Test, connection_.reset(new MockConnectionManager(metadb_.manager(), metadb_.name())); allstatus_.reset(new AllStatus()); - worker_.reset(new ModelSafeWorker()); + worker_ = new ModelSafeWorker(); SyncSessionContext* context = new SyncSessionContext(connection_.get(), metadb_.manager(), this); syncer_thread_ = new SyncerThread(context, allstatus_.get()); @@ -85,7 +85,7 @@ class SyncerThreadWithSyncerTest : public testing::Test, scoped_ptr<MockConnectionManager> connection_; scoped_ptr<AllStatus> allstatus_; scoped_refptr<SyncerThread> syncer_thread_; - scoped_ptr<ModelSafeWorker> worker_; + scoped_refptr<ModelSafeWorker> worker_; scoped_ptr<EventListenerHookup> syncer_event_hookup_; base::WaitableEvent sync_cycle_ended_event_; DISALLOW_COPY_AND_ASSIGN(SyncerThreadWithSyncerTest); diff --git a/chrome/browser/sync/engine/syncer_unittest.cc b/chrome/browser/sync/engine/syncer_unittest.cc index 7d2aa38..2177e5b 100755 --- a/chrome/browser/sync/engine/syncer_unittest.cc +++ b/chrome/browser/sync/engine/syncer_unittest.cc @@ -166,7 +166,7 @@ class SyncerTest : public testing::Test, mock_server_.reset( new MockConnectionManager(syncdb_.manager(), syncdb_.name())); - worker_.reset(new ModelSafeWorker()); + worker_ = new ModelSafeWorker(); context_.reset(new SyncSessionContext(mock_server_.get(), syncdb_.manager(), this)); context_->set_account_name(syncdb_.name()); @@ -399,7 +399,7 @@ class SyncerTest : public testing::Test, std::set<SyncerEvent> syncer_events_; base::TimeDelta last_short_poll_interval_received_; base::TimeDelta last_long_poll_interval_received_; - scoped_ptr<ModelSafeWorker> worker_; + scoped_refptr<ModelSafeWorker> worker_; DISALLOW_COPY_AND_ASSIGN(SyncerTest); }; diff --git a/chrome/browser/sync/glue/database_model_worker.cc b/chrome/browser/sync/glue/database_model_worker.cc new file mode 100644 index 0000000..02516c7 --- /dev/null +++ b/chrome/browser/sync/glue/database_model_worker.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/sync/glue/database_model_worker.h" + +#include "chrome/browser/chrome_thread.h" + +using base::WaitableEvent; + +namespace browser_sync { + +void DatabaseModelWorker::DoWorkAndWaitUntilDone(Closure* work) { + if (ChromeThread::CurrentlyOn(ChromeThread::DB)) { + DLOG(WARNING) << "DoWorkAndWaitUntilDone called from the DB thread."; + work->Run(); + return; + } + WaitableEvent done(false, false); + if (!ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, + NewRunnableMethod(this, &DatabaseModelWorker::CallDoWorkAndSignalTask, + work, &done))) { + NOTREACHED() << "Failed to post task to the db thread."; + return; + } + done.Wait(); +} + +void DatabaseModelWorker::CallDoWorkAndSignalTask(Closure* work, + WaitableEvent* done) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); + work->Run(); + done->Signal(); +} + +} // namespace browser_sync diff --git a/chrome/browser/sync/glue/database_model_worker.h b/chrome/browser/sync/glue/database_model_worker.h new file mode 100644 index 0000000..64f53ed --- /dev/null +++ b/chrome/browser/sync/glue/database_model_worker.h @@ -0,0 +1,33 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SYNC_GLUE_DATABASE_MODEL_WORKER_H_ +#define CHROME_BROWSER_SYNC_GLUE_DATABASE_MODEL_WORKER_H_ + +#include "base/ref_counted.h" +#include "base/waitable_event.h" +#include "chrome/browser/sync/engine/model_safe_worker.h" +#include "chrome/browser/sync/util/closure.h" + +namespace browser_sync { + +// A ModelSafeWorker for database models (eg. autofill) that accepts requests +// from the syncapi that need to be fulfilled on the database thread. +class DatabaseModelWorker : public browser_sync::ModelSafeWorker { + public: + explicit DatabaseModelWorker() {} + + // ModelSafeWorker implementation. Called on syncapi SyncerThread. + void DoWorkAndWaitUntilDone(Closure* work); + virtual ModelSafeGroup GetModelSafeGroup() { return GROUP_DB; } + + private: + void CallDoWorkAndSignalTask(Closure* work, base::WaitableEvent* done); + + DISALLOW_COPY_AND_ASSIGN(DatabaseModelWorker); +}; + +} // namespace browser_sync + +#endif // CHROME_BROWSER_SYNC_GLUE_DATABASE_MODEL_WORKER_H_ diff --git a/chrome/browser/sync/glue/database_model_worker_unittest.cc b/chrome/browser/sync/glue/database_model_worker_unittest.cc new file mode 100644 index 0000000..69ad5ce --- /dev/null +++ b/chrome/browser/sync/glue/database_model_worker_unittest.cc @@ -0,0 +1,90 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/scoped_ptr.h" +#include "base/thread.h" +#include "base/timer.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/sync/glue/database_model_worker.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::OneShotTimer; +using base::Thread; +using base::TimeDelta; +using browser_sync::DatabaseModelWorker; + +namespace { + +class DatabaseModelWorkerTest : public testing::Test { + public: + DatabaseModelWorkerTest() : + did_do_work_(false), + db_thread_(ChromeThread::DB), + io_thread_(ChromeThread::IO, &io_loop_), + ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {}; + + bool did_do_work() { return did_do_work_; } + DatabaseModelWorker* worker() { return worker_.get(); } + OneShotTimer<DatabaseModelWorkerTest>* timer() { return &timer_; } + ScopedRunnableMethodFactory<DatabaseModelWorkerTest>* factory() { + return &method_factory_; + } + + // Schedule DoWork to be executed on the DB thread and have the test fail if + // DoWork hasn't executed within 10 seconds. + void ScheduleWork() { + scoped_ptr<Closure> c(NewCallback(this, &DatabaseModelWorkerTest::DoWork)); + timer()->Start(TimeDelta::FromSeconds(10), + this, &DatabaseModelWorkerTest::Timeout); + worker()->DoWorkAndWaitUntilDone(c.get()); + } + + // This is the work that will be scheduled to be done on the DB thread. + void DoWork() { + EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::DB)); + timer_.Stop(); // Stop the failure timer so the test succeeds. + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, new MessageLoop::QuitTask()); + did_do_work_ = true; + } + + // This will be called by the OneShotTimer and make the test fail unless + // DoWork is called first. + void Timeout() { + ADD_FAILURE() << "Timed out waiting for work to be done on the DB thread."; + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, new MessageLoop::QuitTask()); + } + + protected: + virtual void SetUp() { + db_thread_.Start(); + worker_ = new DatabaseModelWorker(); + } + + virtual void Teardown() { + worker_.release(); + db_thread_.Stop(); + } + + private: + bool did_do_work_; + scoped_refptr<DatabaseModelWorker> worker_; + OneShotTimer<DatabaseModelWorkerTest> timer_; + + ChromeThread db_thread_; + MessageLoopForIO io_loop_; + ChromeThread io_thread_; + + ScopedRunnableMethodFactory<DatabaseModelWorkerTest> method_factory_; +}; + +TEST_F(DatabaseModelWorkerTest, DoesWorkOnDatabaseThread) { + MessageLoop::current()->PostTask(FROM_HERE, factory()->NewRunnableMethod( + &DatabaseModelWorkerTest::ScheduleWork)); + MessageLoop::current()->Run(); + EXPECT_TRUE(did_do_work()); +} + +} // namespace diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc index 4446659..269c9e4 100644 --- a/chrome/browser/sync/glue/sync_backend_host.cc +++ b/chrome/browser/sync/glue/sync_backend_host.cc @@ -33,9 +33,6 @@ SyncBackendHost::SyncBackendHost(SyncFrontend* frontend, last_auth_error_(AuthError::None()) { // Init our registrar state. - for (int i = 0; i < MODEL_SAFE_GROUP_COUNT; i++) - registrar_.workers[i] = NULL; - for (int i = 0; i < syncable::MODEL_TYPE_COUNT; i++) { syncable::ModelType t(syncable::ModelTypeFromInt(i)); registrar_.routing_info[t] = GROUP_PASSIVE; // Init to syncing 0 types. @@ -46,9 +43,7 @@ SyncBackendHost::SyncBackendHost(SyncFrontend* frontend, SyncBackendHost::~SyncBackendHost() { DCHECK(!core_ && !frontend_) << "Must call Shutdown before destructor."; - - for (int i = 0; i < MODEL_SAFE_GROUP_COUNT; ++i) - DCHECK(registrar_.workers[i] == NULL); + DCHECK(registrar_.workers.empty()); } void SyncBackendHost::Initialize( @@ -115,8 +110,8 @@ void SyncBackendHost::Shutdown(bool sync_disabled) { core_thread_.Stop(); registrar_.routing_info.clear(); - delete registrar_.workers[GROUP_UI]; registrar_.workers[GROUP_UI] = NULL; + registrar_.workers.erase(GROUP_UI); frontend_ = NULL; core_ = NULL; // Releases reference to core_. } @@ -160,10 +155,9 @@ const GoogleServiceAuthError& SyncBackendHost::GetAuthError() const { void SyncBackendHost::GetWorkers(std::vector<ModelSafeWorker*>* out) { AutoLock lock(registrar_lock_); out->clear(); - for (int i = 0; i < MODEL_SAFE_GROUP_COUNT; i++) { - if (registrar_.workers[i] == NULL) - continue; - out->push_back(registrar_.workers[i]); + for (WorkerMap::const_iterator it = registrar_.workers.begin(); + it != registrar_.workers.end(); ++it) { + out->push_back((*it).second); } } diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index dd4db30..204dc6e 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -64,6 +64,8 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar { typedef sync_api::UserShare* UserShareHandle; typedef sync_api::SyncManager::Status::Summary StatusSummary; typedef sync_api::SyncManager::Status Status; + typedef std::map<ModelSafeGroup, + scoped_refptr<browser_sync::ModelSafeWorker> > WorkerMap; // Create a SyncBackendHost with a reference to the |frontend| that it serves // and communicates to via the SyncFrontend interface (on the same thread @@ -287,10 +289,9 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar { // longer needed because all types that get routed to it have been disabled // (from syncing). In that case, we'll destroy on demand *after* routing // any dependent types to GROUP_PASSIVE, so that the syncapi doesn't call - // into garbage. If an index is non-NULL, it means at least one ModelType - // that routes to that model safe group is being synced. - browser_sync::ModelSafeWorker* - workers[browser_sync::MODEL_SAFE_GROUP_COUNT]; + // into garbage. If a key is present, it means at least one ModelType that + // routes to that model safe group is being synced. + WorkerMap workers; browser_sync::ModelSafeRoutingInfo routing_info; } registrar_; diff --git a/chrome/browser/sync/glue/ui_model_worker_unittest.cc b/chrome/browser/sync/glue/ui_model_worker_unittest.cc index 85b02ab..e90033d 100644 --- a/chrome/browser/sync/glue/ui_model_worker_unittest.cc +++ b/chrome/browser/sync/glue/ui_model_worker_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/ref_counted.h" #include "base/thread.h" #include "chrome/browser/sync/engine/syncapi.h" #include "chrome/browser/sync/glue/ui_model_worker.h" @@ -47,7 +48,7 @@ class Syncer { worker_->DoWorkAndWaitUntilDone(c.get()); } private: - UIModelWorker* worker_; + scoped_refptr<UIModelWorker> worker_; DISALLOW_COPY_AND_ASSIGN(Syncer); }; @@ -92,7 +93,7 @@ class FakeSyncapiShutdownTask : public Task { } private: base::Thread* syncer_thread_; - UIModelWorker* worker_; + scoped_refptr<UIModelWorker> worker_; base::WaitableEvent** jobs_; size_t job_count_; base::WaitableEvent all_jobs_done_; @@ -106,7 +107,7 @@ class UIModelWorkerTest : public testing::Test { virtual void SetUp() { faux_syncer_thread_.Start(); - bmw_.reset(new UIModelWorker(&faux_ui_loop_)); + bmw_ = new UIModelWorker(&faux_ui_loop_); syncer_.reset(new Syncer(bmw_.get())); } @@ -119,7 +120,7 @@ class UIModelWorkerTest : public testing::Test { MessageLoop faux_ui_loop_; base::Thread faux_syncer_thread_; base::Thread faux_core_thread_; - scoped_ptr<UIModelWorker> bmw_; + scoped_refptr<UIModelWorker> bmw_; scoped_ptr<Syncer> syncer_; }; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 33976a9..0c0a453 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1594,6 +1594,8 @@ 'browser/sync/glue/bookmark_model_associator.cc', 'browser/sync/glue/change_processor.cc', 'browser/sync/glue/change_processor.h', + 'browser/sync/glue/database_model_worker.cc', + 'browser/sync/glue/database_model_worker.h', 'browser/sync/glue/http_bridge.cc', 'browser/sync/glue/http_bridge.h', 'browser/sync/glue/model_associator.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index a74e318..e77daa5 100755 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -797,6 +797,7 @@ 'browser/shell_integration_unittest.cc', 'browser/spellchecker_platform_engine_unittest.cc', 'browser/ssl/ssl_host_state_unittest.cc', + 'browser/sync/glue/database_model_worker_unittest.cc', 'browser/sync/glue/http_bridge_unittest.cc', 'browser/sync/glue/ui_model_worker_unittest.cc', 'browser/sync/profile_sync_service_unittest.cc', |