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