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

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: rebase 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 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 GURL url(record.url()); 204 GURL url(record.url());
205 if (!url.is_valid()) 205 if (!url.is_valid())
206 return false; 206 return false;
207 207
208 // Convert ServiceWorkerResourceRecord to ResourceRecord. 208 // Convert ServiceWorkerResourceRecord to ResourceRecord.
209 out->resource_id = record.resource_id(); 209 out->resource_id = record.resource_id();
210 out->url = url; 210 out->url = url;
211 return true; 211 return true;
212 } 212 }
213 213
214 ServiceWorkerStatusCode LevelDBStatusToServiceWorkerStatusCode( 214 ServiceWorkerDatabase::Status LevelDBStatusToStatus(
215 const leveldb::Status& status) { 215 const leveldb::Status& status) {
216 if (status.ok()) 216 if (status.ok())
217 return SERVICE_WORKER_OK; 217 return ServiceWorkerDatabase::STATUS_OK;
218 else if (status.IsNotFound()) 218 else if (status.IsNotFound())
219 return SERVICE_WORKER_ERROR_NOT_FOUND; 219 return ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND;
220 else if (status.IsCorruption()) 220 else if (status.IsCorruption())
221 return SERVICE_WORKER_ERROR_DB_CORRUPTED; 221 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
222 else 222 else
223 return SERVICE_WORKER_ERROR_FAILED; 223 return ServiceWorkerDatabase::STATUS_ERROR_FAILED;
224 } 224 }
225 225
226 } // namespace 226 } // namespace
227 227
228 ServiceWorkerDatabase::RegistrationData::RegistrationData() 228 ServiceWorkerDatabase::RegistrationData::RegistrationData()
229 : registration_id(-1), 229 : registration_id(-1),
230 version_id(-1), 230 version_id(-1),
231 is_active(false), 231 is_active(false),
232 has_fetch_handler(false) { 232 has_fetch_handler(false) {
233 } 233 }
(...skipping 10 matching lines...) Expand all
244 was_corruption_detected_(false), 244 was_corruption_detected_(false),
245 is_initialized_(false) { 245 is_initialized_(false) {
246 sequence_checker_.DetachFromSequence(); 246 sequence_checker_.DetachFromSequence();
247 } 247 }
248 248
249 ServiceWorkerDatabase::~ServiceWorkerDatabase() { 249 ServiceWorkerDatabase::~ServiceWorkerDatabase() {
250 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 250 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
251 db_.reset(); 251 db_.reset();
252 } 252 }
253 253
254 ServiceWorkerStatusCode ServiceWorkerDatabase::GetNextAvailableIds( 254 ServiceWorkerDatabase::Status 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 Status status = LazyOpen(false);
264 if (is_disabled_) 264 if (IsNewOrNonexistentDatabase(status)) {
265 return SERVICE_WORKER_ERROR_FAILED;
266 // Database has never been used.
267 *next_avail_registration_id = 0; 265 *next_avail_registration_id = 0;
268 *next_avail_version_id = 0; 266 *next_avail_version_id = 0;
269 *next_avail_resource_id = 0; 267 *next_avail_resource_id = 0;
270 return SERVICE_WORKER_OK; 268 return STATUS_OK;
271 } 269 }
270 if (status != STATUS_OK)
271 return status;
272 272
273 ServiceWorkerStatusCode status = 273 status = ReadNextAvailableId(kNextRegIdKey, &next_avail_registration_id_);
274 ReadNextAvailableId(kNextRegIdKey, &next_avail_registration_id_); 274 if (status != STATUS_OK)
275 if (status != SERVICE_WORKER_OK)
276 return status; 275 return status;
277 status = ReadNextAvailableId(kNextVerIdKey, &next_avail_version_id_); 276 status = ReadNextAvailableId(kNextVerIdKey, &next_avail_version_id_);
278 if (status != SERVICE_WORKER_OK) 277 if (status != STATUS_OK)
279 return status; 278 return status;
280 status = ReadNextAvailableId(kNextResIdKey, &next_avail_resource_id_); 279 status = ReadNextAvailableId(kNextResIdKey, &next_avail_resource_id_);
281 if (status != SERVICE_WORKER_OK) 280 if (status != STATUS_OK)
282 return status; 281 return status;
283 282
284 *next_avail_registration_id = next_avail_registration_id_; 283 *next_avail_registration_id = next_avail_registration_id_;
285 *next_avail_version_id = next_avail_version_id_; 284 *next_avail_version_id = next_avail_version_id_;
286 *next_avail_resource_id = next_avail_resource_id_; 285 *next_avail_resource_id = next_avail_resource_id_;
287 return SERVICE_WORKER_OK; 286 return STATUS_OK;
288 } 287 }
289 288
290 ServiceWorkerStatusCode ServiceWorkerDatabase::GetOriginsWithRegistrations( 289 ServiceWorkerDatabase::Status
291 std::set<GURL>* origins) { 290 ServiceWorkerDatabase::GetOriginsWithRegistrations(std::set<GURL>* origins) {
292 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 291 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
293 DCHECK(origins); 292 DCHECK(origins->empty());
294 293
295 if (!LazyOpen(false)) { 294 Status status = LazyOpen(false);
296 if (is_disabled_) 295 if (IsNewOrNonexistentDatabase(status))
297 return SERVICE_WORKER_ERROR_FAILED; 296 return STATUS_OK;
298 // Database has never been used. 297 if (status != STATUS_OK)
299 origins->clear(); 298 return status;
300 return SERVICE_WORKER_OK;
301 }
302 299
303 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 300 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
304 for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) { 301 for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) {
305 if (!itr->status().ok()) { 302 if (!itr->status().ok()) {
306 HandleError(FROM_HERE, itr->status()); 303 HandleError(FROM_HERE, itr->status());
307 origins->clear(); 304 origins->clear();
308 return LevelDBStatusToServiceWorkerStatusCode(itr->status()); 305 return LevelDBStatusToStatus(itr->status());
309 } 306 }
310 307
311 std::string origin; 308 std::string origin;
312 if (!RemovePrefix(itr->key().ToString(), kUniqueOriginKey, &origin)) 309 if (!RemovePrefix(itr->key().ToString(), kUniqueOriginKey, &origin))
313 break; 310 break;
314 origins->insert(GURL(origin)); 311 origins->insert(GURL(origin));
315 } 312 }
316 return SERVICE_WORKER_OK; 313 return STATUS_OK;
317 } 314 }
318 315
319 bool ServiceWorkerDatabase::GetRegistrationsForOrigin( 316 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetRegistrationsForOrigin(
320 const GURL& origin, 317 const GURL& origin,
321 std::vector<RegistrationData>* registrations) { 318 std::vector<RegistrationData>* registrations) {
322 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 319 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
323 DCHECK(registrations); 320 DCHECK(registrations->empty());
324 321
325 if (!LazyOpen(false)) { 322 Status status = LazyOpen(false);
326 if (is_disabled_) 323 if (IsNewOrNonexistentDatabase(status))
327 return false; 324 return STATUS_OK;
328 // Database has never been used. 325 if (status != STATUS_OK)
329 registrations->clear(); 326 return status;
330 return true;
331 }
332 327
333 // Create a key prefix for registrations. 328 // Create a key prefix for registrations.
334 std::string prefix = base::StringPrintf( 329 std::string prefix = base::StringPrintf(
335 "%s%s%c", kRegKeyPrefix, origin.spec().c_str(), kKeySeparator); 330 "%s%s%c", kRegKeyPrefix, origin.spec().c_str(), kKeySeparator);
336 331
337 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 332 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
338 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { 333 for (itr->Seek(prefix); itr->Valid(); itr->Next()) {
339 if (!itr->status().ok()) { 334 if (!itr->status().ok()) {
340 HandleError(FROM_HERE, itr->status()); 335 HandleError(FROM_HERE, itr->status());
341 registrations->clear(); 336 registrations->clear();
342 return false; 337 return LevelDBStatusToStatus(itr->status());
343 } 338 }
344 339
345 if (!RemovePrefix(itr->key().ToString(), prefix, NULL)) 340 if (!RemovePrefix(itr->key().ToString(), prefix, NULL))
346 break; 341 break;
347 342
348 RegistrationData registration; 343 RegistrationData registration;
349 if (!ParseRegistrationData(itr->value().ToString(), &registration)) { 344 if (!ParseRegistrationData(itr->value().ToString(), &registration)) {
350 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 345 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
351 registrations->clear(); 346 registrations->clear();
352 return false; 347 return STATUS_ERROR_CORRUPTED;
353 } 348 }
354 registrations->push_back(registration); 349 registrations->push_back(registration);
355 } 350 }
356 return true; 351 return STATUS_OK;
357 } 352 }
358 353
359 bool ServiceWorkerDatabase::GetAllRegistrations( 354 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetAllRegistrations(
360 std::vector<RegistrationData>* registrations) { 355 std::vector<RegistrationData>* registrations) {
361 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 356 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
362 DCHECK(registrations); 357 DCHECK(registrations->empty());
363 358
364 if (!LazyOpen(false)) { 359 Status status = LazyOpen(false);
365 if (is_disabled_) 360 if (IsNewOrNonexistentDatabase(status))
366 return false; 361 return STATUS_OK;
367 // Database has never been used. 362 if (status != STATUS_OK)
368 registrations->clear(); 363 return status;
369 return true;
370 }
371 364
372 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 365 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
373 for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) { 366 for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) {
374 if (!itr->status().ok()) { 367 if (!itr->status().ok()) {
375 HandleError(FROM_HERE, itr->status()); 368 HandleError(FROM_HERE, itr->status());
376 registrations->clear(); 369 registrations->clear();
377 return false; 370 return LevelDBStatusToStatus(itr->status());
378 } 371 }
379 372
380 if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, NULL)) 373 if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, NULL))
381 break; 374 break;
382 375
383 RegistrationData registration; 376 RegistrationData registration;
384 if (!ParseRegistrationData(itr->value().ToString(), &registration)) { 377 if (!ParseRegistrationData(itr->value().ToString(), &registration)) {
385 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 378 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
386 registrations->clear(); 379 registrations->clear();
387 return false; 380 return STATUS_ERROR_CORRUPTED;
388 } 381 }
389 registrations->push_back(registration); 382 registrations->push_back(registration);
390 } 383 }
391 return true; 384 return STATUS_OK;
392 } 385 }
393 386
394 bool ServiceWorkerDatabase::ReadRegistration( 387 bool ServiceWorkerDatabase::ReadRegistration(
395 int64 registration_id, 388 int64 registration_id,
396 const GURL& origin, 389 const GURL& origin,
397 RegistrationData* registration, 390 RegistrationData* registration,
398 std::vector<ResourceRecord>* resources) { 391 std::vector<ResourceRecord>* resources) {
399 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 392 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
400 DCHECK(registration); 393 DCHECK(registration);
401 DCHECK(resources); 394 DCHECK(resources);
402 395
403 if (!LazyOpen(false) || is_disabled_) 396 Status status = LazyOpen(false);
397 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK)
404 return false; 398 return false;
405 399
406 RegistrationData value; 400 RegistrationData value;
407 if (!ReadRegistrationData(registration_id, origin, &value)) 401 if (!ReadRegistrationData(registration_id, origin, &value))
408 return false; 402 return false;
409 403
410 if (!ReadResourceRecords(value.version_id, resources)) 404 if (!ReadResourceRecords(value.version_id, resources))
411 return false; 405 return false;
412 406
413 *registration = value; 407 *registration = value;
414 return true; 408 return true;
415 } 409 }
416 410
417 bool ServiceWorkerDatabase::WriteRegistration( 411 bool ServiceWorkerDatabase::WriteRegistration(
418 const RegistrationData& registration, 412 const RegistrationData& registration,
419 const std::vector<ResourceRecord>& resources) { 413 const std::vector<ResourceRecord>& resources) {
420 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 414 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
421 if (!LazyOpen(true) || is_disabled_) 415 if (LazyOpen(true) != STATUS_OK)
422 return false; 416 return false;
423 417
424 leveldb::WriteBatch batch; 418 leveldb::WriteBatch batch;
425 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch); 419 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch);
426 BumpNextVersionIdIfNeeded(registration.version_id, &batch); 420 BumpNextVersionIdIfNeeded(registration.version_id, &batch);
427 421
428 // TODO(nhiroki): Skip to add the origin into the unique origin list if it 422 // TODO(nhiroki): Skip to add the origin into the unique origin list if it
429 // has already been added. 423 // has already been added.
430 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch); 424 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch);
431 425
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 batch.Delete(CreateResourceIdKey( 461 batch.Delete(CreateResourceIdKey(
468 kUncommittedResIdKeyPrefix, itr->resource_id)); 462 kUncommittedResIdKeyPrefix, itr->resource_id));
469 } 463 }
470 464
471 return WriteBatch(&batch); 465 return WriteBatch(&batch);
472 } 466 }
473 467
474 bool ServiceWorkerDatabase::UpdateVersionToActive(int64 registration_id, 468 bool ServiceWorkerDatabase::UpdateVersionToActive(int64 registration_id,
475 const GURL& origin) { 469 const GURL& origin) {
476 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 470 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
477 if (!LazyOpen(false) || is_disabled_) 471 ServiceWorkerDatabase::Status status = LazyOpen(false);
472 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK)
478 return false; 473 return false;
479 474
480 RegistrationData registration; 475 RegistrationData registration;
481 if (!ReadRegistrationData(registration_id, origin, &registration)) 476 if (!ReadRegistrationData(registration_id, origin, &registration))
482 return false; 477 return false;
483 478
484 registration.is_active = true; 479 registration.is_active = true;
485 480
486 leveldb::WriteBatch batch; 481 leveldb::WriteBatch batch;
487 PutRegistrationDataToBatch(registration, &batch); 482 PutRegistrationDataToBatch(registration, &batch);
488 return WriteBatch(&batch); 483 return WriteBatch(&batch);
489 } 484 }
490 485
491 bool ServiceWorkerDatabase::UpdateLastCheckTime(int64 registration_id, 486 bool ServiceWorkerDatabase::UpdateLastCheckTime(int64 registration_id,
492 const GURL& origin, 487 const GURL& origin,
493 const base::Time& time) { 488 const base::Time& time) {
494 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 489 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
495 if (!LazyOpen(false) || is_disabled_) 490 ServiceWorkerDatabase::Status status = LazyOpen(false);
491 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK)
496 return false; 492 return false;
497 493
498 RegistrationData registration; 494 RegistrationData registration;
499 if (!ReadRegistrationData(registration_id, origin, &registration)) 495 if (!ReadRegistrationData(registration_id, origin, &registration))
500 return false; 496 return false;
501 497
502 registration.last_update_check = time; 498 registration.last_update_check = time;
503 499
504 leveldb::WriteBatch batch; 500 leveldb::WriteBatch batch;
505 PutRegistrationDataToBatch(registration, &batch); 501 PutRegistrationDataToBatch(registration, &batch);
506 return WriteBatch(&batch); 502 return WriteBatch(&batch);
507 } 503 }
508 504
509 bool ServiceWorkerDatabase::DeleteRegistration(int64 registration_id, 505 bool ServiceWorkerDatabase::DeleteRegistration(int64 registration_id,
510 const GURL& origin) { 506 const GURL& origin) {
511 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 507 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
512 if (!LazyOpen(false) || is_disabled_) 508 Status status = LazyOpen(false);
509 if (IsNewOrNonexistentDatabase(status))
510 return STATUS_OK;
511 if (status != STATUS_OK || !origin.is_valid())
513 return false; 512 return false;
514 513
515 leveldb::WriteBatch batch; 514 leveldb::WriteBatch batch;
516 515
517 // Remove |origin| from unique origins if a registration specified by 516 // Remove |origin| from unique origins if a registration specified by
518 // |registration_id| is the only one for |origin|. 517 // |registration_id| is the only one for |origin|.
519 // TODO(nhiroki): Check the uniqueness by more efficient way. 518 // TODO(nhiroki): Check the uniqueness by more efficient way.
520 std::vector<RegistrationData> registrations; 519 std::vector<RegistrationData> registrations;
521 if (!GetRegistrationsForOrigin(origin, &registrations)) 520 if (GetRegistrationsForOrigin(origin, &registrations) != STATUS_OK)
522 return false; 521 return false;
523 if (registrations.size() == 1 && 522 if (registrations.size() == 1 &&
524 registrations[0].registration_id == registration_id) { 523 registrations[0].registration_id == registration_id) {
525 batch.Delete(CreateUniqueOriginKey(origin)); 524 batch.Delete(CreateUniqueOriginKey(origin));
526 } 525 }
527 526
528 // Delete a registration specified by |registration_id|. 527 // Delete a registration specified by |registration_id|.
529 batch.Delete(CreateRegistrationKey(registration_id, origin)); 528 batch.Delete(CreateRegistrationKey(registration_id, origin));
530 529
531 // Delete resource records associated with the registration. 530 // Delete resource records associated with the registration.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids); 563 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids);
565 } 564 }
566 565
567 bool ServiceWorkerDatabase::ClearPurgeableResourceIds( 566 bool ServiceWorkerDatabase::ClearPurgeableResourceIds(
568 const std::set<int64>& ids) { 567 const std::set<int64>& ids) {
569 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids); 568 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids);
570 } 569 }
571 570
572 bool ServiceWorkerDatabase::DeleteAllDataForOrigin(const GURL& origin) { 571 bool ServiceWorkerDatabase::DeleteAllDataForOrigin(const GURL& origin) {
573 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 572 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
574 if (!LazyOpen(true) || is_disabled_ || !origin.is_valid()) 573 Status status = LazyOpen(false);
574 if (IsNewOrNonexistentDatabase(status))
575 return STATUS_OK;
576 if (status != STATUS_OK || !origin.is_valid())
575 return false; 577 return false;
576 578
577 leveldb::WriteBatch batch; 579 leveldb::WriteBatch batch;
578 580
579 // Delete from the unique origin list. 581 // Delete from the unique origin list.
580 batch.Delete(CreateUniqueOriginKey(origin)); 582 batch.Delete(CreateUniqueOriginKey(origin));
581 583
582 std::vector<RegistrationData> registrations; 584 std::vector<RegistrationData> registrations;
583 if (!GetRegistrationsForOrigin(origin, &registrations)) 585 if (GetRegistrationsForOrigin(origin, &registrations) != STATUS_OK)
584 return false; 586 return false;
585 587
586 // Delete registrations and resource records. 588 // Delete registrations and resource records.
587 for (std::vector<RegistrationData>::const_iterator itr = 589 for (std::vector<RegistrationData>::const_iterator itr =
588 registrations.begin(); itr != registrations.end(); ++itr) { 590 registrations.begin(); itr != registrations.end(); ++itr) {
589 batch.Delete(CreateRegistrationKey(itr->registration_id, origin)); 591 batch.Delete(CreateRegistrationKey(itr->registration_id, origin));
590 if (!DeleteResourceRecords(itr->version_id, &batch)) 592 if (!DeleteResourceRecords(itr->version_id, &batch))
591 return false; 593 return false;
592 } 594 }
593 595
594 return WriteBatch(&batch); 596 return WriteBatch(&batch);
595 } 597 }
596 598
597 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) { 599 ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen(
600 bool create_if_missing) {
598 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 601 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
599 if (IsOpen())
600 return true;
601 602
602 // Do not try to open a database if we tried and failed once. 603 // Do not try to open a database if we tried and failed once.
603 if (is_disabled_) 604 if (is_disabled_)
604 return false; 605 return STATUS_ERROR_FAILED;
606 if (IsOpen())
607 return STATUS_OK;
605 608
606 // When |path_| is empty, open a database in-memory. 609 // When |path_| is empty, open a database in-memory.
607 bool use_in_memory_db = path_.empty(); 610 bool use_in_memory_db = path_.empty();
608 611
609 if (!create_if_needed) { 612 if (!create_if_missing) {
610 // Avoid opening a database if it does not exist at the |path_|. 613 // Avoid opening a database if it does not exist at the |path_|.
611 if (use_in_memory_db || 614 if (use_in_memory_db ||
612 !base::PathExists(path_) || 615 !base::PathExists(path_) ||
613 base::IsDirectoryEmpty(path_)) { 616 base::IsDirectoryEmpty(path_)) {
614 return false; 617 return STATUS_ERROR_NOT_FOUND;
615 } 618 }
616 } 619 }
617 620
618 leveldb::Options options; 621 leveldb::Options options;
619 options.create_if_missing = create_if_needed; 622 options.create_if_missing = create_if_missing;
620 if (use_in_memory_db) { 623 if (use_in_memory_db) {
621 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); 624 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
622 options.env = env_.get(); 625 options.env = env_.get();
623 } 626 }
624 627
625 leveldb::DB* db = NULL; 628 leveldb::DB* db = NULL;
626 leveldb::Status status = 629 leveldb::Status db_status =
627 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 630 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db);
628 if (!status.ok()) { 631 if (!db_status.ok()) {
629 DCHECK(!db); 632 DCHECK(!db);
630 // TODO(nhiroki): Should we retry to open the database? 633 // TODO(nhiroki): Should we retry to open the database?
631 HandleError(FROM_HERE, status); 634 HandleError(FROM_HERE, db_status);
632 return false; 635 return LevelDBStatusToStatus(db_status);
633 } 636 }
634 db_.reset(db); 637 db_.reset(db);
635 638
636 int64 db_version; 639 int64 db_version;
637 if (!ReadDatabaseVersion(&db_version)) 640 Status status = ReadDatabaseVersion(&db_version);
638 return false; 641 if (status != STATUS_OK)
642 return status;
643 DCHECK_LE(0, db_version);
639 if (db_version > 0) 644 if (db_version > 0)
640 is_initialized_ = true; 645 is_initialized_ = true;
641 return true; 646 return STATUS_OK;
642 } 647 }
643 648
644 ServiceWorkerStatusCode ServiceWorkerDatabase::ReadNextAvailableId( 649 bool ServiceWorkerDatabase::IsNewOrNonexistentDatabase(
650 ServiceWorkerDatabase::Status status) {
651 if (status == STATUS_ERROR_NOT_FOUND)
652 return true;
653 if (status == STATUS_OK && !is_initialized_)
654 return true;
655 return false;
656 }
657
658 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadNextAvailableId(
645 const char* id_key, 659 const char* id_key,
646 int64* next_avail_id) { 660 int64* next_avail_id) {
647 DCHECK(id_key); 661 DCHECK(id_key);
648 DCHECK(next_avail_id); 662 DCHECK(next_avail_id);
649 663
650 std::string value; 664 std::string value;
651 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value); 665 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value);
652 if (status.IsNotFound()) { 666 if (status.IsNotFound()) {
653 // Nobody has gotten the next resource id for |id_key|. 667 // Nobody has gotten the next resource id for |id_key|.
654 *next_avail_id = 0; 668 *next_avail_id = 0;
655 return SERVICE_WORKER_OK; 669 return STATUS_OK;
656 } 670 }
657 671
658 if (!status.ok()) { 672 if (!status.ok()) {
659 HandleError(FROM_HERE, status); 673 HandleError(FROM_HERE, status);
660 return LevelDBStatusToServiceWorkerStatusCode(status); 674 return LevelDBStatusToStatus(status);
661 } 675 }
662 676
663 int64 parsed; 677 int64 parsed;
664 if (!base::StringToInt64(value, &parsed)) { 678 if (!base::StringToInt64(value, &parsed)) {
665 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 679 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
666 return SERVICE_WORKER_ERROR_DB_CORRUPTED; 680 return STATUS_ERROR_CORRUPTED;
667 } 681 }
668 682
669 *next_avail_id = parsed; 683 *next_avail_id = parsed;
670 return SERVICE_WORKER_OK; 684 return STATUS_OK;
671 } 685 }
672 686
673 bool ServiceWorkerDatabase::ReadRegistrationData( 687 bool ServiceWorkerDatabase::ReadRegistrationData(
674 int64 registration_id, 688 int64 registration_id,
675 const GURL& origin, 689 const GURL& origin,
676 RegistrationData* registration) { 690 RegistrationData* registration) {
677 DCHECK(registration); 691 DCHECK(registration);
678 692
679 std::string key = CreateRegistrationKey(registration_id, origin); 693 std::string key = CreateRegistrationKey(registration_id, origin);
680 694
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 // supported, so we can purge this without caring about it. 769 // supported, so we can purge this without caring about it.
756 PutPurgeableResourceIdToBatch(resource_id, batch); 770 PutPurgeableResourceIdToBatch(resource_id, batch);
757 } 771 }
758 return true; 772 return true;
759 } 773 }
760 774
761 bool ServiceWorkerDatabase::ReadResourceIds(const char* id_key_prefix, 775 bool ServiceWorkerDatabase::ReadResourceIds(const char* id_key_prefix,
762 std::set<int64>* ids) { 776 std::set<int64>* ids) {
763 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 777 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
764 DCHECK(id_key_prefix); 778 DCHECK(id_key_prefix);
765 DCHECK(ids); 779 DCHECK(ids->empty());
766 780
767 if (!LazyOpen(false) || is_disabled_) 781 Status status = LazyOpen(false);
782 if (IsNewOrNonexistentDatabase(status))
783 return true;
784 if (status != STATUS_OK)
768 return false; 785 return false;
769 786
770 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 787 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
771 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) { 788 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) {
772 if (!itr->status().ok()) { 789 if (!itr->status().ok()) {
773 HandleError(FROM_HERE, itr->status()); 790 HandleError(FROM_HERE, itr->status());
774 ids->clear(); 791 ids->clear();
775 return false; 792 return false;
776 } 793 }
777 794
(...skipping 10 matching lines...) Expand all
788 ids->insert(resource_id); 805 ids->insert(resource_id);
789 } 806 }
790 return true; 807 return true;
791 } 808 }
792 809
793 bool ServiceWorkerDatabase::WriteResourceIds(const char* id_key_prefix, 810 bool ServiceWorkerDatabase::WriteResourceIds(const char* id_key_prefix,
794 const std::set<int64>& ids) { 811 const std::set<int64>& ids) {
795 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 812 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
796 DCHECK(id_key_prefix); 813 DCHECK(id_key_prefix);
797 814
798 if (!LazyOpen(true) || is_disabled_) 815 if (LazyOpen(true) != STATUS_OK)
799 return false; 816 return false;
800 if (ids.empty()) 817 if (ids.empty())
801 return true; 818 return true;
802 819
803 leveldb::WriteBatch batch; 820 leveldb::WriteBatch batch;
804 for (std::set<int64>::const_iterator itr = ids.begin(); 821 for (std::set<int64>::const_iterator itr = ids.begin();
805 itr != ids.end(); ++itr) { 822 itr != ids.end(); ++itr) {
806 // Value should be empty. 823 // Value should be empty.
807 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), ""); 824 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), "");
808 } 825 }
809 return WriteBatch(&batch); 826 return WriteBatch(&batch);
810 } 827 }
811 828
812 bool ServiceWorkerDatabase::DeleteResourceIds(const char* id_key_prefix, 829 bool ServiceWorkerDatabase::DeleteResourceIds(const char* id_key_prefix,
813 const std::set<int64>& ids) { 830 const std::set<int64>& ids) {
814 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 831 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
815 DCHECK(id_key_prefix); 832 DCHECK(id_key_prefix);
816 833
817 if (!LazyOpen(true) || is_disabled_) 834 Status status = LazyOpen(false);
835 if (IsNewOrNonexistentDatabase(status))
836 return true;
837 if (status != STATUS_OK)
818 return false; 838 return false;
839
819 if (ids.empty()) 840 if (ids.empty())
820 return true; 841 return true;
821 842
822 leveldb::WriteBatch batch; 843 leveldb::WriteBatch batch;
823 for (std::set<int64>::const_iterator itr = ids.begin(); 844 for (std::set<int64>::const_iterator itr = ids.begin();
824 itr != ids.end(); ++itr) { 845 itr != ids.end(); ++itr) {
825 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr)); 846 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr));
826 } 847 }
827 return WriteBatch(&batch); 848 return WriteBatch(&batch);
828 } 849 }
829 850
830 bool ServiceWorkerDatabase::ReadDatabaseVersion(int64* db_version) { 851 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadDatabaseVersion(
852 int64* db_version) {
831 std::string value; 853 std::string value;
832 leveldb::Status status = 854 leveldb::Status status =
833 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); 855 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value);
834 if (status.IsNotFound()) { 856 if (status.IsNotFound()) {
835 // The database hasn't been initialized yet. 857 // The database hasn't been initialized yet.
836 *db_version = 0; 858 *db_version = 0;
837 return true; 859 return STATUS_OK;
838 } 860 }
839 if (!status.ok()) { 861 if (!status.ok()) {
840 HandleError(FROM_HERE, status); 862 HandleError(FROM_HERE, status);
841 return false; 863 return LevelDBStatusToStatus(status);
842 } 864 }
843 865
844 int64 parsed; 866 int64 parsed;
845 if (!base::StringToInt64(value, &parsed)) { 867 if (!base::StringToInt64(value, &parsed)) {
846 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 868 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
847 return false; 869 return STATUS_ERROR_CORRUPTED;
848 } 870 }
849 871
850 const int kFirstValidVersion = 1; 872 const int kFirstValidVersion = 1;
851 if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) { 873 if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) {
852 HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version")); 874 HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version"));
853 return false; 875 return STATUS_ERROR_CORRUPTED;
854 } 876 }
855 877
856 *db_version = parsed; 878 *db_version = parsed;
857 return true; 879 return STATUS_OK;
858 } 880 }
859 881
860 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) { 882 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) {
861 DCHECK(batch); 883 DCHECK(batch);
862 DCHECK(!is_disabled_); 884 DCHECK(!is_disabled_);
863 885
864 if (!is_initialized_) { 886 if (!is_initialized_) {
865 // Write the database schema version. 887 // Write the database schema version.
866 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion)); 888 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion));
867 is_initialized_ = true; 889 is_initialized_ = true;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 // TODO(nhiroki): Add an UMA histogram. 925 // TODO(nhiroki): Add an UMA histogram.
904 DLOG(ERROR) << "Failed at: " << from_here.ToString() 926 DLOG(ERROR) << "Failed at: " << from_here.ToString()
905 << " with error: " << status.ToString(); 927 << " with error: " << status.ToString();
906 is_disabled_ = true; 928 is_disabled_ = true;
907 if (status.IsCorruption()) 929 if (status.IsCorruption())
908 was_corruption_detected_ = true; 930 was_corruption_detected_ = true;
909 db_.reset(); 931 db_.reset();
910 } 932 }
911 933
912 } // namespace content 934 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698