Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: chrome/browser/invalidation/invalidator_storage.cc

Issue 56113003: Implement new invalidations ack tracking system (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Modify drive TODO comment + rebase Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "chrome/browser/invalidation/invalidator_storage.h" 5 #include "chrome/browser/invalidation/invalidator_storage.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/prefs/pref_service.h" 13 #include "base/prefs/pref_service.h"
14 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/task_runner.h" 15 #include "base/task_runner.h"
16 #include "base/values.h" 16 #include "base/values.h"
17 #include "chrome/common/pref_names.h" 17 #include "chrome/common/pref_names.h"
18 #include "components/user_prefs/pref_registry_syncable.h" 18 #include "components/user_prefs/pref_registry_syncable.h"
19 #include "sync/internal_api/public/base/model_type.h"
20
21 using syncer::InvalidationStateMap;
22 19
23 namespace { 20 namespace {
24 21
25 const char kSourceKey[] = "source"; 22 const char kInvalidatorMaxInvalidationVersions[] =
26 const char kNameKey[] = "name"; 23 "invalidator.max_invalidation_versions";
27 const char kMaxVersionKey[] = "max-version";
28 const char kPayloadKey[] = "payload";
29 const char kCurrentAckHandleKey[] = "current-ack";
30 const char kExpectedAckHandleKey[] = "expected-ack";
31 24
32 bool ValueToObjectIdAndState(const DictionaryValue& value, 25
33 invalidation::ObjectId* id, 26 bool ValueToUnackedInvalidationStorageMap(
34 syncer::InvalidationState* state) { 27 const ListValue& value,
35 std::string source_str; 28 syncer::UnackedInvalidationsMap* map) {
36 if (!value.GetString(kSourceKey, &source_str)) { 29 for (size_t i = 0; i != value.GetSize(); ++i) {
37 DLOG(WARNING) << "Unable to deserialize source"; 30 invalidation::ObjectId invalid_id;
38 return false; 31 syncer::UnackedInvalidationSet storage(invalid_id);
39 } 32 const base::DictionaryValue* dict;
40 int source = 0; 33 if (!value.GetDictionary(i, &dict) || !storage.ResetFromValue(*dict)) {
41 if (!base::StringToInt(source_str, &source)) { 34 DLOG(WARNING) << "Failed to parse ObjectState at position " << i;
42 DLOG(WARNING) << "Invalid source: " << source_str; 35 return false;
43 return false; 36 }
44 } 37 map->insert(std::make_pair(storage.object_id(), storage));
45 std::string name;
46 if (!value.GetString(kNameKey, &name)) {
47 DLOG(WARNING) << "Unable to deserialize name";
48 return false;
49 }
50 *id = invalidation::ObjectId(source, name);
51 std::string max_version_str;
52 if (!value.GetString(kMaxVersionKey, &max_version_str)) {
53 DLOG(WARNING) << "Unable to deserialize max version";
54 return false;
55 }
56 if (!base::StringToInt64(max_version_str, &state->version)) {
57 DLOG(WARNING) << "Invalid max invalidation version: " << max_version_str;
58 return false;
59 }
60 value.GetString(kPayloadKey, &state->payload);
61 // The ack handle fields won't be set if upgrading from previous versions of
62 // Chrome.
63 const base::DictionaryValue* current_ack_handle_value = NULL;
64 if (value.GetDictionary(kCurrentAckHandleKey, &current_ack_handle_value)) {
65 state->current.ResetFromValue(*current_ack_handle_value);
66 }
67 const base::DictionaryValue* expected_ack_handle_value = NULL;
68 if (value.GetDictionary(kExpectedAckHandleKey, &expected_ack_handle_value)) {
69 state->expected.ResetFromValue(*expected_ack_handle_value);
70 } else {
71 // In this case, we should never have a valid current value set.
72 DCHECK(!state->current.IsValid());
73 state->current = syncer::AckHandle::InvalidAckHandle();
74 } 38 }
75 return true; 39 return true;
76 } 40 }
77 41
78 // The caller owns the returned value. 42 scoped_ptr<base::ListValue> UnackedInvalidationStorageMapToValue(
79 DictionaryValue* ObjectIdAndStateToValue( 43 const syncer::UnackedInvalidationsMap& map) {
80 const invalidation::ObjectId& id, const syncer::InvalidationState& state) { 44 scoped_ptr<base::ListValue> value(new base::ListValue);
81 DictionaryValue* value = new DictionaryValue; 45 for (syncer::UnackedInvalidationsMap::const_iterator it = map.begin();
82 value->SetString(kSourceKey, base::IntToString(id.source())); 46 it != map.end(); ++it) {
83 value->SetString(kNameKey, id.name()); 47 value->Append(it->second.ToValue().release());
84 value->SetString(kMaxVersionKey, base::Int64ToString(state.version)); 48 }
85 value->SetString(kPayloadKey, state.payload); 49 return value.Pass();
86 if (state.current.IsValid())
87 value->Set(kCurrentAckHandleKey, state.current.ToValue().release());
88 if (state.expected.IsValid())
89 value->Set(kExpectedAckHandleKey, state.expected.ToValue().release());
90 return value;
91 } 50 }
92 51
93 } // namespace 52 } // namespace
94 53
95 namespace invalidation { 54 namespace invalidation {
96 55
97 // static 56 // static
98 void InvalidatorStorage::RegisterProfilePrefs( 57 void InvalidatorStorage::RegisterProfilePrefs(
99 user_prefs::PrefRegistrySyncable* registry) { 58 user_prefs::PrefRegistrySyncable* registry) {
100 registry->RegisterListPref(prefs::kInvalidatorMaxInvalidationVersions, 59 registry->RegisterListPref(prefs::kInvalidatorSavedInvalidations,
101 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 60 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
102 registry->RegisterStringPref( 61 registry->RegisterStringPref(
103 prefs::kInvalidatorInvalidationState, 62 prefs::kInvalidatorInvalidationState,
104 std::string(), 63 std::string(),
105 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 64 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
106 registry->RegisterStringPref( 65 registry->RegisterStringPref(
107 prefs::kInvalidatorClientId, 66 prefs::kInvalidatorClientId,
108 std::string(), 67 std::string(),
109 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 68 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
110 registry->RegisterDictionaryPref( 69
111 prefs::kSyncMaxInvalidationVersions, 70 // This pref is obsolete. We register it so we can clear it.
112 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 71 // At some point in the future, it will be safe to remove this.
72 registry->RegisterListPref(kInvalidatorMaxInvalidationVersions,
73 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
113 } 74 }
114 75
115 InvalidatorStorage::InvalidatorStorage(PrefService* pref_service) 76 InvalidatorStorage::InvalidatorStorage(PrefService* pref_service)
116 : pref_service_(pref_service) { 77 : pref_service_(pref_service) {
117 DCHECK(pref_service); 78 DCHECK(pref_service);
118 MigrateMaxInvalidationVersionsPref(); 79 pref_service_->ClearPref(kInvalidatorMaxInvalidationVersions);
119 } 80 }
120 81
121 InvalidatorStorage::~InvalidatorStorage() { 82 InvalidatorStorage::~InvalidatorStorage() {
122 } 83 }
123 84
124 InvalidationStateMap InvalidatorStorage::GetAllInvalidationStates() const {
125 DCHECK(thread_checker_.CalledOnValidThread());
126 InvalidationStateMap state_map;
127 const base::ListValue* state_map_list =
128 pref_service_->GetList(prefs::kInvalidatorMaxInvalidationVersions);
129 CHECK(state_map_list);
130 DeserializeFromList(*state_map_list, &state_map);
131 return state_map;
132 }
133
134 void InvalidatorStorage::SetMaxVersionAndPayload(
135 const invalidation::ObjectId& id,
136 int64 max_version,
137 const std::string& payload) {
138 DCHECK(thread_checker_.CalledOnValidThread());
139 InvalidationStateMap state_map = GetAllInvalidationStates();
140 InvalidationStateMap::iterator it = state_map.find(id);
141 if ((it != state_map.end()) && (max_version <= it->second.version)) {
142 NOTREACHED();
143 return;
144 }
145 state_map[id].version = max_version;
146 state_map[id].payload = payload;
147
148 base::ListValue state_map_list;
149 SerializeToList(state_map, &state_map_list);
150 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
151 state_map_list);
152 }
153
154 void InvalidatorStorage::Forget(const syncer::ObjectIdSet& ids) {
155 DCHECK(thread_checker_.CalledOnValidThread());
156 InvalidationStateMap state_map = GetAllInvalidationStates();
157 for (syncer::ObjectIdSet::const_iterator it = ids.begin(); it != ids.end();
158 ++it) {
159 state_map.erase(*it);
160 }
161
162 base::ListValue state_map_list;
163 SerializeToList(state_map, &state_map_list);
164 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
165 state_map_list);
166 }
167
168 // static
169 void InvalidatorStorage::DeserializeFromList(
170 const base::ListValue& state_map_list,
171 InvalidationStateMap* state_map) {
172 state_map->clear();
173 for (size_t i = 0; i < state_map_list.GetSize(); ++i) {
174 const DictionaryValue* value = NULL;
175 if (!state_map_list.GetDictionary(i, &value)) {
176 DLOG(WARNING) << "Unable to deserialize entry " << i;
177 continue;
178 }
179 invalidation::ObjectId id;
180 syncer::InvalidationState state;
181 if (!ValueToObjectIdAndState(*value, &id, &state)) {
182 DLOG(WARNING) << "Error while deserializing entry " << i;
183 continue;
184 }
185 (*state_map)[id] = state;
186 }
187 }
188
189 // static
190 void InvalidatorStorage::SerializeToList(
191 const InvalidationStateMap& state_map,
192 base::ListValue* state_map_list) {
193 for (InvalidationStateMap::const_iterator it = state_map.begin();
194 it != state_map.end(); ++it) {
195 state_map_list->Append(ObjectIdAndStateToValue(it->first, it->second));
196 }
197 }
198
199 // Legacy migration code.
200 void InvalidatorStorage::MigrateMaxInvalidationVersionsPref() {
201 const base::DictionaryValue* max_versions_dict =
202 pref_service_->GetDictionary(prefs::kSyncMaxInvalidationVersions);
203 CHECK(max_versions_dict);
204 if (!max_versions_dict->empty()) {
205 InvalidationStateMap state_map;
206 DeserializeMap(max_versions_dict, &state_map);
207 base::ListValue state_map_list;
208 SerializeToList(state_map, &state_map_list);
209 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
210 state_map_list);
211 UMA_HISTOGRAM_BOOLEAN("InvalidatorStorage.MigrateInvalidationVersionsPref",
212 true);
213 } else {
214 UMA_HISTOGRAM_BOOLEAN("InvalidatorStorage.MigrateInvalidationVersionsPref",
215 false);
216 }
217 pref_service_->ClearPref(prefs::kSyncMaxInvalidationVersions);
218 }
219
220 // Legacy migration code.
221 // static
222 void InvalidatorStorage::DeserializeMap(
223 const base::DictionaryValue* max_versions_dict,
224 InvalidationStateMap* map) {
225 map->clear();
226 // Convert from a string -> string DictionaryValue to a
227 // ModelType -> int64 map.
228 for (base::DictionaryValue::Iterator it(*max_versions_dict); !it.IsAtEnd();
229 it.Advance()) {
230 int model_type_int = 0;
231 if (!base::StringToInt(it.key(), &model_type_int)) {
232 LOG(WARNING) << "Invalid model type key: " << it.key();
233 continue;
234 }
235 if ((model_type_int < syncer::FIRST_REAL_MODEL_TYPE) ||
236 (model_type_int >= syncer::MODEL_TYPE_COUNT)) {
237 LOG(WARNING) << "Out-of-range model type key: " << model_type_int;
238 continue;
239 }
240 const syncer::ModelType model_type =
241 syncer::ModelTypeFromInt(model_type_int);
242 std::string max_version_str;
243 CHECK(it.value().GetAsString(&max_version_str));
244 int64 max_version = 0;
245 if (!base::StringToInt64(max_version_str, &max_version)) {
246 LOG(WARNING) << "Invalid max invalidation version for "
247 << syncer::ModelTypeToString(model_type) << ": "
248 << max_version_str;
249 continue;
250 }
251 invalidation::ObjectId id;
252 if (!syncer::RealModelTypeToObjectId(model_type, &id)) {
253 DLOG(WARNING) << "Invalid model type: " << model_type;
254 continue;
255 }
256 (*map)[id].version = max_version;
257 }
258 }
259
260 void InvalidatorStorage::SetInvalidatorClientId(const std::string& client_id) { 85 void InvalidatorStorage::SetInvalidatorClientId(const std::string& client_id) {
261 DCHECK(thread_checker_.CalledOnValidThread()); 86 DCHECK(thread_checker_.CalledOnValidThread());
262 Clear(); // We can't reuse our old invalidation state if the ID changes. 87 Clear(); // We can't reuse our old invalidation state if the ID changes.
263 pref_service_->SetString(prefs::kInvalidatorClientId, client_id); 88 pref_service_->SetString(prefs::kInvalidatorClientId, client_id);
264 } 89 }
265 90
266 std::string InvalidatorStorage::GetInvalidatorClientId() const { 91 std::string InvalidatorStorage::GetInvalidatorClientId() const {
267 return pref_service_->GetString(prefs::kInvalidatorClientId); 92 return pref_service_->GetString(prefs::kInvalidatorClientId);
268 } 93 }
269 94
270 void InvalidatorStorage::SetBootstrapData(const std::string& data) { 95 void InvalidatorStorage::SetBootstrapData(const std::string& data) {
271 DCHECK(thread_checker_.CalledOnValidThread()); 96 DCHECK(thread_checker_.CalledOnValidThread());
272 std::string base64_data; 97 std::string base64_data;
273 base::Base64Encode(data, &base64_data); 98 base::Base64Encode(data, &base64_data);
274 pref_service_->SetString(prefs::kInvalidatorInvalidationState, 99 pref_service_->SetString(prefs::kInvalidatorInvalidationState,
275 base64_data); 100 base64_data);
276 } 101 }
277 102
278 std::string InvalidatorStorage::GetBootstrapData() const { 103 std::string InvalidatorStorage::GetBootstrapData() const {
279 std::string base64_data( 104 std::string base64_data(
280 pref_service_->GetString(prefs::kInvalidatorInvalidationState)); 105 pref_service_->GetString(prefs::kInvalidatorInvalidationState));
281 std::string data; 106 std::string data;
282 base::Base64Decode(base64_data, &data); 107 base::Base64Decode(base64_data, &data);
283 return data; 108 return data;
284 } 109 }
285 110
111 void InvalidatorStorage::SetSavedInvalidations(
112 const syncer::UnackedInvalidationsMap& map) {
113 scoped_ptr<base::ListValue> value(UnackedInvalidationStorageMapToValue(map));
114 pref_service_->Set(prefs::kInvalidatorSavedInvalidations, *value.get());
115 }
116
117 syncer::UnackedInvalidationsMap
118 InvalidatorStorage::GetSavedInvalidations() const {
119 syncer::UnackedInvalidationsMap map;
120 const base::ListValue* value =
121 pref_service_->GetList(prefs::kInvalidatorSavedInvalidations);
122 if (!ValueToUnackedInvalidationStorageMap(*value, &map)) {
123 return syncer::UnackedInvalidationsMap();
124 } else {
125 return map;
126 }
127 }
128
286 void InvalidatorStorage::Clear() { 129 void InvalidatorStorage::Clear() {
287 DCHECK(thread_checker_.CalledOnValidThread()); 130 DCHECK(thread_checker_.CalledOnValidThread());
288 pref_service_->ClearPref(prefs::kInvalidatorMaxInvalidationVersions); 131 pref_service_->ClearPref(prefs::kInvalidatorSavedInvalidations);
289 pref_service_->ClearPref(prefs::kInvalidatorClientId); 132 pref_service_->ClearPref(prefs::kInvalidatorClientId);
290 pref_service_->ClearPref(prefs::kInvalidatorInvalidationState); 133 pref_service_->ClearPref(prefs::kInvalidatorInvalidationState);
291 } 134 }
292 135
293 void InvalidatorStorage::GenerateAckHandles(
294 const syncer::ObjectIdSet& ids,
295 const scoped_refptr<base::TaskRunner>& task_runner,
296 const base::Callback<void(const syncer::AckHandleMap&)> callback) {
297 DCHECK(thread_checker_.CalledOnValidThread());
298 InvalidationStateMap state_map = GetAllInvalidationStates();
299
300 syncer::AckHandleMap ack_handles;
301 for (syncer::ObjectIdSet::const_iterator it = ids.begin(); it != ids.end();
302 ++it) {
303 state_map[*it].expected = syncer::AckHandle::CreateUnique();
304 ack_handles.insert(std::make_pair(*it, state_map[*it].expected));
305 }
306
307 base::ListValue state_map_list;
308 SerializeToList(state_map, &state_map_list);
309 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
310 state_map_list);
311
312 ignore_result(task_runner->PostTask(FROM_HERE,
313 base::Bind(callback, ack_handles)));
314 }
315
316 void InvalidatorStorage::Acknowledge(const invalidation::ObjectId& id,
317 const syncer::AckHandle& ack_handle) {
318 DCHECK(thread_checker_.CalledOnValidThread());
319 InvalidationStateMap state_map = GetAllInvalidationStates();
320
321 InvalidationStateMap::iterator it = state_map.find(id);
322 // This could happen if the acknowledgement is delayed and Forget() has
323 // already been called.
324 if (it == state_map.end())
325 return;
326 it->second.current = ack_handle;
327
328 base::ListValue state_map_list;
329 SerializeToList(state_map, &state_map_list);
330 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
331 state_map_list);
332 }
333
334 } // namespace invalidation 136 } // namespace invalidation
OLDNEW
« no previous file with comments | « chrome/browser/invalidation/invalidator_storage.h ('k') | chrome/browser/invalidation/invalidator_storage_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698