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