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 <utility> 9 10 #include "base/logging.h" 11 12 namespace syncer { 13 14 InvalidatorRegistrar::InvalidatorRegistrar() 15 : state_(DEFAULT_INVALIDATION_ERROR) {} 16 17 InvalidatorRegistrar::~InvalidatorRegistrar() { 18 DCHECK(thread_checker_.CalledOnValidThread()); 19 CHECK(!handlers_.might_have_observers()); 20 // |id_to_handler_map_| may be non-empty but that's okay. 21 } 22 23 void InvalidatorRegistrar::RegisterHandler(InvalidationHandler* handler) { 24 DCHECK(thread_checker_.CalledOnValidThread()); 25 CHECK(handler); 26 CHECK(!handlers_.HasObserver(handler)); 27 handlers_.AddObserver(handler); 28 } 29 30 void InvalidatorRegistrar::UpdateRegisteredIds( 31 InvalidationHandler* handler, 32 const ObjectIdSet& ids) { 33 DCHECK(thread_checker_.CalledOnValidThread()); 34 CHECK(handler); 35 CHECK(handlers_.HasObserver(handler)); 36 // Remove all existing entries for |handler|. 37 for (IdHandlerMap::iterator it = id_to_handler_map_.begin(); 38 it != id_to_handler_map_.end(); ) { 39 if (it->second == handler) { 40 IdHandlerMap::iterator erase_it = it; 41 ++it; 42 id_to_handler_map_.erase(erase_it); 43 } else { 44 ++it; 45 } 46 } 47 48 // Now add the entries for |handler|. We keep track of the last insertion 49 // point so we only traverse the map once to insert all the new entries. 50 IdHandlerMap::iterator insert_it = id_to_handler_map_.begin(); 51 for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) { 52 insert_it = 53 id_to_handler_map_.insert(insert_it, std::make_pair(*it, handler)); 54 CHECK_EQ(handler, insert_it->second) 55 << "Duplicate registration: trying to register " 56 << ObjectIdToString(insert_it->first) << " for " 57 << handler << " when it's already registered for " 58 << insert_it->second; 59 } 60 } 61 62 void InvalidatorRegistrar::UnregisterHandler(InvalidationHandler* handler) { 63 DCHECK(thread_checker_.CalledOnValidThread()); 64 CHECK(handler); 65 CHECK(handlers_.HasObserver(handler)); 66 handlers_.RemoveObserver(handler); 67 } 68 69 ObjectIdSet InvalidatorRegistrar::GetRegisteredIds( 70 InvalidationHandler* handler) const { 71 DCHECK(thread_checker_.CalledOnValidThread()); 72 ObjectIdSet registered_ids; 73 for (IdHandlerMap::const_iterator it = id_to_handler_map_.begin(); 74 it != id_to_handler_map_.end(); ++it) { 75 if (it->second == handler) { 76 registered_ids.insert(it->first); 77 } 78 } 79 return registered_ids; 80 } 81 82 ObjectIdSet InvalidatorRegistrar::GetAllRegisteredIds() const { 83 DCHECK(thread_checker_.CalledOnValidThread()); 84 ObjectIdSet registered_ids; 85 for (IdHandlerMap::const_iterator it = id_to_handler_map_.begin(); 86 it != id_to_handler_map_.end(); ++it) { 87 registered_ids.insert(it->first); 88 } 89 return registered_ids; 90 } 91 92 void InvalidatorRegistrar::DispatchInvalidationsToHandlers( 93 const ObjectIdInvalidationMap& invalidation_map) { 94 DCHECK(thread_checker_.CalledOnValidThread()); 95 // If we have no handlers, there's nothing to do. 96 if (!handlers_.might_have_observers()) { 97 return; 98 } 99 100 typedef std::map<InvalidationHandler*, ObjectIdInvalidationMap> DispatchMap; 101 DispatchMap dispatch_map; 102 for (ObjectIdInvalidationMap::const_iterator it = invalidation_map.begin(); 103 it != invalidation_map.end(); ++it) { 104 InvalidationHandler* const handler = ObjectIdToHandler(it->first); 105 // Filter out invalidations for IDs with no handler. 106 if (handler) 107 dispatch_map[handler].insert(*it); 108 } 109 110 // Emit invalidations only for handlers in |handlers_|. 111 ObserverListBase<InvalidationHandler>::Iterator it(handlers_); 112 InvalidationHandler* handler = NULL; 113 while ((handler = it.GetNext()) != NULL) { 114 DispatchMap::const_iterator dispatch_it = dispatch_map.find(handler); 115 if (dispatch_it != dispatch_map.end()) 116 handler->OnIncomingInvalidation(dispatch_it->second); 117 } 118 } 119 120 void InvalidatorRegistrar::UpdateInvalidatorState(InvalidatorState state) { 121 DCHECK(thread_checker_.CalledOnValidThread()); 122 DVLOG(1) << "New invalidator state: " << InvalidatorStateToString(state_) 123 << " -> " << InvalidatorStateToString(state); 124 state_ = state; 125 FOR_EACH_OBSERVER(InvalidationHandler, handlers_, 126 OnInvalidatorStateChange(state)); 127 } 128 129 InvalidatorState InvalidatorRegistrar::GetInvalidatorState() const { 130 DCHECK(thread_checker_.CalledOnValidThread()); 131 return state_; 132 } 133 134 bool InvalidatorRegistrar::IsHandlerRegisteredForTest( 135 InvalidationHandler* handler) const { 136 DCHECK(thread_checker_.CalledOnValidThread()); 137 return handlers_.HasObserver(handler); 138 } 139 140 void InvalidatorRegistrar::DetachFromThreadForTest() { 141 DCHECK(thread_checker_.CalledOnValidThread()); 142 thread_checker_.DetachFromThread(); 143 } 144 145 InvalidationHandler* InvalidatorRegistrar::ObjectIdToHandler( 146 const invalidation::ObjectId& id) { 147 DCHECK(thread_checker_.CalledOnValidThread()); 148 IdHandlerMap::const_iterator it = id_to_handler_map_.find(id); 149 return (it == id_to_handler_map_.end()) ? NULL : it->second; 150 } 151 152 } // namespace syncer 153