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

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

Issue 287843002: ServiceWorker: DB functions should return status code instead of boolean (2) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix Created 6 years, 7 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"
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 253
254 ServiceWorkerStatusCode ServiceWorkerDatabase::GetNextAvailableIds( 254 ServiceWorkerStatusCode ServiceWorkerDatabase::GetNextAvailableIds(
255 int64* next_avail_registration_id, 255 int64* next_avail_registration_id,
256 int64* next_avail_version_id, 256 int64* next_avail_version_id,
257 int64* next_avail_resource_id) { 257 int64* next_avail_resource_id) {
258 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 258 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
259 DCHECK(next_avail_registration_id); 259 DCHECK(next_avail_registration_id);
260 DCHECK(next_avail_version_id); 260 DCHECK(next_avail_version_id);
261 DCHECK(next_avail_resource_id); 261 DCHECK(next_avail_resource_id);
262 262
263 if (!LazyOpen(false)) { 263 ServiceWorkerStatusCode status = LazyOpen(false);
264 if (is_disabled_) 264 if (status == SERVICE_WORKER_ERROR_NOT_FOUND ||
265 return SERVICE_WORKER_ERROR_FAILED; 265 (status == SERVICE_WORKER_OK && !is_initialized_)) {
266 // Database has never been used. 266 // Database has never been used.
267 *next_avail_registration_id = 0; 267 *next_avail_registration_id = 0;
268 *next_avail_version_id = 0; 268 *next_avail_version_id = 0;
269 *next_avail_resource_id = 0; 269 *next_avail_resource_id = 0;
270 return SERVICE_WORKER_OK; 270 return SERVICE_WORKER_OK;
271 } 271 }
272 if (status != SERVICE_WORKER_OK)
273 return status;
272 274
273 ServiceWorkerStatusCode status = 275 status = ReadNextAvailableId(kNextRegIdKey, &next_avail_registration_id_);
274 ReadNextAvailableId(kNextRegIdKey, &next_avail_registration_id_);
275 if (status != SERVICE_WORKER_OK) 276 if (status != SERVICE_WORKER_OK)
276 return status; 277 return status;
277 status = ReadNextAvailableId(kNextVerIdKey, &next_avail_version_id_); 278 status = ReadNextAvailableId(kNextVerIdKey, &next_avail_version_id_);
278 if (status != SERVICE_WORKER_OK) 279 if (status != SERVICE_WORKER_OK)
279 return status; 280 return status;
280 status = ReadNextAvailableId(kNextResIdKey, &next_avail_resource_id_); 281 status = ReadNextAvailableId(kNextResIdKey, &next_avail_resource_id_);
281 if (status != SERVICE_WORKER_OK) 282 if (status != SERVICE_WORKER_OK)
282 return status; 283 return status;
283 284
284 *next_avail_registration_id = next_avail_registration_id_; 285 *next_avail_registration_id = next_avail_registration_id_;
285 *next_avail_version_id = next_avail_version_id_; 286 *next_avail_version_id = next_avail_version_id_;
286 *next_avail_resource_id = next_avail_resource_id_; 287 *next_avail_resource_id = next_avail_resource_id_;
287 return SERVICE_WORKER_OK; 288 return SERVICE_WORKER_OK;
288 } 289 }
289 290
290 ServiceWorkerStatusCode ServiceWorkerDatabase::GetOriginsWithRegistrations( 291 ServiceWorkerStatusCode ServiceWorkerDatabase::GetOriginsWithRegistrations(
291 std::set<GURL>* origins) { 292 std::set<GURL>* origins) {
292 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 293 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
293 DCHECK(origins); 294 DCHECK(origins);
294 295
295 if (!LazyOpen(false)) { 296 ServiceWorkerStatusCode status = LazyOpen(false);
296 if (is_disabled_) 297 if (status == SERVICE_WORKER_ERROR_NOT_FOUND ||
297 return SERVICE_WORKER_ERROR_FAILED; 298 (status == SERVICE_WORKER_OK && !is_initialized_)) {
298 // Database has never been used. 299 // Database has never been used.
299 origins->clear(); 300 origins->clear();
michaeln 2014/05/15 19:59:30 if origins needs to be cleared here, then it also
nhiroki 2014/05/16 02:11:11 Done.
300 return SERVICE_WORKER_OK; 301 return SERVICE_WORKER_OK;
301 } 302 }
303 if (status != SERVICE_WORKER_OK)
304 return status;
302 305
303 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 306 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
304 for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) { 307 for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) {
305 if (!itr->status().ok()) { 308 if (!itr->status().ok()) {
306 HandleError(FROM_HERE, itr->status()); 309 HandleError(FROM_HERE, itr->status());
307 origins->clear(); 310 origins->clear();
308 return LevelDBStatusToServiceWorkerStatusCode(itr->status()); 311 return LevelDBStatusToServiceWorkerStatusCode(itr->status());
309 } 312 }
310 313
311 std::string origin; 314 std::string origin;
312 if (!RemovePrefix(itr->key().ToString(), kUniqueOriginKey, &origin)) 315 if (!RemovePrefix(itr->key().ToString(), kUniqueOriginKey, &origin))
313 break; 316 break;
314 origins->insert(GURL(origin)); 317 origins->insert(GURL(origin));
315 } 318 }
316 return SERVICE_WORKER_OK; 319 return SERVICE_WORKER_OK;
317 } 320 }
318 321
319 bool ServiceWorkerDatabase::GetRegistrationsForOrigin( 322 ServiceWorkerStatusCode ServiceWorkerDatabase::GetRegistrationsForOrigin(
320 const GURL& origin, 323 const GURL& origin,
321 std::vector<RegistrationData>* registrations) { 324 std::vector<RegistrationData>* registrations) {
322 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 325 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
323 DCHECK(registrations); 326 DCHECK(registrations);
324 327
325 if (!LazyOpen(false)) { 328 ServiceWorkerStatusCode status = LazyOpen(false);
326 if (is_disabled_) 329 if (status == SERVICE_WORKER_ERROR_NOT_FOUND ||
327 return false; 330 (status == SERVICE_WORKER_OK && !is_initialized_)) {
328 // Database has never been used. 331 // Database has never been used.
329 registrations->clear(); 332 registrations->clear();
michaeln 2014/05/15 19:59:30 ditto clearing the collection
nhiroki 2014/05/16 02:11:11 Done.
330 return true; 333 return SERVICE_WORKER_OK;
331 } 334 }
335 if (status != SERVICE_WORKER_OK)
336 return status;
332 337
333 // Create a key prefix for registrations. 338 // Create a key prefix for registrations.
334 std::string prefix = base::StringPrintf( 339 std::string prefix = base::StringPrintf(
335 "%s%s%c", kRegKeyPrefix, origin.spec().c_str(), kKeySeparator); 340 "%s%s%c", kRegKeyPrefix, origin.spec().c_str(), kKeySeparator);
336 341
337 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 342 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
338 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { 343 for (itr->Seek(prefix); itr->Valid(); itr->Next()) {
339 if (!itr->status().ok()) { 344 if (!itr->status().ok()) {
340 HandleError(FROM_HERE, itr->status()); 345 HandleError(FROM_HERE, itr->status());
341 registrations->clear(); 346 registrations->clear();
342 return false; 347 return LevelDBStatusToServiceWorkerStatusCode(itr->status());
343 } 348 }
344 349
345 if (!RemovePrefix(itr->key().ToString(), prefix, NULL)) 350 if (!RemovePrefix(itr->key().ToString(), prefix, NULL))
346 break; 351 break;
347 352
348 RegistrationData registration; 353 RegistrationData registration;
349 if (!ParseRegistrationData(itr->value().ToString(), &registration)) { 354 if (!ParseRegistrationData(itr->value().ToString(), &registration)) {
350 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 355 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
351 registrations->clear(); 356 registrations->clear();
352 return false; 357 return SERVICE_WORKER_ERROR_DB_CORRUPTED;
353 } 358 }
354 registrations->push_back(registration); 359 registrations->push_back(registration);
355 } 360 }
356 return true; 361 return SERVICE_WORKER_OK;
357 } 362 }
358 363
359 bool ServiceWorkerDatabase::GetAllRegistrations( 364 ServiceWorkerStatusCode ServiceWorkerDatabase::GetAllRegistrations(
360 std::vector<RegistrationData>* registrations) { 365 std::vector<RegistrationData>* registrations) {
361 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 366 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
362 DCHECK(registrations); 367 DCHECK(registrations);
363 368
364 if (!LazyOpen(false)) { 369 ServiceWorkerStatusCode status = LazyOpen(false);
365 if (is_disabled_) 370 if (status == SERVICE_WORKER_ERROR_NOT_FOUND ||
366 return false; 371 (status == SERVICE_WORKER_OK && !is_initialized_)) {
367 // Database has never been used. 372 // Database has never been used.
368 registrations->clear(); 373 registrations->clear();
michaeln 2014/05/15 19:59:30 ditt
nhiroki 2014/05/16 02:11:11 Done.
369 return true; 374 return SERVICE_WORKER_OK;
370 } 375 }
376 if (status != SERVICE_WORKER_OK)
377 return status;
371 378
372 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 379 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
373 for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) { 380 for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) {
374 if (!itr->status().ok()) { 381 if (!itr->status().ok()) {
375 HandleError(FROM_HERE, itr->status()); 382 HandleError(FROM_HERE, itr->status());
376 registrations->clear(); 383 registrations->clear();
377 return false; 384 return LevelDBStatusToServiceWorkerStatusCode(itr->status());
378 } 385 }
379 386
380 if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, NULL)) 387 if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, NULL))
381 break; 388 break;
382 389
383 RegistrationData registration; 390 RegistrationData registration;
384 if (!ParseRegistrationData(itr->value().ToString(), &registration)) { 391 if (!ParseRegistrationData(itr->value().ToString(), &registration)) {
385 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 392 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
386 registrations->clear(); 393 registrations->clear();
387 return false; 394 return SERVICE_WORKER_ERROR_DB_CORRUPTED;
388 } 395 }
389 registrations->push_back(registration); 396 registrations->push_back(registration);
390 } 397 }
391 return true; 398 return SERVICE_WORKER_OK;
392 } 399 }
393 400
394 bool ServiceWorkerDatabase::ReadRegistration( 401 bool ServiceWorkerDatabase::ReadRegistration(
395 int64 registration_id, 402 int64 registration_id,
396 const GURL& origin, 403 const GURL& origin,
397 RegistrationData* registration, 404 RegistrationData* registration,
398 std::vector<ResourceRecord>* resources) { 405 std::vector<ResourceRecord>* resources) {
399 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 406 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
400 DCHECK(registration); 407 DCHECK(registration);
401 DCHECK(resources); 408 DCHECK(resources);
402 409
403 if (!LazyOpen(false) || is_disabled_) 410 ServiceWorkerStatusCode status = LazyOpen(false);
411 if (status != SERVICE_WORKER_OK || !is_initialized_)
404 return false; 412 return false;
405 413
406 RegistrationData value; 414 RegistrationData value;
407 if (!ReadRegistrationData(registration_id, origin, &value)) 415 if (!ReadRegistrationData(registration_id, origin, &value))
408 return false; 416 return false;
409 417
410 if (!ReadResourceRecords(value.version_id, resources)) 418 if (!ReadResourceRecords(value.version_id, resources))
411 return false; 419 return false;
412 420
413 *registration = value; 421 *registration = value;
414 return true; 422 return true;
415 } 423 }
416 424
417 bool ServiceWorkerDatabase::WriteRegistration( 425 bool ServiceWorkerDatabase::WriteRegistration(
418 const RegistrationData& registration, 426 const RegistrationData& registration,
419 const std::vector<ResourceRecord>& resources) { 427 const std::vector<ResourceRecord>& resources) {
420 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 428 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
421 if (!LazyOpen(true) || is_disabled_) 429 if (LazyOpen(true) != SERVICE_WORKER_OK)
422 return false; 430 return false;
423 431
424 leveldb::WriteBatch batch; 432 leveldb::WriteBatch batch;
425 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch); 433 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch);
426 BumpNextVersionIdIfNeeded(registration.version_id, &batch); 434 BumpNextVersionIdIfNeeded(registration.version_id, &batch);
427 435
428 // TODO(nhiroki): Skip to add the origin into the unique origin list if it 436 // TODO(nhiroki): Skip to add the origin into the unique origin list if it
429 // has already been added. 437 // has already been added.
430 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch); 438 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch);
431 439
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 batch.Delete(CreateResourceIdKey( 475 batch.Delete(CreateResourceIdKey(
468 kUncommittedResIdKeyPrefix, itr->resource_id)); 476 kUncommittedResIdKeyPrefix, itr->resource_id));
469 } 477 }
470 478
471 return WriteBatch(&batch); 479 return WriteBatch(&batch);
472 } 480 }
473 481
474 bool ServiceWorkerDatabase::UpdateVersionToActive(int64 registration_id, 482 bool ServiceWorkerDatabase::UpdateVersionToActive(int64 registration_id,
475 const GURL& origin) { 483 const GURL& origin) {
476 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 484 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
477 if (!LazyOpen(false) || is_disabled_) 485 if (LazyOpen(false) != SERVICE_WORKER_OK || !is_initialized_)
478 return false; 486 return false;
479 487
480 RegistrationData registration; 488 RegistrationData registration;
481 if (!ReadRegistrationData(registration_id, origin, &registration)) 489 if (!ReadRegistrationData(registration_id, origin, &registration))
482 return false; 490 return false;
483 491
484 registration.is_active = true; 492 registration.is_active = true;
485 493
486 leveldb::WriteBatch batch; 494 leveldb::WriteBatch batch;
487 PutRegistrationDataToBatch(registration, &batch); 495 PutRegistrationDataToBatch(registration, &batch);
488 return WriteBatch(&batch); 496 return WriteBatch(&batch);
489 } 497 }
490 498
491 bool ServiceWorkerDatabase::UpdateLastCheckTime(int64 registration_id, 499 bool ServiceWorkerDatabase::UpdateLastCheckTime(int64 registration_id,
492 const GURL& origin, 500 const GURL& origin,
493 const base::Time& time) { 501 const base::Time& time) {
494 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 502 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
495 if (!LazyOpen(false) || is_disabled_) 503 if (LazyOpen(false) != SERVICE_WORKER_OK || !is_initialized_)
496 return false; 504 return false;
497 505
498 RegistrationData registration; 506 RegistrationData registration;
499 if (!ReadRegistrationData(registration_id, origin, &registration)) 507 if (!ReadRegistrationData(registration_id, origin, &registration))
500 return false; 508 return false;
501 509
502 registration.last_update_check = time; 510 registration.last_update_check = time;
503 511
504 leveldb::WriteBatch batch; 512 leveldb::WriteBatch batch;
505 PutRegistrationDataToBatch(registration, &batch); 513 PutRegistrationDataToBatch(registration, &batch);
506 return WriteBatch(&batch); 514 return WriteBatch(&batch);
507 } 515 }
508 516
509 bool ServiceWorkerDatabase::DeleteRegistration(int64 registration_id, 517 bool ServiceWorkerDatabase::DeleteRegistration(int64 registration_id,
510 const GURL& origin) { 518 const GURL& origin) {
511 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 519 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
512 if (!LazyOpen(false) || is_disabled_) 520 ServiceWorkerStatusCode status = LazyOpen(false);
521 if (status == SERVICE_WORKER_ERROR_NOT_FOUND ||
522 (status == SERVICE_WORKER_OK && !is_initialized_)) {
523 // Database has never been used.
524 return true;
525 }
526 if (status != SERVICE_WORKER_OK || !origin.is_valid())
513 return false; 527 return false;
514 528
515 leveldb::WriteBatch batch; 529 leveldb::WriteBatch batch;
516 530
517 // Remove |origin| from unique origins if a registration specified by 531 // Remove |origin| from unique origins if a registration specified by
518 // |registration_id| is the only one for |origin|. 532 // |registration_id| is the only one for |origin|.
519 // TODO(nhiroki): Check the uniqueness by more efficient way. 533 // TODO(nhiroki): Check the uniqueness by more efficient way.
520 std::vector<RegistrationData> registrations; 534 std::vector<RegistrationData> registrations;
521 if (!GetRegistrationsForOrigin(origin, &registrations)) 535 if (GetRegistrationsForOrigin(origin, &registrations) != SERVICE_WORKER_OK)
522 return false; 536 return false;
523 if (registrations.size() == 1 && 537 if (registrations.size() == 1 &&
524 registrations[0].registration_id == registration_id) { 538 registrations[0].registration_id == registration_id) {
525 batch.Delete(CreateUniqueOriginKey(origin)); 539 batch.Delete(CreateUniqueOriginKey(origin));
526 } 540 }
527 541
528 // Delete a registration specified by |registration_id|. 542 // Delete a registration specified by |registration_id|.
529 batch.Delete(CreateRegistrationKey(registration_id, origin)); 543 batch.Delete(CreateRegistrationKey(registration_id, origin));
530 544
531 // Delete resource records associated with the registration. 545 // Delete resource records associated with the registration.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids); 578 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids);
565 } 579 }
566 580
567 bool ServiceWorkerDatabase::ClearPurgeableResourceIds( 581 bool ServiceWorkerDatabase::ClearPurgeableResourceIds(
568 const std::set<int64>& ids) { 582 const std::set<int64>& ids) {
569 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids); 583 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids);
570 } 584 }
571 585
572 bool ServiceWorkerDatabase::DeleteAllDataForOrigin(const GURL& origin) { 586 bool ServiceWorkerDatabase::DeleteAllDataForOrigin(const GURL& origin) {
573 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 587 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
574 if (!LazyOpen(true) || is_disabled_ || !origin.is_valid()) 588 ServiceWorkerStatusCode status = LazyOpen(false);
589 if (status == SERVICE_WORKER_ERROR_NOT_FOUND ||
590 (status == SERVICE_WORKER_OK && !is_initialized_)) {
591 // Database has never been used.
592 return true;
593 }
594 if (status != SERVICE_WORKER_OK || !origin.is_valid())
575 return false; 595 return false;
576 596
577 leveldb::WriteBatch batch; 597 leveldb::WriteBatch batch;
578 598
579 // Delete from the unique origin list. 599 // Delete from the unique origin list.
580 batch.Delete(CreateUniqueOriginKey(origin)); 600 batch.Delete(CreateUniqueOriginKey(origin));
581 601
582 std::vector<RegistrationData> registrations; 602 std::vector<RegistrationData> registrations;
583 if (!GetRegistrationsForOrigin(origin, &registrations)) 603 if (GetRegistrationsForOrigin(origin, &registrations) != SERVICE_WORKER_OK)
584 return false; 604 return false;
585 605
586 // Delete registrations and resource records. 606 // Delete registrations and resource records.
587 for (std::vector<RegistrationData>::const_iterator itr = 607 for (std::vector<RegistrationData>::const_iterator itr =
588 registrations.begin(); itr != registrations.end(); ++itr) { 608 registrations.begin(); itr != registrations.end(); ++itr) {
589 batch.Delete(CreateRegistrationKey(itr->registration_id, origin)); 609 batch.Delete(CreateRegistrationKey(itr->registration_id, origin));
590 if (!DeleteResourceRecords(itr->version_id, &batch)) 610 if (!DeleteResourceRecords(itr->version_id, &batch))
591 return false; 611 return false;
592 } 612 }
593 613
594 return WriteBatch(&batch); 614 return WriteBatch(&batch);
595 } 615 }
596 616
597 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) { 617 ServiceWorkerStatusCode ServiceWorkerDatabase::LazyOpen(
618 bool create_if_missing) {
598 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 619 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
599 if (IsOpen())
600 return true;
601 620
602 // Do not try to open a database if we tried and failed once. 621 // Do not try to open a database if we tried and failed once.
603 if (is_disabled_) 622 if (is_disabled_)
604 return false; 623 return SERVICE_WORKER_ERROR_FAILED;
624 if (IsOpen())
625 return SERVICE_WORKER_OK;
605 626
606 // When |path_| is empty, open a database in-memory. 627 // When |path_| is empty, open a database in-memory.
607 bool use_in_memory_db = path_.empty(); 628 bool use_in_memory_db = path_.empty();
608 629
609 if (!create_if_needed) { 630 if (!create_if_missing) {
610 // Avoid opening a database if it does not exist at the |path_|. 631 // Avoid opening a database if it does not exist at the |path_|.
611 if (use_in_memory_db || 632 if (use_in_memory_db ||
612 !base::PathExists(path_) || 633 !base::PathExists(path_) ||
613 base::IsDirectoryEmpty(path_)) { 634 base::IsDirectoryEmpty(path_)) {
614 return false; 635 return SERVICE_WORKER_ERROR_NOT_FOUND;
615 } 636 }
616 } 637 }
617 638
618 leveldb::Options options; 639 leveldb::Options options;
619 options.create_if_missing = create_if_needed; 640 options.create_if_missing = create_if_missing;
620 if (use_in_memory_db) { 641 if (use_in_memory_db) {
621 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); 642 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
622 options.env = env_.get(); 643 options.env = env_.get();
623 } 644 }
624 645
625 leveldb::DB* db = NULL; 646 leveldb::DB* db = NULL;
626 leveldb::Status status = 647 leveldb::Status db_status =
627 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 648 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db);
628 if (!status.ok()) { 649 if (!db_status.ok()) {
629 DCHECK(!db); 650 DCHECK(!db);
630 // TODO(nhiroki): Should we retry to open the database? 651 // TODO(nhiroki): Should we retry to open the database?
631 HandleError(FROM_HERE, status); 652 HandleError(FROM_HERE, db_status);
632 return false; 653 return LevelDBStatusToServiceWorkerStatusCode(db_status);
633 } 654 }
634 db_.reset(db); 655 db_.reset(db);
635 656
636 int64 db_version; 657 int64 db_version;
637 if (!ReadDatabaseVersion(&db_version)) 658 ServiceWorkerStatusCode status = ReadDatabaseVersion(&db_version);
638 return false; 659 if (status != SERVICE_WORKER_OK)
660 return status;
661 DCHECK_LE(0, db_version);
639 if (db_version > 0) 662 if (db_version > 0)
640 is_initialized_ = true; 663 is_initialized_ = true;
641 return true; 664 return SERVICE_WORKER_OK;
642 } 665 }
643 666
644 ServiceWorkerStatusCode ServiceWorkerDatabase::ReadNextAvailableId( 667 ServiceWorkerStatusCode ServiceWorkerDatabase::ReadNextAvailableId(
645 const char* id_key, 668 const char* id_key,
646 int64* next_avail_id) { 669 int64* next_avail_id) {
647 DCHECK(id_key); 670 DCHECK(id_key);
648 DCHECK(next_avail_id); 671 DCHECK(next_avail_id);
649 672
650 std::string value; 673 std::string value;
651 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value); 674 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 } 780 }
758 return true; 781 return true;
759 } 782 }
760 783
761 bool ServiceWorkerDatabase::ReadResourceIds(const char* id_key_prefix, 784 bool ServiceWorkerDatabase::ReadResourceIds(const char* id_key_prefix,
762 std::set<int64>* ids) { 785 std::set<int64>* ids) {
763 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 786 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
764 DCHECK(id_key_prefix); 787 DCHECK(id_key_prefix);
765 DCHECK(ids); 788 DCHECK(ids);
766 789
767 if (!LazyOpen(false) || is_disabled_) 790 ServiceWorkerStatusCode status = LazyOpen(false);
791 if (status == SERVICE_WORKER_ERROR_NOT_FOUND ||
792 (status == SERVICE_WORKER_OK && !is_initialized_)) {
793 // Database has never been used.
794 ids->clear();
michaeln 2014/05/15 19:59:30 ditto clearing collection
nhiroki 2014/05/16 02:11:11 Done.
795 return true;
796 }
797 if (status != SERVICE_WORKER_OK)
768 return false; 798 return false;
769 799
770 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 800 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
771 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) { 801 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) {
772 if (!itr->status().ok()) { 802 if (!itr->status().ok()) {
773 HandleError(FROM_HERE, itr->status()); 803 HandleError(FROM_HERE, itr->status());
774 ids->clear(); 804 ids->clear();
775 return false; 805 return false;
776 } 806 }
777 807
(...skipping 10 matching lines...) Expand all
788 ids->insert(resource_id); 818 ids->insert(resource_id);
789 } 819 }
790 return true; 820 return true;
791 } 821 }
792 822
793 bool ServiceWorkerDatabase::WriteResourceIds(const char* id_key_prefix, 823 bool ServiceWorkerDatabase::WriteResourceIds(const char* id_key_prefix,
794 const std::set<int64>& ids) { 824 const std::set<int64>& ids) {
795 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 825 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
796 DCHECK(id_key_prefix); 826 DCHECK(id_key_prefix);
797 827
798 if (!LazyOpen(true) || is_disabled_) 828 if (LazyOpen(true) != SERVICE_WORKER_OK)
799 return false; 829 return false;
800 if (ids.empty()) 830 if (ids.empty())
801 return true; 831 return true;
802 832
803 leveldb::WriteBatch batch; 833 leveldb::WriteBatch batch;
804 for (std::set<int64>::const_iterator itr = ids.begin(); 834 for (std::set<int64>::const_iterator itr = ids.begin();
805 itr != ids.end(); ++itr) { 835 itr != ids.end(); ++itr) {
806 // Value should be empty. 836 // Value should be empty.
807 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), ""); 837 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), "");
808 } 838 }
809 return WriteBatch(&batch); 839 return WriteBatch(&batch);
810 } 840 }
811 841
812 bool ServiceWorkerDatabase::DeleteResourceIds(const char* id_key_prefix, 842 bool ServiceWorkerDatabase::DeleteResourceIds(const char* id_key_prefix,
813 const std::set<int64>& ids) { 843 const std::set<int64>& ids) {
814 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 844 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
815 DCHECK(id_key_prefix); 845 DCHECK(id_key_prefix);
816 846
817 if (!LazyOpen(true) || is_disabled_) 847 ServiceWorkerStatusCode status = LazyOpen(false);
848 if (status == SERVICE_WORKER_ERROR_NOT_FOUND ||
849 (status == SERVICE_WORKER_OK && !is_initialized_)) {
850 // Database has never been used.
851 return true;
852 }
853 if (status != SERVICE_WORKER_OK)
818 return false; 854 return false;
855
819 if (ids.empty()) 856 if (ids.empty())
820 return true; 857 return true;
821 858
822 leveldb::WriteBatch batch; 859 leveldb::WriteBatch batch;
823 for (std::set<int64>::const_iterator itr = ids.begin(); 860 for (std::set<int64>::const_iterator itr = ids.begin();
824 itr != ids.end(); ++itr) { 861 itr != ids.end(); ++itr) {
825 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr)); 862 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr));
826 } 863 }
827 return WriteBatch(&batch); 864 return WriteBatch(&batch);
828 } 865 }
829 866
830 bool ServiceWorkerDatabase::ReadDatabaseVersion(int64* db_version) { 867 ServiceWorkerStatusCode ServiceWorkerDatabase::ReadDatabaseVersion(
868 int64* db_version) {
831 std::string value; 869 std::string value;
832 leveldb::Status status = 870 leveldb::Status status =
833 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); 871 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value);
834 if (status.IsNotFound()) { 872 if (status.IsNotFound()) {
835 // The database hasn't been initialized yet. 873 // The database hasn't been initialized yet.
836 *db_version = 0; 874 *db_version = 0;
837 return true; 875 return SERVICE_WORKER_OK;
838 } 876 }
839 if (!status.ok()) { 877 if (!status.ok()) {
840 HandleError(FROM_HERE, status); 878 HandleError(FROM_HERE, status);
841 return false; 879 return LevelDBStatusToServiceWorkerStatusCode(status);
842 } 880 }
843 881
844 int64 parsed; 882 int64 parsed;
845 if (!base::StringToInt64(value, &parsed)) { 883 if (!base::StringToInt64(value, &parsed)) {
846 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 884 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
847 return false; 885 return SERVICE_WORKER_ERROR_DB_CORRUPTED;
848 } 886 }
849 887
850 const int kFirstValidVersion = 1; 888 const int kFirstValidVersion = 1;
851 if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) { 889 if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) {
852 HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version")); 890 HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version"));
853 return false; 891 return SERVICE_WORKER_ERROR_DB_CORRUPTED;
854 } 892 }
855 893
856 *db_version = parsed; 894 *db_version = parsed;
857 return true; 895 return SERVICE_WORKER_OK;
858 } 896 }
859 897
860 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) { 898 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) {
861 DCHECK(batch); 899 DCHECK(batch);
862 DCHECK(!is_disabled_); 900 DCHECK(!is_disabled_);
863 901
864 if (!is_initialized_) { 902 if (!is_initialized_) {
865 // Write the database schema version. 903 // Write the database schema version.
866 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion)); 904 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion));
867 is_initialized_ = true; 905 is_initialized_ = true;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 // TODO(nhiroki): Add an UMA histogram. 941 // TODO(nhiroki): Add an UMA histogram.
904 DLOG(ERROR) << "Failed at: " << from_here.ToString() 942 DLOG(ERROR) << "Failed at: " << from_here.ToString()
905 << " with error: " << status.ToString(); 943 << " with error: " << status.ToString();
906 is_disabled_ = true; 944 is_disabled_ = true;
907 if (status.IsCorruption()) 945 if (status.IsCorruption())
908 was_corruption_detected_ = true; 946 was_corruption_detected_ = true;
909 db_.reset(); 947 db_.reset();
910 } 948 }
911 949
912 } // namespace content 950 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698