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

Side by Side Diff: content/browser/service_worker/service_worker_database.cc

Issue 303483007: ServiceWorker: Add UMA for ServiceWorkerDatabase (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 6 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 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 "content/browser/service_worker/service_worker_database.h" 5 #include "content/browser/service_worker/service_worker_database.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.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/stl_util.h" 13 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h" 15 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
17 #include "content/browser/service_worker/service_worker_database.pb.h" 18 #include "content/browser/service_worker/service_worker_database.pb.h"
18 #include "content/common/service_worker/service_worker_types.h" 19 #include "content/common/service_worker/service_worker_types.h"
19 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 20 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
20 #include "third_party/leveldatabase/src/include/leveldb/db.h" 21 #include "third_party/leveldatabase/src/include/leveldb/db.h"
21 #include "third_party/leveldatabase/src/include/leveldb/env.h" 22 #include "third_party/leveldatabase/src/include/leveldb/env.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 71
71 const char kRegKeyPrefix[] = "REG:"; 72 const char kRegKeyPrefix[] = "REG:";
72 const char kResKeyPrefix[] = "RES:"; 73 const char kResKeyPrefix[] = "RES:";
73 const char kKeySeparator = '\x00'; 74 const char kKeySeparator = '\x00';
74 75
75 const char kUncommittedResIdKeyPrefix[] = "URES:"; 76 const char kUncommittedResIdKeyPrefix[] = "URES:";
76 const char kPurgeableResIdKeyPrefix[] = "PRES:"; 77 const char kPurgeableResIdKeyPrefix[] = "PRES:";
77 78
78 const int64 kCurrentSchemaVersion = 1; 79 const int64 kCurrentSchemaVersion = 1;
79 80
81 // For histogram.
82 const char kOpenResultHistogramLabel[] =
83 "ServiceWorker.Database.OpenResult";
84 const char kReadResultHistogramLabel[] =
85 "ServiceWorker.Database.ReadResult";
86 const char kWriteResultHistogramLabel[] =
87 "ServiceWorker.Database.WriteResult";
88
80 bool RemovePrefix(const std::string& str, 89 bool RemovePrefix(const std::string& str,
81 const std::string& prefix, 90 const std::string& prefix,
82 std::string* out) { 91 std::string* out) {
83 if (!StartsWithASCII(str, prefix, true)) 92 if (!StartsWithASCII(str, prefix, true))
84 return false; 93 return false;
85 if (out) 94 if (out)
86 *out = str.substr(prefix.size()); 95 *out = str.substr(prefix.size());
87 return true; 96 return true;
88 } 97 }
89 98
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 // Value should be empty. 171 // Value should be empty.
163 batch->Put(CreateUniqueOriginKey(origin), ""); 172 batch->Put(CreateUniqueOriginKey(origin), "");
164 } 173 }
165 174
166 void PutPurgeableResourceIdToBatch(int64 resource_id, 175 void PutPurgeableResourceIdToBatch(int64 resource_id,
167 leveldb::WriteBatch* batch) { 176 leveldb::WriteBatch* batch) {
168 // Value should be empty. 177 // Value should be empty.
169 batch->Put(CreateResourceIdKey(kPurgeableResIdKeyPrefix, resource_id), ""); 178 batch->Put(CreateResourceIdKey(kPurgeableResIdKeyPrefix, resource_id), "");
170 } 179 }
171 180
172 bool ParseRegistrationData(const std::string& serialized, 181 ServiceWorkerDatabase::Status ParseId(
173 ServiceWorkerDatabase::RegistrationData* out) { 182 const std::string& serialized,
183 int64* out) {
184 DCHECK(out);
185 int64 id;
186 if (!base::StringToInt64(serialized, &id) || id < 0)
187 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
188 *out = id;
189 return ServiceWorkerDatabase::STATUS_OK;
190 }
191
192 ServiceWorkerDatabase::Status ParseDatabaseVersion(
193 const std::string& serialized,
194 int64* out) {
195 DCHECK(out);
196 const int kFirstValidVersion = 1;
197 int64 version;
198 if (!base::StringToInt64(serialized, &version) ||
199 version < kFirstValidVersion) {
200 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
201 }
202 if (kCurrentSchemaVersion < version) {
203 DLOG(ERROR) << "ServiceWorkerDatabase has newer schema version"
204 << " than the current latest version: "
205 << version << " vs " << kCurrentSchemaVersion;
206 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
207 }
208 *out = version;
209 return ServiceWorkerDatabase::STATUS_OK;
210 }
211
212 ServiceWorkerDatabase::Status ParseRegistrationData(
213 const std::string& serialized,
214 ServiceWorkerDatabase::RegistrationData* out) {
174 DCHECK(out); 215 DCHECK(out);
175 ServiceWorkerRegistrationData data; 216 ServiceWorkerRegistrationData data;
176 if (!data.ParseFromString(serialized)) 217 if (!data.ParseFromString(serialized))
177 return false; 218 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
178 219
179 GURL scope_url(data.scope_url()); 220 GURL scope_url(data.scope_url());
180 GURL script_url(data.script_url()); 221 GURL script_url(data.script_url());
181 if (!scope_url.is_valid() || 222 if (!scope_url.is_valid() ||
182 !script_url.is_valid() || 223 !script_url.is_valid() ||
183 scope_url.GetOrigin() != script_url.GetOrigin()) { 224 scope_url.GetOrigin() != script_url.GetOrigin()) {
184 return false; 225 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
185 } 226 }
186 227
187 // Convert ServiceWorkerRegistrationData to RegistrationData. 228 // Convert ServiceWorkerRegistrationData to RegistrationData.
188 out->registration_id = data.registration_id(); 229 out->registration_id = data.registration_id();
189 out->scope = scope_url; 230 out->scope = scope_url;
190 out->script = script_url; 231 out->script = script_url;
191 out->version_id = data.version_id(); 232 out->version_id = data.version_id();
192 out->is_active = data.is_active(); 233 out->is_active = data.is_active();
193 out->has_fetch_handler = data.has_fetch_handler(); 234 out->has_fetch_handler = data.has_fetch_handler();
194 out->last_update_check = 235 out->last_update_check =
195 base::Time::FromInternalValue(data.last_update_check_time()); 236 base::Time::FromInternalValue(data.last_update_check_time());
196 return true; 237 return ServiceWorkerDatabase::STATUS_OK;
197 } 238 }
198 239
199 bool ParseResourceRecord(const std::string& serialized, 240 ServiceWorkerDatabase::Status ParseResourceRecord(
200 ServiceWorkerDatabase::ResourceRecord* out) { 241 const std::string& serialized,
242 ServiceWorkerDatabase::ResourceRecord* out) {
201 DCHECK(out); 243 DCHECK(out);
202 ServiceWorkerResourceRecord record; 244 ServiceWorkerResourceRecord record;
203 if (!record.ParseFromString(serialized)) 245 if (!record.ParseFromString(serialized))
204 return false; 246 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
205 247
206 GURL url(record.url()); 248 GURL url(record.url());
207 if (!url.is_valid()) 249 if (!url.is_valid())
208 return false; 250 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
209 251
210 // Convert ServiceWorkerResourceRecord to ResourceRecord. 252 // Convert ServiceWorkerResourceRecord to ResourceRecord.
211 out->resource_id = record.resource_id(); 253 out->resource_id = record.resource_id();
212 out->url = url; 254 out->url = url;
213 return true; 255 return ServiceWorkerDatabase::STATUS_OK;
214 } 256 }
215 257
216 ServiceWorkerDatabase::Status LevelDBStatusToStatus( 258 ServiceWorkerDatabase::Status LevelDBStatusToStatus(
217 const leveldb::Status& status) { 259 const leveldb::Status& status) {
218 if (status.ok()) 260 if (status.ok())
219 return ServiceWorkerDatabase::STATUS_OK; 261 return ServiceWorkerDatabase::STATUS_OK;
220 else if (status.IsNotFound()) 262 else if (status.IsNotFound())
221 return ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND; 263 return ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND;
264 else if (status.IsIOError())
265 return ServiceWorkerDatabase::STATUS_ERROR_IO_ERROR;
222 else if (status.IsCorruption()) 266 else if (status.IsCorruption())
223 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED; 267 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
224 else 268 else
225 return ServiceWorkerDatabase::STATUS_ERROR_FAILED; 269 return ServiceWorkerDatabase::STATUS_ERROR_FAILED;
226 } 270 }
227 271
272 const char* StatusToString(ServiceWorkerDatabase::Status status) {
273 switch (status) {
274 case ServiceWorkerDatabase::STATUS_OK:
275 return "Database OK";
276 case ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND:
277 return "Database not found";
278 case ServiceWorkerDatabase::STATUS_ERROR_IO_ERROR:
279 return "Database IO error";
280 case ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED:
281 return "Database corrupted";
282 case ServiceWorkerDatabase::STATUS_ERROR_FAILED:
283 return "Database operation failed";
284 case ServiceWorkerDatabase::STATUS_ERROR_MAX:
285 NOTREACHED();
286 return "Database unknown error";
287 }
288 NOTREACHED();
289 return "Database unknown error";
290 }
291
228 } // namespace 292 } // namespace
229 293
230 ServiceWorkerDatabase::RegistrationData::RegistrationData() 294 ServiceWorkerDatabase::RegistrationData::RegistrationData()
231 : registration_id(kInvalidServiceWorkerRegistrationId), 295 : registration_id(kInvalidServiceWorkerRegistrationId),
232 version_id(kInvalidServiceWorkerVersionId), 296 version_id(kInvalidServiceWorkerVersionId),
233 is_active(false), 297 is_active(false),
234 has_fetch_handler(false) { 298 has_fetch_handler(false) {
235 } 299 }
236 300
237 ServiceWorkerDatabase::RegistrationData::~RegistrationData() { 301 ServiceWorkerDatabase::RegistrationData::~RegistrationData() {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 DCHECK(origins->empty()); 356 DCHECK(origins->empty());
293 357
294 Status status = LazyOpen(false); 358 Status status = LazyOpen(false);
295 if (IsNewOrNonexistentDatabase(status)) 359 if (IsNewOrNonexistentDatabase(status))
296 return STATUS_OK; 360 return STATUS_OK;
297 if (status != STATUS_OK) 361 if (status != STATUS_OK)
298 return status; 362 return status;
299 363
300 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 364 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
301 for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) { 365 for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) {
302 if (!itr->status().ok()) { 366 status = LevelDBStatusToStatus(itr->status());
303 HandleError(FROM_HERE, itr->status()); 367 if (status != STATUS_OK) {
368 HandleReadResult(FROM_HERE, status);
304 origins->clear(); 369 origins->clear();
305 return LevelDBStatusToStatus(itr->status()); 370 return status;
306 } 371 }
307 372
308 std::string origin; 373 std::string origin;
309 if (!RemovePrefix(itr->key().ToString(), kUniqueOriginKey, &origin)) 374 if (!RemovePrefix(itr->key().ToString(), kUniqueOriginKey, &origin))
310 break; 375 break;
311 origins->insert(GURL(origin)); 376 origins->insert(GURL(origin));
312 } 377 }
313 return STATUS_OK; 378
379 HandleReadResult(FROM_HERE, status);
380 return status;
314 } 381 }
315 382
316 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetRegistrationsForOrigin( 383 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetRegistrationsForOrigin(
317 const GURL& origin, 384 const GURL& origin,
318 std::vector<RegistrationData>* registrations) { 385 std::vector<RegistrationData>* registrations) {
319 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 386 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
320 DCHECK(registrations->empty()); 387 DCHECK(registrations->empty());
321 388
322 Status status = LazyOpen(false); 389 Status status = LazyOpen(false);
323 if (IsNewOrNonexistentDatabase(status)) 390 if (IsNewOrNonexistentDatabase(status))
324 return STATUS_OK; 391 return STATUS_OK;
325 if (status != STATUS_OK) 392 if (status != STATUS_OK)
326 return status; 393 return status;
327 394
328 // Create a key prefix for registrations. 395 // Create a key prefix for registrations.
329 std::string prefix = base::StringPrintf( 396 std::string prefix = base::StringPrintf(
330 "%s%s%c", kRegKeyPrefix, origin.spec().c_str(), kKeySeparator); 397 "%s%s%c", kRegKeyPrefix, origin.spec().c_str(), kKeySeparator);
331 398
332 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 399 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
333 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { 400 for (itr->Seek(prefix); itr->Valid(); itr->Next()) {
334 if (!itr->status().ok()) { 401 status = LevelDBStatusToStatus(itr->status());
335 HandleError(FROM_HERE, itr->status()); 402 if (status != STATUS_OK) {
403 HandleReadResult(FROM_HERE, status);
336 registrations->clear(); 404 registrations->clear();
337 return LevelDBStatusToStatus(itr->status()); 405 return status;
338 } 406 }
339 407
340 if (!RemovePrefix(itr->key().ToString(), prefix, NULL)) 408 if (!RemovePrefix(itr->key().ToString(), prefix, NULL))
341 break; 409 break;
342 410
343 RegistrationData registration; 411 RegistrationData registration;
344 if (!ParseRegistrationData(itr->value().ToString(), &registration)) { 412 status = ParseRegistrationData(itr->value().ToString(), &registration);
345 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 413 if (status != STATUS_OK) {
414 HandleReadResult(FROM_HERE, status);
346 registrations->clear(); 415 registrations->clear();
347 return STATUS_ERROR_CORRUPTED; 416 return status;
348 } 417 }
349 registrations->push_back(registration); 418 registrations->push_back(registration);
350 } 419 }
351 return STATUS_OK; 420
421 HandleReadResult(FROM_HERE, status);
422 return status;
352 } 423 }
353 424
354 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetAllRegistrations( 425 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetAllRegistrations(
355 std::vector<RegistrationData>* registrations) { 426 std::vector<RegistrationData>* registrations) {
356 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 427 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
357 DCHECK(registrations->empty()); 428 DCHECK(registrations->empty());
358 429
359 Status status = LazyOpen(false); 430 Status status = LazyOpen(false);
360 if (IsNewOrNonexistentDatabase(status)) 431 if (IsNewOrNonexistentDatabase(status))
361 return STATUS_OK; 432 return STATUS_OK;
362 if (status != STATUS_OK) 433 if (status != STATUS_OK)
363 return status; 434 return status;
364 435
365 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 436 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
366 for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) { 437 for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) {
367 if (!itr->status().ok()) { 438 status = LevelDBStatusToStatus(itr->status());
368 HandleError(FROM_HERE, itr->status()); 439 if (status != STATUS_OK) {
440 HandleReadResult(FROM_HERE, status);
369 registrations->clear(); 441 registrations->clear();
370 return LevelDBStatusToStatus(itr->status()); 442 return status;
371 } 443 }
372 444
373 if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, NULL)) 445 if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, NULL))
374 break; 446 break;
375 447
376 RegistrationData registration; 448 RegistrationData registration;
377 if (!ParseRegistrationData(itr->value().ToString(), &registration)) { 449 status = ParseRegistrationData(itr->value().ToString(), &registration);
378 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 450 if (status != STATUS_OK) {
451 HandleReadResult(FROM_HERE, status);
379 registrations->clear(); 452 registrations->clear();
380 return STATUS_ERROR_CORRUPTED; 453 return status;
381 } 454 }
382 registrations->push_back(registration); 455 registrations->push_back(registration);
383 } 456 }
384 return STATUS_OK; 457
458 HandleReadResult(FROM_HERE, status);
459 return status;
385 } 460 }
386 461
387 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration( 462 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration(
388 int64 registration_id, 463 int64 registration_id,
389 const GURL& origin, 464 const GURL& origin,
390 RegistrationData* registration, 465 RegistrationData* registration,
391 std::vector<ResourceRecord>* resources) { 466 std::vector<ResourceRecord>* resources) {
392 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 467 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
393 DCHECK(registration); 468 DCHECK(registration);
394 DCHECK(resources); 469 DCHECK(resources);
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 } 743 }
669 744
670 leveldb::Options options; 745 leveldb::Options options;
671 options.create_if_missing = create_if_missing; 746 options.create_if_missing = create_if_missing;
672 if (use_in_memory_db) { 747 if (use_in_memory_db) {
673 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); 748 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
674 options.env = env_.get(); 749 options.env = env_.get();
675 } 750 }
676 751
677 leveldb::DB* db = NULL; 752 leveldb::DB* db = NULL;
678 leveldb::Status db_status = 753 Status status = LevelDBStatusToStatus(
679 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 754 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db));
680 if (!db_status.ok()) { 755 HandleOpenResult(FROM_HERE, status);
756 if (status != STATUS_OK) {
681 DCHECK(!db); 757 DCHECK(!db);
682 // TODO(nhiroki): Should we retry to open the database? 758 // TODO(nhiroki): Should we retry to open the database?
683 HandleError(FROM_HERE, db_status); 759 return status;
684 return LevelDBStatusToStatus(db_status);
685 } 760 }
686 db_.reset(db); 761 db_.reset(db);
687 762
688 int64 db_version; 763 int64 db_version;
689 Status status = ReadDatabaseVersion(&db_version); 764 status = ReadDatabaseVersion(&db_version);
690 if (status != STATUS_OK) 765 if (status != STATUS_OK)
691 return status; 766 return status;
692 DCHECK_LE(0, db_version); 767 DCHECK_LE(0, db_version);
693 if (db_version > 0) 768 if (db_version > 0)
694 state_ = INITIALIZED; 769 state_ = INITIALIZED;
695 return STATUS_OK; 770 return STATUS_OK;
696 } 771 }
697 772
698 bool ServiceWorkerDatabase::IsNewOrNonexistentDatabase( 773 bool ServiceWorkerDatabase::IsNewOrNonexistentDatabase(
699 ServiceWorkerDatabase::Status status) { 774 ServiceWorkerDatabase::Status status) {
700 if (status == STATUS_ERROR_NOT_FOUND) 775 if (status == STATUS_ERROR_NOT_FOUND)
701 return true; 776 return true;
702 if (status == STATUS_OK && state_ == UNINITIALIZED) 777 if (status == STATUS_OK && state_ == UNINITIALIZED)
703 return true; 778 return true;
704 return false; 779 return false;
705 } 780 }
706 781
707 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadNextAvailableId( 782 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadNextAvailableId(
708 const char* id_key, 783 const char* id_key,
709 int64* next_avail_id) { 784 int64* next_avail_id) {
710 DCHECK(id_key); 785 DCHECK(id_key);
711 DCHECK(next_avail_id); 786 DCHECK(next_avail_id);
712 787
713 std::string value; 788 std::string value;
714 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value); 789 Status status = LevelDBStatusToStatus(
715 if (status.IsNotFound()) { 790 db_->Get(leveldb::ReadOptions(), id_key, &value));
791 if (status == STATUS_ERROR_NOT_FOUND) {
716 // Nobody has gotten the next resource id for |id_key|. 792 // Nobody has gotten the next resource id for |id_key|.
717 *next_avail_id = 0; 793 *next_avail_id = 0;
794 HandleReadResult(FROM_HERE, STATUS_OK);
718 return STATUS_OK; 795 return STATUS_OK;
796 } else if (status != STATUS_OK) {
797 HandleReadResult(FROM_HERE, status);
798 return status;
719 } 799 }
720 800
721 if (!status.ok()) { 801 status = ParseId(value, next_avail_id);
722 HandleError(FROM_HERE, status); 802 HandleReadResult(FROM_HERE, status);
723 return LevelDBStatusToStatus(status); 803 return status;
724 }
725
726 int64 parsed;
727 if (!base::StringToInt64(value, &parsed)) {
728 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
729 return STATUS_ERROR_CORRUPTED;
730 }
731
732 *next_avail_id = parsed;
733 return STATUS_OK;
734 } 804 }
735 805
736 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationData( 806 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationData(
737 int64 registration_id, 807 int64 registration_id,
738 const GURL& origin, 808 const GURL& origin,
739 RegistrationData* registration) { 809 RegistrationData* registration) {
740 DCHECK(registration); 810 DCHECK(registration);
741 811
742 std::string key = CreateRegistrationKey(registration_id, origin); 812 const std::string key = CreateRegistrationKey(registration_id, origin);
743
744 std::string value; 813 std::string value;
745 leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value); 814 Status status = LevelDBStatusToStatus(
746 if (!status.ok()) { 815 db_->Get(leveldb::ReadOptions(), key, &value));
747 if (!status.IsNotFound()) 816 if (status != STATUS_OK) {
748 HandleError(FROM_HERE, status); 817 HandleReadResult(
749 return LevelDBStatusToStatus(status); 818 FROM_HERE,
819 status == STATUS_ERROR_NOT_FOUND ? STATUS_OK : status);
820 return status;
750 } 821 }
751 822
752 RegistrationData parsed; 823 status = ParseRegistrationData(value, registration);
753 if (!ParseRegistrationData(value, &parsed)) { 824 HandleReadResult(FROM_HERE, status);
754 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 825 return status;
755 return STATUS_ERROR_CORRUPTED;
756 }
757
758 *registration = parsed;
759 return STATUS_OK;
760 } 826 }
761 827
762 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceRecords( 828 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceRecords(
763 int64 version_id, 829 int64 version_id,
764 std::vector<ResourceRecord>* resources) { 830 std::vector<ResourceRecord>* resources) {
765 DCHECK(resources); 831 DCHECK(resources->empty());
766 832
767 std::string prefix = CreateResourceRecordKeyPrefix(version_id); 833 Status status = STATUS_OK;
834 const std::string prefix = CreateResourceRecordKeyPrefix(version_id);
835
768 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 836 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
769 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { 837 for (itr->Seek(prefix); itr->Valid(); itr->Next()) {
770 if (!itr->status().ok()) { 838 Status status = LevelDBStatusToStatus(itr->status());
771 HandleError(FROM_HERE, itr->status()); 839 if (status != STATUS_OK) {
840 HandleReadResult(FROM_HERE, status);
772 resources->clear(); 841 resources->clear();
773 return LevelDBStatusToStatus(itr->status()); 842 return status;
774 } 843 }
775 844
776 if (!RemovePrefix(itr->key().ToString(), prefix, NULL)) 845 if (!RemovePrefix(itr->key().ToString(), prefix, NULL))
777 break; 846 break;
778 847
779 ResourceRecord resource; 848 ResourceRecord resource;
780 if (!ParseResourceRecord(itr->value().ToString(), &resource)) { 849 status = ParseResourceRecord(itr->value().ToString(), &resource);
781 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 850 if (status != STATUS_OK) {
851 HandleReadResult(FROM_HERE, status);
782 resources->clear(); 852 resources->clear();
783 return STATUS_ERROR_CORRUPTED; 853 return status;
784 } 854 }
785 resources->push_back(resource); 855 resources->push_back(resource);
786 } 856 }
787 return STATUS_OK; 857
858 HandleReadResult(FROM_HERE, status);
859 return status;
788 } 860 }
789 861
790 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords( 862 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords(
791 int64 version_id, 863 int64 version_id,
792 std::vector<int64>* newly_purgeable_resources, 864 std::vector<int64>* newly_purgeable_resources,
793 leveldb::WriteBatch* batch) { 865 leveldb::WriteBatch* batch) {
794 DCHECK(batch); 866 DCHECK(batch);
795 867
796 std::string prefix = CreateResourceRecordKeyPrefix(version_id); 868 Status status = STATUS_OK;
869 const std::string prefix = CreateResourceRecordKeyPrefix(version_id);
870
797 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 871 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
798 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { 872 for (itr->Seek(prefix); itr->Valid(); itr->Next()) {
799 if (!itr->status().ok()) { 873 status = LevelDBStatusToStatus(itr->status());
800 HandleError(FROM_HERE, itr->status()); 874 if (status != STATUS_OK) {
801 return LevelDBStatusToStatus(itr->status()); 875 HandleReadResult(FROM_HERE, status);
876 return status;
802 } 877 }
803 878
804 std::string key = itr->key().ToString(); 879 const std::string key = itr->key().ToString();
805 std::string unprefixed; 880 std::string unprefixed;
806 if (!RemovePrefix(key, prefix, &unprefixed)) 881 if (!RemovePrefix(key, prefix, &unprefixed))
807 break; 882 break;
808 883
809 int64 resource_id; 884 int64 resource_id;
810 if (!base::StringToInt64(unprefixed, &resource_id)) { 885 status = ParseId(unprefixed, &resource_id);
811 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 886 if (status != STATUS_OK) {
812 return STATUS_ERROR_CORRUPTED; 887 HandleReadResult(FROM_HERE, status);
888 return status;
813 } 889 }
814 890
815 // Remove a resource record. 891 // Remove a resource record.
816 batch->Delete(key); 892 batch->Delete(key);
817 893
818 // Currently resource sharing across versions and registrations is not 894 // Currently resource sharing across versions and registrations is not
819 // supported, so we can purge this without caring about it. 895 // supported, so we can purge this without caring about it.
820 PutPurgeableResourceIdToBatch(resource_id, batch); 896 PutPurgeableResourceIdToBatch(resource_id, batch);
821 newly_purgeable_resources->push_back(resource_id); 897 newly_purgeable_resources->push_back(resource_id);
822 } 898 }
823 return STATUS_OK; 899
900 HandleReadResult(FROM_HERE, status);
901 return status;
824 } 902 }
825 903
826 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds( 904 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds(
827 const char* id_key_prefix, 905 const char* id_key_prefix,
828 std::set<int64>* ids) { 906 std::set<int64>* ids) {
829 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 907 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
830 DCHECK(id_key_prefix); 908 DCHECK(id_key_prefix);
831 DCHECK(ids->empty()); 909 DCHECK(ids->empty());
832 910
833 Status status = LazyOpen(false); 911 Status status = LazyOpen(false);
834 if (IsNewOrNonexistentDatabase(status)) 912 if (IsNewOrNonexistentDatabase(status))
835 return STATUS_OK; 913 return STATUS_OK;
836 if (status != STATUS_OK) 914 if (status != STATUS_OK)
837 return status; 915 return status;
838 916
839 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 917 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
840 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) { 918 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) {
841 if (!itr->status().ok()) { 919 status = LevelDBStatusToStatus(itr->status());
842 HandleError(FROM_HERE, itr->status()); 920 if (status != STATUS_OK) {
921 HandleReadResult(FROM_HERE, status);
843 ids->clear(); 922 ids->clear();
844 return LevelDBStatusToStatus(itr->status()); 923 return status;
845 } 924 }
846 925
847 std::string unprefixed; 926 std::string unprefixed;
848 if (!RemovePrefix(itr->key().ToString(), id_key_prefix, &unprefixed)) 927 if (!RemovePrefix(itr->key().ToString(), id_key_prefix, &unprefixed))
849 break; 928 break;
850 929
851 int64 resource_id; 930 int64 resource_id;
852 if (!base::StringToInt64(unprefixed, &resource_id)) { 931 status = ParseId(unprefixed, &resource_id);
853 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 932 if (status != STATUS_OK) {
933 HandleReadResult(FROM_HERE, status);
854 ids->clear(); 934 ids->clear();
855 return STATUS_ERROR_CORRUPTED; 935 return status;
856 } 936 }
857 ids->insert(resource_id); 937 ids->insert(resource_id);
858 } 938 }
859 return STATUS_OK; 939
940 HandleReadResult(FROM_HERE, status);
941 return status;
860 } 942 }
861 943
862 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteResourceIds( 944 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteResourceIds(
863 const char* id_key_prefix, 945 const char* id_key_prefix,
864 const std::set<int64>& ids) { 946 const std::set<int64>& ids) {
865 leveldb::WriteBatch batch; 947 leveldb::WriteBatch batch;
866 Status status = WriteResourceIdsInBatch(id_key_prefix, ids, &batch); 948 Status status = WriteResourceIdsInBatch(id_key_prefix, ids, &batch);
867 if (status != STATUS_OK) 949 if (status != STATUS_OK)
868 return status; 950 return status;
869 return WriteBatch(&batch); 951 return WriteBatch(&batch);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 for (std::set<int64>::const_iterator itr = ids.begin(); 996 for (std::set<int64>::const_iterator itr = ids.begin();
915 itr != ids.end(); ++itr) { 997 itr != ids.end(); ++itr) {
916 batch->Delete(CreateResourceIdKey(id_key_prefix, *itr)); 998 batch->Delete(CreateResourceIdKey(id_key_prefix, *itr));
917 } 999 }
918 return STATUS_OK; 1000 return STATUS_OK;
919 } 1001 }
920 1002
921 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadDatabaseVersion( 1003 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadDatabaseVersion(
922 int64* db_version) { 1004 int64* db_version) {
923 std::string value; 1005 std::string value;
924 leveldb::Status status = 1006 Status status = LevelDBStatusToStatus(
925 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); 1007 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value));
926 if (status.IsNotFound()) { 1008 if (status == STATUS_ERROR_NOT_FOUND) {
927 // The database hasn't been initialized yet. 1009 // The database hasn't been initialized yet.
928 *db_version = 0; 1010 *db_version = 0;
1011 HandleReadResult(FROM_HERE, STATUS_OK);
929 return STATUS_OK; 1012 return STATUS_OK;
930 } 1013 }
931 if (!status.ok()) { 1014
932 HandleError(FROM_HERE, status); 1015 if (status != STATUS_OK) {
933 return LevelDBStatusToStatus(status); 1016 HandleReadResult(FROM_HERE, status);
1017 return status;
934 } 1018 }
935 1019
936 int64 parsed; 1020 status = ParseDatabaseVersion(value, db_version);
937 if (!base::StringToInt64(value, &parsed)) { 1021 HandleReadResult(FROM_HERE, status);
938 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 1022 return status;
939 return STATUS_ERROR_CORRUPTED;
940 }
941
942 const int kFirstValidVersion = 1;
943 if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) {
944 HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version"));
945 return STATUS_ERROR_CORRUPTED;
946 }
947
948 *db_version = parsed;
949 return STATUS_OK;
950 } 1023 }
951 1024
952 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteBatch( 1025 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteBatch(
953 leveldb::WriteBatch* batch) { 1026 leveldb::WriteBatch* batch) {
954 DCHECK(batch); 1027 DCHECK(batch);
955 DCHECK_NE(DISABLED, state_); 1028 DCHECK_NE(DISABLED, state_);
956 1029
957 if (state_ == UNINITIALIZED) { 1030 if (state_ == UNINITIALIZED) {
958 // Write the database schema version. 1031 // Write the database schema version.
959 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion)); 1032 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion));
960 state_ = INITIALIZED; 1033 state_ = INITIALIZED;
961 } 1034 }
962 1035
963 leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch); 1036 Status status = LevelDBStatusToStatus(
964 if (!status.ok()) 1037 db_->Write(leveldb::WriteOptions(), batch));
965 HandleError(FROM_HERE, status); 1038 HandleWriteResult(FROM_HERE, status);
966 return LevelDBStatusToStatus(status); 1039 return status;
967 } 1040 }
968 1041
969 void ServiceWorkerDatabase::BumpNextRegistrationIdIfNeeded( 1042 void ServiceWorkerDatabase::BumpNextRegistrationIdIfNeeded(
970 int64 used_id, leveldb::WriteBatch* batch) { 1043 int64 used_id, leveldb::WriteBatch* batch) {
971 DCHECK(batch); 1044 DCHECK(batch);
972 if (next_avail_registration_id_ <= used_id) { 1045 if (next_avail_registration_id_ <= used_id) {
973 next_avail_registration_id_ = used_id + 1; 1046 next_avail_registration_id_ = used_id + 1;
974 batch->Put(kNextRegIdKey, base::Int64ToString(next_avail_registration_id_)); 1047 batch->Put(kNextRegIdKey, base::Int64ToString(next_avail_registration_id_));
975 } 1048 }
976 } 1049 }
977 1050
978 void ServiceWorkerDatabase::BumpNextVersionIdIfNeeded( 1051 void ServiceWorkerDatabase::BumpNextVersionIdIfNeeded(
979 int64 used_id, leveldb::WriteBatch* batch) { 1052 int64 used_id, leveldb::WriteBatch* batch) {
980 DCHECK(batch); 1053 DCHECK(batch);
981 if (next_avail_version_id_ <= used_id) { 1054 if (next_avail_version_id_ <= used_id) {
982 next_avail_version_id_ = used_id + 1; 1055 next_avail_version_id_ = used_id + 1;
983 batch->Put(kNextVerIdKey, base::Int64ToString(next_avail_version_id_)); 1056 batch->Put(kNextVerIdKey, base::Int64ToString(next_avail_version_id_));
984 } 1057 }
985 } 1058 }
986 1059
987 bool ServiceWorkerDatabase::IsOpen() { 1060 bool ServiceWorkerDatabase::IsOpen() {
988 return db_ != NULL; 1061 return db_ != NULL;
989 } 1062 }
990 1063
991 void ServiceWorkerDatabase::HandleError( 1064 void ServiceWorkerDatabase::Disable(
992 const tracked_objects::Location& from_here, 1065 const tracked_objects::Location& from_here,
993 const leveldb::Status& status) { 1066 Status status) {
994 // TODO(nhiroki): Add an UMA histogram.
995 DLOG(ERROR) << "Failed at: " << from_here.ToString() 1067 DLOG(ERROR) << "Failed at: " << from_here.ToString()
996 << " with error: " << status.ToString(); 1068 << " with error: " << StatusToString(status);
1069 DLOG(ERROR) << "ServiceWorkerDatabase is disabled.";
997 state_ = DISABLED; 1070 state_ = DISABLED;
998 db_.reset(); 1071 db_.reset();
999 } 1072 }
1000 1073
1074 void ServiceWorkerDatabase::HandleOpenResult(
1075 const tracked_objects::Location& from_here,
1076 Status status) {
1077 if (status != ServiceWorkerDatabase::STATUS_OK)
1078 Disable(from_here, status);
1079 UMA_HISTOGRAM_ENUMERATION(kOpenResultHistogramLabel,
1080 status,
1081 ServiceWorkerDatabase::STATUS_ERROR_MAX);
1082 }
1083
1084 void ServiceWorkerDatabase::HandleReadResult(
1085 const tracked_objects::Location& from_here,
1086 Status status) {
1087 if (status != ServiceWorkerDatabase::STATUS_OK)
1088 Disable(from_here, status);
1089 UMA_HISTOGRAM_ENUMERATION(kReadResultHistogramLabel,
1090 status,
1091 ServiceWorkerDatabase::STATUS_ERROR_MAX);
1092 }
1093
1094 void ServiceWorkerDatabase::HandleWriteResult(
1095 const tracked_objects::Location& from_here,
1096 Status status) {
1097 if (status != ServiceWorkerDatabase::STATUS_OK)
1098 Disable(from_here, status);
1099 UMA_HISTOGRAM_ENUMERATION(kWriteResultHistogramLabel,
1100 status,
1101 ServiceWorkerDatabase::STATUS_ERROR_MAX);
1102 }
1103
1001 } // namespace content 1104 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/service_worker/service_worker_database.h ('k') | content/browser/service_worker/service_worker_storage.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698