1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "sync/notifier/invalidator_registrar.h" 6 7 #include <cstddef> 8 #include <iterator> 9 #include <utility> 10 11 #include "base/logging.h" 12 #include "sync/notifier/object_id_invalidation_map.h" 13 14 namespace syncer { 15 16 InvalidatorRegistrar::InvalidatorRegistrar() 17 : state_(DEFAULT_INVALIDATION_ERROR) {} 18 19 InvalidatorRegistrar::~InvalidatorRegistrar() { 20 DCHECK(thread_checker_.CalledOnValidThread()); 21 CHECK(!handlers_.might_have_observers()); 22 CHECK(handler_to_ids_map_.empty()); 23 } 24 25 void InvalidatorRegistrar::RegisterHandler(InvalidationHandler* handler) { 26 DCHECK(thread_checker_.CalledOnValidThread()); 27 CHECK(handler); 28 CHECK(!handlers_.HasObserver(handler)); 29 handlers_.AddObserver(handler); 30 } 31 32 void InvalidatorRegistrar::UpdateRegisteredIds( 33 InvalidationHandler* handler, 34 const ObjectIdSet& ids) { 35 DCHECK(thread_checker_.CalledOnValidThread()); 36 CHECK(handler); 37 CHECK(handlers_.HasObserver(handler)); 38 39 for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin(); 40 it != handler_to_ids_map_.end(); ++it) { 41 if (it->first == handler) { 42 continue; 43 } 44 45 std::vector<invalidation::ObjectId> intersection; 46 std::set_intersection( 47 it->second.begin(), it->second.end(), 48 ids.begin(), ids.end(), 49 std::inserter(intersection, intersection.end()), 50 ObjectIdLessThan()); 51 CHECK(intersection.empty()) 52 << "Duplicate registration: trying to register " 53 << ObjectIdToString(*intersection.begin()) << " for " 54 << handler << " when it's already registered for " 55 << it->first; 56 } 57 58 if (ids.empty()) { 59 handler_to_ids_map_.erase(handler); 60 } else { 61 handler_to_ids_map_[handler] = ids; 62 } 63 } 64 65 void InvalidatorRegistrar::UnregisterHandler(InvalidationHandler* handler) { 66 DCHECK(thread_checker_.CalledOnValidThread()); 67 CHECK(handler); 68 CHECK(handlers_.HasObserver(handler)); 69 handlers_.RemoveObserver(handler); 70 handler_to_ids_map_.erase(handler); 71 } 72 73 ObjectIdSet InvalidatorRegistrar::GetRegisteredIds( 74 InvalidationHandler* handler) const { 75 DCHECK(thread_checker_.CalledOnValidThread()); 76 HandlerIdsMap::const_iterator lookup = handler_to_ids_map_.find(handler); 77 if (lookup != handler_to_ids_map_.end()) { 78 return lookup->second; 79 } else { 80 return ObjectIdSet(); 81 } 82 } 83 84 ObjectIdSet InvalidatorRegistrar::GetAllRegisteredIds() const { 85 DCHECK(thread_checker_.CalledOnValidThread()); 86 ObjectIdSet registered_ids; 87 for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin(); 88 it != handler_to_ids_map_.end(); ++it) { 89 registered_ids.insert(it->second.begin(), it->second.end()); 90 } 91 return registered_ids; 92 } 93 94 void InvalidatorRegistrar::DispatchInvalidationsToHandlers( 95 const ObjectIdInvalidationMap& invalidation_map) { 96 DCHECK(thread_checker_.CalledOnValidThread()); 97 // If we have no handlers, there's nothing to do. 98 if (!handlers_.might_have_observers()) { 99 return; 100 } 101 102 for (HandlerIdsMap::iterator it = handler_to_ids_map_.begin(); 103 it != handler_to_ids_map_.end(); ++it) { 104 ObjectIdInvalidationMap to_emit = 105 invalidation_map.GetSubsetWithObjectIds(it->second); 106 if (!to_emit.Empty()) { 107 it->first->OnIncomingInvalidation(to_emit); 108 } 109 } 110 } 111 112 void InvalidatorRegistrar::UpdateInvalidatorState(InvalidatorState state) { 113 DCHECK(thread_checker_.CalledOnValidThread()); 114 DVLOG(1) << "New invalidator state: " << InvalidatorStateToString(state_) 115 << " -> " << InvalidatorStateToString(state); 116 state_ = state; 117 FOR_EACH_OBSERVER(InvalidationHandler, handlers_, 118 OnInvalidatorStateChange(state)); 119 } 120 121 InvalidatorState InvalidatorRegistrar::GetInvalidatorState() const { 122 DCHECK(thread_checker_.CalledOnValidThread()); 123 return state_; 124 } 125 126 bool InvalidatorRegistrar::IsHandlerRegisteredForTest( 127 InvalidationHandler* handler) const { 128 DCHECK(thread_checker_.CalledOnValidThread()); 129 return handlers_.HasObserver(handler); 130 } 131 132 void InvalidatorRegistrar::DetachFromThreadForTest() { 133 DCHECK(thread_checker_.CalledOnValidThread()); 134 thread_checker_.DetachFromThread(); 135 } 136 137 } // namespace syncer 138