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

Side by Side Diff: chrome/browser/sync/invalidations/invalidator_storage.cc

Issue 10911084: Implement Invalidator::Acknowledge (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Restart test + more cleanup Created 8 years, 2 months 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/sync/invalidations/invalidator_storage.h" 5 #include "chrome/browser/sync/invalidations/invalidator_storage.h"
6 6
7 #include "base/bind.h"
7 #include "base/base64.h" 8 #include "base/base64.h"
9 #include "base/callback.h"
10 #include "base/location.h"
8 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/task_runner.h"
9 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
10 #include "base/string_number_conversions.h" 14 #include "base/string_number_conversions.h"
11 #include "base/values.h" 15 #include "base/values.h"
12 #include "chrome/browser/prefs/pref_service.h" 16 #include "chrome/browser/prefs/pref_service.h"
13 #include "chrome/common/pref_names.h" 17 #include "chrome/common/pref_names.h"
14 #include "sync/internal_api/public/base/model_type.h" 18 #include "sync/internal_api/public/base/model_type.h"
19 #include "sync/notifier/invalidation_util.h"
15 20
16 using syncer::InvalidationVersionMap; 21 using syncer::InvalidationStateMap;
17 22
18 namespace browser_sync { 23 namespace browser_sync {
19 24
20 namespace { 25 namespace {
21 26
22 const char kSourceKey[] = "source"; 27 const char kSourceKey[] = "source";
23 const char kNameKey[] = "name"; 28 const char kNameKey[] = "name";
24 const char kMaxVersionKey[] = "max-version"; 29 const char kMaxVersionKey[] = "max-version";
30 const char kCurrentAckHandleKey[] = "current-ack";
31 const char kExpectedAckHandleKey[] = "expected-ack";
25 32
33 // TODO(dcheng): Rename.
akalin 2012/10/19 13:27:16 !
dcheng 2012/10/19 19:38:11 Done. I thought I updated this when I updated the
26 bool ValueToObjectIdAndVersion(const DictionaryValue& value, 34 bool ValueToObjectIdAndVersion(const DictionaryValue& value,
27 invalidation::ObjectId* id, 35 invalidation::ObjectId* id,
28 int64* max_version) { 36 syncer::LocalState* state) {
29 std::string source_str; 37 std::string source_str;
30 int source = 0; 38 int source = 0;
31 std::string name; 39 std::string name;
32 std::string max_version_str; 40 std::string max_version_str;
33 if (!value.GetString(kSourceKey, &source_str)) { 41 if (!value.GetString(kSourceKey, &source_str)) {
34 DLOG(WARNING) << "Unable to deserialize source"; 42 DLOG(WARNING) << "Unable to deserialize source";
35 return false; 43 return false;
36 } 44 }
37 if (!value.GetString(kNameKey, &name)) { 45 if (!value.GetString(kNameKey, &name)) {
38 DLOG(WARNING) << "Unable to deserialize name"; 46 DLOG(WARNING) << "Unable to deserialize name";
39 return false; 47 return false;
40 } 48 }
41 if (!value.GetString(kMaxVersionKey, &max_version_str)) { 49 if (!value.GetString(kMaxVersionKey, &max_version_str)) {
42 DLOG(WARNING) << "Unable to deserialize max version"; 50 DLOG(WARNING) << "Unable to deserialize max version";
43 return false; 51 return false;
44 } 52 }
45 if (!base::StringToInt(source_str, &source)) { 53 if (!base::StringToInt(source_str, &source)) {
46 DLOG(WARNING) << "Invalid source: " << source_str; 54 DLOG(WARNING) << "Invalid source: " << source_str;
47 return false; 55 return false;
48 } 56 }
49 if (!base::StringToInt64(max_version_str, max_version)) { 57 if (!base::StringToInt64(max_version_str, &state->version)) {
50 DLOG(WARNING) << "Invalid max invalidation version: " << max_version_str; 58 DLOG(WARNING) << "Invalid max invalidation version: " << max_version_str;
51 return false; 59 return false;
52 } 60 }
53 *id = invalidation::ObjectId(source, name); 61 *id = invalidation::ObjectId(source, name);
62 // The following field is optional, as it may not always be set (for
63 // example, when upgrading from previous versions of Chrome).
64 const base::Value* current_ack_handle_value = NULL;
65 if (value.Get(kCurrentAckHandleKey, &current_ack_handle_value)) {
66 state->current.ResetFromValue(*current_ack_handle_value);
67 }
68 // TODO(dcheng): Consider regenerating the latest ack handle value on Chrome
69 // startup to allow for format changes?
70 const base::Value* expected_ack_handle_value = NULL;
71 if (value.Get(kExpectedAckHandleKey, &expected_ack_handle_value)) {
72 state->expected.ResetFromValue(*expected_ack_handle_value);
73 }
akalin 2012/10/19 13:27:16 does it make sense to have only one ack handle fie
dcheng 2012/10/19 19:38:11 It's possible to have an expected value but no cur
54 return true; 74 return true;
55 } 75 }
56 76
57 // The caller owns the returned value. 77 // The caller owns the returned value.
58 DictionaryValue* ObjectIdAndVersionToValue(const invalidation::ObjectId& id, 78 DictionaryValue* ObjectIdAndStateToValue(const invalidation::ObjectId& id,
59 int64 max_version) { 79 const syncer::LocalState& state) {
60 DictionaryValue* value = new DictionaryValue; 80 DictionaryValue* value = new DictionaryValue;
61 value->SetString(kSourceKey, base::IntToString(id.source())); 81 value->SetString(kSourceKey, base::IntToString(id.source()));
62 value->SetString(kNameKey, id.name()); 82 value->SetString(kNameKey, id.name());
63 value->SetString(kMaxVersionKey, base::Int64ToString(max_version)); 83 value->SetString(kMaxVersionKey, base::Int64ToString(state.version));
84 value->Set(kCurrentAckHandleKey, state.current.ToValue().release());
85 value->Set(kExpectedAckHandleKey, state.expected.ToValue().release());
64 return value; 86 return value;
65 } 87 }
66 88
89 // Simple helper to allow us to bind the last parameter to a partial callback
90 // and call it on the right thread.
91 void GenerateAckHandleReplyHelper(
akalin 2012/10/19 13:27:16 almost certain you can just rebind callback with a
dcheng 2012/10/19 19:38:11 Apparently base::Bind(callback, ack_handles) works
92 base::Callback<void(const syncer::AckHandleMap&)> callback,
93 const syncer::AckHandleMap& ack_handles) {
94 callback.Run(ack_handles);
95 }
96
67 } // namespace 97 } // namespace
68 98
69 InvalidatorStorage::InvalidatorStorage(PrefService* pref_service) 99 InvalidatorStorage::InvalidatorStorage(PrefService* pref_service)
70 : pref_service_(pref_service) { 100 : pref_service_(pref_service) {
71 // TODO(tim): Create a Mock instead of maintaining the if(!pref_service_) case 101 // TODO(tim): Create a Mock instead of maintaining the if(!pref_service_) case
72 // throughout this file. This is a problem now due to lack of injection at 102 // throughout this file. This is a problem now due to lack of injection at
73 // ProfileSyncService. Bug 130176. 103 // ProfileSyncService. Bug 130176.
74 if (pref_service_) { 104 if (pref_service_) {
75 pref_service_->RegisterListPref(prefs::kInvalidatorMaxInvalidationVersions, 105 pref_service_->RegisterListPref(prefs::kInvalidatorMaxInvalidationVersions,
76 PrefService::UNSYNCABLE_PREF); 106 PrefService::UNSYNCABLE_PREF);
77 pref_service_->RegisterStringPref(prefs::kInvalidatorInvalidationState, 107 pref_service_->RegisterStringPref(prefs::kInvalidatorInvalidationState,
78 std::string(), 108 std::string(),
79 PrefService::UNSYNCABLE_PREF); 109 PrefService::UNSYNCABLE_PREF);
80 110
81 MigrateMaxInvalidationVersionsPref(); 111 MigrateMaxInvalidationVersionsPref();
82 } 112 }
83 } 113 }
84 114
85 InvalidatorStorage::~InvalidatorStorage() { 115 InvalidatorStorage::~InvalidatorStorage() {
86 } 116 }
87 117
88 InvalidationVersionMap InvalidatorStorage::GetAllMaxVersions() const { 118 InvalidationStateMap InvalidatorStorage::GetStateMap() const {
89 DCHECK(thread_checker_.CalledOnValidThread()); 119 DCHECK(thread_checker_.CalledOnValidThread());
90 InvalidationVersionMap max_versions; 120 InvalidationStateMap state;
91 if (!pref_service_) { 121 if (!pref_service_) {
92 return max_versions; 122 return state;
93 } 123 }
94 const base::ListValue* max_versions_list = 124 const base::ListValue* state_map_list =
95 pref_service_->GetList(prefs::kInvalidatorMaxInvalidationVersions); 125 pref_service_->GetList(prefs::kInvalidatorMaxInvalidationVersions);
96 CHECK(max_versions_list); 126 CHECK(state_map_list);
97 DeserializeFromList(*max_versions_list, &max_versions); 127 DeserializeFromList(*state_map_list, &state);
98 return max_versions; 128 return state;
99 } 129 }
100 130
101 void InvalidatorStorage::SetMaxVersion(const invalidation::ObjectId& id, 131 void InvalidatorStorage::SetMaxVersion(const invalidation::ObjectId& id,
102 int64 max_version) { 132 int64 max_version) {
103 DCHECK(thread_checker_.CalledOnValidThread()); 133 DCHECK(thread_checker_.CalledOnValidThread());
104 CHECK(pref_service_); 134 CHECK(pref_service_);
105 InvalidationVersionMap max_versions = GetAllMaxVersions(); 135 InvalidationStateMap state_map = GetStateMap();
106 InvalidationVersionMap::iterator it = max_versions.find(id); 136 InvalidationStateMap::iterator it = state_map.find(id);
107 if ((it != max_versions.end()) && (max_version <= it->second)) { 137 if ((it != state_map.end()) && (max_version <= it->second.version)) {
108 NOTREACHED(); 138 NOTREACHED();
109 return; 139 return;
110 } 140 }
111 max_versions[id] = max_version; 141 state_map[id].version = max_version;
112 142
113 base::ListValue max_versions_list; 143 base::ListValue state_map_list;
114 SerializeToList(max_versions, &max_versions_list); 144 SerializeToList(state_map, &state_map_list);
115 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions, 145 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
116 max_versions_list); 146 state_map_list);
117 } 147 }
118 148
119 void InvalidatorStorage::Forget(const syncer::ObjectIdSet& ids) { 149 void InvalidatorStorage::Forget(const syncer::ObjectIdSet& ids) {
120 DCHECK(thread_checker_.CalledOnValidThread()); 150 DCHECK(thread_checker_.CalledOnValidThread());
121 CHECK(pref_service_); 151 CHECK(pref_service_);
122 InvalidationVersionMap max_versions = GetAllMaxVersions(); 152 InvalidationStateMap state_map = GetStateMap();
123 for (syncer::ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); 153 for (syncer::ObjectIdSet::const_iterator it = ids.begin(); it != ids.end();
124 ++it) { 154 ++it) {
125 max_versions.erase(*it); 155 state_map.erase(*it);
126 } 156 }
127 157
128 base::ListValue max_versions_list; 158 base::ListValue state_map_list;
129 SerializeToList(max_versions, &max_versions_list); 159 SerializeToList(state_map, &state_map_list);
130 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions, 160 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
131 max_versions_list); 161 state_map_list);
132 } 162 }
133 163
134 // static 164 // static
135 void InvalidatorStorage::DeserializeFromList( 165 void InvalidatorStorage::DeserializeFromList(
136 const base::ListValue& max_versions_list, 166 const base::ListValue& state_map_list,
137 InvalidationVersionMap* max_versions_map) { 167 InvalidationStateMap* state_map) {
138 max_versions_map->clear(); 168 state_map->clear();
139 for (size_t i = 0; i < max_versions_list.GetSize(); ++i) { 169 for (size_t i = 0; i < state_map_list.GetSize(); ++i) {
140 const DictionaryValue* value = NULL; 170 const DictionaryValue* value = NULL;
141 if (!max_versions_list.GetDictionary(i, &value)) { 171 if (!state_map_list.GetDictionary(i, &value)) {
142 DLOG(WARNING) << "Unable to deserialize entry " << i; 172 DLOG(WARNING) << "Unable to deserialize entry " << i;
143 continue; 173 continue;
144 } 174 }
145 invalidation::ObjectId id; 175 invalidation::ObjectId id;
146 int64 max_version = 0; 176 syncer::LocalState state;
147 if (!ValueToObjectIdAndVersion(*value, &id, &max_version)) { 177 if (!ValueToObjectIdAndVersion(*value, &id, &state)) {
148 DLOG(WARNING) << "Error while deserializing entry " << i; 178 DLOG(WARNING) << "Error while deserializing entry " << i;
149 continue; 179 continue;
150 } 180 }
151 (*max_versions_map)[id] = max_version; 181 (*state_map)[id] = state;
152 } 182 }
153 } 183 }
154 184
155 // static 185 // static
156 void InvalidatorStorage::SerializeToList( 186 void InvalidatorStorage::SerializeToList(
157 const InvalidationVersionMap& max_versions_map, 187 const InvalidationStateMap& state_map,
158 base::ListValue* max_versions_list) { 188 base::ListValue* state_map_list) {
159 for (InvalidationVersionMap::const_iterator it = max_versions_map.begin(); 189 for (InvalidationStateMap::const_iterator it = state_map.begin();
160 it != max_versions_map.end(); ++it) { 190 it != state_map.end(); ++it) {
161 max_versions_list->Append(ObjectIdAndVersionToValue(it->first, it->second)); 191 state_map_list->Append(ObjectIdAndStateToValue(it->first, it->second));
162 } 192 }
163 } 193 }
164 194
165 // Legacy migration code. 195 // Legacy migration code.
166 void InvalidatorStorage::MigrateMaxInvalidationVersionsPref() { 196 void InvalidatorStorage::MigrateMaxInvalidationVersionsPref() {
167 pref_service_->RegisterDictionaryPref(prefs::kSyncMaxInvalidationVersions, 197 pref_service_->RegisterDictionaryPref(prefs::kSyncMaxInvalidationVersions,
168 PrefService::UNSYNCABLE_PREF); 198 PrefService::UNSYNCABLE_PREF);
169 const base::DictionaryValue* max_versions_dict = 199 const base::DictionaryValue* max_versions_dict =
170 pref_service_->GetDictionary(prefs::kSyncMaxInvalidationVersions); 200 pref_service_->GetDictionary(prefs::kSyncMaxInvalidationVersions);
171 CHECK(max_versions_dict); 201 CHECK(max_versions_dict);
172 if (!max_versions_dict->empty()) { 202 if (!max_versions_dict->empty()) {
173 InvalidationVersionMap max_versions; 203 InvalidationStateMap state_map;
174 DeserializeMap(max_versions_dict, &max_versions); 204 DeserializeMap(max_versions_dict, &state_map);
175 base::ListValue max_versions_list; 205 base::ListValue state_map_list;
176 SerializeToList(max_versions, &max_versions_list); 206 SerializeToList(state_map, &state_map_list);
177 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions, 207 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
178 max_versions_list); 208 state_map_list);
179 UMA_HISTOGRAM_BOOLEAN("InvalidatorStorage.MigrateInvalidationVersionsPref", 209 UMA_HISTOGRAM_BOOLEAN("InvalidatorStorage.MigrateInvalidationVersionsPref",
180 true); 210 true);
181 } else { 211 } else {
182 UMA_HISTOGRAM_BOOLEAN("InvalidatorStorage.MigrateInvalidationVersionsPref", 212 UMA_HISTOGRAM_BOOLEAN("InvalidatorStorage.MigrateInvalidationVersionsPref",
183 false); 213 false);
184 } 214 }
185 pref_service_->ClearPref(prefs::kSyncMaxInvalidationVersions); 215 pref_service_->ClearPref(prefs::kSyncMaxInvalidationVersions);
186 } 216 }
187 217
188 // Legacy migration code. 218 // Legacy migration code.
189 // static 219 // static
190 void InvalidatorStorage::DeserializeMap( 220 void InvalidatorStorage::DeserializeMap(
191 const base::DictionaryValue* max_versions_dict, 221 const base::DictionaryValue* max_versions_dict,
192 InvalidationVersionMap* map) { 222 InvalidationStateMap* map) {
193 map->clear(); 223 map->clear();
194 // Convert from a string -> string DictionaryValue to a 224 // Convert from a string -> string DictionaryValue to a
195 // ModelType -> int64 map. 225 // ModelType -> int64 map.
196 for (base::DictionaryValue::key_iterator it = 226 for (base::DictionaryValue::key_iterator it =
197 max_versions_dict->begin_keys(); 227 max_versions_dict->begin_keys();
198 it != max_versions_dict->end_keys(); ++it) { 228 it != max_versions_dict->end_keys(); ++it) {
199 int model_type_int = 0; 229 int model_type_int = 0;
200 if (!base::StringToInt(*it, &model_type_int)) { 230 if (!base::StringToInt(*it, &model_type_int)) {
201 LOG(WARNING) << "Invalid model type key: " << *it; 231 LOG(WARNING) << "Invalid model type key: " << *it;
202 continue; 232 continue;
(...skipping 12 matching lines...) Expand all
215 LOG(WARNING) << "Invalid max invalidation version for " 245 LOG(WARNING) << "Invalid max invalidation version for "
216 << syncer::ModelTypeToString(model_type) << ": " 246 << syncer::ModelTypeToString(model_type) << ": "
217 << max_version_str; 247 << max_version_str;
218 continue; 248 continue;
219 } 249 }
220 invalidation::ObjectId id; 250 invalidation::ObjectId id;
221 if (!syncer::RealModelTypeToObjectId(model_type, &id)) { 251 if (!syncer::RealModelTypeToObjectId(model_type, &id)) {
222 DLOG(WARNING) << "Invalid model type: " << model_type; 252 DLOG(WARNING) << "Invalid model type: " << model_type;
223 continue; 253 continue;
224 } 254 }
225 (*map)[id] = max_version; 255 (*map)[id].version = max_version;
226 } 256 }
227 } 257 }
228 258
229 void InvalidatorStorage::SetBootstrapData(const std::string& data) { 259 void InvalidatorStorage::SetBootstrapData(const std::string& data) {
230 DCHECK(thread_checker_.CalledOnValidThread()); 260 DCHECK(thread_checker_.CalledOnValidThread());
231 std::string base64_data; 261 std::string base64_data;
232 base::Base64Encode(data, &base64_data); 262 base::Base64Encode(data, &base64_data);
233 pref_service_->SetString(prefs::kInvalidatorInvalidationState, 263 pref_service_->SetString(prefs::kInvalidatorInvalidationState,
234 base64_data); 264 base64_data);
235 } 265 }
236 266
237 std::string InvalidatorStorage::GetBootstrapData() const { 267 std::string InvalidatorStorage::GetBootstrapData() const {
238 std::string base64_data(pref_service_ ? 268 std::string base64_data(pref_service_ ?
239 pref_service_->GetString(prefs::kInvalidatorInvalidationState) : ""); 269 pref_service_->GetString(prefs::kInvalidatorInvalidationState) : "");
240 std::string data; 270 std::string data;
241 base::Base64Decode(base64_data, &data); 271 base::Base64Decode(base64_data, &data);
242 return data; 272 return data;
243 } 273 }
244 274
245 void InvalidatorStorage::Clear() { 275 void InvalidatorStorage::Clear() {
246 DCHECK(thread_checker_.CalledOnValidThread()); 276 DCHECK(thread_checker_.CalledOnValidThread());
247 pref_service_->ClearPref(prefs::kInvalidatorMaxInvalidationVersions); 277 pref_service_->ClearPref(prefs::kInvalidatorMaxInvalidationVersions);
248 pref_service_->ClearPref(prefs::kInvalidatorInvalidationState); 278 pref_service_->ClearPref(prefs::kInvalidatorInvalidationState);
249 } 279 }
250 280
281 void InvalidatorStorage::GenerateAckHandles(
282 const syncer::ObjectIdSet& ids,
283 const scoped_refptr<base::TaskRunner>& task_runner,
284 const base::Callback<void(const syncer::AckHandleMap&)> callback) {
285 DCHECK(thread_checker_.CalledOnValidThread());
286 CHECK(pref_service_);
287 InvalidationStateMap state_map = GetStateMap();
288
289 syncer::AckHandleMap ack_handles;
290 for (syncer::ObjectIdSet::const_iterator it = ids.begin(); it != ids.end();
291 ++it) {
292 state_map[*it].expected = syncer::AckHandle::CreateUnique();
293 ack_handles.insert(std::make_pair(*it, state_map[*it].expected));
294 }
295
296 base::ListValue state_map_list;
297 SerializeToList(state_map, &state_map_list);
298 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
299 state_map_list);
300
301 task_runner->PostTask(FROM_HERE,
302 base::Bind(&GenerateAckHandleReplyHelper,
303 callback, ack_handles));
304 }
305
306 void InvalidatorStorage::Acknowledge(const invalidation::ObjectId& id,
307 const syncer::AckHandle& ack_handle) {
308 DCHECK(thread_checker_.CalledOnValidThread());
309 CHECK(pref_service_);
310 InvalidationStateMap state_map = GetStateMap();
311
312 InvalidationStateMap::iterator it = state_map.find(id);
313 // This could happen if the acknowledgement is delayed and Forget() has
314 // already been called.
315 if (it == state_map.end())
316 return;
317 it->second.current = ack_handle;
318
319 base::ListValue state_map_list;
320 SerializeToList(state_map, &state_map_list);
321 pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
322 state_map_list);
323 }
324
251 } // namespace browser_sync 325 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698