diff options
42 files changed, 909 insertions, 532 deletions
diff --git a/chrome/browser/sync/glue/invalidation_adapter.cc b/chrome/browser/sync/glue/invalidation_adapter.cc new file mode 100644 index 0000000..96aca500 --- /dev/null +++ b/chrome/browser/sync/glue/invalidation_adapter.cc @@ -0,0 +1,39 @@ +// Copyright 2014 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/invalidation_adapter.h" + +#include <string> + +namespace browser_sync { + +InvalidationAdapter::InvalidationAdapter( + const syncer::Invalidation& invalidation) + : invalidation_(invalidation) { +} + +InvalidationAdapter::~InvalidationAdapter() { +} + +bool InvalidationAdapter::IsUnknownVersion() const { + return invalidation_.is_unknown_version(); +} + +const std::string& InvalidationAdapter::GetPayload() const { + return invalidation_.payload(); +} + +int64 InvalidationAdapter::GetVersion() const { + return invalidation_.version(); +} + +void InvalidationAdapter::Acknowledge() { + invalidation_.Acknowledge(); +} + +void InvalidationAdapter::Drop() { + invalidation_.Drop(); +} + +} // namespace browser_sync diff --git a/chrome/browser/sync/glue/invalidation_adapter.h b/chrome/browser/sync/glue/invalidation_adapter.h new file mode 100644 index 0000000..509a872 --- /dev/null +++ b/chrome/browser/sync/glue/invalidation_adapter.h @@ -0,0 +1,32 @@ +// Copyright 2014 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_INVALIDATION_ADAPTER_H_ +#define CHROME_BROWSER_SYNC_GLUE_INVALIDATION_ADAPTER_H_ + +#include "sync/internal_api/public/base/invalidation.h" +#include "sync/internal_api/public/base/invalidation_interface.h" + +namespace browser_sync { + +// Wraps a syncer::Invalidation in the syncer::InvalidationInterface. +class InvalidationAdapter : public syncer::InvalidationInterface { + public: + explicit InvalidationAdapter(const syncer::Invalidation& invalidation); + virtual ~InvalidationAdapter(); + + // Implementation of InvalidationInterface. + virtual bool IsUnknownVersion() const OVERRIDE; + virtual const std::string& GetPayload() const OVERRIDE; + virtual int64 GetVersion() const OVERRIDE; + virtual void Acknowledge() OVERRIDE; + virtual void Drop() OVERRIDE; + + private: + syncer::Invalidation invalidation_; +}; + +} // namespace browser_sync + +#endif // CHROME_BROWSER_SYNC_GLUE_INVALIDATION_ADAPTER_H_ diff --git a/chrome/browser/sync/glue/sync_backend_host_core.cc b/chrome/browser/sync/glue/sync_backend_host_core.cc index 1b6a5ff..50f16cc 100644 --- a/chrome/browser/sync/glue/sync_backend_host_core.cc +++ b/chrome/browser/sync/glue/sync_backend_host_core.cc @@ -7,6 +7,7 @@ #include "base/file_util.h" #include "base/metrics/histogram.h" #include "chrome/browser/sync/glue/device_info.h" +#include "chrome/browser/sync/glue/invalidation_adapter.h" #include "chrome/browser/sync/glue/sync_backend_registrar.h" #include "chrome/browser/sync/glue/synced_device_tracker.h" #include "chrome/common/chrome_version_info.h" @@ -20,6 +21,8 @@ #include "sync/internal_api/public/sync_context_proxy.h" #include "sync/internal_api/public/sync_manager.h" #include "sync/internal_api/public/sync_manager_factory.h" +#include "sync/notifier/invalidation_util.h" +#include "sync/notifier/object_id_invalidation_map.h" // Helper macros to log with the syncer thread name; useful when there // are multiple syncers involved. @@ -369,7 +372,28 @@ void SyncBackendHostCore::DoOnInvalidatorStateChange( void SyncBackendHostCore::DoOnIncomingInvalidation( const syncer::ObjectIdInvalidationMap& invalidation_map) { DCHECK_EQ(base::MessageLoop::current(), sync_loop_); - sync_manager_->OnIncomingInvalidation(invalidation_map); + + syncer::ObjectIdSet ids = invalidation_map.GetObjectIds(); + for (syncer::ObjectIdSet::const_iterator ids_it = ids.begin(); + ids_it != ids.end(); + ++ids_it) { + syncer::ModelType type; + if (!NotificationTypeToRealModelType(ids_it->name(), &type)) { + DLOG(WARNING) << "Notification has invalid id: " + << syncer::ObjectIdToString(*ids_it); + } else { + syncer::SingleObjectInvalidationSet invalidation_set = + invalidation_map.ForObject(*ids_it); + for (syncer::SingleObjectInvalidationSet::const_iterator inv_it = + invalidation_set.begin(); + inv_it != invalidation_set.end(); + ++inv_it) { + scoped_ptr<syncer::InvalidationInterface> inv_adapter( + new InvalidationAdapter(*inv_it)); + sync_manager_->OnIncomingInvalidation(type, inv_adapter.Pass()); + } + } + } } void SyncBackendHostCore::DoInitialize( diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 0d03fa0..4c5ceab 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1320,6 +1320,8 @@ 'browser/sync/glue/frontend_data_type_controller.h', 'browser/sync/glue/history_model_worker.cc', 'browser/sync/glue/history_model_worker.h', + 'browser/sync/glue/invalidation_adapter.cc', + 'browser/sync/glue/invalidation_adapter.h', 'browser/sync/glue/non_frontend_data_type_controller.cc', 'browser/sync/glue/non_frontend_data_type_controller.h', 'browser/sync/glue/password_data_type_controller.cc', diff --git a/components/invalidation/sync_invalidation_listener_unittest.cc b/components/invalidation/sync_invalidation_listener_unittest.cc index f7ff05a..0399039 100644 --- a/components/invalidation/sync_invalidation_listener_unittest.cc +++ b/components/invalidation/sync_invalidation_listener_unittest.cc @@ -18,7 +18,6 @@ #include "google/cacheinvalidation/include/types.h" #include "jingle/notifier/listener/fake_push_client.h" #include "sync/internal_api/public/util/weak_handle.h" -#include "sync/notifier/dropped_invalidation_tracker.h" #include "sync/notifier/invalidation_util.h" #include "sync/notifier/object_id_invalidation_map.h" #include "sync/notifier/unacked_invalidation_set_test_util.h" @@ -138,8 +137,7 @@ class FakeInvalidationClient : public invalidation::InvalidationClient { class FakeDelegate : public SyncInvalidationListener::Delegate { public: explicit FakeDelegate(SyncInvalidationListener* listener) - : state_(TRANSIENT_INVALIDATION_ERROR), - drop_handlers_deleter_(&drop_handlers_) {} + : state_(TRANSIENT_INVALIDATION_ERROR) {} virtual ~FakeDelegate() {} size_t GetInvalidationCount(const ObjectId& id) const { @@ -195,17 +193,6 @@ class FakeDelegate : public SyncInvalidationListener::Delegate { return state_; } - DroppedInvalidationTracker* GetDropTrackerForObject(const ObjectId& id) { - DropHandlers::iterator it = drop_handlers_.find(id); - if (it == drop_handlers_.end()) { - drop_handlers_.insert( - std::make_pair(id, new DroppedInvalidationTracker(id))); - return drop_handlers_.find(id)->second; - } else { - return it->second; - } - } - void AcknowledgeNthInvalidation(const ObjectId& id, size_t n) { List& list = invalidations_[id]; List::iterator it = list.begin() + n; @@ -220,15 +207,19 @@ class FakeDelegate : public SyncInvalidationListener::Delegate { } void DropNthInvalidation(const ObjectId& id, size_t n) { - DroppedInvalidationTracker* drop_tracker = GetDropTrackerForObject(id); List& list = invalidations_[id]; List::iterator it = list.begin() + n; - it->Drop(drop_tracker); + it->Drop(); + dropped_invalidations_map_.erase(id); + dropped_invalidations_map_.insert(std::make_pair(id, *it)); } void RecoverFromDropEvent(const ObjectId& id) { - DroppedInvalidationTracker* drop_tracker = GetDropTrackerForObject(id); - drop_tracker->RecordRecoveryFromDropEvent(); + DropMap::iterator it = dropped_invalidations_map_.find(id); + if (it != dropped_invalidations_map_.end()) { + it->second.Acknowledge(); + dropped_invalidations_map_.erase(it); + } } // SyncInvalidationListener::Delegate implementation. @@ -250,14 +241,11 @@ class FakeDelegate : public SyncInvalidationListener::Delegate { private: typedef std::vector<Invalidation> List; typedef std::map<ObjectId, List, ObjectIdLessThan> Map; - typedef std::map<ObjectId, - DroppedInvalidationTracker*, - ObjectIdLessThan> DropHandlers; + typedef std::map<ObjectId, Invalidation, ObjectIdLessThan> DropMap; Map invalidations_; InvalidatorState state_; - DropHandlers drop_handlers_; - STLValueDeleter<DropHandlers> drop_handlers_deleter_; + DropMap dropped_invalidations_map_; }; invalidation::InvalidationClient* CreateFakeInvalidationClient( diff --git a/sync/engine/get_updates_processor_unittest.cc b/sync/engine/get_updates_processor_unittest.cc index 7c87fed..54ce503 100644 --- a/sync/engine/get_updates_processor_unittest.cc +++ b/sync/engine/get_updates_processor_unittest.cc @@ -15,11 +15,23 @@ #include "sync/sessions/status_controller.h" #include "sync/test/engine/fake_model_worker.h" #include "sync/test/engine/mock_update_handler.h" +#include "sync/test/mock_invalidation.h" #include "sync/test/sessions/mock_debug_info_getter.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { +namespace { + +scoped_ptr<InvalidationInterface> BuildInvalidation( + int64 version, + const std::string& payload) { + return MockInvalidation::Build(version, payload) + .PassAs<InvalidationInterface>(); +} + +} // namespace + using sessions::MockDebugInfoGetter; // A test fixture for tests exercising download updates functions. @@ -133,11 +145,11 @@ TEST_F(GetUpdatesProcessorTest, BookmarkNudge) { TEST_F(GetUpdatesProcessorTest, NotifyMany) { sessions::NudgeTracker nudge_tracker; nudge_tracker.RecordRemoteInvalidation( - BuildInvalidationMap(AUTOFILL, 1, "autofill_payload")); + AUTOFILL, BuildInvalidation(1, "autofill_payload")); nudge_tracker.RecordRemoteInvalidation( - BuildInvalidationMap(BOOKMARKS, 1, "bookmark_payload")); + BOOKMARKS, BuildInvalidation(1, "bookmark_payload")); nudge_tracker.RecordRemoteInvalidation( - BuildInvalidationMap(PREFERENCES, 1, "preferences_payload")); + PREFERENCES, BuildInvalidation(1, "preferences_payload")); ModelTypeSet notified_types; notified_types.Put(AUTOFILL); notified_types.Put(BOOKMARKS); diff --git a/sync/engine/sync_scheduler.h b/sync/engine/sync_scheduler.h index aef0118..b512042 100644 --- a/sync/engine/sync_scheduler.h +++ b/sync/engine/sync_scheduler.h @@ -13,6 +13,7 @@ #include "base/time/time.h" #include "sync/base/sync_export.h" #include "sync/engine/nudge_source.h" +#include "sync/internal_api/public/base/invalidation_interface.h" #include "sync/sessions/sync_session.h" namespace tracked_objects { @@ -21,7 +22,6 @@ class Location; namespace syncer { -class ObjectIdInvalidationMap; struct ServerConnectionEvent; struct SYNC_EXPORT_PRIVATE ConfigurationParams { @@ -115,7 +115,8 @@ class SYNC_EXPORT_PRIVATE SyncScheduler // order to fetch the update. virtual void ScheduleInvalidationNudge( const base::TimeDelta& desired_delay, - const ObjectIdInvalidationMap& invalidations, + syncer::ModelType type, + scoped_ptr<InvalidationInterface> invalidation, const tracked_objects::Location& nudge_location) = 0; // Change status of notifications in the SyncSessionContext. diff --git a/sync/engine/sync_scheduler_impl.cc b/sync/engine/sync_scheduler_impl.cc index 01a054a..c5629ba 100644 --- a/sync/engine/sync_scheduler_impl.cc +++ b/sync/engine/sync_scheduler_impl.cc @@ -387,16 +387,15 @@ void SyncSchedulerImpl::ScheduleLocalRefreshRequest( void SyncSchedulerImpl::ScheduleInvalidationNudge( const TimeDelta& desired_delay, - const ObjectIdInvalidationMap& invalidation_map, + syncer::ModelType model_type, + scoped_ptr<InvalidationInterface> invalidation, const tracked_objects::Location& nudge_location) { DCHECK(CalledOnValidThread()); - DCHECK(!invalidation_map.Empty()); SDVLOG_LOC(nudge_location, 2) << "Scheduling sync because we received invalidation for " - << ModelTypeSetToString( - ObjectIdSetToModelTypeSet(invalidation_map.GetObjectIds())); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + << ModelTypeToString(model_type); + nudge_tracker_.RecordRemoteInvalidation(model_type, invalidation.Pass()); ScheduleNudgeImpl(desired_delay, nudge_location); } diff --git a/sync/engine/sync_scheduler_impl.h b/sync/engine/sync_scheduler_impl.h index 75cad3e..d78b5d6 100644 --- a/sync/engine/sync_scheduler_impl.h +++ b/sync/engine/sync_scheduler_impl.h @@ -65,7 +65,8 @@ class SYNC_EXPORT_PRIVATE SyncSchedulerImpl const tracked_objects::Location& nudge_location) OVERRIDE; virtual void ScheduleInvalidationNudge( const base::TimeDelta& desired_delay, - const ObjectIdInvalidationMap& invalidation_map, + syncer::ModelType type, + scoped_ptr<InvalidationInterface> invalidation, const tracked_objects::Location& nudge_location) OVERRIDE; virtual void SetNotificationsEnabled(bool notifications_enabled) OVERRIDE; diff --git a/sync/engine/sync_scheduler_unittest.cc b/sync/engine/sync_scheduler_unittest.cc index c231087..8348eab 100644 --- a/sync/engine/sync_scheduler_unittest.cc +++ b/sync/engine/sync_scheduler_unittest.cc @@ -20,6 +20,7 @@ #include "sync/test/engine/fake_model_worker.h" #include "sync/test/engine/mock_connection_manager.h" #include "sync/test/engine/test_directory_setter_upper.h" +#include "sync/test/mock_invalidation.h" #include "sync/util/extensions_activity.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -220,6 +221,13 @@ class SyncSchedulerTest : public testing::Test { return scheduler_->retry_timer_.GetCurrentDelay(); } + static scoped_ptr<InvalidationInterface> BuildInvalidation( + int64 version, + const std::string& payload) { + return MockInvalidation::Build(version, payload) + .PassAs<InvalidationInterface>(); + } + private: syncable::Directory* directory() { return dir_maker_.directory(); @@ -523,25 +531,23 @@ TEST_F(SyncSchedulerTest, NudgeWithStates) { StartSyncScheduler(SyncScheduler::NORMAL_MODE); SyncShareTimes times1; - ObjectIdInvalidationMap invalidations1 = - BuildInvalidationMap(BOOKMARKS, 10, "test"); EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), RecordSyncShare(×1))) .RetiresOnSaturation(); - scheduler()->ScheduleInvalidationNudge(zero(), invalidations1, FROM_HERE); + scheduler()->ScheduleInvalidationNudge( + zero(), BOOKMARKS, BuildInvalidation(10, "test"), FROM_HERE); RunLoop(); Mock::VerifyAndClearExpectations(syncer()); // Make sure a second, later, nudge is unaffected by first (no coalescing). SyncShareTimes times2; - ObjectIdInvalidationMap invalidations2 = - BuildInvalidationMap(AUTOFILL, 10, "test2"); EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), RecordSyncShare(×2))); - scheduler()->ScheduleInvalidationNudge(zero(), invalidations2, FROM_HERE); + scheduler()->ScheduleInvalidationNudge( + zero(), AUTOFILL, BuildInvalidation(10, "test2"), FROM_HERE); RunLoop(); } @@ -834,9 +840,8 @@ TEST_F(SyncSchedulerTest, TypeThrottlingDoesBlockOtherSources) { EXPECT_TRUE(GetThrottledTypes().HasAll(throttled_types)); // Ignore invalidations for throttled types. - ObjectIdInvalidationMap invalidations = - BuildInvalidationMap(BOOKMARKS, 10, "test"); - scheduler()->ScheduleInvalidationNudge(zero(), invalidations, FROM_HERE); + scheduler()->ScheduleInvalidationNudge( + zero(), BOOKMARKS, BuildInvalidation(10, "test"), FROM_HERE); PumpLoop(); // Ignore refresh requests for throttled types. diff --git a/sync/internal_api/public/base/invalidation.cc b/sync/internal_api/public/base/invalidation.cc index ff7a5a7..e6a64be 100644 --- a/sync/internal_api/public/base/invalidation.cc +++ b/sync/internal_api/public/base/invalidation.cc @@ -11,7 +11,6 @@ #include "base/strings/string_number_conversions.h" #include "base/values.h" #include "sync/notifier/ack_handler.h" -#include "sync/notifier/dropped_invalidation_tracker.h" #include "sync/notifier/invalidation_util.h" namespace syncer { @@ -43,6 +42,15 @@ Invalidation Invalidation::InitFromDroppedInvalidation( std::string(), dropped.ack_handle_); } +Invalidation::Invalidation(const Invalidation& other) + : id_(other.id_), + is_unknown_version_(other.is_unknown_version_), + version_(other.version_), + payload_(other.payload_), + ack_handle_(other.ack_handle_), + ack_handler_(other.ack_handler_) { +} + scoped_ptr<Invalidation> Invalidation::InitFromValue( const base::DictionaryValue& value) { invalidation::ObjectId id; @@ -128,9 +136,7 @@ void Invalidation::Acknowledge() const { } } -void Invalidation::Drop(DroppedInvalidationTracker* tracker) const { - DCHECK(tracker->object_id() == object_id()); - tracker->RecordDropEvent(ack_handler_, ack_handle_); +void Invalidation::Drop() { if (SupportsAcknowledgement()) { ack_handler_.Call(FROM_HERE, &AckHandler::Drop, diff --git a/sync/internal_api/public/base/invalidation.h b/sync/internal_api/public/base/invalidation.h index cf26112..309eb7d 100644 --- a/sync/internal_api/public/base/invalidation.h +++ b/sync/internal_api/public/base/invalidation.h @@ -35,6 +35,7 @@ class SYNC_EXPORT Invalidation { static scoped_ptr<Invalidation> InitFromValue( const base::DictionaryValue& value); + Invalidation(const Invalidation& other); ~Invalidation(); // Compares two invalidations. The comparison ignores ack-tracking state. @@ -84,12 +85,9 @@ class SYNC_EXPORT Invalidation { // invalidations in order to allow the ack tracker to drop the invalidation, // too. // - // The drop record will be tracked by the specified - // DroppedInvalidationTracker. The caller should hang on to this tracker. It - // will need to use it when it recovers from this drop event, or if it needs - // to record another drop event for the same ObjectID. Refer to the - // documentation of DroppedInvalidationTracker for more details. - void Drop(DroppedInvalidationTracker* tracker) const; + // To indicate recovery from a drop event, the client should call + // Acknowledge() on the most recently dropped inavlidation. + void Drop(); scoped_ptr<base::DictionaryValue> ToValue() const; std::string ToString() const; diff --git a/sync/internal_api/public/base/invalidation_interface.cc b/sync/internal_api/public/base/invalidation_interface.cc new file mode 100644 index 0000000..0284170 --- /dev/null +++ b/sync/internal_api/public/base/invalidation_interface.cc @@ -0,0 +1,29 @@ +// Copyright 2014 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 "sync/internal_api/public/base/invalidation_interface.h" + +namespace syncer { + +bool InvalidationInterface::LessThanByVersion(const InvalidationInterface& a, + const InvalidationInterface& b) { + if (a.IsUnknownVersion() && !b.IsUnknownVersion()) + return true; + + if (!a.IsUnknownVersion() && b.IsUnknownVersion()) + return false; + + if (a.IsUnknownVersion() && b.IsUnknownVersion()) + return false; + + return a.GetVersion() < b.GetVersion(); +} + +InvalidationInterface::InvalidationInterface() { +} + +InvalidationInterface::~InvalidationInterface() { +} + +} // namespace syncer diff --git a/sync/internal_api/public/base/invalidation_interface.h b/sync/internal_api/public/base/invalidation_interface.h new file mode 100644 index 0000000..d7dbbe8 --- /dev/null +++ b/sync/internal_api/public/base/invalidation_interface.h @@ -0,0 +1,55 @@ +// Copyright 2014 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 SYNC_INTERNAL_API_PUBLIC_BASE_INVALIDATION_INTERFACE_H_ +#define SYNC_INTERNAL_API_PUBLIC_BASE_INVALIDATION_INTERFACE_H_ + +#include <string> + +#include "base/basictypes.h" +#include "sync/base/sync_export.h" + +namespace syncer { + +// An interface that wraps sync's interactions with the component that provides +// it with invalidations. +class SYNC_EXPORT InvalidationInterface { + public: + // Orders invalidations based on version number and IsUnknownVersion(). + static bool LessThanByVersion(const InvalidationInterface& a, + const InvalidationInterface& b); + + InvalidationInterface(); + virtual ~InvalidationInterface(); + + // Returns true if this is an 'unknown version' invalidation. + // Such invalidations have no valid payload or version number. + virtual bool IsUnknownVersion() const = 0; + + // Returns the payload of this item. + // DCHECKs if this is an unknown version invalidation. + virtual const std::string& GetPayload() const = 0; + + // Retursn the version of this item. + // DCHECKs if this is an unknown version invalidation. + // + // It is preferable to use the LessThan() function, which handles unknown + // versions properly, rather than this function. + virtual int64 GetVersion() const = 0; + + // This function will be called when the invalidation has been handled + // successfully. + virtual void Acknowledge() = 0; + + // This function should be called if a lack of buffer space required that we + // drop this invalidation. + // + // To indicate recovery from a drop event, the receiver of this invalidation + // will call Acknowledge() on the most recently dropped invalidation. + virtual void Drop() = 0; +}; + +} // namespace syncer + +#endif diff --git a/sync/internal_api/public/base/model_type_test_util.cc b/sync/internal_api/public/base/model_type_test_util.cc index 4876962..5893922 100644 --- a/sync/internal_api/public/base/model_type_test_util.cc +++ b/sync/internal_api/public/base/model_type_test_util.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "sync/internal_api/public/base/model_type_test_util.h" -#include "sync/internal_api/public/base/ack_handle.h" namespace syncer { diff --git a/sync/internal_api/public/sync_manager.h b/sync/internal_api/public/sync_manager.h index 073b8ed..b8cc50d 100644 --- a/sync/internal_api/public/sync_manager.h +++ b/sync/internal_api/public/sync_manager.h @@ -12,11 +12,13 @@ #include "base/callback_forward.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/task_runner.h" #include "base/threading/thread_checker.h" #include "google_apis/gaia/oauth2_token_service.h" #include "sync/base/sync_export.h" +#include "sync/internal_api/public/base/invalidation_interface.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/change_record.h" #include "sync/internal_api/public/configure_reason.h" @@ -89,7 +91,7 @@ struct SYNC_EXPORT SyncCredentials { // // Unless stated otherwise, all methods of SyncManager should be called on the // same thread. -class SYNC_EXPORT SyncManager : public syncer::InvalidationHandler { +class SYNC_EXPORT SyncManager { public: // An interface the embedding application implements to be notified // on change events. Note that these methods may be called on *any* @@ -314,7 +316,8 @@ class SYNC_EXPORT SyncManager : public syncer::InvalidationHandler { // Inform the syncer that its cached information about a type is obsolete. virtual void OnIncomingInvalidation( - const ObjectIdInvalidationMap& invalidation_map) = 0; + syncer::ModelType type, + scoped_ptr<syncer::InvalidationInterface> invalidation) = 0; // Adds a listener to be notified of sync events. // NOTE: It is OK (in fact, it's probably a good idea) to call this before diff --git a/sync/internal_api/public/test/fake_sync_manager.h b/sync/internal_api/public/test/fake_sync_manager.h index df14a52..f4ea19a 100644 --- a/sync/internal_api/public/test/fake_sync_manager.h +++ b/sync/internal_api/public/test/fake_sync_manager.h @@ -63,14 +63,12 @@ class FakeSyncManager : public SyncManager { // Posts a method to invalidate the given IDs on the sync thread. virtual void OnIncomingInvalidation( - const ObjectIdInvalidationMap& invalidation_map) OVERRIDE; + syncer::ModelType type, + scoped_ptr<InvalidationInterface> interface) OVERRIDE; // Posts a method to update the invalidator state on the sync thread. virtual void OnInvalidatorStateChange(InvalidatorState state) OVERRIDE; - // Returns this class name for logging purposes. - virtual std::string GetOwnerName() const OVERRIDE; - // Block until the sync thread has finished processing any pending messages. void WaitForSyncThread(); diff --git a/sync/internal_api/sync_manager_impl.cc b/sync/internal_api/sync_manager_impl.cc index 0e3caf3..d0ae309 100644 --- a/sync/internal_api/sync_manager_impl.cc +++ b/sync/internal_api/sync_manager_impl.cc @@ -20,6 +20,7 @@ #include "sync/engine/syncer_types.h" #include "sync/internal_api/change_reorder_buffer.h" #include "sync/internal_api/public/base/cancelation_signal.h" +#include "sync/internal_api/public/base/invalidation_interface.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/base_node.h" #include "sync/internal_api/public/configure_reason.h" @@ -979,30 +980,17 @@ void SyncManagerImpl::OnInvalidatorStateChange(InvalidatorState state) { } void SyncManagerImpl::OnIncomingInvalidation( - const ObjectIdInvalidationMap& invalidation_map) { + syncer::ModelType type, + scoped_ptr<InvalidationInterface> invalidation) { DCHECK(thread_checker_.CalledOnValidThread()); - // We should never receive IDs from non-sync objects. - ObjectIdSet ids = invalidation_map.GetObjectIds(); - for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) { - ModelType type; - if (!ObjectIdToRealModelType(*it, &type)) { - DLOG(WARNING) << "Notification has invalid id: " << ObjectIdToString(*it); - } - } - - if (invalidation_map.Empty()) { - LOG(WARNING) << "Sync received invalidation without any type information."; - } else { - scheduler_->ScheduleInvalidationNudge( - TimeDelta::FromMilliseconds(kSyncSchedulerDelayMsec), - invalidation_map, FROM_HERE); - debug_info_event_listener_.OnIncomingNotification(invalidation_map); - } + scheduler_->ScheduleInvalidationNudge( + TimeDelta::FromMilliseconds(kSyncSchedulerDelayMsec), + type, + invalidation.Pass(), + FROM_HERE); } -std::string SyncManagerImpl::GetOwnerName() const { return "SyncManagerImpl"; } - void SyncManagerImpl::RefreshTypes(ModelTypeSet types) { DCHECK(thread_checker_.CalledOnValidThread()); if (types.Empty()) { diff --git a/sync/internal_api/sync_manager_impl.h b/sync/internal_api/sync_manager_impl.h index 2ca5fd6..7efde2d 100644 --- a/sync/internal_api/sync_manager_impl.h +++ b/sync/internal_api/sync_manager_impl.h @@ -104,8 +104,8 @@ class SYNC_EXPORT_PRIVATE SyncManagerImpl : const base::Closure& retry_task) OVERRIDE; virtual void OnInvalidatorStateChange(InvalidatorState state) OVERRIDE; virtual void OnIncomingInvalidation( - const ObjectIdInvalidationMap& invalidation_map) OVERRIDE; - virtual std::string GetOwnerName() const OVERRIDE; + syncer::ModelType type, + scoped_ptr<InvalidationInterface> invalidation) OVERRIDE; virtual void AddObserver(SyncManager::Observer* observer) OVERRIDE; virtual void RemoveObserver(SyncManager::Observer* observer) OVERRIDE; virtual SyncStatus GetDetailedStatus() const OVERRIDE; diff --git a/sync/internal_api/sync_manager_impl_unittest.cc b/sync/internal_api/sync_manager_impl_unittest.cc index 3fd4c5d..b4b5f87 100644 --- a/sync/internal_api/sync_manager_impl_unittest.cc +++ b/sync/internal_api/sync_manager_impl_unittest.cc @@ -983,14 +983,6 @@ class SyncManagerTest : public testing::Test, sync_manager_.OnInvalidatorStateChange(state); } - void TriggerOnIncomingNotificationForTest(ModelTypeSet model_types) { - DCHECK(sync_manager_.thread_checker_.CalledOnValidThread()); - ObjectIdSet id_set = ModelTypeSetToObjectIdSet(model_types); - ObjectIdInvalidationMap invalidation_map = - ObjectIdInvalidationMap::InvalidateAll(id_set); - sync_manager_.OnIncomingInvalidation(invalidation_map); - } - void SetProgressMarkerForType(ModelType type, bool set) { if (set) { sync_pb::DataTypeProgressMarker marker; diff --git a/sync/internal_api/sync_rollback_manager_base.cc b/sync/internal_api/sync_rollback_manager_base.cc index 28afb8b..b7d1fef 100644 --- a/sync/internal_api/sync_rollback_manager_base.cc +++ b/sync/internal_api/sync_rollback_manager_base.cc @@ -133,7 +133,8 @@ void SyncRollbackManagerBase::OnInvalidatorStateChange(InvalidatorState state) { } void SyncRollbackManagerBase::OnIncomingInvalidation( - const ObjectIdInvalidationMap& invalidation_map) { + syncer::ModelType type, + scoped_ptr<InvalidationInterface> invalidation) { NOTREACHED(); } @@ -233,10 +234,6 @@ void SyncRollbackManagerBase::NotifyInitializationFailure() { false, ModelTypeSet())); } -std::string SyncRollbackManagerBase::GetOwnerName() const { - return ""; -} - syncer::SyncContextProxy* SyncRollbackManagerBase::GetSyncContextProxy() { return NULL; } diff --git a/sync/internal_api/sync_rollback_manager_base.h b/sync/internal_api/sync_rollback_manager_base.h index 8d32d7d..e18535f 100644 --- a/sync/internal_api/sync_rollback_manager_base.h +++ b/sync/internal_api/sync_rollback_manager_base.h @@ -73,7 +73,8 @@ class SYNC_EXPORT_PRIVATE SyncRollbackManagerBase : const base::Closure& retry_task) OVERRIDE; virtual void OnInvalidatorStateChange(InvalidatorState state) OVERRIDE; virtual void OnIncomingInvalidation( - const ObjectIdInvalidationMap& invalidation_map) OVERRIDE; + syncer::ModelType type, + scoped_ptr<InvalidationInterface> invalidation) OVERRIDE; virtual void AddObserver(SyncManager::Observer* observer) OVERRIDE; virtual void RemoveObserver(SyncManager::Observer* observer) OVERRIDE; virtual SyncStatus GetDetailedStatus() const OVERRIDE; @@ -85,7 +86,6 @@ class SYNC_EXPORT_PRIVATE SyncRollbackManagerBase : virtual bool HasUnsyncedItems() OVERRIDE; virtual SyncEncryptionHandler* GetEncryptionHandler() OVERRIDE; virtual void RefreshTypes(ModelTypeSet types) OVERRIDE; - virtual std::string GetOwnerName() const OVERRIDE; virtual SyncContextProxy* GetSyncContextProxy() OVERRIDE; virtual ScopedVector<ProtocolEvent> GetBufferedProtocolEvents() OVERRIDE; diff --git a/sync/internal_api/test/fake_sync_manager.cc b/sync/internal_api/test/fake_sync_manager.cc index 7b5e32f..5bb4f10 100644 --- a/sync/internal_api/test/fake_sync_manager.cc +++ b/sync/internal_api/test/fake_sync_manager.cc @@ -263,7 +263,8 @@ bool FakeSyncManager::HasDirectoryTypeDebugInfoObserver( void FakeSyncManager::RequestEmitDebugInfo() {} void FakeSyncManager::OnIncomingInvalidation( - const ObjectIdInvalidationMap& invalidation_map) { + syncer::ModelType type, + scoped_ptr<InvalidationInterface> invalidation) { // Do nothing. } @@ -275,6 +276,4 @@ void FakeSyncManager::OnInvalidatorStateChange(InvalidatorState state) { // Do nothing. } -std::string FakeSyncManager::GetOwnerName() const { return "FakeSyncManager"; } - } // namespace syncer diff --git a/sync/notifier/dropped_invalidation_tracker.cc b/sync/notifier/dropped_invalidation_tracker.cc deleted file mode 100644 index fc576e8..0000000 --- a/sync/notifier/dropped_invalidation_tracker.cc +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 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 "sync/notifier/dropped_invalidation_tracker.h" - -#include "sync/internal_api/public/base/invalidation.h" - -namespace syncer { - -DroppedInvalidationTracker::DroppedInvalidationTracker( - const invalidation::ObjectId& id) - : id_(id), - drop_ack_handle_(AckHandle::InvalidAckHandle()), - recovering_from_drop_(false) {} - -DroppedInvalidationTracker::~DroppedInvalidationTracker() {} - -const invalidation::ObjectId& DroppedInvalidationTracker::object_id() const { - return id_; -} - -void DroppedInvalidationTracker::RecordDropEvent( - WeakHandle<AckHandler> handler, AckHandle handle) { - drop_ack_handler_ = handler; - drop_ack_handle_ = handle; - recovering_from_drop_ = true; -} - -void DroppedInvalidationTracker::RecordRecoveryFromDropEvent() { - if (drop_ack_handler_.IsInitialized()) { - drop_ack_handler_.Call(FROM_HERE, - &AckHandler::Acknowledge, - id_, - drop_ack_handle_); - } - drop_ack_handler_ = syncer::WeakHandle<AckHandler>(); - recovering_from_drop_ = false; -} - -bool DroppedInvalidationTracker::IsRecoveringFromDropEvent() const { - return recovering_from_drop_; -} - -} // namespace syncer diff --git a/sync/notifier/dropped_invalidation_tracker.h b/sync/notifier/dropped_invalidation_tracker.h deleted file mode 100644 index 20f32af..0000000 --- a/sync/notifier/dropped_invalidation_tracker.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 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 SYNC_NOTIFIER_DROPPED_INVALIDATION_TRACKER_H_ -#define SYNC_NOTIFIER_DROPPED_INVALIDATION_TRACKER_H_ - -#include "google/cacheinvalidation/include/types.h" -#include "sync/base/sync_export.h" -#include "sync/internal_api/public/base/ack_handle.h" -#include "sync/internal_api/public/util/weak_handle.h" -#include "sync/notifier/ack_handler.h" - -namespace syncer { - -class Invalidation; - -// Helps InvalidationHandlers keep track of dropped invalidations for a given -// ObjectId. -// -// The intent of this class is to hide some of the implementation details around -// how the invalidations system manages dropping and drop recovery. Any -// invalidation handler that intends to buffer and occasionally drop -// invalidations should keep one instance of it per registered ObjectId. -// -// When an invalidation handler wishes to drop an invalidation, it must provide -// an instance of this class to that Invalidation's Drop() method. In order to -// indicate recovery from a drop, the handler can call this class' -// RecordRecoveryFromDropEvent(). -// -// Copy and assign are allowed for this class so we can use it in STL -// containers. -class SYNC_EXPORT DroppedInvalidationTracker { - public: - explicit DroppedInvalidationTracker(const invalidation::ObjectId& id); - ~DroppedInvalidationTracker(); - - const invalidation::ObjectId& object_id() const; - - // Called by Invalidation::Drop() to keep track of a drop event. - // - // Takes ownership of the internals belonging to a soon to be discarded - // dropped invalidation. See also the comment for this class' - // |drop_ack_handler_| member. - void RecordDropEvent(WeakHandle<AckHandler> handler, AckHandle handle); - - // Returns true if we're still recovering from a drop event. - bool IsRecoveringFromDropEvent() const; - - // Called by the InvalidationHandler when it recovers from the drop event. - void RecordRecoveryFromDropEvent(); - - private: - invalidation::ObjectId id_; - AckHandle drop_ack_handle_; - - // This flag is set to true when we have dropped an invalidation and have not - // yet recovered from this drop event. Note that this may not always coincide - // with drop_ack_handler_ being initialized because a null AckHandler could be - // passed in to RecordDropEvent(). - bool recovering_from_drop_; - - // A WeakHandle to the enitity responsible for persisting invalidation - // acknowledgement state on disk. We can get away with using a WeakHandle - // because we don't care if our drop recovery message doesn't gets delivered - // in some shutdown cases. If that happens, we'll have to process the - // invalidation state again on the next restart. It would be a waste of time - // and resources, but otherwise not particularly harmful. - WeakHandle<AckHandler> drop_ack_handler_; -}; - -} // namespace syncer - -#endif // SYNC_NOTIFIER_DROPPED_INVALIDATION_TRACKER_H_ diff --git a/sync/sessions/data_type_tracker.cc b/sync/sessions/data_type_tracker.cc index 5e0ee90..ed7f07f 100644 --- a/sync/sessions/data_type_tracker.cc +++ b/sync/sessions/data_type_tracker.cc @@ -5,19 +5,17 @@ #include "sync/sessions/data_type_tracker.h" #include "base/logging.h" -#include "sync/internal_api/public/base/invalidation.h" -#include "sync/notifier/invalidation_util.h" -#include "sync/notifier/single_object_invalidation_set.h" +#include "sync/internal_api/public/base/invalidation_interface.h" #include "sync/sessions/nudge_tracker.h" namespace syncer { namespace sessions { -DataTypeTracker::DataTypeTracker(const invalidation::ObjectId& object_id) - : local_nudge_count_(0), - local_refresh_request_count_(0), - payload_buffer_size_(NudgeTracker::kDefaultMaxPayloadsPerType), - drop_tracker_(object_id) { } +DataTypeTracker::DataTypeTracker() + : local_nudge_count_(0), + local_refresh_request_count_(0), + payload_buffer_size_(NudgeTracker::kDefaultMaxPayloadsPerType) { +} DataTypeTracker::~DataTypeTracker() { } @@ -29,20 +27,11 @@ void DataTypeTracker::RecordLocalRefreshRequest() { local_refresh_request_count_++; } -namespace { - -bool IsInvalidationVersionLessThan( - const Invalidation& a, - const Invalidation& b) { - InvalidationVersionLessThan comparator; - return comparator(a, b); -} - -} // namespace +void DataTypeTracker::RecordRemoteInvalidation( + scoped_ptr<InvalidationInterface> incoming) { + DCHECK(incoming); -void DataTypeTracker::RecordRemoteInvalidations( - const SingleObjectInvalidationSet& invalidations) { - // Merge the incoming invalidations into our list of pending invalidations. + // Merge the incoming invalidation into our list of pending invalidations. // // We won't use STL algorithms here because our concept of equality doesn't // quite fit the expectations of set_intersection. In particular, two @@ -50,52 +39,50 @@ void DataTypeTracker::RecordRemoteInvalidations( // rules (ie. have equal versions), but still have different AckHandle values // and need to be acknowledged separately. // - // The invalidaitons service can only track one outsanding invalidation per + // The invalidations service can only track one outsanding invalidation per // type and version, so the acknowledgement here should be redundant. We'll // acknowledge them anyway since it should do no harm, and makes this code a // bit easier to test. // // Overlaps should be extremely rare for most invalidations. They can happen // for unknown version invalidations, though. - SingleObjectInvalidationSet::const_iterator incoming_it = - invalidations.begin(); - SingleObjectInvalidationSet::const_iterator existing_it = + + ScopedVector<InvalidationInterface>::iterator it = pending_invalidations_.begin(); - while (incoming_it != invalidations.end()) { - // Keep existing_it ahead of incoming_it. - while (existing_it != pending_invalidations_.end() - && IsInvalidationVersionLessThan(*existing_it, *incoming_it)) { - existing_it++; - } + // Find the lower bound. + while (it != pending_invalidations_.end() && + InvalidationInterface::LessThanByVersion(**it, *incoming)) { + it++; + } - if (existing_it != pending_invalidations_.end() - && !IsInvalidationVersionLessThan(*incoming_it, *existing_it) - && !IsInvalidationVersionLessThan(*existing_it, *incoming_it)) { - // Incoming overlaps with existing. Either both are unknown versions - // (likely) or these two have the same version number (very unlikely). - // Acknowledge and overwrite existing. - SingleObjectInvalidationSet::const_iterator old_inv = existing_it; - existing_it++; - old_inv->Acknowledge(); - pending_invalidations_.Erase(old_inv); - pending_invalidations_.Insert(*incoming_it); - incoming_it++; - } else { - DCHECK(existing_it == pending_invalidations_.end() - || IsInvalidationVersionLessThan(*incoming_it, *existing_it)); - // The incoming_it points at a version not in the pending_invalidations_ - // list. Add it to the list then increment past it. - pending_invalidations_.Insert(*incoming_it); - incoming_it++; - } + if (it != pending_invalidations_.end() && + !InvalidationInterface::LessThanByVersion(*incoming, **it) && + !InvalidationInterface::LessThanByVersion(**it, *incoming)) { + // Incoming overlaps with existing. Either both are unknown versions + // (likely) or these two have the same version number (very unlikely). + // Acknowledge and overwrite existing. + + // Insert before the existing and get iterator to inserted. + ScopedVector<InvalidationInterface>::iterator it2 = + pending_invalidations_.insert(it, incoming.release()); + + // Increment that iterator to the old one, then acknowledge and remove it. + ++it2; + (*it2)->Acknowledge(); + pending_invalidations_.erase(it2); + } else { + // The incoming has a version not in the pending_invalidations_ list. + // Add it to the list at the proper position. + pending_invalidations_.insert(it, incoming.release()); } - // Those incoming invalidations may have caused us to exceed our buffer size. + // The incoming invalidation may have caused us to exceed our buffer size. // Trim some items from our list, if necessary. - while (pending_invalidations_.GetSize() > payload_buffer_size_) { - pending_invalidations_.begin()->Drop(&drop_tracker_); - pending_invalidations_.Erase(pending_invalidations_.begin()); + while (pending_invalidations_.size() > payload_buffer_size_) { + last_dropped_invalidation_.reset(pending_invalidations_.front()); + last_dropped_invalidation_->Drop(); + pending_invalidations_.weak_erase(pending_invalidations_.begin()); } } @@ -112,15 +99,17 @@ void DataTypeTracker::RecordSuccessfulSyncCycle() { // crash before writing all our state, we should wait until the results of // this sync cycle have been written to disk before updating the invalidations // state. See crbug.com/324996. - for (SingleObjectInvalidationSet::const_iterator it = - pending_invalidations_.begin(); - it != pending_invalidations_.end(); ++it) { - it->Acknowledge(); + for (ScopedVector<InvalidationInterface>::const_iterator it = + pending_invalidations_.begin(); + it != pending_invalidations_.end(); + ++it) { + (*it)->Acknowledge(); } - pending_invalidations_.Clear(); + pending_invalidations_.clear(); - if (drop_tracker_.IsRecoveringFromDropEvent()) { - drop_tracker_.RecordRecoveryFromDropEvent(); + if (last_dropped_invalidation_) { + last_dropped_invalidation_->Acknowledge(); + last_dropped_invalidation_.reset(); } } @@ -147,8 +136,7 @@ bool DataTypeTracker::HasRefreshRequestPending() const { } bool DataTypeTracker::HasPendingInvalidation() const { - return !pending_invalidations_.IsEmpty() - || drop_tracker_.IsRecoveringFromDropEvent(); + return !pending_invalidations_.empty() || last_dropped_invalidation_; } void DataTypeTracker::SetLegacyNotificationHint( @@ -156,16 +144,17 @@ void DataTypeTracker::SetLegacyNotificationHint( DCHECK(!IsThrottled()) << "We should not make requests if the type is throttled."; - if (!pending_invalidations_.IsEmpty() && - !pending_invalidations_.back().is_unknown_version()) { + if (!pending_invalidations_.empty() && + !pending_invalidations_.back()->IsUnknownVersion()) { // The old-style source info can contain only one hint per type. We grab // the most recent, to mimic the old coalescing behaviour. - progress->set_notification_hint(pending_invalidations_.back().payload()); + progress->set_notification_hint( + pending_invalidations_.back()->GetPayload()); } else if (HasLocalChangePending()) { // The old-style source info sent up an empty string (as opposed to // nothing at all) when the type was locally nudged, but had not received // any invalidations. - progress->set_notification_hint(""); + progress->set_notification_hint(std::string()); } } @@ -174,17 +163,19 @@ void DataTypeTracker::FillGetUpdatesTriggersMessage( // Fill the list of payloads, if applicable. The payloads must be ordered // oldest to newest, so we insert them in the same order as we've been storing // them internally. - for (SingleObjectInvalidationSet::const_iterator it = - pending_invalidations_.begin(); - it != pending_invalidations_.end(); ++it) { - if (!it->is_unknown_version()) { - msg->add_notification_hint(it->payload()); + for (ScopedVector<InvalidationInterface>::const_iterator it = + pending_invalidations_.begin(); + it != pending_invalidations_.end(); + ++it) { + if (!(*it)->IsUnknownVersion()) { + msg->add_notification_hint((*it)->GetPayload()); } } msg->set_server_dropped_hints( - pending_invalidations_.StartsWithUnknownVersion()); - msg->set_client_dropped_hints(drop_tracker_.IsRecoveringFromDropEvent()); + !pending_invalidations_.empty() && + (*pending_invalidations_.begin())->IsUnknownVersion()); + msg->set_client_dropped_hints(last_dropped_invalidation_); msg->set_local_modification_nudges(local_nudge_count_); msg->set_datatype_refresh_nudges(local_refresh_request_count_); } diff --git a/sync/sessions/data_type_tracker.h b/sync/sessions/data_type_tracker.h index 59ec993..8d78cde 100644 --- a/sync/sessions/data_type_tracker.h +++ b/sync/sessions/data_type_tracker.h @@ -1,32 +1,30 @@ // Copyright 2013 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. -// -// A class to track the per-type scheduling data. + #ifndef SYNC_SESSIONS_DATA_TYPE_TRACKER_H_ #define SYNC_SESSIONS_DATA_TYPE_TRACKER_H_ -#include <deque> #include <string> #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" #include "base/time/time.h" -#include "sync/notifier/dropped_invalidation_tracker.h" -#include "sync/notifier/single_object_invalidation_set.h" +#include "sync/internal_api/public/base/invalidation_interface.h" +#include "sync/internal_api/public/base/model_type.h" #include "sync/protocol/sync.pb.h" namespace syncer { -class Invalidation; -class SingleObjectInvalidationSet; +class InvalidationInterface; namespace sessions { -typedef std::deque<std::string> PayloadList; - +// A class to track the per-type scheduling data. class DataTypeTracker { public: - explicit DataTypeTracker(const invalidation::ObjectId& object_id); + explicit DataTypeTracker(); ~DataTypeTracker(); // For STL compatibility, we do not forbid the creation of a default copy @@ -39,8 +37,7 @@ class DataTypeTracker { void RecordLocalRefreshRequest(); // Tracks that we received invalidation notifications for this type. - void RecordRemoteInvalidations( - const SingleObjectInvalidationSet& invalidations); + void RecordRemoteInvalidation(scoped_ptr<InvalidationInterface> incoming); // Records that a sync cycle has been performed successfully. // Generally, this means that all local changes have been committed and all @@ -105,7 +102,9 @@ class DataTypeTracker { // The list of invalidations received since the last successful sync cycle. // This list may be incomplete. See also: // drop_tracker_.IsRecoveringFromDropEvent() and server_payload_overflow_. - SingleObjectInvalidationSet pending_invalidations_; + // + // This list takes ownership of its contents. + ScopedVector<InvalidationInterface> pending_invalidations_; size_t payload_buffer_size_; @@ -114,10 +113,12 @@ class DataTypeTracker { base::TimeTicks unthrottle_time_; // A helper to keep track invalidations we dropped due to overflow. - DroppedInvalidationTracker drop_tracker_; + scoped_ptr<InvalidationInterface> last_dropped_invalidation_; + + DISALLOW_COPY_AND_ASSIGN(DataTypeTracker); }; -} // namespace syncer } // namespace sessions +} // namespace syncer #endif // SYNC_SESSIONS_DATA_TYPE_TRACKER_H_ diff --git a/sync/sessions/nudge_tracker.cc b/sync/sessions/nudge_tracker.cc index e9e731d..8dd6d2a 100644 --- a/sync/sessions/nudge_tracker.cc +++ b/sync/sessions/nudge_tracker.cc @@ -16,18 +16,14 @@ namespace sessions { size_t NudgeTracker::kDefaultMaxPayloadsPerType = 10; NudgeTracker::NudgeTracker() - : invalidations_enabled_(false), + : type_tracker_deleter_(&type_trackers_), + invalidations_enabled_(false), invalidations_out_of_sync_(true) { ModelTypeSet protocol_types = ProtocolTypes(); // Default initialize all the type trackers. for (ModelTypeSet::Iterator it = protocol_types.First(); it.Good(); it.Inc()) { - invalidation::ObjectId id; - if (!RealModelTypeToObjectId(it.Get(), &id)) { - NOTREACHED(); - } else { - type_trackers_.insert(std::make_pair(it.Get(), DataTypeTracker(id))); - } + type_trackers_.insert(std::make_pair(it.Get(), new DataTypeTracker())); } } @@ -39,7 +35,7 @@ bool NudgeTracker::IsSyncRequired() const { for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - if (it->second.IsSyncRequired()) { + if (it->second->IsSyncRequired()) { return true; } } @@ -56,7 +52,7 @@ bool NudgeTracker::IsGetUpdatesRequired() const { for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - if (it->second.IsGetUpdatesRequired()) { + if (it->second->IsGetUpdatesRequired()) { return true; } } @@ -83,7 +79,7 @@ void NudgeTracker::RecordSuccessfulSyncCycle() { for (TypeTrackerMap::iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - it->second.RecordSuccessfulSyncCycle(); + it->second->RecordSuccessfulSyncCycle(); } } @@ -92,7 +88,7 @@ void NudgeTracker::RecordLocalChange(ModelTypeSet types) { type_it.Inc()) { TypeTrackerMap::iterator tracker_it = type_trackers_.find(type_it.Get()); DCHECK(tracker_it != type_trackers_.end()); - tracker_it->second.RecordLocalChange(); + tracker_it->second->RecordLocalChange(); } } @@ -100,34 +96,17 @@ void NudgeTracker::RecordLocalRefreshRequest(ModelTypeSet types) { for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { TypeTrackerMap::iterator tracker_it = type_trackers_.find(it.Get()); DCHECK(tracker_it != type_trackers_.end()); - tracker_it->second.RecordLocalRefreshRequest(); + tracker_it->second->RecordLocalRefreshRequest(); } } void NudgeTracker::RecordRemoteInvalidation( - const ObjectIdInvalidationMap& invalidation_map) { - // Be very careful here. The invalidations acknowledgement system requires a - // sort of manual memory management. We'll leak a small amount of memory if - // we fail to acknowledge or drop any of these incoming invalidations. - - ObjectIdSet id_set = invalidation_map.GetObjectIds(); - for (ObjectIdSet::iterator it = id_set.begin(); it != id_set.end(); ++it) { - ModelType type; - - // This should never happen. If it does, we'll start to leak memory. - if (!ObjectIdToRealModelType(*it, &type)) { - NOTREACHED() - << "Object ID " << ObjectIdToString(*it) - << " does not map to valid model type"; - continue; - } - - // Forward the invalidations to the proper recipient. - TypeTrackerMap::iterator tracker_it = type_trackers_.find(type); - DCHECK(tracker_it != type_trackers_.end()); - tracker_it->second.RecordRemoteInvalidations( - invalidation_map.ForObject(*it)); - } + syncer::ModelType type, + scoped_ptr<InvalidationInterface> invalidation) { + // Forward the invalidations to the proper recipient. + TypeTrackerMap::iterator tracker_it = type_trackers_.find(type); + DCHECK(tracker_it != type_trackers_.end()); + tracker_it->second->RecordRemoteInvalidation(invalidation.Pass()); } void NudgeTracker::OnInvalidationsEnabled() { @@ -145,21 +124,21 @@ void NudgeTracker::SetTypesThrottledUntil( base::TimeTicks now) { for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { TypeTrackerMap::iterator tracker_it = type_trackers_.find(it.Get()); - tracker_it->second.ThrottleType(length, now); + tracker_it->second->ThrottleType(length, now); } } void NudgeTracker::UpdateTypeThrottlingState(base::TimeTicks now) { for (TypeTrackerMap::iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - it->second.UpdateThrottleState(now); + it->second->UpdateThrottleState(now); } } bool NudgeTracker::IsAnyTypeThrottled() const { for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - if (it->second.IsThrottled()) { + if (it->second->IsThrottled()) { return true; } } @@ -168,7 +147,7 @@ bool NudgeTracker::IsAnyTypeThrottled() const { bool NudgeTracker::IsTypeThrottled(ModelType type) const { DCHECK(type_trackers_.find(type) != type_trackers_.end()); - return type_trackers_.find(type)->second.IsThrottled(); + return type_trackers_.find(type)->second->IsThrottled(); } base::TimeDelta NudgeTracker::GetTimeUntilNextUnthrottle( @@ -179,10 +158,9 @@ base::TimeDelta NudgeTracker::GetTimeUntilNextUnthrottle( base::TimeDelta time_until_next_unthrottle = base::TimeDelta::Max(); for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - if (it->second.IsThrottled()) { - time_until_next_unthrottle = - std::min(time_until_next_unthrottle, - it->second.GetTimeUntilUnthrottle(now)); + if (it->second->IsThrottled()) { + time_until_next_unthrottle = std::min( + time_until_next_unthrottle, it->second->GetTimeUntilUnthrottle(now)); } } DCHECK(!time_until_next_unthrottle.is_max()); @@ -194,7 +172,7 @@ ModelTypeSet NudgeTracker::GetThrottledTypes() const { ModelTypeSet result; for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - if (it->second.IsThrottled()) { + if (it->second->IsThrottled()) { result.Put(it->first); } } @@ -205,7 +183,7 @@ ModelTypeSet NudgeTracker::GetNudgedTypes() const { ModelTypeSet result; for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - if (it->second.HasLocalChangePending()) { + if (it->second->HasLocalChangePending()) { result.Put(it->first); } } @@ -216,7 +194,7 @@ ModelTypeSet NudgeTracker::GetNotifiedTypes() const { ModelTypeSet result; for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - if (it->second.HasPendingInvalidation()) { + if (it->second->HasPendingInvalidation()) { result.Put(it->first); } } @@ -227,7 +205,7 @@ ModelTypeSet NudgeTracker::GetRefreshRequestedTypes() const { ModelTypeSet result; for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - if (it->second.HasRefreshRequestPending()) { + if (it->second->HasRefreshRequestPending()) { result.Put(it->first); } } @@ -238,7 +216,7 @@ void NudgeTracker::SetLegacyNotificationHint( ModelType type, sync_pb::DataTypeProgressMarker* progress) const { DCHECK(type_trackers_.find(type) != type_trackers_.end()); - type_trackers_.find(type)->second.SetLegacyNotificationHint(progress); + type_trackers_.find(type)->second->SetLegacyNotificationHint(progress); } sync_pb::GetUpdatesCallerInfo::GetUpdatesSource NudgeTracker::GetLegacySource() @@ -257,7 +235,7 @@ sync_pb::GetUpdatesCallerInfo::GetUpdatesSource NudgeTracker::GetLegacySource() for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - const DataTypeTracker& tracker = it->second; + const DataTypeTracker& tracker = *it->second; if (!tracker.IsThrottled() && tracker.HasPendingInvalidation()) { has_invalidation_pending = true; } @@ -291,7 +269,7 @@ void NudgeTracker::FillProtoMessage( msg->set_invalidations_out_of_sync(invalidations_out_of_sync_); // Delegate the type-specific work to the DataTypeTracker class. - type_trackers_.find(type)->second.FillGetUpdatesTriggersMessage(msg); + type_trackers_.find(type)->second->FillGetUpdatesTriggersMessage(msg); } void NudgeTracker::SetSyncCycleStartTime(base::TimeTicks now) { @@ -320,7 +298,7 @@ void NudgeTracker::SetSyncCycleStartTime(base::TimeTicks now) { void NudgeTracker::SetHintBufferSize(size_t size) { for (TypeTrackerMap::iterator it = type_trackers_.begin(); it != type_trackers_.end(); ++it) { - it->second.UpdatePayloadBufferSize(size); + it->second->UpdatePayloadBufferSize(size); } } diff --git a/sync/sessions/nudge_tracker.h b/sync/sessions/nudge_tracker.h index e14f31f..4c8d445 100644 --- a/sync/sessions/nudge_tracker.h +++ b/sync/sessions/nudge_tracker.h @@ -11,6 +11,7 @@ #include <map> #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "sync/base/sync_export.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/protocol/sync.pb.h" @@ -57,8 +58,8 @@ class SYNC_EXPORT_PRIVATE NudgeTracker { void RecordLocalRefreshRequest(ModelTypeSet types); // Takes note of the receipt of an invalidation notice from the server. - void RecordRemoteInvalidation( - const ObjectIdInvalidationMap& invalidation_map); + void RecordRemoteInvalidation(syncer::ModelType type, + scoped_ptr<InvalidationInterface> invalidation); // These functions should be called to keep this class informed of the status // of the connection to the invalidations server. @@ -137,9 +138,10 @@ class SYNC_EXPORT_PRIVATE NudgeTracker { void SetNextRetryTime(base::TimeTicks next_retry_time); private: - typedef std::map<ModelType, DataTypeTracker> TypeTrackerMap; + typedef std::map<ModelType, DataTypeTracker*> TypeTrackerMap; TypeTrackerMap type_trackers_; + STLValueDeleter<TypeTrackerMap> type_tracker_deleter_; // Merged updates source. This should be obsolete, but the server still // relies on it for some heuristics. diff --git a/sync/sessions/nudge_tracker_unittest.cc b/sync/sessions/nudge_tracker_unittest.cc index dc7f5ba..53b38a7 100644 --- a/sync/sessions/nudge_tracker_unittest.cc +++ b/sync/sessions/nudge_tracker_unittest.cc @@ -9,6 +9,9 @@ #include "sync/notifier/mock_ack_handler.h" #include "sync/notifier/object_id_invalidation_map.h" #include "sync/sessions/nudge_tracker.h" +#include "sync/test/mock_invalidation.h" +#include "sync/test/mock_invalidation_tracker.h" +#include "sync/test/trackable_mock_invalidation.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { @@ -25,14 +28,6 @@ testing::AssertionResult ModelTypeSetEquals(ModelTypeSet a, ModelTypeSet b) { } } -syncer::Invalidation BuildUnknownVersionInvalidation(ModelType type) { - invalidation::ObjectId id; - bool result = RealModelTypeToObjectId(type, &id); - DCHECK(result); - return Invalidation::InitUnknownVersion(id); -} - - } // namespace namespace sessions { @@ -72,6 +67,18 @@ class NudgeTrackerTest : public ::testing::Test { nudge_tracker_.RecordSuccessfulSyncCycle(); } + scoped_ptr<InvalidationInterface> BuildInvalidation( + int64 version, + const std::string& payload) { + return MockInvalidation::Build(version, payload) + .PassAs<InvalidationInterface>(); + } + + static scoped_ptr<InvalidationInterface> BuildUnknownVersionInvalidation() { + return MockInvalidation::BuildUnknownVersion() + .PassAs<InvalidationInterface>(); + } + protected: NudgeTracker nudge_tracker_; }; @@ -119,9 +126,8 @@ TEST_F(NudgeTrackerTest, SourcePriorities) { nudge_tracker_.GetLegacySource()); // An invalidation will override the refresh request source. - ObjectIdInvalidationMap invalidation_map = - BuildInvalidationMap(PREFERENCES, 1, "hint"); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation(PREFERENCES, + BuildInvalidation(1, "hint")); EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION, nudge_tracker_.GetLegacySource()); @@ -138,9 +144,8 @@ TEST_F(NudgeTrackerTest, SourcePriorities) { TEST_F(NudgeTrackerTest, HintCoalescing) { // Easy case: record one hint. { - ObjectIdInvalidationMap invalidation_map = - BuildInvalidationMap(BOOKMARKS, 1, "bm_hint_1"); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation(BOOKMARKS, + BuildInvalidation(1, "bm_hint_1")); sync_pb::GetUpdateTriggers gu_trigger; nudge_tracker_.FillProtoMessage(BOOKMARKS, &gu_trigger); @@ -151,9 +156,8 @@ TEST_F(NudgeTrackerTest, HintCoalescing) { // Record a second hint for the same type. { - ObjectIdInvalidationMap invalidation_map = - BuildInvalidationMap(BOOKMARKS, 2, "bm_hint_2"); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation(BOOKMARKS, + BuildInvalidation(2, "bm_hint_2")); sync_pb::GetUpdateTriggers gu_trigger; nudge_tracker_.FillProtoMessage(BOOKMARKS, &gu_trigger); @@ -167,9 +171,8 @@ TEST_F(NudgeTrackerTest, HintCoalescing) { // Record a hint for a different type. { - ObjectIdInvalidationMap invalidation_map = - BuildInvalidationMap(PASSWORDS, 1, "pw_hint_1"); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation(PASSWORDS, + BuildInvalidation(1, "pw_hint_1")); // Re-verify the bookmarks to make sure they're unaffected. sync_pb::GetUpdateTriggers bm_gu_trigger; @@ -192,9 +195,8 @@ TEST_F(NudgeTrackerTest, HintCoalescing) { // Test the dropping of invalidation hints. Receives invalidations one by one. TEST_F(NudgeTrackerTest, DropHintsLocally_OneAtATime) { for (size_t i = 0; i < GetHintBufferSize(); ++i) { - ObjectIdInvalidationMap invalidation_map = - BuildInvalidationMap(BOOKMARKS, i, "hint"); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation(BOOKMARKS, + BuildInvalidation(i, "hint")); } { sync_pb::GetUpdateTriggers gu_trigger; @@ -205,9 +207,8 @@ TEST_F(NudgeTrackerTest, DropHintsLocally_OneAtATime) { } // Force an overflow. - ObjectIdInvalidationMap invalidation_map2 = - BuildInvalidationMap(BOOKMARKS, 1000, "new_hint"); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map2); + nudge_tracker_.RecordRemoteInvalidation(BOOKMARKS, + BuildInvalidation(1000, "new_hint")); { sync_pb::GetUpdateTriggers gu_trigger; @@ -224,52 +225,11 @@ TEST_F(NudgeTrackerTest, DropHintsLocally_OneAtATime) { } } -// Test the dropping of invalidation hints. -// Receives invalidations in large batches. -TEST_F(NudgeTrackerTest, DropHintsLocally_ManyHints) { - ObjectIdInvalidationMap invalidation_map; - for (size_t i = 0; i < GetHintBufferSize(); ++i) { - invalidation_map.Insert(BuildInvalidation(BOOKMARKS, i, "hint")); - } - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); - { - sync_pb::GetUpdateTriggers gu_trigger; - nudge_tracker_.FillProtoMessage(BOOKMARKS, &gu_trigger); - EXPECT_EQ(GetHintBufferSize(), - static_cast<size_t>(gu_trigger.notification_hint_size())); - EXPECT_FALSE(gu_trigger.client_dropped_hints()); - } - - // Force an overflow. - ObjectIdInvalidationMap invalidation_map2; - invalidation_map2.Insert(BuildInvalidation(BOOKMARKS, 1000, "new_hint")); - invalidation_map2.Insert(BuildInvalidation(BOOKMARKS, 1001, "newer_hint")); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map2); - - { - sync_pb::GetUpdateTriggers gu_trigger; - nudge_tracker_.FillProtoMessage(BOOKMARKS, &gu_trigger); - EXPECT_TRUE(gu_trigger.client_dropped_hints()); - ASSERT_EQ(GetHintBufferSize(), - static_cast<size_t>(gu_trigger.notification_hint_size())); - - // Verify the newest hints were not dropped and are the last in the list. - EXPECT_EQ("newer_hint", - gu_trigger.notification_hint(GetHintBufferSize()-1)); - EXPECT_EQ("new_hint", gu_trigger.notification_hint(GetHintBufferSize()-2)); - - // Verify the oldest hint, too. - EXPECT_EQ("hint", gu_trigger.notification_hint(0)); - } -} - // Tests the receipt of 'unknown version' invalidations. TEST_F(NudgeTrackerTest, DropHintsAtServer_Alone) { - ObjectIdInvalidationMap invalidation_map; - invalidation_map.Insert(BuildUnknownVersionInvalidation(BOOKMARKS)); - // Record the unknown version invalidation. - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation(BOOKMARKS, + BuildUnknownVersionInvalidation()); { sync_pb::GetUpdateTriggers gu_trigger; nudge_tracker_.FillProtoMessage(BOOKMARKS, &gu_trigger); @@ -292,12 +252,12 @@ TEST_F(NudgeTrackerTest, DropHintsAtServer_Alone) { // Tests the receipt of 'unknown version' invalidations. This test also // includes a known version invalidation to mix things up a bit. TEST_F(NudgeTrackerTest, DropHintsAtServer_WithOtherInvalidations) { - ObjectIdInvalidationMap invalidation_map; - invalidation_map.Insert(BuildUnknownVersionInvalidation(BOOKMARKS)); - invalidation_map.Insert(BuildInvalidation(BOOKMARKS, 10, "hint")); + // Record the two invalidations, one with unknown version, the other known. + nudge_tracker_.RecordRemoteInvalidation(BOOKMARKS, + BuildUnknownVersionInvalidation()); + nudge_tracker_.RecordRemoteInvalidation(BOOKMARKS, + BuildInvalidation(10, "hint")); - // Record the two invalidations, one with unknown version, the other unknown. - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); { sync_pb::GetUpdateTriggers gu_trigger; nudge_tracker_.FillProtoMessage(BOOKMARKS, &gu_trigger); @@ -400,9 +360,8 @@ TEST_F(NudgeTrackerTest, IsSyncRequired) { EXPECT_FALSE(nudge_tracker_.IsSyncRequired()); // Invalidations. - ObjectIdInvalidationMap invalidation_map = - BuildInvalidationMap(PREFERENCES, 1, "hint"); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation(PREFERENCES, + BuildInvalidation(1, "hint")); EXPECT_TRUE(nudge_tracker_.IsSyncRequired()); nudge_tracker_.RecordSuccessfulSyncCycle(); EXPECT_FALSE(nudge_tracker_.IsSyncRequired()); @@ -425,9 +384,8 @@ TEST_F(NudgeTrackerTest, IsGetUpdatesRequired) { EXPECT_FALSE(nudge_tracker_.IsGetUpdatesRequired()); // Invalidations. - ObjectIdInvalidationMap invalidation_map = - BuildInvalidationMap(PREFERENCES, 1, "hint"); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation(PREFERENCES, + BuildInvalidation(1, "hint")); EXPECT_TRUE(nudge_tracker_.IsGetUpdatesRequired()); nudge_tracker_.RecordSuccessfulSyncCycle(); EXPECT_FALSE(nudge_tracker_.IsGetUpdatesRequired()); @@ -744,60 +702,48 @@ class NudgeTrackerAckTrackingTest : public NudgeTrackerTest { public: NudgeTrackerAckTrackingTest() {} - bool IsInvalidationUnacknowledged(const syncer::Invalidation& invalidation) { - // Run pending tasks before checking with the MockAckHandler. - // The WeakHandle may have posted some tasks for it. - base::RunLoop().RunUntilIdle(); - return mock_ack_handler_.IsUnacked(invalidation); + bool IsInvalidationUnacknowledged(int tracking_id) { + return tracker_.IsUnacked(tracking_id); } - bool IsInvalidationAcknowledged(const syncer::Invalidation& invalidation) { - // Run pending tasks before checking with the MockAckHandler. - // The WeakHandle may have posted some tasks for it. - base::RunLoop().RunUntilIdle(); - return mock_ack_handler_.IsAcknowledged(invalidation); + bool IsInvalidationAcknowledged(int tracking_id) { + return tracker_.IsAcknowledged(tracking_id); } - bool IsInvalidationDropped(const syncer::Invalidation& invalidation) { - // Run pending tasks before checking with the MockAckHandler. - // The WeakHandle may have posted some tasks for it. - base::RunLoop().RunUntilIdle(); - return mock_ack_handler_.IsDropped(invalidation); + bool IsInvalidationDropped(int tracking_id) { + return tracker_.IsDropped(tracking_id); } - bool AllInvalidationsAccountedFor() { - return mock_ack_handler_.AllInvalidationsAccountedFor(); - } - - Invalidation SendInvalidation( - ModelType type, - int64 version, - const std::string& hint) { + int SendInvalidation(ModelType type, int version, const std::string& hint) { // Build and register the invalidation. - syncer::Invalidation invalidation = BuildInvalidation(type, version, hint); - mock_ack_handler_.RegisterInvalidation(&invalidation); + scoped_ptr<TrackableMockInvalidation> inv = + tracker_.IssueInvalidation(version, hint); + int id = inv->GetTrackingId(); // Send it to the NudgeTracker. - ObjectIdInvalidationMap invalidation_map; - invalidation_map.Insert(invalidation); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation( + type, inv.PassAs<InvalidationInterface>()); - // Return it to the test framework for use in assertions. - return invalidation; + // Return its ID to the test framework for use in assertions. + return id; } - Invalidation SendUnknownVersionInvalidation(ModelType type) { + int SendUnknownVersionInvalidation(ModelType type) { // Build and register the invalidation. - syncer::Invalidation invalidation = BuildUnknownVersionInvalidation(type); - mock_ack_handler_.RegisterInvalidation(&invalidation); + scoped_ptr<TrackableMockInvalidation> inv = + tracker_.IssueUnknownVersionInvalidation(); + int id = inv->GetTrackingId(); // Send it to the NudgeTracker. - ObjectIdInvalidationMap invalidation_map; - invalidation_map.Insert(invalidation); - nudge_tracker_.RecordRemoteInvalidation(invalidation_map); + nudge_tracker_.RecordRemoteInvalidation( + type, inv.PassAs<InvalidationInterface>()); + + // Return its ID to the test framework for use in assertions. + return id; + } - // Return it to the test framework for use in assertions. - return invalidation; + bool AllInvalidationsAccountedFor() const { + return tracker_.AllInvalidationsAccountedFor(); } void RecordSuccessfulSyncCycle() { @@ -805,109 +751,110 @@ class NudgeTrackerAckTrackingTest : public NudgeTrackerTest { } private: - syncer::MockAckHandler mock_ack_handler_; - base::MessageLoop loop_; + MockInvalidationTracker tracker_; }; // Test the acknowledgement of a single invalidation. TEST_F(NudgeTrackerAckTrackingTest, SimpleAcknowledgement) { - Invalidation inv = SendInvalidation(BOOKMARKS, 10, "hint"); + int inv_id = SendInvalidation(BOOKMARKS, 10, "hint"); - EXPECT_TRUE(IsInvalidationUnacknowledged(inv)); + EXPECT_TRUE(IsInvalidationUnacknowledged(inv_id)); RecordSuccessfulSyncCycle(); - EXPECT_TRUE(IsInvalidationAcknowledged(inv)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv_id)); EXPECT_TRUE(AllInvalidationsAccountedFor()); } // Test the acknowledgement of many invalidations. TEST_F(NudgeTrackerAckTrackingTest, ManyAcknowledgements) { - Invalidation inv1 = SendInvalidation(BOOKMARKS, 10, "hint"); - Invalidation inv2 = SendInvalidation(BOOKMARKS, 14, "hint2"); - Invalidation inv3 = SendInvalidation(PREFERENCES, 8, "hint3"); + int inv1_id = SendInvalidation(BOOKMARKS, 10, "hint"); + int inv2_id = SendInvalidation(BOOKMARKS, 14, "hint2"); + int inv3_id = SendInvalidation(PREFERENCES, 8, "hint3"); - EXPECT_TRUE(IsInvalidationUnacknowledged(inv1)); - EXPECT_TRUE(IsInvalidationUnacknowledged(inv2)); - EXPECT_TRUE(IsInvalidationUnacknowledged(inv3)); + EXPECT_TRUE(IsInvalidationUnacknowledged(inv1_id)); + EXPECT_TRUE(IsInvalidationUnacknowledged(inv2_id)); + EXPECT_TRUE(IsInvalidationUnacknowledged(inv3_id)); RecordSuccessfulSyncCycle(); - EXPECT_TRUE(IsInvalidationAcknowledged(inv1)); - EXPECT_TRUE(IsInvalidationAcknowledged(inv2)); - EXPECT_TRUE(IsInvalidationAcknowledged(inv3)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv1_id)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv2_id)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv3_id)); EXPECT_TRUE(AllInvalidationsAccountedFor()); } // Test dropping when the buffer overflows and subsequent drop recovery. TEST_F(NudgeTrackerAckTrackingTest, OverflowAndRecover) { - std::vector<Invalidation> invalidations; + std::vector<int> invalidation_ids; - Invalidation inv10 = SendInvalidation(BOOKMARKS, 10, "hint"); + int inv10_id = SendInvalidation(BOOKMARKS, 10, "hint"); for (size_t i = 1; i < GetHintBufferSize(); ++i) { - invalidations.push_back(SendInvalidation(BOOKMARKS, i+10, "hint")); + invalidation_ids.push_back(SendInvalidation(BOOKMARKS, i + 10, "hint")); } - for (std::vector<Invalidation>::iterator it = invalidations.begin(); - it != invalidations.end(); ++it) { + for (std::vector<int>::iterator it = invalidation_ids.begin(); + it != invalidation_ids.end(); + ++it) { EXPECT_TRUE(IsInvalidationUnacknowledged(*it)); } // This invalidation, though arriving the most recently, has the oldest // version number so it should be dropped first. - Invalidation inv5 = SendInvalidation(BOOKMARKS, 5, "old_hint"); - EXPECT_TRUE(IsInvalidationDropped(inv5)); + int inv5_id = SendInvalidation(BOOKMARKS, 5, "old_hint"); + EXPECT_TRUE(IsInvalidationDropped(inv5_id)); // This invalidation has a larger version number, so it will force a // previously delivered invalidation to be dropped. - Invalidation inv100 = SendInvalidation(BOOKMARKS, 100, "new_hint"); - EXPECT_TRUE(IsInvalidationDropped(inv10)); + int inv100_id = SendInvalidation(BOOKMARKS, 100, "new_hint"); + EXPECT_TRUE(IsInvalidationDropped(inv10_id)); // This should recover from the drop and bring us back into sync. RecordSuccessfulSyncCycle(); - for (std::vector<Invalidation>::iterator it = invalidations.begin(); - it != invalidations.end(); ++it) { + for (std::vector<int>::iterator it = invalidation_ids.begin(); + it != invalidation_ids.end(); + ++it) { EXPECT_TRUE(IsInvalidationAcknowledged(*it)); } - EXPECT_TRUE(IsInvalidationAcknowledged(inv100)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv100_id)); EXPECT_TRUE(AllInvalidationsAccountedFor()); } // Test receipt of an unknown version invalidation from the server. TEST_F(NudgeTrackerAckTrackingTest, UnknownVersionFromServer_Simple) { - Invalidation inv = SendUnknownVersionInvalidation(BOOKMARKS); - EXPECT_TRUE(IsInvalidationUnacknowledged(inv)); + int inv_id = SendUnknownVersionInvalidation(BOOKMARKS); + EXPECT_TRUE(IsInvalidationUnacknowledged(inv_id)); RecordSuccessfulSyncCycle(); - EXPECT_TRUE(IsInvalidationAcknowledged(inv)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv_id)); EXPECT_TRUE(AllInvalidationsAccountedFor()); } // Test receipt of multiple unknown version invalidations from the server. TEST_F(NudgeTrackerAckTrackingTest, UnknownVersionFromServer_Complex) { - Invalidation inv1 = SendUnknownVersionInvalidation(BOOKMARKS); - Invalidation inv2 = SendInvalidation(BOOKMARKS, 10, "hint"); - Invalidation inv3 = SendUnknownVersionInvalidation(BOOKMARKS); - Invalidation inv4 = SendUnknownVersionInvalidation(BOOKMARKS); - Invalidation inv5 = SendInvalidation(BOOKMARKS, 20, "hint2"); + int inv1_id = SendUnknownVersionInvalidation(BOOKMARKS); + int inv2_id = SendInvalidation(BOOKMARKS, 10, "hint"); + int inv3_id = SendUnknownVersionInvalidation(BOOKMARKS); + int inv4_id = SendUnknownVersionInvalidation(BOOKMARKS); + int inv5_id = SendInvalidation(BOOKMARKS, 20, "hint2"); // These invalidations have been overridden, so they got acked early. - EXPECT_TRUE(IsInvalidationAcknowledged(inv1)); - EXPECT_TRUE(IsInvalidationAcknowledged(inv3)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv1_id)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv3_id)); // These invalidations are still waiting to be used. - EXPECT_TRUE(IsInvalidationUnacknowledged(inv2)); - EXPECT_TRUE(IsInvalidationUnacknowledged(inv4)); - EXPECT_TRUE(IsInvalidationUnacknowledged(inv5)); + EXPECT_TRUE(IsInvalidationUnacknowledged(inv2_id)); + EXPECT_TRUE(IsInvalidationUnacknowledged(inv4_id)); + EXPECT_TRUE(IsInvalidationUnacknowledged(inv5_id)); // Finish the sync cycle and expect all remaining invalidations to be acked. RecordSuccessfulSyncCycle(); - EXPECT_TRUE(IsInvalidationAcknowledged(inv1)); - EXPECT_TRUE(IsInvalidationAcknowledged(inv2)); - EXPECT_TRUE(IsInvalidationAcknowledged(inv3)); - EXPECT_TRUE(IsInvalidationAcknowledged(inv4)); - EXPECT_TRUE(IsInvalidationAcknowledged(inv5)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv1_id)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv2_id)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv3_id)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv4_id)); + EXPECT_TRUE(IsInvalidationAcknowledged(inv5_id)); EXPECT_TRUE(AllInvalidationsAccountedFor()); } diff --git a/sync/sync_internal_api.gypi b/sync/sync_internal_api.gypi index 6920ea0..1ff913f 100644 --- a/sync/sync_internal_api.gypi +++ b/sync/sync_internal_api.gypi @@ -64,6 +64,8 @@ 'internal_api/public/base/enum_set.h', 'internal_api/public/base/invalidation.cc', 'internal_api/public/base/invalidation.h', + 'internal_api/public/base/invalidation_interface.cc', + 'internal_api/public/base/invalidation_interface.h', 'internal_api/public/base/invalidator_state.cc', 'internal_api/public/base/invalidator_state.h', 'internal_api/public/base/model_type.h', diff --git a/sync/sync_notifier.gypi b/sync/sync_notifier.gypi index 9c6dc38..dbbc232 100644 --- a/sync/sync_notifier.gypi +++ b/sync/sync_notifier.gypi @@ -25,8 +25,6 @@ 'sources': [ 'notifier/ack_handler.cc', 'notifier/ack_handler.h', - 'notifier/dropped_invalidation_tracker.cc', - 'notifier/dropped_invalidation_tracker.h', 'notifier/invalidation_handler.h', 'notifier/invalidation_state_tracker.cc', 'notifier/invalidation_state_tracker.h', diff --git a/sync/sync_tests.gypi b/sync/sync_tests.gypi index 416cd8a..1b48fe4 100644 --- a/sync/sync_tests.gypi +++ b/sync/sync_tests.gypi @@ -59,6 +59,12 @@ 'test/fake_encryptor.h', 'test/fake_sync_encryption_handler.cc', 'test/fake_sync_encryption_handler.h', + 'test/mock_invalidation.cc', + 'test/mock_invalidation.h', + 'test/mock_invalidation_tracker.cc', + 'test/mock_invalidation_tracker.h', + 'test/trackable_mock_invalidation.cc', + 'test/trackable_mock_invalidation.h', 'test/null_directory_change_delegate.cc', 'test/null_directory_change_delegate.h', 'test/null_transaction_observer.cc', diff --git a/sync/test/engine/fake_sync_scheduler.cc b/sync/test/engine/fake_sync_scheduler.cc index acbd701..9fbbf14 100644 --- a/sync/test/engine/fake_sync_scheduler.cc +++ b/sync/test/engine/fake_sync_scheduler.cc @@ -30,7 +30,8 @@ void FakeSyncScheduler::ScheduleLocalRefreshRequest( void FakeSyncScheduler::ScheduleInvalidationNudge( const base::TimeDelta& desired_delay, - const ObjectIdInvalidationMap& invalidation_map, + syncer::ModelType type, + scoped_ptr<InvalidationInterface> interface, const tracked_objects::Location& nudge_location) { } diff --git a/sync/test/engine/fake_sync_scheduler.h b/sync/test/engine/fake_sync_scheduler.h index 9da8a0f..c43e503 100644 --- a/sync/test/engine/fake_sync_scheduler.h +++ b/sync/test/engine/fake_sync_scheduler.h @@ -31,7 +31,8 @@ class FakeSyncScheduler : public SyncScheduler { const tracked_objects::Location& nudge_location) OVERRIDE; virtual void ScheduleInvalidationNudge( const base::TimeDelta& desired_delay, - const ObjectIdInvalidationMap& invalidation_map, + syncer::ModelType type, + scoped_ptr<InvalidationInterface> interface, const tracked_objects::Location& nudge_location) OVERRIDE; virtual void ScheduleConfiguration( const ConfigurationParams& params) OVERRIDE; diff --git a/sync/test/mock_invalidation.cc b/sync/test/mock_invalidation.cc new file mode 100644 index 0000000..bfcb3c3 --- /dev/null +++ b/sync/test/mock_invalidation.cc @@ -0,0 +1,57 @@ +// Copyright 2014 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 "sync/test/mock_invalidation.h" + +#include "base/logging.h" +#include "sync/test/mock_invalidation_tracker.h" + +namespace syncer { + +scoped_ptr<MockInvalidation> MockInvalidation::BuildUnknownVersion() { + return scoped_ptr<MockInvalidation>( + new MockInvalidation(true, -1, std::string())); +} + +scoped_ptr<MockInvalidation> MockInvalidation::Build( + int64 version, + const std::string& payload) { + return scoped_ptr<MockInvalidation>( + new MockInvalidation(false, version, payload)); +} + +MockInvalidation::~MockInvalidation() { +} + +bool MockInvalidation::IsUnknownVersion() const { + return is_unknown_version_; +} + +const std::string& MockInvalidation::GetPayload() const { + DCHECK(!is_unknown_version_); + return payload_; +} + +int64 MockInvalidation::GetVersion() const { + DCHECK(!is_unknown_version_); + return version_; +} + +void MockInvalidation::Acknowledge() { + // Do nothing. +} + +void MockInvalidation::Drop() { + // Do nothing. +} + +MockInvalidation::MockInvalidation(bool is_unknown_version, + int64 version, + const std::string& payload) + : is_unknown_version_(is_unknown_version), + version_(version), + payload_(payload) { +} + +} // namespace syncer diff --git a/sync/test/mock_invalidation.h b/sync/test/mock_invalidation.h new file mode 100644 index 0000000..808f02c --- /dev/null +++ b/sync/test/mock_invalidation.h @@ -0,0 +1,48 @@ +// Copyright 2014 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 SYNC_TEST_MOCK_INVALIDATION_H_ +#define SYNC_TEST_MOCK_INVALIDATION_H_ + +#include "base/memory/scoped_ptr.h" +#include "sync/internal_api/public/base/invalidation_interface.h" + +namespace syncer { + +// An InvalidationInterface used by sync for testing. +// It does not support any form of acknowledgements. +class MockInvalidation : public InvalidationInterface { + public: + // Helpers to build new MockInvalidations. + static scoped_ptr<MockInvalidation> BuildUnknownVersion(); + static scoped_ptr<MockInvalidation> Build(int64 version, + const std::string& payload); + + virtual ~MockInvalidation(); + + // Implementation of InvalidationInterface. + virtual bool IsUnknownVersion() const OVERRIDE; + virtual const std::string& GetPayload() const OVERRIDE; + virtual int64 GetVersion() const OVERRIDE; + virtual void Acknowledge() OVERRIDE; + virtual void Drop() OVERRIDE; + + protected: + MockInvalidation(bool is_unknown_version, + int64 version, + const std::string& payload); + + // Whether or not this is an 'unknown version' invalidation. + const bool is_unknown_version_; + + // The version of this invalidation. Valid only if !is_unknown_version_. + const int64 version_; + + // The payload of this invalidation. Valid only if !is_unknown_version_. + const std::string payload_; +}; + +} // namespace syncer + +#endif // SYNC_TEST_MOCK_INVALIDATION_H_ diff --git a/sync/test/mock_invalidation_tracker.cc b/sync/test/mock_invalidation_tracker.cc new file mode 100644 index 0000000..6e816a6 --- /dev/null +++ b/sync/test/mock_invalidation_tracker.cc @@ -0,0 +1,63 @@ +// Copyright 2014 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 "sync/test/mock_invalidation_tracker.h" + +#include "base/logging.h" +#include "sync/test/trackable_mock_invalidation.h" + +namespace syncer { + +scoped_ptr<TrackableMockInvalidation> +MockInvalidationTracker::IssueUnknownVersionInvalidation() { + return scoped_ptr<TrackableMockInvalidation>( + new TrackableMockInvalidation(true, -1, std::string(), this, next_id_++)); +} + +scoped_ptr<TrackableMockInvalidation> +MockInvalidationTracker::IssueInvalidation(int64 version, + const std::string& payload) { + return scoped_ptr<TrackableMockInvalidation>( + new TrackableMockInvalidation(false, version, payload, this, next_id_++)); +} + +MockInvalidationTracker::MockInvalidationTracker() : next_id_(0) { +} + +MockInvalidationTracker::~MockInvalidationTracker() { +} + +void MockInvalidationTracker::Acknowledge(int invalidation_id) { + acknowledged_.insert(invalidation_id); +} + +void MockInvalidationTracker::Drop(int invalidation_id) { + dropped_.insert(invalidation_id); +} + +bool MockInvalidationTracker::IsUnacked(int invalidation_id) const { + DCHECK_LE(invalidation_id, next_id_); + return !IsAcknowledged(invalidation_id) && !IsDropped(invalidation_id); +} + +bool MockInvalidationTracker::IsAcknowledged(int invalidation_id) const { + DCHECK_LE(invalidation_id, next_id_); + return acknowledged_.find(invalidation_id) != acknowledged_.end(); +} + +bool MockInvalidationTracker::IsDropped(int invalidation_id) const { + DCHECK_LE(invalidation_id, next_id_); + return dropped_.find(invalidation_id) != dropped_.end(); +} + +bool MockInvalidationTracker::AllInvalidationsAccountedFor() const { + for (int i = 0; i < next_id_; ++i) { + if (IsUnacked(i)) { + return false; + } + } + return true; +} + +} // namespace syncer diff --git a/sync/test/mock_invalidation_tracker.h b/sync/test/mock_invalidation_tracker.h new file mode 100644 index 0000000..9f0e5bd --- /dev/null +++ b/sync/test/mock_invalidation_tracker.h @@ -0,0 +1,65 @@ +// Copyright 2014 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 SYNC_TEST_MOCK_INVALIDATION_TRACKER_H_ +#define SYNC_TEST_MOCK_INVALIDATION_TRACKER_H_ + +#include <set> + +#include "base/memory/scoped_ptr.h" +#include "sync/test/trackable_mock_invalidation.h" + +namespace syncer { + +// Instantiates and track the acknowledgement state of +// TrackableMockInvalidations. +class MockInvalidationTracker { + public: + // Builers to return new TrackableMockInvalidations associated with this + // object. + scoped_ptr<TrackableMockInvalidation> IssueUnknownVersionInvalidation(); + scoped_ptr<TrackableMockInvalidation> IssueInvalidation( + int64 version, + const std::string& payload); + + MockInvalidationTracker(); + ~MockInvalidationTracker(); + + // Records the acknowledgement of the invalidation + // specified by the given ID. + void Acknowledge(int invaliation_id); + + // Records the drop of the invalidation specified by the given ID. + void Drop(int invalidation_id); + + // Returns true if the invalidation associated with the given ID is neither + // acknowledged nor dropped. + bool IsUnacked(int invalidation_id) const; + + // Returns true if the invalidation associated with the given ID is + // acknowledged. + bool IsAcknowledged(int invalidation_id) const; + + // Returns true if the invalidation associated with the given ID is dropped. + bool IsDropped(int invalidation_id) const; + + // Returns true if all issued invalidations were acknowledged or dropped. + bool AllInvalidationsAccountedFor() const; + + private: + // A counter used to assign strictly increasing IDs to each invalidation + // issued by this class. + int next_id_; + + // Acknowledgements and drops are tracked by adding the IDs for the + // acknowledged or dropped items to the proper set. An invalidation may be + // both dropped and acknowledged if it represents the recovery from a drop + // event. + std::set<int> dropped_; + std::set<int> acknowledged_; +}; + +} // namespace syncer + +#endif // SYNC_TEST_MOCK_INVALIDATION_TRACKER_H_ diff --git a/sync/test/trackable_mock_invalidation.cc b/sync/test/trackable_mock_invalidation.cc new file mode 100644 index 0000000..0f00814 --- /dev/null +++ b/sync/test/trackable_mock_invalidation.cc @@ -0,0 +1,41 @@ +// Copyright 2014 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 "sync/test/trackable_mock_invalidation.h" + +#include "sync/test/mock_invalidation_tracker.h" + +namespace syncer { + +TrackableMockInvalidation::TrackableMockInvalidation( + bool is_unknown_version, + int64 version, + const std::string& payload, + MockInvalidationTracker* tracker, + int tracking_id) + : MockInvalidation(is_unknown_version, version, payload), + tracker_(tracker), + tracking_id_(tracking_id) { +} + +TrackableMockInvalidation::~TrackableMockInvalidation() { +} + +void TrackableMockInvalidation::Acknowledge() { + if (tracker_) { + tracker_->Acknowledge(tracking_id_); + } +} + +void TrackableMockInvalidation::Drop() { + if (tracker_) { + tracker_->Drop(tracking_id_); + } +} + +int TrackableMockInvalidation::GetTrackingId() { + return tracking_id_; +} + +} // namespace syncer diff --git a/sync/test/trackable_mock_invalidation.h b/sync/test/trackable_mock_invalidation.h new file mode 100644 index 0000000..1ad3697 --- /dev/null +++ b/sync/test/trackable_mock_invalidation.h @@ -0,0 +1,54 @@ +// Copyright 2014 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 SYNC_TEST_TRACKABLE_MOCK_INVALIDATION_H_ +#define SYNC_TEST_TRACKABLE_MOCK_INVALIDATION_H_ + +#include "sync/test/mock_invalidation.h" + +namespace syncer { + +class MockInvalidationTracker; + +// A variant of MockInvalidation that supports acknowledgements. +// +// With the help of a MockInvalidationTracker, this can be used to test +// sync's use of the Drop() and Acknowledge() methods. +class TrackableMockInvalidation : public MockInvalidation { + public: + TrackableMockInvalidation(bool is_unknown_version, + int64 version, + const std::string& payload, + MockInvalidationTracker* tracker, + int tracking_id); + virtual ~TrackableMockInvalidation(); + + // Forwards notice of the acknowledgement of this invalidation to the + // |tracker_|. + virtual void Acknowledge() OVERRIDE; + + // Forwards notice of the drop of this invalidation to the |tracker_|. + virtual void Drop() OVERRIDE; + + // Returns the integer used to identify this object with the |tracker_|. + int GetTrackingId(); + + private: + // The MockInvalidationTracker that initialized this object, and which keeps + // track of its acknowledgement status. It is expected to outlive the + // invalidations. The data required for unit test assertions lives there. + MockInvalidationTracker* tracker_; + + // An identifier that uniquely identifies this invalidation to its + // |tracker_|. + // + // This is necessary in part because invalidations may be short lived; the + // invalidation may be deleted by the time we want to make assertions about + // its state. + int tracking_id_; +}; + +} // namespace syncer + +#endif // SYNC_TEST_TRACKABLE_MOCK_INVALIDATION_H_ diff --git a/sync/tools/sync_client.cc b/sync/tools/sync_client.cc index a5890cf..2b626db 100644 --- a/sync/tools/sync_client.cc +++ b/sync/tools/sync_client.cc @@ -42,6 +42,7 @@ #include "sync/internal_api/public/util/weak_handle.h" #include "sync/js/js_event_details.h" #include "sync/js/js_event_handler.h" +#include "sync/notifier/object_id_invalidation_map.h" #include "sync/test/fake_encryptor.h" #include "sync/tools/null_invalidation_state_tracker.h" @@ -184,6 +185,78 @@ class LoggingJsEventHandler } }; +class InvalidationAdapter : public syncer::InvalidationInterface { + public: + explicit InvalidationAdapter(const syncer::Invalidation& invalidation) + : invalidation_(invalidation) {} + virtual ~InvalidationAdapter() {} + + virtual bool IsUnknownVersion() const OVERRIDE { + return invalidation_.is_unknown_version(); + } + + virtual const std::string& GetPayload() const OVERRIDE { + return invalidation_.payload(); + } + + virtual int64 GetVersion() const OVERRIDE { + return invalidation_.version(); + } + + virtual void Acknowledge() OVERRIDE { + invalidation_.Acknowledge(); + } + + virtual void Drop() OVERRIDE { + invalidation_.Drop(); + } + + private: + syncer::Invalidation invalidation_; +}; + +class InvalidatorShim : public InvalidationHandler { + public: + explicit InvalidatorShim(SyncManager* sync_manager) + : sync_manager_(sync_manager) {} + + virtual void OnInvalidatorStateChange(InvalidatorState state) OVERRIDE { + sync_manager_->OnInvalidatorStateChange(state); + } + + virtual void OnIncomingInvalidation( + const ObjectIdInvalidationMap& invalidation_map) OVERRIDE { + syncer::ObjectIdSet ids = invalidation_map.GetObjectIds(); + for (syncer::ObjectIdSet::const_iterator ids_it = ids.begin(); + ids_it != ids.end(); + ++ids_it) { + syncer::ModelType type; + if (!NotificationTypeToRealModelType(ids_it->name(), &type)) { + DLOG(WARNING) << "Notification has invalid id: " + << syncer::ObjectIdToString(*ids_it); + } else { + syncer::SingleObjectInvalidationSet invalidation_set = + invalidation_map.ForObject(*ids_it); + for (syncer::SingleObjectInvalidationSet::const_iterator inv_it = + invalidation_set.begin(); + inv_it != invalidation_set.end(); + ++inv_it) { + scoped_ptr<syncer::InvalidationInterface> inv_adapter( + new InvalidationAdapter(*inv_it)); + sync_manager_->OnIncomingInvalidation(type, inv_adapter.Pass()); + } + } + } + } + + virtual std::string GetOwnerName() const OVERRIDE { + return "InvalidatorShim"; + } + + private: + SyncManager* sync_manager_; +}; + void LogUnrecoverableErrorContext() { base::debug::StackTrace().Print(); } @@ -380,9 +453,10 @@ int SyncClientMain(int argc, char* argv[]) { // TODO(akalin): Avoid passing in model parameters multiple times by // organizing handling of model types. invalidator->UpdateCredentials(credentials.email, credentials.sync_token); - invalidator->RegisterHandler(sync_manager.get()); + scoped_ptr<InvalidatorShim> shim(new InvalidatorShim(sync_manager.get())); + invalidator->RegisterHandler(shim.get()); invalidator->UpdateRegisteredIds( - sync_manager.get(), ModelTypeSetToObjectIdSet(model_types)); + shim.get(), ModelTypeSetToObjectIdSet(model_types)); sync_manager->StartSyncingNormally(routing_info); sync_loop.Run(); |