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

Side by Side Diff: google_apis/gcm/engine/gcm_store_impl.cc

Issue 910093003: Reset the GCM store to recover from it when it is busted (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address more feedback Created 5 years, 10 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "google_apis/gcm/engine/gcm_store_impl.h" 5 #include "google_apis/gcm/engine/gcm_store_impl.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/message_loop/message_loop_proxy.h" 13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram_macros.h"
15 #include "base/sequenced_task_runner.h" 15 #include "base/sequenced_task_runner.h"
16 #include "base/stl_util.h" 16 #include "base/stl_util.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_piece.h" 18 #include "base/strings/string_piece.h"
19 #include "base/strings/string_tokenizer.h" 19 #include "base/strings/string_tokenizer.h"
20 #include "base/time/time.h" 20 #include "base/time/time.h"
21 #include "base/tracked_objects.h" 21 #include "base/tracked_objects.h"
22 #include "google_apis/gcm/base/encryptor.h" 22 #include "google_apis/gcm/base/encryptor.h"
23 #include "google_apis/gcm/base/mcs_message.h" 23 #include "google_apis/gcm/base/mcs_message.h"
24 #include "google_apis/gcm/base/mcs_util.h" 24 #include "google_apis/gcm/base/mcs_util.h"
25 #include "google_apis/gcm/protocol/mcs.pb.h" 25 #include "google_apis/gcm/protocol/mcs.pb.h"
26 #include "third_party/leveldatabase/src/include/leveldb/db.h" 26 #include "third_party/leveldatabase/src/include/leveldb/db.h"
27 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 27 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
28 28
29 namespace gcm { 29 namespace gcm {
30 30
31 namespace { 31 namespace {
32 32
33 // This enum is used in an UMA histogram (GCMLoadStatus enum defined in
34 // tools/metrics/histograms/histogram.xml). Hence the entries here shouldn't
35 // be deleted or re-ordered and new ones should be added to the end.
36 enum LoadStatus {
37 LOADING_SUCCEEDED,
38 RELOADING_OPEN_STORE,
39 OPENING_STORE_FAILED,
40 LOADING_DEVICE_CREDENTIALS_FAILED,
41 LOADING_REGISTRATION_FAILED,
42 LOADING_INCOMING_MESSAGES_FAILED,
43 LOADING_OUTGOING_MESSAGES_FAILED,
44 LOADING_LAST_CHECKIN_INFO_FAILED,
45 LOADING_GSERVICE_SETTINGS_FAILED,
46 LOADING_ACCOUNT_MAPPING_FAILED,
47 LOADING_LAST_TOKEN_TIME_FAILED,
48
49 // NOTE: always keep this entry at the end. Add new status types only
50 // immediately above this line. Make sure to update the corresponding
51 // histogram enum accordingly.
52 LOAD_STATUS_COUNT
53 };
54
33 // Limit to the number of outstanding messages per app. 55 // Limit to the number of outstanding messages per app.
34 const int kMessagesPerAppLimit = 20; 56 const int kMessagesPerAppLimit = 20;
35 57
36 // ---- LevelDB keys. ---- 58 // ---- LevelDB keys. ----
37 // Key for this device's android id. 59 // Key for this device's android id.
38 const char kDeviceAIDKey[] = "device_aid_key"; 60 const char kDeviceAIDKey[] = "device_aid_key";
39 // Key for this device's android security token. 61 // Key for this device's android security token.
40 const char kDeviceTokenKey[] = "device_token_key"; 62 const char kDeviceTokenKey[] = "device_token_key";
41 // Lowest lexicographically ordered app ids. 63 // Lowest lexicographically ordered app ids.
42 // Used for prefixing app id. 64 // Used for prefixing app id.
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 void SetLastTokenFetchTime(const base::Time& time, 193 void SetLastTokenFetchTime(const base::Time& time,
172 const UpdateCallback& callback); 194 const UpdateCallback& callback);
173 void SetValue(const std::string& key, 195 void SetValue(const std::string& key,
174 const std::string& value, 196 const std::string& value,
175 const UpdateCallback& callback); 197 const UpdateCallback& callback);
176 198
177 private: 199 private:
178 friend class base::RefCountedThreadSafe<Backend>; 200 friend class base::RefCountedThreadSafe<Backend>;
179 ~Backend(); 201 ~Backend();
180 202
203 LoadStatus OpenStoreAndLoadData(LoadResult* result);
181 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); 204 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token);
182 bool LoadRegistrations(RegistrationInfoMap* registrations); 205 bool LoadRegistrations(RegistrationInfoMap* registrations);
183 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); 206 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages);
184 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); 207 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages);
185 bool LoadLastCheckinInfo(base::Time* last_checkin_time, 208 bool LoadLastCheckinInfo(base::Time* last_checkin_time,
186 std::set<std::string>* accounts); 209 std::set<std::string>* accounts);
187 bool LoadGServicesSettings(std::map<std::string, std::string>* settings, 210 bool LoadGServicesSettings(std::map<std::string, std::string>* settings,
188 std::string* digest); 211 std::string* digest);
189 bool LoadAccountMappingInfo(AccountMappings* account_mappings); 212 bool LoadAccountMappingInfo(AccountMappings* account_mappings);
190 bool LoadLastTokenFetchTime(base::Time* last_token_fetch_time); 213 bool LoadLastTokenFetchTime(base::Time* last_token_fetch_time);
191 214
192 const base::FilePath path_; 215 const base::FilePath path_;
193 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; 216 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_;
194 scoped_ptr<Encryptor> encryptor_; 217 scoped_ptr<Encryptor> encryptor_;
195 218
196 scoped_ptr<leveldb::DB> db_; 219 scoped_ptr<leveldb::DB> db_;
197 }; 220 };
198 221
199 GCMStoreImpl::Backend::Backend( 222 GCMStoreImpl::Backend::Backend(
200 const base::FilePath& path, 223 const base::FilePath& path,
201 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner, 224 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner,
202 scoped_ptr<Encryptor> encryptor) 225 scoped_ptr<Encryptor> encryptor)
203 : path_(path), 226 : path_(path),
204 foreground_task_runner_(foreground_task_runner), 227 foreground_task_runner_(foreground_task_runner),
205 encryptor_(encryptor.Pass()) { 228 encryptor_(encryptor.Pass()) {
206 } 229 }
207 230
208 GCMStoreImpl::Backend::~Backend() {} 231 GCMStoreImpl::Backend::~Backend() {}
209 232
210 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { 233 LoadStatus GCMStoreImpl::Backend::OpenStoreAndLoadData(LoadResult* result) {
211 scoped_ptr<LoadResult> result(new LoadResult()); 234 LoadStatus load_status;
212 if (db_.get()) { 235 if (db_.get()) {
213 LOG(ERROR) << "Attempting to reload open database."; 236 LOG(ERROR) << "Attempting to reload open database.";
214 foreground_task_runner_->PostTask(FROM_HERE, 237 return RELOADING_OPEN_STORE;
215 base::Bind(callback,
216 base::Passed(&result)));
217 return;
218 } 238 }
219 239
220 leveldb::Options options; 240 leveldb::Options options;
221 options.create_if_missing = true; 241 options.create_if_missing = true;
222 leveldb::DB* db; 242 leveldb::DB* db;
223 leveldb::Status status = 243 leveldb::Status status =
224 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 244 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db);
225 UMA_HISTOGRAM_BOOLEAN("GCM.LoadSucceeded", status.ok());
226 if (!status.ok()) { 245 if (!status.ok()) {
227 LOG(ERROR) << "Failed to open database " << path_.value() << ": " 246 LOG(ERROR) << "Failed to open database " << path_.value() << ": "
228 << status.ToString(); 247 << status.ToString();
229 foreground_task_runner_->PostTask(FROM_HERE, 248 return OPENING_STORE_FAILED;
230 base::Bind(callback,
231 base::Passed(&result)));
232 return;
233 } 249 }
250
234 db_.reset(db); 251 db_.reset(db);
252 if (!LoadDeviceCredentials(&result->device_android_id,
253 &result->device_security_token)) {
254 return LOADING_DEVICE_CREDENTIALS_FAILED;
255 }
256 if (!LoadRegistrations(&result->registrations))
257 return LOADING_REGISTRATION_FAILED;
258 if (!LoadIncomingMessages(&result->incoming_messages))
259 return LOADING_INCOMING_MESSAGES_FAILED;
260 if (!LoadOutgoingMessages(&result->outgoing_messages))
261 return LOADING_OUTGOING_MESSAGES_FAILED;
262 if (!LoadLastCheckinInfo(&result->last_checkin_time,
263 &result->last_checkin_accounts)) {
264 return LOADING_LAST_CHECKIN_INFO_FAILED;
265 }
266 if (!LoadGServicesSettings(&result->gservices_settings,
267 &result->gservices_digest)) {
268 return load_status = LOADING_GSERVICE_SETTINGS_FAILED;
269 }
270 if (!LoadAccountMappingInfo(&result->account_mappings))
271 return LOADING_ACCOUNT_MAPPING_FAILED;
272 if (!LoadLastTokenFetchTime(&result->last_token_fetch_time))
273 return LOADING_LAST_TOKEN_TIME_FAILED;
235 274
236 if (!LoadDeviceCredentials(&result->device_android_id, 275 return LOADING_SUCCEEDED;
237 &result->device_security_token) || 276 }
238 !LoadRegistrations(&result->registrations) || 277
239 !LoadIncomingMessages(&result->incoming_messages) || 278 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) {
240 !LoadOutgoingMessages(&result->outgoing_messages) || 279 scoped_ptr<LoadResult> result(new LoadResult());
241 !LoadLastCheckinInfo(&result->last_checkin_time, 280 LoadStatus load_status = OpenStoreAndLoadData(result.get());
242 &result->last_checkin_accounts) || 281 UMA_HISTOGRAM_ENUMERATION("GCM.LoadStatus", load_status, LOAD_STATUS_COUNT);
243 !LoadGServicesSettings(&result->gservices_settings, 282 if (load_status != LOADING_SUCCEEDED) {
244 &result->gservices_digest) ||
245 !LoadAccountMappingInfo(&result->account_mappings) ||
246 !LoadLastTokenFetchTime(&result->last_token_fetch_time)) {
247 result->Reset(); 283 result->Reset();
248 foreground_task_runner_->PostTask(FROM_HERE, 284 foreground_task_runner_->PostTask(FROM_HERE,
249 base::Bind(callback, 285 base::Bind(callback,
250 base::Passed(&result))); 286 base::Passed(&result)));
251 return; 287 return;
252 } 288 }
253 289
254 // Only record histograms if GCM had already been set up for this device. 290 // Only record histograms if GCM had already been set up for this device.
255 if (result->device_android_id != 0 && result->device_security_token != 0) { 291 if (result->device_android_id != 0 && result->device_security_token != 0) {
256 int64 file_size = 0; 292 int64 file_size = 0;
(...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after
1179 removed_message_counts.begin(); 1215 removed_message_counts.begin();
1180 iter != removed_message_counts.end(); ++iter) { 1216 iter != removed_message_counts.end(); ++iter) {
1181 DCHECK_NE(app_message_counts_.count(iter->first), 0U); 1217 DCHECK_NE(app_message_counts_.count(iter->first), 0U);
1182 app_message_counts_[iter->first] -= iter->second; 1218 app_message_counts_[iter->first] -= iter->second;
1183 DCHECK_GE(app_message_counts_[iter->first], 0); 1219 DCHECK_GE(app_message_counts_[iter->first], 0);
1184 } 1220 }
1185 callback.Run(true); 1221 callback.Run(true);
1186 } 1222 }
1187 1223
1188 } // namespace gcm 1224 } // namespace gcm
OLDNEW
« no previous file with comments | « components/gcm_driver/gcm_client_impl_unittest.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698