OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/indexed_db/indexed_db_backing_store.h" | 5 #include "content/browser/indexed_db/indexed_db_backing_store.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/strings/string_piece.h" | 10 #include "base/strings/string_piece.h" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/strings/stringprintf.h" |
12 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "content/browser/child_process_security_policy_impl.h" |
| 15 #include "content/browser/indexed_db/indexed_db_blob_info.h" |
13 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" | 16 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" |
14 #include "content/browser/indexed_db/indexed_db_metadata.h" | 17 #include "content/browser/indexed_db/indexed_db_metadata.h" |
15 #include "content/browser/indexed_db/indexed_db_tracing.h" | 18 #include "content/browser/indexed_db/indexed_db_tracing.h" |
| 19 #include "content/browser/indexed_db/indexed_db_value.h" |
16 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" | 20 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" |
17 #include "content/browser/indexed_db/leveldb/leveldb_database.h" | 21 #include "content/browser/indexed_db/leveldb/leveldb_database.h" |
18 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" | 22 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" |
19 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" | 23 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" |
20 #include "content/common/indexed_db/indexed_db_key.h" | 24 #include "content/common/indexed_db/indexed_db_key.h" |
21 #include "content/common/indexed_db/indexed_db_key_path.h" | 25 #include "content/common/indexed_db/indexed_db_key_path.h" |
22 #include "content/common/indexed_db/indexed_db_key_range.h" | 26 #include "content/common/indexed_db/indexed_db_key_range.h" |
| 27 #include "content/public/browser/browser_thread.h" |
| 28 #include "net/url_request/url_request_context.h" |
23 #include "third_party/WebKit/public/platform/WebIDBTypes.h" | 29 #include "third_party/WebKit/public/platform/WebIDBTypes.h" |
24 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h" | 30 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h" |
25 #include "third_party/leveldatabase/env_chromium.h" | 31 #include "third_party/leveldatabase/env_chromium.h" |
| 32 #include "webkit/browser/blob/blob_data_handle.h" |
| 33 #include "webkit/browser/fileapi/file_stream_writer.h" |
| 34 #include "webkit/browser/fileapi/file_writer_delegate.h" |
| 35 #include "webkit/browser/fileapi/local_file_stream_writer.h" |
26 #include "webkit/common/database/database_identifier.h" | 36 #include "webkit/common/database/database_identifier.h" |
27 | 37 |
| 38 using base::FilePath; |
28 using base::StringPiece; | 39 using base::StringPiece; |
| 40 using fileapi::FileWriterDelegate; |
29 | 41 |
30 namespace content { | 42 namespace content { |
31 | 43 |
32 namespace { | 44 namespace { |
33 | 45 |
| 46 FilePath GetBlobDirectoryName(const FilePath& pathBase, int64 database_id) { |
| 47 return pathBase.AppendASCII(base::StringPrintf("%lx", database_id)); |
| 48 } |
| 49 |
| 50 FilePath GetBlobDirectoryNameForKey(const FilePath& pathBase, |
| 51 int64 database_id, |
| 52 int64 key) { |
| 53 FilePath path = GetBlobDirectoryName(pathBase, database_id); |
| 54 path = path.AppendASCII( |
| 55 base::StringPrintf("%0x", static_cast<int>(key & 0x0000ff00) >> 8)); |
| 56 return path; |
| 57 } |
| 58 |
| 59 // This assumes a file path of dbId/3rd-byte-of-counter/counter. |
| 60 bool MakeIDBBlobDirectory(const FilePath& pathBase, |
| 61 int64 database_id, |
| 62 int64 key) { |
| 63 FilePath path = GetBlobDirectoryNameForKey(pathBase, database_id, key); |
| 64 return file_util::CreateDirectory(path); |
| 65 } |
| 66 |
34 static std::string ComputeOriginIdentifier(const GURL& origin_url) { | 67 static std::string ComputeOriginIdentifier(const GURL& origin_url) { |
35 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1"; | 68 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1"; |
36 } | 69 } |
37 | 70 |
38 static base::FilePath ComputeFileName(const GURL& origin_url) { | 71 static base::FilePath ComputeFileName(const GURL& origin_url) { |
39 return base::FilePath() | 72 return base::FilePath() |
40 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) | 73 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) |
41 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); | 74 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); |
42 } | 75 } |
43 | 76 |
| 77 static base::FilePath ComputeBlobPath(const GURL& origin_url) { |
| 78 return base::FilePath() |
| 79 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) |
| 80 .AddExtension(FILE_PATH_LITERAL(".indexeddb.blob")); |
| 81 } |
| 82 |
44 } // namespace | 83 } // namespace |
45 | 84 |
46 static const int64 kKeyGeneratorInitialNumber = | 85 static const int64 kKeyGeneratorInitialNumber = |
47 1; // From the IndexedDB specification. | 86 1; // From the IndexedDB specification. |
48 | 87 |
49 enum IndexedDBBackingStoreErrorSource { | 88 enum IndexedDBBackingStoreErrorSource { |
50 // 0 - 2 are no longer used. | 89 // 0 - 2 are no longer used. |
51 FIND_KEY_IN_INDEX = 3, | 90 FIND_KEY_IN_INDEX = 3, |
52 GET_IDBDATABASE_METADATA, | 91 GET_IDBDATABASE_METADATA, |
53 GET_INDEXES, | 92 GET_INDEXES, |
54 GET_KEY_GENERATOR_CURRENT_NUMBER, | 93 GET_KEY_GENERATOR_CURRENT_NUMBER, |
55 GET_OBJECT_STORES, | 94 GET_OBJECT_STORES, |
56 GET_RECORD, | 95 GET_RECORD, |
57 KEY_EXISTS_IN_OBJECT_STORE, | 96 KEY_EXISTS_IN_OBJECT_STORE, |
58 LOAD_CURRENT_ROW, | 97 LOAD_CURRENT_ROW, |
59 SET_UP_METADATA, | 98 SET_UP_METADATA, |
60 GET_PRIMARY_KEY_VIA_INDEX, | 99 GET_PRIMARY_KEY_VIA_INDEX, |
61 KEY_EXISTS_IN_INDEX, | 100 KEY_EXISTS_IN_INDEX, |
62 VERSION_EXISTS, | 101 VERSION_EXISTS, |
63 DELETE_OBJECT_STORE, | 102 DELETE_OBJECT_STORE, |
64 SET_MAX_OBJECT_STORE_ID, | 103 SET_MAX_OBJECT_STORE_ID, |
65 SET_MAX_INDEX_ID, | 104 SET_MAX_INDEX_ID, |
66 GET_NEW_DATABASE_ID, | 105 GET_NEW_DATABASE_ID, |
67 GET_NEW_VERSION_NUMBER, | 106 GET_NEW_VERSION_NUMBER, |
68 CREATE_IDBDATABASE_METADATA, | 107 CREATE_IDBDATABASE_METADATA, |
69 DELETE_DATABASE, | 108 DELETE_DATABASE, |
70 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro | 109 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro |
71 GET_DATABASE_NAMES, | 110 GET_DATABASE_NAMES, |
| 111 GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER, |
| 112 GET_BLOB_INFO_FOR_RECORD, |
| 113 DECODE_BLOB_JOURNAL, |
72 INTERNAL_ERROR_MAX, | 114 INTERNAL_ERROR_MAX, |
73 }; | 115 }; |
74 | 116 |
75 static void RecordInternalError(const char* type, | 117 static void RecordInternalError(const char* type, |
76 IndexedDBBackingStoreErrorSource location) { | 118 IndexedDBBackingStoreErrorSource location) { |
77 std::string name; | 119 std::string name; |
78 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); | 120 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); |
79 base::Histogram::FactoryGet(name, | 121 base::Histogram::FactoryGet(name, |
80 1, | 122 1, |
81 INTERNAL_ERROR_MAX, | 123 INTERNAL_ERROR_MAX, |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 | 277 |
236 if (db_data_version > latest_known_data_version) { | 278 if (db_data_version > latest_known_data_version) { |
237 *known = false; | 279 *known = false; |
238 return true; | 280 return true; |
239 } | 281 } |
240 | 282 |
241 *known = true; | 283 *known = true; |
242 return true; | 284 return true; |
243 } | 285 } |
244 | 286 |
245 WARN_UNUSED_RESULT static bool SetUpMetadata( | 287 WARN_UNUSED_RESULT bool IndexedDBBackingStore::SetUpMetadata() { |
246 LevelDBDatabase* db, | |
247 const std::string& origin_identifier) { | |
248 const uint32 latest_known_data_version = | 288 const uint32 latest_known_data_version = |
249 blink::kSerializedScriptValueVersion; | 289 blink::kSerializedScriptValueVersion; |
250 const std::string schema_version_key = SchemaVersionKey::Encode(); | 290 const std::string schema_version_key = SchemaVersionKey::Encode(); |
251 const std::string data_version_key = DataVersionKey::Encode(); | 291 const std::string data_version_key = DataVersionKey::Encode(); |
252 | 292 |
253 scoped_refptr<LevelDBTransaction> transaction = new LevelDBTransaction(db); | 293 scoped_refptr<LevelDBTransaction> transaction = |
| 294 new LevelDBTransaction(db_.get()); |
254 | 295 |
255 int64 db_schema_version = 0; | 296 int64 db_schema_version = 0; |
256 int64 db_data_version = 0; | 297 int64 db_data_version = 0; |
257 bool found = false; | 298 bool found = false; |
258 bool ok = | 299 bool ok = |
259 GetInt(transaction.get(), schema_version_key, &db_schema_version, &found); | 300 GetInt(transaction.get(), schema_version_key, &db_schema_version, &found); |
260 if (!ok) { | 301 if (!ok) { |
261 INTERNAL_READ_ERROR(SET_UP_METADATA); | 302 INTERNAL_READ_ERROR(SET_UP_METADATA); |
262 return false; | 303 return false; |
263 } | 304 } |
264 if (!found) { | 305 if (!found) { |
265 // Initialize new backing store. | 306 // Initialize new backing store. |
266 db_schema_version = kLatestKnownSchemaVersion; | 307 db_schema_version = kLatestKnownSchemaVersion; |
267 PutInt(transaction.get(), schema_version_key, db_schema_version); | 308 PutInt(transaction.get(), schema_version_key, db_schema_version); |
268 db_data_version = latest_known_data_version; | 309 db_data_version = latest_known_data_version; |
269 PutInt(transaction.get(), data_version_key, db_data_version); | 310 PutInt(transaction.get(), data_version_key, db_data_version); |
270 } else { | 311 } else { |
271 // Upgrade old backing store. | 312 // Upgrade old backing store. |
272 DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion); | 313 DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion); |
273 if (db_schema_version < 1) { | 314 if (db_schema_version < 1) { |
274 db_schema_version = 1; | 315 db_schema_version = 1; |
275 PutInt(transaction.get(), schema_version_key, db_schema_version); | 316 PutInt(transaction.get(), schema_version_key, db_schema_version); |
276 const std::string start_key = | 317 const std::string start_key = |
277 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier); | 318 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_); |
278 const std::string stop_key = | 319 const std::string stop_key = |
279 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier); | 320 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_); |
280 scoped_ptr<LevelDBIterator> it = db->CreateIterator(); | 321 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); |
281 for (it->Seek(start_key); | 322 for (it->Seek(start_key); |
282 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; | 323 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; |
283 it->Next()) { | 324 it->Next()) { |
284 int64 database_id = 0; | 325 int64 database_id = 0; |
285 found = false; | 326 found = false; |
286 bool ok = GetInt(transaction.get(), it->Key(), &database_id, &found); | 327 bool ok = GetInt(transaction.get(), it->Key(), &database_id, &found); |
287 if (!ok) { | 328 if (!ok) { |
288 INTERNAL_READ_ERROR(SET_UP_METADATA); | 329 INTERNAL_READ_ERROR(SET_UP_METADATA); |
289 return false; | 330 return false; |
290 } | 331 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 } | 403 } |
363 | 404 |
364 class DefaultLevelDBFactory : public LevelDBFactory { | 405 class DefaultLevelDBFactory : public LevelDBFactory { |
365 public: | 406 public: |
366 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name, | 407 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name, |
367 const LevelDBComparator* comparator, | 408 const LevelDBComparator* comparator, |
368 scoped_ptr<LevelDBDatabase>* db, | 409 scoped_ptr<LevelDBDatabase>* db, |
369 bool* is_disk_full) OVERRIDE { | 410 bool* is_disk_full) OVERRIDE { |
370 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full); | 411 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full); |
371 } | 412 } |
372 virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE { | 413 virtual bool DestroyLevelDB(const FilePath& file_name) OVERRIDE { |
373 return LevelDBDatabase::Destroy(file_name); | 414 return LevelDBDatabase::Destroy(file_name); |
374 } | 415 } |
375 }; | 416 }; |
376 | 417 |
| 418 static bool GetBlobKeyGeneratorCurrentNumber( |
| 419 LevelDBTransaction* leveldb_transaction, |
| 420 int64 database_id, |
| 421 int64* blob_key_generator_current_number) { |
| 422 const std::string key_gen_key = DatabaseMetaDataKey::Encode( |
| 423 database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER); |
| 424 |
| 425 // Default to initial number if not found. |
| 426 int64 cur_number = DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber; |
| 427 std::string data; |
| 428 |
| 429 bool found = false; |
| 430 bool ok = leveldb_transaction->Get(key_gen_key, &data, &found); |
| 431 if (!ok) { |
| 432 INTERNAL_READ_ERROR(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER); |
| 433 return false; |
| 434 } |
| 435 if (found) { |
| 436 StringPiece slice(data); |
| 437 if (!DecodeVarInt(&slice, &cur_number) || !slice.empty() || |
| 438 !DatabaseMetaDataKey::IsValidBlobKey(cur_number)) { |
| 439 INTERNAL_READ_ERROR(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER); |
| 440 return false; |
| 441 } |
| 442 } |
| 443 *blob_key_generator_current_number = cur_number; |
| 444 return true; |
| 445 } |
| 446 |
| 447 static bool UpdateBlobKeyGeneratorCurrentNumber( |
| 448 LevelDBTransaction* leveldb_transaction, |
| 449 int64 database_id, |
| 450 int64 blob_key_generator_current_number) { |
| 451 #ifndef NDEBUG |
| 452 int64 old_number; |
| 453 if (!GetBlobKeyGeneratorCurrentNumber( |
| 454 leveldb_transaction, database_id, &old_number)) |
| 455 return false; |
| 456 DCHECK_LT(old_number, blob_key_generator_current_number); |
| 457 #endif |
| 458 DCHECK( |
| 459 DatabaseMetaDataKey::IsValidBlobKey(blob_key_generator_current_number)); |
| 460 const std::string key = DatabaseMetaDataKey::Encode( |
| 461 database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER); |
| 462 |
| 463 PutInt(leveldb_transaction, key, blob_key_generator_current_number); |
| 464 return true; |
| 465 } |
| 466 |
| 467 static bool DecodeBlobJournal( |
| 468 const std::string& data, |
| 469 IndexedDBBackingStore::Transaction::BlobJournalType* journal) { |
| 470 // TODO(ericu): Yell something on errors. If we persistently can't read the |
| 471 // blob journal, the safe thing to do is to clear it and leak the blobs, |
| 472 // though that may be costly. Still, database/directory deletion should always |
| 473 // clean things up, and we can write an fsck that will do a full correction if |
| 474 // need be. |
| 475 IndexedDBBackingStore::Transaction::BlobJournalType output; |
| 476 StringPiece slice(data); |
| 477 while (!slice.empty()) { |
| 478 int64 database_id = -1; |
| 479 int64 blob_key = -1; |
| 480 if (!DecodeVarInt(&slice, &database_id)) |
| 481 return false; |
| 482 if (!KeyPrefix::IsValidDatabaseId(database_id)) |
| 483 return false; |
| 484 if (!DecodeVarInt(&slice, &blob_key)) |
| 485 return false; |
| 486 if (!DatabaseMetaDataKey::IsValidBlobKey(blob_key) && |
| 487 (blob_key != DatabaseMetaDataKey::kAllBlobsKey)) { |
| 488 return false; |
| 489 } |
| 490 output.push_back(std::make_pair(database_id, blob_key)); |
| 491 } |
| 492 journal->swap(output); |
| 493 return true; |
| 494 } |
| 495 |
| 496 template <typename T> |
| 497 static bool GetBlobJournal( |
| 498 const StringPiece& leveldb_key, |
| 499 T* leveldb_transaction, |
| 500 IndexedDBBackingStore::Transaction::BlobJournalType* journal) { |
| 501 std::string data; |
| 502 bool found = false; |
| 503 bool ok = leveldb_transaction->Get(leveldb_key, &data, &found); |
| 504 if (!ok) { |
| 505 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE); |
| 506 return false; |
| 507 } |
| 508 journal->clear(); |
| 509 if (!found) |
| 510 return true; |
| 511 if (!data.size()) |
| 512 return true; |
| 513 if (!DecodeBlobJournal(data, journal)) { |
| 514 INTERNAL_READ_ERROR(DECODE_BLOB_JOURNAL); |
| 515 return false; |
| 516 } |
| 517 return true; |
| 518 } |
| 519 |
| 520 static std::string EncodeBlobJournal( |
| 521 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) { |
| 522 std::string data; |
| 523 IndexedDBBackingStore::Transaction::BlobJournalType::const_iterator iter; |
| 524 for (iter = journal.begin(); iter != journal.end(); ++iter) { |
| 525 EncodeVarInt(iter->first, &data); |
| 526 EncodeVarInt(iter->second, &data); |
| 527 } |
| 528 return data; |
| 529 } |
| 530 |
| 531 static void ClearBlobJournal(LevelDBTransaction* leveldb_transaction, |
| 532 const std::string& level_db_key) { |
| 533 leveldb_transaction->Remove(level_db_key); |
| 534 } |
| 535 |
| 536 static void UpdatePrimaryJournalWithBlobList( |
| 537 LevelDBTransaction* leveldb_transaction, |
| 538 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) { |
| 539 const std::string leveldb_key = BlobJournalKey::Encode(); |
| 540 std::string data = EncodeBlobJournal(journal); |
| 541 leveldb_transaction->Put(leveldb_key, &data); |
| 542 } |
| 543 |
| 544 static void UpdateLiveBlobJournalWithBlobList( |
| 545 LevelDBTransaction* leveldb_transaction, |
| 546 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) { |
| 547 const std::string leveldb_key = LiveBlobJournalKey::Encode(); |
| 548 std::string data = EncodeBlobJournal(journal); |
| 549 leveldb_transaction->Put(leveldb_key, &data); |
| 550 } |
| 551 |
| 552 static bool MergeBlobsIntoLiveBlobJournal( |
| 553 LevelDBTransaction* leveldb_transaction, |
| 554 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) { |
| 555 IndexedDBBackingStore::Transaction::BlobJournalType old_journal; |
| 556 std::string key = LiveBlobJournalKey::Encode(); |
| 557 if (!GetBlobJournal(key, leveldb_transaction, &old_journal)) |
| 558 return false; |
| 559 |
| 560 old_journal.insert(old_journal.end(), journal.begin(), journal.end()); |
| 561 |
| 562 UpdateLiveBlobJournalWithBlobList(leveldb_transaction, old_journal); |
| 563 return true; |
| 564 } |
| 565 |
| 566 static void UpdateBlobJournalWithDatabase( |
| 567 LevelDBUncachedTransaction* leveldb_transaction, |
| 568 int64 database_id) { |
| 569 IndexedDBBackingStore::Transaction::BlobJournalType journal; |
| 570 journal.push_back( |
| 571 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey)); |
| 572 const std::string key = BlobJournalKey::Encode(); |
| 573 std::string data = EncodeBlobJournal(journal); |
| 574 leveldb_transaction->Put(key, &data); |
| 575 } |
| 576 |
| 577 static bool MergeDatabaseIntoLiveBlobJournal( |
| 578 LevelDBUncachedTransaction* leveldb_transaction, |
| 579 int64 database_id) { |
| 580 IndexedDBBackingStore::Transaction::BlobJournalType journal; |
| 581 std::string key = LiveBlobJournalKey::Encode(); |
| 582 if (!GetBlobJournal(key, leveldb_transaction, &journal)) |
| 583 return false; |
| 584 journal.push_back( |
| 585 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey)); |
| 586 std::string data = EncodeBlobJournal(journal); |
| 587 leveldb_transaction->Put(key, &data); |
| 588 return true; |
| 589 } |
| 590 |
| 591 // Blob Data is encoded as { is_file [bool], key [int64 as varInt], |
| 592 // type [string-with-length, may be empty], then [for Blobs] size |
| 593 // [int64 as varInt] or [for Files] fileName [string-with-length] } |
| 594 static std::string EncodeBlobData( |
| 595 const std::vector<IndexedDBBlobInfo*>& blob_info) { |
| 596 std::string ret; |
| 597 std::vector<IndexedDBBlobInfo*>::const_iterator iter; |
| 598 for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) { |
| 599 const IndexedDBBlobInfo& info = **iter; |
| 600 EncodeBool(info.is_file(), &ret); |
| 601 EncodeVarInt(info.key(), &ret); |
| 602 EncodeStringWithLength(info.type(), &ret); |
| 603 if (info.is_file()) |
| 604 EncodeStringWithLength(info.file_name(), &ret); |
| 605 else |
| 606 EncodeVarInt(info.size(), &ret); |
| 607 } |
| 608 return ret; |
| 609 } |
| 610 |
| 611 static bool DecodeBlobData(const std::string& data, |
| 612 std::vector<IndexedDBBlobInfo>* output) { |
| 613 std::vector<IndexedDBBlobInfo> ret; |
| 614 output->clear(); |
| 615 StringPiece slice(data); |
| 616 while (!slice.empty()) { |
| 617 bool is_file; |
| 618 int64 key; |
| 619 string16 type; |
| 620 int64 size; |
| 621 string16 file_name; |
| 622 |
| 623 if (!DecodeBool(&slice, &is_file)) |
| 624 return false; |
| 625 if (!DecodeVarInt(&slice, &key) || |
| 626 !DatabaseMetaDataKey::IsValidBlobKey(key)) |
| 627 return false; |
| 628 if (!DecodeStringWithLength(&slice, &type)) |
| 629 return false; |
| 630 if (is_file) { |
| 631 if (!DecodeStringWithLength(&slice, &file_name)) |
| 632 return false; |
| 633 ret.push_back(IndexedDBBlobInfo(key, type, file_name)); |
| 634 } else { |
| 635 if (!DecodeVarInt(&slice, &size) || size < 0) |
| 636 return false; |
| 637 ret.push_back(IndexedDBBlobInfo(type, static_cast<uint64>(size), key)); |
| 638 } |
| 639 } |
| 640 output->swap(ret); |
| 641 |
| 642 return true; |
| 643 } |
| 644 |
377 IndexedDBBackingStore::IndexedDBBackingStore( | 645 IndexedDBBackingStore::IndexedDBBackingStore( |
| 646 IndexedDBFactory* indexed_db_factory, |
378 const GURL& origin_url, | 647 const GURL& origin_url, |
| 648 const FilePath& blob_path, |
| 649 net::URLRequestContext* request_context, |
379 scoped_ptr<LevelDBDatabase> db, | 650 scoped_ptr<LevelDBDatabase> db, |
380 scoped_ptr<LevelDBComparator> comparator) | 651 scoped_ptr<LevelDBComparator> comparator, |
381 : origin_url_(origin_url), | 652 base::TaskRunner* task_runner) |
| 653 : indexed_db_factory_(indexed_db_factory), |
| 654 origin_url_(origin_url), |
382 origin_identifier_(ComputeOriginIdentifier(origin_url)), | 655 origin_identifier_(ComputeOriginIdentifier(origin_url)), |
| 656 blob_path_(blob_path), |
| 657 request_context_(request_context), |
| 658 task_runner_(task_runner), |
383 db_(db.Pass()), | 659 db_(db.Pass()), |
384 comparator_(comparator.Pass()) {} | 660 comparator_(comparator.Pass()), |
| 661 active_blob_registry_(this) {} |
385 | 662 |
386 IndexedDBBackingStore::~IndexedDBBackingStore() { | 663 IndexedDBBackingStore::~IndexedDBBackingStore() { |
| 664 if (!blob_path_.empty() && !child_process_ids_granted_.empty()) { |
| 665 ChildProcessSecurityPolicyImpl* policy = |
| 666 ChildProcessSecurityPolicyImpl::GetInstance(); |
| 667 for (std::set<int>::iterator iter = child_process_ids_granted_.begin(); |
| 668 iter != child_process_ids_granted_.end(); |
| 669 ++iter) { |
| 670 policy->RevokeAllPermissionsForFile(*iter, blob_path_); |
| 671 } |
| 672 } |
387 // db_'s destructor uses comparator_. The order of destruction is important. | 673 // db_'s destructor uses comparator_. The order of destruction is important. |
388 db_.reset(); | 674 db_.reset(); |
389 comparator_.reset(); | 675 comparator_.reset(); |
390 } | 676 } |
391 | 677 |
392 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier( | 678 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier( |
393 const std::string& primary_key, | 679 const std::string& primary_key, |
394 int64 version) | 680 int64 version) |
395 : primary_key_(primary_key), version_(version) { | 681 : primary_key_(primary_key), version_(version) { |
396 DCHECK(!primary_key.empty()); | 682 DCHECK(!primary_key.empty()); |
(...skipping 18 matching lines...) Expand all Loading... |
415 INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, | 701 INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, |
416 INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII, | 702 INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII, |
417 INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED, | 703 INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED, |
418 INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, | 704 INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, |
419 INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, | 705 INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, |
420 INDEXED_DB_BACKING_STORE_OPEN_MAX, | 706 INDEXED_DB_BACKING_STORE_OPEN_MAX, |
421 }; | 707 }; |
422 | 708 |
423 // static | 709 // static |
424 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( | 710 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( |
| 711 IndexedDBFactory* indexed_db_factory, |
425 const GURL& origin_url, | 712 const GURL& origin_url, |
426 const base::FilePath& path_base, | 713 const base::FilePath& path_base, |
| 714 net::URLRequestContext* request_context, |
427 blink::WebIDBDataLoss* data_loss, | 715 blink::WebIDBDataLoss* data_loss, |
428 std::string* data_loss_message, | 716 std::string* data_loss_message, |
429 bool* disk_full) { | 717 bool* disk_full, |
| 718 base::TaskRunner* task_runner, |
| 719 bool clean_journal) { |
430 *data_loss = blink::WebIDBDataLossNone; | 720 *data_loss = blink::WebIDBDataLossNone; |
431 DefaultLevelDBFactory leveldb_factory; | 721 DefaultLevelDBFactory leveldb_factory; |
432 return IndexedDBBackingStore::Open(origin_url, | 722 return IndexedDBBackingStore::Open(indexed_db_factory, |
| 723 origin_url, |
433 path_base, | 724 path_base, |
| 725 request_context, |
434 data_loss, | 726 data_loss, |
435 data_loss_message, | 727 data_loss_message, |
436 disk_full, | 728 disk_full, |
437 &leveldb_factory); | 729 &leveldb_factory, |
| 730 task_runner, |
| 731 clean_journal); |
438 } | 732 } |
439 | 733 |
440 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) { | 734 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) { |
441 if (origin_url.host() == "docs.google.com") | 735 if (origin_url.host() == "docs.google.com") |
442 return ".Docs"; | 736 return ".Docs"; |
443 return std::string(); | 737 return std::string(); |
444 } | 738 } |
445 | 739 |
446 static void HistogramOpenStatus(IndexedDBBackingStoreOpenResult result, | 740 static void HistogramOpenStatus(IndexedDBBackingStoreOpenResult result, |
447 const GURL& origin_url) { | 741 const GURL& origin_url) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 min, | 782 min, |
489 max, | 783 max, |
490 num_buckets); | 784 num_buckets); |
491 return true; | 785 return true; |
492 } | 786 } |
493 return false; | 787 return false; |
494 } | 788 } |
495 | 789 |
496 // static | 790 // static |
497 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( | 791 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( |
| 792 IndexedDBFactory* indexed_db_factory, |
498 const GURL& origin_url, | 793 const GURL& origin_url, |
499 const base::FilePath& path_base, | 794 const base::FilePath& path_base, |
| 795 net::URLRequestContext* request_context, |
500 blink::WebIDBDataLoss* data_loss, | 796 blink::WebIDBDataLoss* data_loss, |
501 std::string* data_loss_message, | 797 std::string* data_loss_message, |
502 bool* is_disk_full, | 798 bool* is_disk_full, |
503 LevelDBFactory* leveldb_factory) { | 799 LevelDBFactory* leveldb_factory, |
| 800 base::TaskRunner* task_runner, |
| 801 bool clean_journal) { |
504 IDB_TRACE("IndexedDBBackingStore::Open"); | 802 IDB_TRACE("IndexedDBBackingStore::Open"); |
505 DCHECK(!path_base.empty()); | 803 DCHECK(!path_base.empty()); |
506 *data_loss = blink::WebIDBDataLossNone; | 804 *data_loss = blink::WebIDBDataLossNone; |
507 *data_loss_message = ""; | 805 *data_loss_message = ""; |
508 *is_disk_full = false; | 806 *is_disk_full = false; |
509 | 807 |
510 scoped_ptr<LevelDBComparator> comparator(new Comparator()); | 808 scoped_ptr<LevelDBComparator> comparator(new Comparator()); |
511 | 809 |
512 if (!IsStringASCII(path_base.AsUTF8Unsafe())) { | 810 if (!IsStringASCII(path_base.AsUTF8Unsafe())) { |
513 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII, | 811 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII, |
514 origin_url); | 812 origin_url); |
515 } | 813 } |
516 if (!file_util::CreateDirectory(path_base)) { | 814 if (!file_util::CreateDirectory(path_base)) { |
517 LOG(ERROR) << "Unable to create IndexedDB database path " | 815 LOG(ERROR) << "Unable to create IndexedDB database path " |
518 << path_base.AsUTF8Unsafe(); | 816 << path_base.AsUTF8Unsafe(); |
519 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY, | 817 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY, |
520 origin_url); | 818 origin_url); |
521 return scoped_refptr<IndexedDBBackingStore>(); | 819 return scoped_refptr<IndexedDBBackingStore>(); |
522 } | 820 } |
523 | 821 |
524 const base::FilePath file_path = | 822 const base::FilePath file_path = |
525 path_base.Append(ComputeFileName(origin_url)); | 823 path_base.Append(ComputeFileName(origin_url)); |
| 824 const base::FilePath blob_path = |
| 825 path_base.Append(ComputeBlobPath(origin_url)); |
526 | 826 |
527 if (IsPathTooLong(file_path)) { | 827 if (IsPathTooLong(file_path)) { |
528 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, | 828 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, |
529 origin_url); | 829 origin_url); |
530 return scoped_refptr<IndexedDBBackingStore>(); | 830 return scoped_refptr<IndexedDBBackingStore>(); |
531 } | 831 } |
532 | 832 |
533 scoped_ptr<LevelDBDatabase> db; | 833 scoped_ptr<LevelDBDatabase> db; |
534 leveldb::Status status = leveldb_factory->OpenLevelDB( | 834 leveldb::Status status = leveldb_factory->OpenLevelDB( |
535 file_path, comparator.get(), &db, is_disk_full); | 835 file_path, comparator.get(), &db, is_disk_full); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 origin_url); | 900 origin_url); |
601 } | 901 } |
602 | 902 |
603 if (!db) { | 903 if (!db) { |
604 NOTREACHED(); | 904 NOTREACHED(); |
605 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR, | 905 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR, |
606 origin_url); | 906 origin_url); |
607 return scoped_refptr<IndexedDBBackingStore>(); | 907 return scoped_refptr<IndexedDBBackingStore>(); |
608 } | 908 } |
609 | 909 |
610 return Create(origin_url, db.Pass(), comparator.Pass()); | 910 scoped_refptr<IndexedDBBackingStore> backing_store = |
611 } | 911 Create(indexed_db_factory, |
| 912 origin_url, |
| 913 blob_path, |
| 914 request_context, |
| 915 db.Pass(), |
| 916 comparator.Pass(), |
| 917 task_runner); |
612 | 918 |
613 // static | 919 if (clean_journal && |
614 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( | 920 !backing_store->CleanUpBlobJournal(LiveBlobJournalKey::Encode())) |
615 const GURL& origin_url) { | 921 return scoped_refptr<IndexedDBBackingStore>(); |
616 DefaultLevelDBFactory leveldb_factory; | 922 return backing_store; |
617 return IndexedDBBackingStore::OpenInMemory(origin_url, &leveldb_factory); | |
618 } | 923 } |
619 | 924 |
620 // static | 925 // static |
621 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( | 926 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( |
622 const GURL& origin_url, | 927 const GURL& origin_url, |
623 LevelDBFactory* leveldb_factory) { | 928 base::TaskRunner* task_runner) { |
| 929 DefaultLevelDBFactory leveldb_factory; |
| 930 return IndexedDBBackingStore::OpenInMemory( |
| 931 origin_url, &leveldb_factory, task_runner); |
| 932 } |
| 933 |
| 934 // static |
| 935 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( |
| 936 const GURL& origin_url, |
| 937 LevelDBFactory* leveldb_factory, |
| 938 base::TaskRunner* task_runner) { |
624 IDB_TRACE("IndexedDBBackingStore::OpenInMemory"); | 939 IDB_TRACE("IndexedDBBackingStore::OpenInMemory"); |
625 | 940 |
626 scoped_ptr<LevelDBComparator> comparator(new Comparator()); | 941 scoped_ptr<LevelDBComparator> comparator(new Comparator()); |
627 scoped_ptr<LevelDBDatabase> db = | 942 scoped_ptr<LevelDBDatabase> db = |
628 LevelDBDatabase::OpenInMemory(comparator.get()); | 943 LevelDBDatabase::OpenInMemory(comparator.get()); |
629 if (!db) { | 944 if (!db) { |
630 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed."; | 945 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed."; |
631 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, | 946 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, |
632 origin_url); | 947 origin_url); |
633 return scoped_refptr<IndexedDBBackingStore>(); | 948 return scoped_refptr<IndexedDBBackingStore>(); |
634 } | 949 } |
635 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url); | 950 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url); |
636 | 951 |
637 return Create(origin_url, db.Pass(), comparator.Pass()); | 952 return Create(NULL, |
| 953 origin_url, |
| 954 FilePath(), |
| 955 NULL, |
| 956 db.Pass(), |
| 957 comparator.Pass(), |
| 958 task_runner); |
638 } | 959 } |
639 | 960 |
640 // static | 961 // static |
641 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( | 962 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( |
| 963 IndexedDBFactory* indexed_db_factory, |
642 const GURL& origin_url, | 964 const GURL& origin_url, |
| 965 const FilePath& blob_path, |
| 966 net::URLRequestContext* request_context, |
643 scoped_ptr<LevelDBDatabase> db, | 967 scoped_ptr<LevelDBDatabase> db, |
644 scoped_ptr<LevelDBComparator> comparator) { | 968 scoped_ptr<LevelDBComparator> comparator, |
| 969 base::TaskRunner* task_runner) { |
645 // TODO(jsbell): Handle comparator name changes. | 970 // TODO(jsbell): Handle comparator name changes. |
646 | |
647 scoped_refptr<IndexedDBBackingStore> backing_store( | 971 scoped_refptr<IndexedDBBackingStore> backing_store( |
648 new IndexedDBBackingStore(origin_url, db.Pass(), comparator.Pass())); | 972 new IndexedDBBackingStore(indexed_db_factory, |
649 if (!SetUpMetadata(backing_store->db_.get(), | 973 origin_url, |
650 backing_store->origin_identifier_)) | 974 blob_path, |
| 975 request_context, |
| 976 db.Pass(), |
| 977 comparator.Pass(), |
| 978 task_runner)); |
| 979 if (!backing_store->SetUpMetadata()) |
651 return scoped_refptr<IndexedDBBackingStore>(); | 980 return scoped_refptr<IndexedDBBackingStore>(); |
652 | 981 |
653 return backing_store; | 982 return backing_store; |
654 } | 983 } |
655 | 984 |
| 985 void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) { |
| 986 if (!child_process_ids_granted_.count(child_process_id)) { |
| 987 child_process_ids_granted_.insert(child_process_id); |
| 988 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( |
| 989 child_process_id, blob_path_); |
| 990 } |
| 991 } |
| 992 |
656 std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() { | 993 std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() { |
657 std::vector<string16> found_names; | 994 std::vector<string16> found_names; |
658 const std::string start_key = | 995 const std::string start_key = |
659 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_); | 996 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_); |
660 const std::string stop_key = | 997 const std::string stop_key = |
661 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_); | 998 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_); |
662 | 999 |
663 DCHECK(found_names.empty()); | 1000 DCHECK(found_names.empty()); |
664 | 1001 |
665 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); | 1002 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) | 1060 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) |
724 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION; | 1061 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION; |
725 | 1062 |
726 ok = GetMaxObjectStoreId( | 1063 ok = GetMaxObjectStoreId( |
727 db_.get(), metadata->id, &metadata->max_object_store_id); | 1064 db_.get(), metadata->id, &metadata->max_object_store_id); |
728 if (!ok) { | 1065 if (!ok) { |
729 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); | 1066 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); |
730 return false; | 1067 return false; |
731 } | 1068 } |
732 | 1069 |
| 1070 int64 blob_key_generator_current_number = |
| 1071 DatabaseMetaDataKey::kInvalidBlobKey; |
| 1072 |
| 1073 ok = GetVarInt( |
| 1074 db_.get(), |
| 1075 DatabaseMetaDataKey::Encode( |
| 1076 metadata->id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER), |
| 1077 &blob_key_generator_current_number, |
| 1078 found); |
| 1079 if (!ok) { |
| 1080 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); |
| 1081 return false; |
| 1082 } |
| 1083 if (!*found) { |
| 1084 // This database predates blob support. |
| 1085 *found = true; |
| 1086 } else if (!DatabaseMetaDataKey::IsValidBlobKey( |
| 1087 blob_key_generator_current_number)) { |
| 1088 INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA); |
| 1089 return false; |
| 1090 } |
| 1091 |
733 return true; | 1092 return true; |
734 } | 1093 } |
735 | 1094 |
736 WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBTransaction* transaction, | 1095 WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBTransaction* transaction, |
737 int64* new_id) { | 1096 int64* new_id) { |
738 *new_id = -1; | 1097 *new_id = -1; |
739 int64 max_database_id = -1; | 1098 int64 max_database_id = -1; |
740 bool found = false; | 1099 bool found = false; |
741 bool ok = | 1100 bool ok = |
742 GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found); | 1101 GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
774 DatabaseNameKey::Encode(origin_identifier_, name), | 1133 DatabaseNameKey::Encode(origin_identifier_, name), |
775 *row_id); | 1134 *row_id); |
776 PutString( | 1135 PutString( |
777 transaction.get(), | 1136 transaction.get(), |
778 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION), | 1137 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION), |
779 version); | 1138 version); |
780 PutVarInt(transaction.get(), | 1139 PutVarInt(transaction.get(), |
781 DatabaseMetaDataKey::Encode(*row_id, | 1140 DatabaseMetaDataKey::Encode(*row_id, |
782 DatabaseMetaDataKey::USER_INT_VERSION), | 1141 DatabaseMetaDataKey::USER_INT_VERSION), |
783 int_version); | 1142 int_version); |
| 1143 PutVarInt( |
| 1144 transaction.get(), |
| 1145 DatabaseMetaDataKey::Encode( |
| 1146 *row_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER), |
| 1147 DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber); |
784 if (!transaction->Commit()) { | 1148 if (!transaction->Commit()) { |
785 INTERNAL_WRITE_ERROR(CREATE_IDBDATABASE_METADATA); | 1149 INTERNAL_WRITE_ERROR(CREATE_IDBDATABASE_METADATA); |
786 return false; | 1150 return false; |
787 } | 1151 } |
788 return true; | 1152 return true; |
789 } | 1153 } |
790 | 1154 |
791 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion( | 1155 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion( |
792 IndexedDBBackingStore::Transaction* transaction, | 1156 IndexedDBBackingStore::Transaction* transaction, |
793 int64 row_id, | 1157 int64 row_id, |
794 int64 int_version) { | 1158 int64 int_version) { |
795 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) | 1159 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) |
796 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION; | 1160 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION; |
797 DCHECK_GE(int_version, 0) << "int_version was " << int_version; | 1161 DCHECK_GE(int_version, 0) << "int_version was " << int_version; |
798 PutVarInt(transaction->transaction(), | 1162 PutVarInt(transaction->transaction(), |
799 DatabaseMetaDataKey::Encode(row_id, | 1163 DatabaseMetaDataKey::Encode(row_id, |
800 DatabaseMetaDataKey::USER_INT_VERSION), | 1164 DatabaseMetaDataKey::USER_INT_VERSION), |
801 int_version); | 1165 int_version); |
802 return true; | 1166 return true; |
803 } | 1167 } |
804 | 1168 |
805 static void DeleteRange(LevelDBTransaction* transaction, | 1169 // Note that if you're deleting a range that contains user keys that have blob |
806 const std::string& begin, | 1170 // info, this won't clean up the blobs. |
807 const std::string& end) { | 1171 static void DeleteRangeByKeys(LevelDBTransaction* transaction, |
| 1172 const std::string& begin, |
| 1173 const std::string& end) { |
808 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); | 1174 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); |
809 for (it->Seek(begin); it->IsValid() && CompareKeys(it->Key(), end) < 0; | 1175 for (it->Seek(begin); it->IsValid() && CompareKeys(it->Key(), end) < 0; |
810 it->Next()) | 1176 it->Next()) |
811 transaction->Remove(it->Key()); | 1177 transaction->Remove(it->Key()); |
812 } | 1178 } |
813 | 1179 |
| 1180 // For a whole-object-store deletion, we still use the one-blob-record-at-a-time |
| 1181 // deletion mechanism designed for normal transactions. We could go with the |
| 1182 // nuke-the-whole-directory method used for deleteDatabase if we structured the |
| 1183 // directories accordingly, but that would complicate the kind of info we store |
| 1184 // in the LevelDBTransaction and lengthen paths. |
| 1185 static bool DeleteBlobsInObjectStore( |
| 1186 IndexedDBBackingStore::Transaction* transaction, |
| 1187 int64 database_id, |
| 1188 int64 object_store_id) { |
| 1189 std::string start_key, end_key; |
| 1190 start_key = |
| 1191 BlobEntryKey::EncodeMinForObjectStore(database_id, object_store_id); |
| 1192 end_key = BlobEntryKey::EncodeMaxForObjectStore(database_id, object_store_id); |
| 1193 |
| 1194 scoped_ptr<LevelDBIterator> it = transaction->transaction()->CreateIterator(); |
| 1195 for (it->Seek(start_key); |
| 1196 it->IsValid() && CompareKeys(it->Key(), end_key) < 0; |
| 1197 it->Next()) { |
| 1198 StringPiece key_piece(it->Key()); |
| 1199 std::string user_key = |
| 1200 BlobEntryKey::ReencodeToObjectStoreDataKey(&key_piece); |
| 1201 if (!user_key.size()) { |
| 1202 INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA); |
| 1203 return false; |
| 1204 } |
| 1205 transaction->PutBlobInfo( |
| 1206 database_id, object_store_id, user_key, NULL, NULL); |
| 1207 } |
| 1208 return true; |
| 1209 } |
| 1210 |
| 1211 static bool GetBlobInfoForRecord(IndexedDBBackingStore* backing_store, |
| 1212 LevelDBTransaction* leveldb_transaction, |
| 1213 int64 database_id, |
| 1214 const std::string& leveldb_key, |
| 1215 IndexedDBValue* value) { |
| 1216 |
| 1217 BlobEntryKey blob_entry_key; |
| 1218 StringPiece leveldb_key_piece(leveldb_key); |
| 1219 if (!BlobEntryKey::FromObjectStoreDataKey(&leveldb_key_piece, |
| 1220 &blob_entry_key)) { |
| 1221 NOTREACHED(); |
| 1222 return false; |
| 1223 } |
| 1224 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); |
| 1225 std::string encoded_key = blob_entry_key.Encode(); |
| 1226 it->Seek(encoded_key); |
| 1227 if (it->IsValid() && CompareKeys(it->Key(), encoded_key) == 0) { |
| 1228 if (!DecodeBlobData(it->Value().as_string(), &value->blob_info)) { |
| 1229 INTERNAL_READ_ERROR(GET_BLOB_INFO_FOR_RECORD); |
| 1230 return false; |
| 1231 } |
| 1232 std::vector<IndexedDBBlobInfo>::iterator iter; |
| 1233 for (iter = value->blob_info.begin(); iter != value->blob_info.end(); |
| 1234 ++iter) { |
| 1235 iter->set_file_path( |
| 1236 backing_store->GetBlobFileName(database_id, iter->key())); |
| 1237 iter->set_mark_used_callback( |
| 1238 backing_store->active_blob_registry()->GetAddBlobRefCallback( |
| 1239 database_id, iter->key())); |
| 1240 iter->set_release_callback( |
| 1241 backing_store->active_blob_registry()->GetFinalReleaseCallback( |
| 1242 database_id, iter->key())); |
| 1243 if (iter->is_file()) { |
| 1244 base::PlatformFileInfo info; |
| 1245 if (file_util::GetFileInfo(iter->file_path(), &info)) { |
| 1246 // This should always work, but it isn't fatal if it doesn't; it just |
| 1247 // means a potential slow synchronous call from the renderer later. |
| 1248 iter->set_last_modified(info.last_modified); |
| 1249 iter->set_size(info.size); |
| 1250 } |
| 1251 } |
| 1252 } |
| 1253 } |
| 1254 return true; |
| 1255 } |
| 1256 |
814 bool IndexedDBBackingStore::DeleteDatabase(const string16& name) { | 1257 bool IndexedDBBackingStore::DeleteDatabase(const string16& name) { |
815 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase"); | 1258 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase"); |
816 scoped_ptr<LevelDBWriteOnlyTransaction> transaction = | 1259 scoped_ptr<LevelDBUncachedTransaction> transaction = |
817 LevelDBWriteOnlyTransaction::Create(db_.get()); | 1260 LevelDBUncachedTransaction::Create(db_.get()); |
| 1261 |
| 1262 if (!CleanUpBlobJournal(BlobJournalKey::Encode())) |
| 1263 return false; |
818 | 1264 |
819 IndexedDBDatabaseMetadata metadata; | 1265 IndexedDBDatabaseMetadata metadata; |
820 bool success = false; | 1266 bool success = false; |
821 bool ok = GetIDBDatabaseMetaData(name, &metadata, &success); | 1267 bool ok = GetIDBDatabaseMetaData(name, &metadata, &success); |
822 if (!ok) | 1268 if (!ok) |
823 return false; | 1269 return false; |
824 if (!success) | 1270 if (!success) |
825 return true; | 1271 return true; |
826 | 1272 |
827 const std::string start_key = DatabaseMetaDataKey::Encode( | 1273 const std::string start_key = DatabaseMetaDataKey::Encode( |
828 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME); | 1274 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME); |
829 const std::string stop_key = DatabaseMetaDataKey::Encode( | 1275 const std::string stop_key = DatabaseMetaDataKey::Encode( |
830 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME); | 1276 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME); |
831 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); | 1277 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); |
832 for (it->Seek(start_key); | 1278 for (it->Seek(start_key); |
833 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; | 1279 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; |
834 it->Next()) | 1280 it->Next()) |
835 transaction->Remove(it->Key()); | 1281 transaction->Remove(it->Key()); |
836 | 1282 |
837 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); | 1283 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); |
838 transaction->Remove(key); | 1284 transaction->Remove(key); |
839 | 1285 |
| 1286 bool need_cleanup = false; |
| 1287 if (active_blob_registry()->MarkDeletedCheckIfUsed( |
| 1288 metadata.id, DatabaseMetaDataKey::kAllBlobsKey)) { |
| 1289 if (!MergeDatabaseIntoLiveBlobJournal(transaction.get(), metadata.id)) |
| 1290 return false; |
| 1291 } else { |
| 1292 UpdateBlobJournalWithDatabase(transaction.get(), metadata.id); |
| 1293 need_cleanup = true; |
| 1294 } |
| 1295 |
840 if (!transaction->Commit()) { | 1296 if (!transaction->Commit()) { |
841 INTERNAL_WRITE_ERROR(DELETE_DATABASE); | 1297 INTERNAL_WRITE_ERROR(DELETE_DATABASE); |
842 return false; | 1298 return false; |
843 } | 1299 } |
| 1300 |
| 1301 if (need_cleanup) |
| 1302 CleanUpBlobJournal(BlobJournalKey::Encode()); |
| 1303 |
844 return true; | 1304 return true; |
845 } | 1305 } |
846 | 1306 |
847 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it, | 1307 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it, |
848 const std::string& stop_key, | 1308 const std::string& stop_key, |
849 int64 object_store_id, | 1309 int64 object_store_id, |
850 int64 meta_data_type) { | 1310 int64 meta_data_type) { |
851 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) | 1311 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) |
852 return false; | 1312 return false; |
853 | 1313 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 1386 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
927 break; | 1387 break; |
928 } | 1388 } |
929 bool auto_increment; | 1389 bool auto_increment; |
930 { | 1390 { |
931 StringPiece slice(it->Value()); | 1391 StringPiece slice(it->Value()); |
932 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) | 1392 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) |
933 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 1393 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
934 } | 1394 } |
935 | 1395 |
936 it->Next(); // Is evicatble. | 1396 it->Next(); // Is evictable. |
937 if (!CheckObjectStoreAndMetaDataType(it.get(), | 1397 if (!CheckObjectStoreAndMetaDataType(it.get(), |
938 stop_key, | 1398 stop_key, |
939 object_store_id, | 1399 object_store_id, |
940 ObjectStoreMetaDataKey::EVICTABLE)) { | 1400 ObjectStoreMetaDataKey::EVICTABLE)) { |
941 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 1401 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
942 break; | 1402 break; |
943 } | 1403 } |
944 | 1404 |
945 it->Next(); // Last version. | 1405 it->Next(); // Last version. |
946 if (!CheckObjectStoreAndMetaDataType( | 1406 if (!CheckObjectStoreAndMetaDataType( |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1113 &found); | 1573 &found); |
1114 if (!ok) { | 1574 if (!ok) { |
1115 INTERNAL_READ_ERROR(DELETE_OBJECT_STORE); | 1575 INTERNAL_READ_ERROR(DELETE_OBJECT_STORE); |
1116 return false; | 1576 return false; |
1117 } | 1577 } |
1118 if (!found) { | 1578 if (!found) { |
1119 INTERNAL_CONSISTENCY_ERROR(DELETE_OBJECT_STORE); | 1579 INTERNAL_CONSISTENCY_ERROR(DELETE_OBJECT_STORE); |
1120 return false; | 1580 return false; |
1121 } | 1581 } |
1122 | 1582 |
1123 DeleteRange( | 1583 if (!DeleteBlobsInObjectStore(transaction, database_id, object_store_id)) |
| 1584 return false; |
| 1585 DeleteRangeByKeys( |
1124 leveldb_transaction, | 1586 leveldb_transaction, |
1125 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0), | 1587 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0), |
1126 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id)); | 1588 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id)); |
1127 | 1589 |
1128 leveldb_transaction->Remove( | 1590 leveldb_transaction->Remove( |
1129 ObjectStoreNamesKey::Encode(database_id, object_store_name)); | 1591 ObjectStoreNamesKey::Encode(database_id, object_store_name)); |
1130 | 1592 |
1131 DeleteRange(leveldb_transaction, | 1593 DeleteRangeByKeys( |
1132 IndexFreeListKey::Encode(database_id, object_store_id, 0), | 1594 leveldb_transaction, |
1133 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id)); | 1595 IndexFreeListKey::Encode(database_id, object_store_id, 0), |
1134 DeleteRange(leveldb_transaction, | 1596 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id)); |
1135 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0), | 1597 DeleteRangeByKeys( |
1136 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id)); | 1598 leveldb_transaction, |
| 1599 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0), |
| 1600 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id)); |
1137 | 1601 |
1138 return ClearObjectStore(transaction, database_id, object_store_id); | 1602 return ClearObjectStore(transaction, database_id, object_store_id); |
1139 } | 1603 } |
1140 | 1604 |
1141 bool IndexedDBBackingStore::GetRecord( | 1605 bool IndexedDBBackingStore::GetRecord( |
1142 IndexedDBBackingStore::Transaction* transaction, | 1606 IndexedDBBackingStore::Transaction* transaction, |
1143 int64 database_id, | 1607 int64 database_id, |
1144 int64 object_store_id, | 1608 int64 object_store_id, |
1145 const IndexedDBKey& key, | 1609 const IndexedDBKey& key, |
1146 std::string* record) { | 1610 IndexedDBValue* record) { |
1147 IDB_TRACE("IndexedDBBackingStore::GetRecord"); | 1611 IDB_TRACE("IndexedDBBackingStore::GetRecord"); |
1148 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1612 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
1149 return false; | 1613 return false; |
1150 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 1614 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
1151 | 1615 |
1152 const std::string leveldb_key = | 1616 const std::string leveldb_key = |
1153 ObjectStoreDataKey::Encode(database_id, object_store_id, key); | 1617 ObjectStoreDataKey::Encode(database_id, object_store_id, key); |
1154 std::string data; | 1618 std::string data; |
1155 | 1619 |
1156 record->clear(); | 1620 record->clear(); |
(...skipping 11 matching lines...) Expand all Loading... |
1168 return false; | 1632 return false; |
1169 } | 1633 } |
1170 | 1634 |
1171 int64 version; | 1635 int64 version; |
1172 StringPiece slice(data); | 1636 StringPiece slice(data); |
1173 if (!DecodeVarInt(&slice, &version)) { | 1637 if (!DecodeVarInt(&slice, &version)) { |
1174 INTERNAL_READ_ERROR(GET_RECORD); | 1638 INTERNAL_READ_ERROR(GET_RECORD); |
1175 return false; | 1639 return false; |
1176 } | 1640 } |
1177 | 1641 |
1178 *record = slice.as_string(); | 1642 record->bits = slice.as_string(); |
1179 return true; | 1643 return GetBlobInfoForRecord( |
| 1644 this, leveldb_transaction, database_id, leveldb_key, record); |
1180 } | 1645 } |
1181 | 1646 |
1182 WARN_UNUSED_RESULT static bool GetNewVersionNumber( | 1647 WARN_UNUSED_RESULT static bool GetNewVersionNumber( |
1183 LevelDBTransaction* transaction, | 1648 LevelDBTransaction* transaction, |
1184 int64 database_id, | 1649 int64 database_id, |
1185 int64 object_store_id, | 1650 int64 object_store_id, |
1186 int64* new_version_number) { | 1651 int64* new_version_number) { |
1187 const std::string last_version_key = ObjectStoreMetaDataKey::Encode( | 1652 const std::string last_version_key = ObjectStoreMetaDataKey::Encode( |
1188 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION); | 1653 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION); |
1189 | 1654 |
(...skipping 18 matching lines...) Expand all Loading... |
1208 | 1673 |
1209 *new_version_number = version; | 1674 *new_version_number = version; |
1210 return true; | 1675 return true; |
1211 } | 1676 } |
1212 | 1677 |
1213 bool IndexedDBBackingStore::PutRecord( | 1678 bool IndexedDBBackingStore::PutRecord( |
1214 IndexedDBBackingStore::Transaction* transaction, | 1679 IndexedDBBackingStore::Transaction* transaction, |
1215 int64 database_id, | 1680 int64 database_id, |
1216 int64 object_store_id, | 1681 int64 object_store_id, |
1217 const IndexedDBKey& key, | 1682 const IndexedDBKey& key, |
1218 const std::string& value, | 1683 IndexedDBValue& value, |
| 1684 ScopedVector<webkit_blob::BlobDataHandle>* handles, |
1219 RecordIdentifier* record_identifier) { | 1685 RecordIdentifier* record_identifier) { |
1220 IDB_TRACE("IndexedDBBackingStore::PutRecord"); | 1686 IDB_TRACE("IndexedDBBackingStore::PutRecord"); |
1221 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1687 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
1222 return false; | 1688 return false; |
1223 DCHECK(key.IsValid()); | 1689 DCHECK(key.IsValid()); |
1224 | 1690 |
1225 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 1691 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
1226 int64 version = -1; | 1692 int64 version = -1; |
1227 bool ok = GetNewVersionNumber( | 1693 bool ok = GetNewVersionNumber( |
1228 leveldb_transaction, database_id, object_store_id, &version); | 1694 leveldb_transaction, database_id, object_store_id, &version); |
1229 if (!ok) | 1695 if (!ok) |
1230 return false; | 1696 return false; |
1231 DCHECK_GE(version, 0); | 1697 DCHECK_GE(version, 0); |
1232 const std::string object_storedata_key = | 1698 const std::string object_store_data_key = |
1233 ObjectStoreDataKey::Encode(database_id, object_store_id, key); | 1699 ObjectStoreDataKey::Encode(database_id, object_store_id, key); |
1234 | 1700 |
1235 std::string v; | 1701 std::string v; |
1236 EncodeVarInt(version, &v); | 1702 EncodeVarInt(version, &v); |
1237 v.append(value); | 1703 v.append(value.bits); |
1238 | 1704 |
1239 leveldb_transaction->Put(object_storedata_key, &v); | 1705 leveldb_transaction->Put(object_store_data_key, &v); |
| 1706 transaction->PutBlobInfo(database_id, |
| 1707 object_store_id, |
| 1708 object_store_data_key, |
| 1709 &value.blob_info, |
| 1710 handles); |
| 1711 DCHECK(!handles->size()); |
1240 | 1712 |
1241 const std::string exists_entry_key = | 1713 const std::string exists_entry_key = |
1242 ExistsEntryKey::Encode(database_id, object_store_id, key); | 1714 ExistsEntryKey::Encode(database_id, object_store_id, key); |
1243 std::string version_encoded; | 1715 std::string version_encoded; |
1244 EncodeInt(version, &version_encoded); | 1716 EncodeInt(version, &version_encoded); |
1245 leveldb_transaction->Put(exists_entry_key, &version_encoded); | 1717 leveldb_transaction->Put(exists_entry_key, &version_encoded); |
1246 | 1718 |
1247 std::string key_encoded; | 1719 std::string key_encoded; |
1248 EncodeIDBKey(key, &key_encoded); | 1720 EncodeIDBKey(key, &key_encoded); |
1249 record_identifier->Reset(key_encoded, version); | 1721 record_identifier->Reset(key_encoded, version); |
1250 return true; | 1722 return true; |
1251 } | 1723 } |
1252 | 1724 |
1253 bool IndexedDBBackingStore::ClearObjectStore( | 1725 bool IndexedDBBackingStore::ClearObjectStore( |
1254 IndexedDBBackingStore::Transaction* transaction, | 1726 IndexedDBBackingStore::Transaction* transaction, |
1255 int64 database_id, | 1727 int64 database_id, |
1256 int64 object_store_id) { | 1728 int64 object_store_id) { |
1257 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore"); | 1729 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore"); |
1258 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1730 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
1259 return false; | 1731 return false; |
1260 const std::string start_key = | 1732 const std::string start_key = |
1261 KeyPrefix(database_id, object_store_id).Encode(); | 1733 KeyPrefix(database_id, object_store_id).Encode(); |
1262 const std::string stop_key = | 1734 const std::string stop_key = |
1263 KeyPrefix(database_id, object_store_id + 1).Encode(); | 1735 KeyPrefix(database_id, object_store_id + 1).Encode(); |
1264 | 1736 |
1265 DeleteRange(transaction->transaction(), start_key, stop_key); | 1737 DeleteRangeByKeys(transaction->transaction(), start_key, stop_key); |
1266 return true; | 1738 return DeleteBlobsInObjectStore(transaction, database_id, object_store_id); |
1267 } | 1739 } |
1268 | 1740 |
1269 bool IndexedDBBackingStore::DeleteRecord( | 1741 bool IndexedDBBackingStore::DeleteRecord( |
1270 IndexedDBBackingStore::Transaction* transaction, | 1742 IndexedDBBackingStore::Transaction* transaction, |
1271 int64 database_id, | 1743 int64 database_id, |
1272 int64 object_store_id, | 1744 int64 object_store_id, |
1273 const RecordIdentifier& record_identifier) { | 1745 const RecordIdentifier& record_identifier) { |
1274 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); | 1746 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); |
1275 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1747 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
1276 return false; | 1748 return false; |
1277 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 1749 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
1278 | 1750 |
1279 const std::string object_store_data_key = ObjectStoreDataKey::Encode( | 1751 const std::string object_store_data_key = ObjectStoreDataKey::Encode( |
1280 database_id, object_store_id, record_identifier.primary_key()); | 1752 database_id, object_store_id, record_identifier.primary_key()); |
1281 leveldb_transaction->Remove(object_store_data_key); | 1753 leveldb_transaction->Remove(object_store_data_key); |
| 1754 transaction->PutBlobInfo( |
| 1755 database_id, object_store_id, object_store_data_key, NULL, NULL); |
1282 | 1756 |
1283 const std::string exists_entry_key = ExistsEntryKey::Encode( | 1757 const std::string exists_entry_key = ExistsEntryKey::Encode( |
1284 database_id, object_store_id, record_identifier.primary_key()); | 1758 database_id, object_store_id, record_identifier.primary_key()); |
1285 leveldb_transaction->Remove(exists_entry_key); | 1759 leveldb_transaction->Remove(exists_entry_key); |
1286 return true; | 1760 return true; |
1287 } | 1761 } |
1288 | 1762 |
| 1763 bool IndexedDBBackingStore::DeleteRange( |
| 1764 IndexedDBBackingStore::Transaction* transaction, |
| 1765 int64 database_id, |
| 1766 int64 object_store_id, |
| 1767 const IndexedDBKeyRange& key_range) { |
| 1768 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor = |
| 1769 OpenObjectStoreCursor(transaction, |
| 1770 database_id, |
| 1771 object_store_id, |
| 1772 key_range, |
| 1773 indexed_db::CURSOR_NEXT); |
| 1774 // TODO(ericu): This does a PutBlobInfo for every record, even if it doesn't |
| 1775 // have any blobs associated with it. We could skip that, and just scan |
| 1776 // through the blob table to see which ones we need to remove. That might |
| 1777 // take a little more time here, but would also potentially allocate a lot |
| 1778 // fewer BlobChangeRecords, shrink the eventual WriteBatch, and do a lot fewer |
| 1779 // seeks in CollectBlobFilesToRemove. |
| 1780 if (backing_store_cursor) { |
| 1781 do { |
| 1782 if (!DeleteRecord(transaction, |
| 1783 database_id, |
| 1784 object_store_id, |
| 1785 backing_store_cursor->record_identifier())) |
| 1786 return false; |
| 1787 } while (backing_store_cursor->Continue()); |
| 1788 } |
| 1789 return true; |
| 1790 } |
| 1791 |
1289 bool IndexedDBBackingStore::GetKeyGeneratorCurrentNumber( | 1792 bool IndexedDBBackingStore::GetKeyGeneratorCurrentNumber( |
1290 IndexedDBBackingStore::Transaction* transaction, | 1793 IndexedDBBackingStore::Transaction* transaction, |
1291 int64 database_id, | 1794 int64 database_id, |
1292 int64 object_store_id, | 1795 int64 object_store_id, |
1293 int64* key_generator_current_number) { | 1796 int64* key_generator_current_number) { |
1294 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1797 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
1295 return false; | 1798 return false; |
1296 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 1799 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
1297 | 1800 |
1298 const std::string key_generator_current_number_key = | 1801 const std::string key_generator_current_number_key = |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1414 StringPiece slice(data); | 1917 StringPiece slice(data); |
1415 if (!DecodeVarInt(&slice, &version)) | 1918 if (!DecodeVarInt(&slice, &version)) |
1416 return false; | 1919 return false; |
1417 | 1920 |
1418 std::string encoded_key; | 1921 std::string encoded_key; |
1419 EncodeIDBKey(key, &encoded_key); | 1922 EncodeIDBKey(key, &encoded_key); |
1420 found_record_identifier->Reset(encoded_key, version); | 1923 found_record_identifier->Reset(encoded_key, version); |
1421 return true; | 1924 return true; |
1422 } | 1925 } |
1423 | 1926 |
| 1927 class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl |
| 1928 : public IndexedDBBackingStore::Transaction::ChainedBlobWriter { |
| 1929 public: |
| 1930 typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec |
| 1931 WriteDescriptorVec; |
| 1932 ChainedBlobWriterImpl( |
| 1933 int64 database_id, |
| 1934 IndexedDBBackingStore* backingStore, |
| 1935 WriteDescriptorVec& blobs, |
| 1936 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback) |
| 1937 : waiting_for_callback_(false), |
| 1938 database_id_(database_id), |
| 1939 backing_store_(backingStore), |
| 1940 callback_(callback), |
| 1941 aborted_(false) { |
| 1942 blobs_.swap(blobs); |
| 1943 iter_ = blobs_.begin(); |
| 1944 WriteNextFile(); |
| 1945 } |
| 1946 |
| 1947 void set_delegate(scoped_ptr<FileWriterDelegate> delegate) { |
| 1948 delegate_.reset(delegate.release()); |
| 1949 } |
| 1950 |
| 1951 void ReportWriteCompletion(bool succeeded, int64 bytes_written) { |
| 1952 // TODO(ericu): Check bytes_written against the blob's snapshot value. |
| 1953 DCHECK(waiting_for_callback_); |
| 1954 DCHECK(!succeeded || bytes_written >= 0); |
| 1955 waiting_for_callback_ = false; |
| 1956 content::BrowserThread::DeleteSoon( |
| 1957 content::BrowserThread::IO, FROM_HERE, delegate_.release()); |
| 1958 if (aborted_) { |
| 1959 self_ref_ = NULL; |
| 1960 return; |
| 1961 } |
| 1962 if (succeeded) |
| 1963 WriteNextFile(); |
| 1964 else |
| 1965 callback_->didFail(); |
| 1966 } |
| 1967 |
| 1968 void Abort() { |
| 1969 if (!waiting_for_callback_) |
| 1970 return; |
| 1971 self_ref_ = this; |
| 1972 aborted_ = true; |
| 1973 } |
| 1974 |
| 1975 private: |
| 1976 void WriteNextFile() { |
| 1977 DCHECK(!waiting_for_callback_); |
| 1978 DCHECK(!aborted_); |
| 1979 if (iter_ == blobs_.end()) { |
| 1980 DCHECK(!self_ref_); |
| 1981 callback_->didSucceed(); |
| 1982 return; |
| 1983 } else { |
| 1984 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) { |
| 1985 callback_->didFail(); |
| 1986 return; |
| 1987 } |
| 1988 waiting_for_callback_ = true; |
| 1989 ++iter_; |
| 1990 } |
| 1991 } |
| 1992 |
| 1993 bool waiting_for_callback_; |
| 1994 scoped_refptr<ChainedBlobWriterImpl> self_ref_; |
| 1995 WriteDescriptorVec blobs_; |
| 1996 WriteDescriptorVec::const_iterator iter_; |
| 1997 int64 database_id_; |
| 1998 IndexedDBBackingStore* backing_store_; |
| 1999 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_; |
| 2000 scoped_ptr<FileWriterDelegate> delegate_; |
| 2001 bool aborted_; |
| 2002 }; |
| 2003 |
| 2004 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback, |
| 2005 public base::RefCounted<LocalWriteClosure> { |
| 2006 public: |
| 2007 LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter* |
| 2008 chained_blob_writer_, |
| 2009 base::TaskRunner* task_runner) |
| 2010 : chained_blob_writer_(chained_blob_writer_), |
| 2011 task_runner_(task_runner), |
| 2012 bytes_written_(-1) {} |
| 2013 |
| 2014 void Run(base::PlatformFileError rv, |
| 2015 int64 bytes, |
| 2016 FileWriterDelegate::WriteProgressStatus write_status) { |
| 2017 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING) |
| 2018 return; // We don't care about progress events. |
| 2019 if (rv == base::PLATFORM_FILE_OK) { |
| 2020 DCHECK(bytes >= 0); |
| 2021 DCHECK(write_status == FileWriterDelegate::SUCCESS_COMPLETED); |
| 2022 bytes_written_ = bytes; |
| 2023 } else { |
| 2024 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED || |
| 2025 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED); |
| 2026 } |
| 2027 task_runner_->PostTask( |
| 2028 FROM_HERE, |
| 2029 base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner, |
| 2030 this, |
| 2031 write_status == FileWriterDelegate::SUCCESS_COMPLETED)); |
| 2032 } |
| 2033 |
| 2034 void writeBlobToFileOnIOThread(const FilePath& file_path, |
| 2035 const GURL& blob_url, |
| 2036 net::URLRequestContext* request_context) { |
| 2037 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 2038 scoped_ptr<fileapi::FileStreamWriter> writer( |
| 2039 fileapi::FileStreamWriter::CreateForLocalFile( |
| 2040 task_runner_, file_path, 0, fileapi::FileStreamWriter::CREATE_NEW)); |
| 2041 scoped_ptr<FileWriterDelegate> delegate( |
| 2042 new FileWriterDelegate(writer.Pass())); |
| 2043 |
| 2044 DCHECK(blob_url.is_valid()); |
| 2045 scoped_ptr<net::URLRequest> blob_request(request_context->CreateRequest( |
| 2046 blob_url, net::DEFAULT_PRIORITY, delegate.get())); |
| 2047 |
| 2048 delegate->Start(blob_request.Pass(), |
| 2049 base::Bind(&LocalWriteClosure::Run, this)); |
| 2050 chained_blob_writer_->set_delegate(delegate.Pass()); |
| 2051 } |
| 2052 |
| 2053 private: |
| 2054 void callBlobCallbackOnIDBTaskRunner(bool succeeded) { |
| 2055 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 2056 chained_blob_writer_->ReportWriteCompletion(succeeded, bytes_written_); |
| 2057 } |
| 2058 |
| 2059 IndexedDBBackingStore::Transaction::ChainedBlobWriter* chained_blob_writer_; |
| 2060 base::TaskRunner* task_runner_; |
| 2061 int64 bytes_written_; |
| 2062 }; |
| 2063 |
| 2064 bool IndexedDBBackingStore::WriteBlobFile( |
| 2065 int64 database_id, |
| 2066 const Transaction::WriteDescriptor& descriptor, |
| 2067 Transaction::ChainedBlobWriter* chained_blob_writer) { |
| 2068 |
| 2069 if (!MakeIDBBlobDirectory(blob_path_, database_id, descriptor.key())) |
| 2070 return false; |
| 2071 |
| 2072 FilePath path = GetBlobFileName(database_id, descriptor.key()); |
| 2073 |
| 2074 if (descriptor.is_file()) { |
| 2075 DCHECK(!descriptor.file_path().empty()); |
| 2076 if (!base::CopyFile(descriptor.file_path(), path)) |
| 2077 return false; |
| 2078 |
| 2079 base::PlatformFileInfo info; |
| 2080 if (file_util::GetFileInfo(descriptor.file_path(), &info)) { |
| 2081 // TODO(ericu): Validate the snapshot date here. Expand WriteDescriptor |
| 2082 // to include snapshot date and file size, and check both. |
| 2083 if (!file_util::TouchFile(path, info.last_accessed, info.last_modified)) |
| 2084 ; // TODO(ericu): Complain quietly; timestamp's probably not vital. |
| 2085 } else { |
| 2086 ; // TODO(ericu): Complain quietly; timestamp's probably not vital. |
| 2087 } |
| 2088 |
| 2089 task_runner_->PostTask( |
| 2090 FROM_HERE, |
| 2091 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion, |
| 2092 chained_blob_writer, |
| 2093 true, |
| 2094 info.size)); |
| 2095 } else { |
| 2096 DCHECK(descriptor.url().is_valid()); |
| 2097 scoped_refptr<LocalWriteClosure> write_closure( |
| 2098 new LocalWriteClosure(chained_blob_writer, task_runner_)); |
| 2099 content::BrowserThread::PostTask( |
| 2100 content::BrowserThread::IO, |
| 2101 FROM_HERE, |
| 2102 base::Bind(&LocalWriteClosure::writeBlobToFileOnIOThread, |
| 2103 write_closure.get(), |
| 2104 path, |
| 2105 descriptor.url(), |
| 2106 request_context_)); |
| 2107 } |
| 2108 return true; |
| 2109 } |
| 2110 |
| 2111 void IndexedDBBackingStore::ReportBlobUnused(int64 database_id, |
| 2112 int64 blob_key) { |
| 2113 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); |
| 2114 bool all_blobs = blob_key == DatabaseMetaDataKey::kAllBlobsKey; |
| 2115 DCHECK(all_blobs || DatabaseMetaDataKey::IsValidBlobKey(blob_key)); |
| 2116 scoped_refptr<LevelDBTransaction> transaction = |
| 2117 new LevelDBTransaction(db_.get()); |
| 2118 |
| 2119 std::string live_blob_key = LiveBlobJournalKey::Encode(); |
| 2120 IndexedDBBackingStore::Transaction::BlobJournalType live_blob_journal; |
| 2121 if (!GetBlobJournal(live_blob_key, transaction.get(), &live_blob_journal)) |
| 2122 return; |
| 2123 DCHECK(live_blob_journal.size()); |
| 2124 |
| 2125 std::string primary_key = BlobJournalKey::Encode(); |
| 2126 IndexedDBBackingStore::Transaction::BlobJournalType primary_journal; |
| 2127 if (!GetBlobJournal(primary_key, transaction.get(), &primary_journal)) |
| 2128 return; |
| 2129 |
| 2130 IndexedDBBackingStore::Transaction::BlobJournalType::iterator journal_iter; |
| 2131 // There are several cases to handle. If blob_key is kAllBlobsKey, we want to |
| 2132 // remove all entries with database_id from the live_blob journal and add only |
| 2133 // kAllBlobsKey to the primary journal. Otherwise if IsValidBlobKey(blob_key) |
| 2134 // and we hit kAllBlobsKey for the right database_id in the journal, we leave |
| 2135 // the kAllBlobsKey entry in the live_blob journal but add the specific blob |
| 2136 // to the primary. Otherwise if IsValidBlobKey(blob_key) and we find a |
| 2137 // matching (database_id, blob_key) tuple, we should move it to the primary |
| 2138 // journal. |
| 2139 IndexedDBBackingStore::Transaction::BlobJournalType new_live_blob_journal; |
| 2140 for (journal_iter = live_blob_journal.begin(); |
| 2141 journal_iter != live_blob_journal.end(); |
| 2142 ++journal_iter) { |
| 2143 int64 current_database_id = journal_iter->first; |
| 2144 int64 current_blob_key = journal_iter->second; |
| 2145 bool current_all_blobs = |
| 2146 current_blob_key == DatabaseMetaDataKey::kAllBlobsKey; |
| 2147 DCHECK(KeyPrefix::IsValidDatabaseId(current_database_id) || |
| 2148 current_all_blobs); |
| 2149 if (current_database_id == database_id && |
| 2150 (all_blobs || current_all_blobs || blob_key == current_blob_key)) { |
| 2151 if (!all_blobs) { |
| 2152 primary_journal.push_back( |
| 2153 std::make_pair(database_id, current_blob_key)); |
| 2154 if (current_all_blobs) |
| 2155 new_live_blob_journal.push_back(*journal_iter); |
| 2156 new_live_blob_journal.insert(new_live_blob_journal.end(), |
| 2157 ++journal_iter, |
| 2158 live_blob_journal.end()); // All the rest. |
| 2159 break; |
| 2160 } |
| 2161 } else { |
| 2162 new_live_blob_journal.push_back(*journal_iter); |
| 2163 } |
| 2164 } |
| 2165 if (all_blobs) { |
| 2166 primary_journal.push_back( |
| 2167 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey)); |
| 2168 } |
| 2169 UpdatePrimaryJournalWithBlobList(transaction.get(), primary_journal); |
| 2170 UpdateLiveBlobJournalWithBlobList(transaction.get(), new_live_blob_journal); |
| 2171 transaction->Commit(); |
| 2172 // We could just do the deletions/cleaning here, but if there are a lot of |
| 2173 // blobs about to be garbage collected, it'd be better to wait and do them all |
| 2174 // at once. |
| 2175 StartJournalCleaningTimer(); |
| 2176 } |
| 2177 |
| 2178 void IndexedDBBackingStore::StartJournalCleaningTimer() { |
| 2179 journal_cleaning_timer_.Start( |
| 2180 FROM_HERE, |
| 2181 base::TimeDelta::FromSeconds(5), |
| 2182 this, |
| 2183 &IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn); |
| 2184 } |
| 2185 |
| 2186 // This assumes a file path of dbId/3rd-byte-of-counter/counter. |
| 2187 FilePath IndexedDBBackingStore::GetBlobFileName(int64 database_id, |
| 2188 int64 key) { |
| 2189 FilePath path = GetBlobDirectoryNameForKey(blob_path_, database_id, key); |
| 2190 path = path.AppendASCII(base::StringPrintf("%lx", key)); |
| 2191 return path; |
| 2192 } |
| 2193 |
1424 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, | 2194 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, |
1425 const std::string& stop_key, | 2195 const std::string& stop_key, |
1426 int64 index_id, | 2196 int64 index_id, |
1427 unsigned char meta_data_type) { | 2197 unsigned char meta_data_type) { |
1428 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) | 2198 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) |
1429 return false; | 2199 return false; |
1430 | 2200 |
1431 StringPiece slice(it->Key()); | 2201 StringPiece slice(it->Key()); |
1432 IndexMetaDataKey meta_data_key; | 2202 IndexMetaDataKey meta_data_key; |
1433 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); | 2203 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1516 | 2286 |
1517 it->Next(); | 2287 it->Next(); |
1518 } | 2288 } |
1519 | 2289 |
1520 (*indexes)[index_id] = IndexedDBIndexMetadata( | 2290 (*indexes)[index_id] = IndexedDBIndexMetadata( |
1521 index_name, index_id, key_path, index_unique, index_multi_entry); | 2291 index_name, index_id, key_path, index_unique, index_multi_entry); |
1522 } | 2292 } |
1523 return true; | 2293 return true; |
1524 } | 2294 } |
1525 | 2295 |
| 2296 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) { |
| 2297 FilePath fileName = GetBlobFileName(database_id, key); |
| 2298 return base::DeleteFile(fileName, false); |
| 2299 } |
| 2300 |
| 2301 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) { |
| 2302 FilePath dirName = GetBlobDirectoryName(blob_path_, database_id); |
| 2303 return base::DeleteFile(dirName, true); |
| 2304 } |
| 2305 |
| 2306 bool IndexedDBBackingStore::CleanUpBlobJournal( |
| 2307 const std::string& level_db_key) { |
| 2308 scoped_refptr<LevelDBTransaction> journal_transaction = |
| 2309 new LevelDBTransaction(db_.get()); |
| 2310 IndexedDBBackingStore::Transaction::BlobJournalType journal; |
| 2311 if (!GetBlobJournal(level_db_key, journal_transaction.get(), &journal)) |
| 2312 return false; |
| 2313 if (!journal.size()) |
| 2314 return true; |
| 2315 IndexedDBBackingStore::Transaction::BlobJournalType::iterator journal_iter; |
| 2316 for (journal_iter = journal.begin(); journal_iter != journal.end(); |
| 2317 ++journal_iter) { |
| 2318 int64 database_id = journal_iter->first; |
| 2319 int64 blob_key = journal_iter->second; |
| 2320 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); |
| 2321 if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) { |
| 2322 RemoveBlobDirectory(database_id); |
| 2323 } else { |
| 2324 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key)); |
| 2325 RemoveBlobFile(database_id, blob_key); |
| 2326 } |
| 2327 } |
| 2328 ClearBlobJournal(journal_transaction.get(), level_db_key); |
| 2329 return journal_transaction->Commit(); |
| 2330 } |
| 2331 |
| 2332 void IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn() { |
| 2333 CleanUpBlobJournal(BlobJournalKey::Encode()); |
| 2334 } |
| 2335 |
1526 WARN_UNUSED_RESULT static bool SetMaxIndexId(LevelDBTransaction* transaction, | 2336 WARN_UNUSED_RESULT static bool SetMaxIndexId(LevelDBTransaction* transaction, |
1527 int64 database_id, | 2337 int64 database_id, |
1528 int64 object_store_id, | 2338 int64 object_store_id, |
1529 int64 index_id) { | 2339 int64 index_id) { |
1530 int64 max_index_id = -1; | 2340 int64 max_index_id = -1; |
1531 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( | 2341 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( |
1532 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); | 2342 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); |
1533 bool found = false; | 2343 bool found = false; |
1534 bool ok = GetInt(transaction, max_index_id_key, &max_index_id, &found); | 2344 bool ok = GetInt(transaction, max_index_id_key, &max_index_id, &found); |
1535 if (!ok) { | 2345 if (!ok) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1588 int64 index_id) { | 2398 int64 index_id) { |
1589 IDB_TRACE("IndexedDBBackingStore::DeleteIndex"); | 2399 IDB_TRACE("IndexedDBBackingStore::DeleteIndex"); |
1590 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) | 2400 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) |
1591 return false; | 2401 return false; |
1592 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 2402 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
1593 | 2403 |
1594 const std::string index_meta_data_start = | 2404 const std::string index_meta_data_start = |
1595 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0); | 2405 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0); |
1596 const std::string index_meta_data_end = | 2406 const std::string index_meta_data_end = |
1597 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id); | 2407 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id); |
1598 DeleteRange(leveldb_transaction, index_meta_data_start, index_meta_data_end); | 2408 DeleteRangeByKeys( |
| 2409 leveldb_transaction, index_meta_data_start, index_meta_data_end); |
1599 | 2410 |
1600 const std::string index_data_start = | 2411 const std::string index_data_start = |
1601 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); | 2412 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); |
1602 const std::string index_data_end = | 2413 const std::string index_data_end = |
1603 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); | 2414 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); |
1604 DeleteRange(leveldb_transaction, index_data_start, index_data_end); | 2415 DeleteRangeByKeys(leveldb_transaction, index_data_start, index_data_end); |
1605 return true; | 2416 return true; |
1606 } | 2417 } |
1607 | 2418 |
1608 bool IndexedDBBackingStore::PutIndexDataForRecord( | 2419 bool IndexedDBBackingStore::PutIndexDataForRecord( |
1609 IndexedDBBackingStore::Transaction* transaction, | 2420 IndexedDBBackingStore::Transaction* transaction, |
1610 int64 database_id, | 2421 int64 database_id, |
1611 int64 object_store_id, | 2422 int64 object_store_id, |
1612 int64 index_id, | 2423 int64 index_id, |
1613 const IndexedDBKey& key, | 2424 const IndexedDBKey& key, |
1614 const RecordIdentifier& record_identifier) { | 2425 const RecordIdentifier& record_identifier) { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1811 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); | 2622 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); |
1812 return false; | 2623 return false; |
1813 } | 2624 } |
1814 | 2625 |
1815 StringPiece slice(found_encoded_primary_key); | 2626 StringPiece slice(found_encoded_primary_key); |
1816 return DecodeIDBKey(&slice, found_primary_key) && slice.empty(); | 2627 return DecodeIDBKey(&slice, found_primary_key) && slice.empty(); |
1817 } | 2628 } |
1818 | 2629 |
1819 IndexedDBBackingStore::Cursor::Cursor( | 2630 IndexedDBBackingStore::Cursor::Cursor( |
1820 const IndexedDBBackingStore::Cursor* other) | 2631 const IndexedDBBackingStore::Cursor* other) |
1821 : transaction_(other->transaction_), | 2632 : backing_store_(other->backing_store_), |
| 2633 transaction_(other->transaction_), |
| 2634 database_id_(other->database_id_), |
1822 cursor_options_(other->cursor_options_), | 2635 cursor_options_(other->cursor_options_), |
1823 current_key_(new IndexedDBKey(*other->current_key_)) { | 2636 current_key_(new IndexedDBKey(*other->current_key_)) { |
1824 if (other->iterator_) { | 2637 if (other->iterator_) { |
1825 iterator_ = transaction_->CreateIterator(); | 2638 iterator_ = transaction_->CreateIterator(); |
1826 | 2639 |
1827 if (other->iterator_->IsValid()) { | 2640 if (other->iterator_->IsValid()) { |
1828 iterator_->Seek(other->iterator_->Key()); | 2641 iterator_->Seek(other->iterator_->Key()); |
1829 DCHECK(iterator_->IsValid()); | 2642 DCHECK(iterator_->IsValid()); |
1830 } | 2643 } |
1831 } | 2644 } |
1832 } | 2645 } |
1833 | 2646 |
1834 IndexedDBBackingStore::Cursor::Cursor(LevelDBTransaction* transaction, | 2647 IndexedDBBackingStore::Cursor::Cursor( |
1835 const CursorOptions& cursor_options) | 2648 scoped_refptr<IndexedDBBackingStore> backing_store, |
1836 : transaction_(transaction), cursor_options_(cursor_options) {} | 2649 LevelDBTransaction* transaction, |
| 2650 int64 database_id, |
| 2651 const CursorOptions& cursor_options) |
| 2652 : backing_store_(backing_store), |
| 2653 transaction_(transaction), |
| 2654 database_id_(database_id), |
| 2655 cursor_options_(cursor_options) {} |
1837 IndexedDBBackingStore::Cursor::~Cursor() {} | 2656 IndexedDBBackingStore::Cursor::~Cursor() {} |
1838 | 2657 |
1839 bool IndexedDBBackingStore::Cursor::FirstSeek() { | 2658 bool IndexedDBBackingStore::Cursor::FirstSeek() { |
1840 iterator_ = transaction_->CreateIterator(); | 2659 iterator_ = transaction_->CreateIterator(); |
1841 if (cursor_options_.forward) | 2660 if (cursor_options_.forward) |
1842 iterator_->Seek(cursor_options_.low_key); | 2661 iterator_->Seek(cursor_options_.low_key); |
1843 else | 2662 else |
1844 iterator_->Seek(cursor_options_.high_key); | 2663 iterator_->Seek(cursor_options_.high_key); |
1845 | 2664 |
1846 return Continue(0, READY); | 2665 return Continue(0, READY); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2006 } | 2825 } |
2007 | 2826 |
2008 const IndexedDBBackingStore::RecordIdentifier& | 2827 const IndexedDBBackingStore::RecordIdentifier& |
2009 IndexedDBBackingStore::Cursor::record_identifier() const { | 2828 IndexedDBBackingStore::Cursor::record_identifier() const { |
2010 return record_identifier_; | 2829 return record_identifier_; |
2011 } | 2830 } |
2012 | 2831 |
2013 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor { | 2832 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor { |
2014 public: | 2833 public: |
2015 ObjectStoreKeyCursorImpl( | 2834 ObjectStoreKeyCursorImpl( |
| 2835 scoped_refptr<IndexedDBBackingStore> backing_store, |
2016 LevelDBTransaction* transaction, | 2836 LevelDBTransaction* transaction, |
| 2837 int64 database_id, |
2017 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) | 2838 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) |
2018 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} | 2839 : IndexedDBBackingStore::Cursor(backing_store, |
| 2840 transaction, |
| 2841 database_id, |
| 2842 cursor_options) {} |
2019 | 2843 |
2020 virtual Cursor* Clone() OVERRIDE { | 2844 virtual Cursor* Clone() OVERRIDE { |
2021 return new ObjectStoreKeyCursorImpl(this); | 2845 return new ObjectStoreKeyCursorImpl(this); |
2022 } | 2846 } |
2023 | 2847 |
2024 // IndexedDBBackingStore::Cursor | 2848 // IndexedDBBackingStore::Cursor |
2025 virtual std::string* Value() OVERRIDE { | 2849 virtual IndexedDBValue* Value() OVERRIDE { |
2026 NOTREACHED(); | 2850 NOTREACHED(); |
2027 return NULL; | 2851 return NULL; |
2028 } | 2852 } |
2029 virtual bool LoadCurrentRow() OVERRIDE; | 2853 virtual bool LoadCurrentRow() OVERRIDE; |
2030 | 2854 |
2031 protected: | 2855 protected: |
2032 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { | 2856 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { |
2033 return ObjectStoreDataKey::Encode( | 2857 return ObjectStoreDataKey::Encode( |
2034 cursor_options_.database_id, cursor_options_.object_store_id, key); | 2858 cursor_options_.database_id, cursor_options_.object_store_id, key); |
2035 } | 2859 } |
(...skipping 29 matching lines...) Expand all Loading... |
2065 std::string encoded_key; | 2889 std::string encoded_key; |
2066 EncodeIDBKey(*current_key_, &encoded_key); | 2890 EncodeIDBKey(*current_key_, &encoded_key); |
2067 record_identifier_.Reset(encoded_key, version); | 2891 record_identifier_.Reset(encoded_key, version); |
2068 | 2892 |
2069 return true; | 2893 return true; |
2070 } | 2894 } |
2071 | 2895 |
2072 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { | 2896 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { |
2073 public: | 2897 public: |
2074 ObjectStoreCursorImpl( | 2898 ObjectStoreCursorImpl( |
| 2899 scoped_refptr<IndexedDBBackingStore> backing_store, |
2075 LevelDBTransaction* transaction, | 2900 LevelDBTransaction* transaction, |
| 2901 int64 database_id, |
2076 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) | 2902 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) |
2077 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} | 2903 : IndexedDBBackingStore::Cursor(backing_store, |
| 2904 transaction, |
| 2905 database_id, |
| 2906 cursor_options) {} |
2078 | 2907 |
2079 virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); } | 2908 virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); } |
2080 | 2909 |
2081 // IndexedDBBackingStore::Cursor | 2910 // IndexedDBBackingStore::Cursor |
2082 virtual std::string* Value() OVERRIDE { return ¤t_value_; } | 2911 virtual IndexedDBValue* Value() OVERRIDE { return ¤t_value_; } |
2083 virtual bool LoadCurrentRow() OVERRIDE; | 2912 virtual bool LoadCurrentRow() OVERRIDE; |
2084 | 2913 |
2085 protected: | 2914 protected: |
2086 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { | 2915 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { |
2087 return ObjectStoreDataKey::Encode( | 2916 return ObjectStoreDataKey::Encode( |
2088 cursor_options_.database_id, cursor_options_.object_store_id, key); | 2917 cursor_options_.database_id, cursor_options_.object_store_id, key); |
2089 } | 2918 } |
2090 virtual std::string EncodeKey(const IndexedDBKey& key, | 2919 virtual std::string EncodeKey(const IndexedDBKey& key, |
2091 const IndexedDBKey& primary_key) OVERRIDE { | 2920 const IndexedDBKey& primary_key) OVERRIDE { |
2092 NOTREACHED(); | 2921 NOTREACHED(); |
2093 return std::string(); | 2922 return std::string(); |
2094 } | 2923 } |
2095 | 2924 |
2096 private: | 2925 private: |
2097 explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other) | 2926 explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other) |
2098 : IndexedDBBackingStore::Cursor(other), | 2927 : IndexedDBBackingStore::Cursor(other), |
2099 current_value_(other->current_value_) {} | 2928 current_value_(other->current_value_) {} |
2100 | 2929 |
2101 std::string current_value_; | 2930 IndexedDBValue current_value_; |
2102 }; | 2931 }; |
2103 | 2932 |
2104 bool ObjectStoreCursorImpl::LoadCurrentRow() { | 2933 bool ObjectStoreCursorImpl::LoadCurrentRow() { |
2105 StringPiece slice(iterator_->Key()); | 2934 StringPiece key_slice(iterator_->Key()); |
2106 ObjectStoreDataKey object_store_data_key; | 2935 ObjectStoreDataKey object_store_data_key; |
2107 if (!ObjectStoreDataKey::Decode(&slice, &object_store_data_key)) { | 2936 if (!ObjectStoreDataKey::Decode(&key_slice, &object_store_data_key)) { |
2108 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2937 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
2109 return false; | 2938 return false; |
2110 } | 2939 } |
2111 | 2940 |
2112 current_key_ = object_store_data_key.user_key(); | 2941 current_key_ = object_store_data_key.user_key(); |
2113 | 2942 |
2114 int64 version; | 2943 int64 version; |
2115 slice = StringPiece(iterator_->Value()); | 2944 StringPiece value_slice = StringPiece(iterator_->Value()); |
2116 if (!DecodeVarInt(&slice, &version)) { | 2945 if (!DecodeVarInt(&value_slice, &version)) { |
2117 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2946 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
2118 return false; | 2947 return false; |
2119 } | 2948 } |
2120 | 2949 |
2121 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. | 2950 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. |
2122 std::string encoded_key; | 2951 std::string encoded_key; |
2123 EncodeIDBKey(*current_key_, &encoded_key); | 2952 EncodeIDBKey(*current_key_, &encoded_key); |
2124 record_identifier_.Reset(encoded_key, version); | 2953 record_identifier_.Reset(encoded_key, version); |
2125 | 2954 |
2126 current_value_ = slice.as_string(); | 2955 if (!GetBlobInfoForRecord(backing_store_, |
| 2956 transaction_, |
| 2957 database_id_, |
| 2958 iterator_->Key().as_string(), |
| 2959 ¤t_value_)) { |
| 2960 return false; |
| 2961 } |
| 2962 current_value_.bits = value_slice.as_string(); |
2127 return true; | 2963 return true; |
2128 } | 2964 } |
2129 | 2965 |
2130 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { | 2966 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { |
2131 public: | 2967 public: |
2132 IndexKeyCursorImpl( | 2968 IndexKeyCursorImpl( |
| 2969 scoped_refptr<IndexedDBBackingStore> backing_store, |
2133 LevelDBTransaction* transaction, | 2970 LevelDBTransaction* transaction, |
| 2971 int64 database_id, |
2134 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) | 2972 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) |
2135 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} | 2973 : IndexedDBBackingStore::Cursor(backing_store, |
| 2974 transaction, |
| 2975 database_id, |
| 2976 cursor_options) {} |
2136 | 2977 |
2137 virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); } | 2978 virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); } |
2138 | 2979 |
2139 // IndexedDBBackingStore::Cursor | 2980 // IndexedDBBackingStore::Cursor |
2140 virtual std::string* Value() OVERRIDE { | 2981 virtual IndexedDBValue* Value() OVERRIDE { |
2141 NOTREACHED(); | 2982 NOTREACHED(); |
2142 return NULL; | 2983 return NULL; |
2143 } | 2984 } |
2144 virtual const IndexedDBKey& primary_key() const OVERRIDE { | 2985 virtual const IndexedDBKey& primary_key() const OVERRIDE { |
2145 return *primary_key_; | 2986 return *primary_key_; |
2146 } | 2987 } |
2147 virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier() | 2988 virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier() |
2148 const { | 2989 const OVERRIDE { |
2149 NOTREACHED(); | 2990 NOTREACHED(); |
2150 return record_identifier_; | 2991 return record_identifier_; |
2151 } | 2992 } |
2152 virtual bool LoadCurrentRow() OVERRIDE; | 2993 virtual bool LoadCurrentRow() OVERRIDE; |
2153 | 2994 |
2154 protected: | 2995 protected: |
2155 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { | 2996 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { |
2156 return IndexDataKey::Encode(cursor_options_.database_id, | 2997 return IndexDataKey::Encode(cursor_options_.database_id, |
2157 cursor_options_.object_store_id, | 2998 cursor_options_.object_store_id, |
2158 cursor_options_.index_id, | 2999 cursor_options_.index_id, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2230 transaction_->Remove(iterator_->Key()); | 3071 transaction_->Remove(iterator_->Key()); |
2231 return false; | 3072 return false; |
2232 } | 3073 } |
2233 | 3074 |
2234 return true; | 3075 return true; |
2235 } | 3076 } |
2236 | 3077 |
2237 class IndexCursorImpl : public IndexedDBBackingStore::Cursor { | 3078 class IndexCursorImpl : public IndexedDBBackingStore::Cursor { |
2238 public: | 3079 public: |
2239 IndexCursorImpl( | 3080 IndexCursorImpl( |
| 3081 scoped_refptr<IndexedDBBackingStore> backing_store, |
2240 LevelDBTransaction* transaction, | 3082 LevelDBTransaction* transaction, |
| 3083 int64 database_id, |
2241 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) | 3084 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) |
2242 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} | 3085 : IndexedDBBackingStore::Cursor(backing_store, |
| 3086 transaction, |
| 3087 database_id, |
| 3088 cursor_options) {} |
2243 | 3089 |
2244 virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); } | 3090 virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); } |
2245 | 3091 |
2246 // IndexedDBBackingStore::Cursor | 3092 // IndexedDBBackingStore::Cursor |
2247 virtual std::string* Value() OVERRIDE { return ¤t_value_; } | 3093 virtual IndexedDBValue* Value() OVERRIDE { return ¤t_value_; } |
2248 virtual const IndexedDBKey& primary_key() const OVERRIDE { | 3094 virtual const IndexedDBKey& primary_key() const OVERRIDE { |
2249 return *primary_key_; | 3095 return *primary_key_; |
2250 } | 3096 } |
2251 virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier() | 3097 virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier() |
2252 const { | 3098 const OVERRIDE { |
2253 NOTREACHED(); | 3099 NOTREACHED(); |
2254 return record_identifier_; | 3100 return record_identifier_; |
2255 } | 3101 } |
2256 virtual bool LoadCurrentRow() OVERRIDE; | 3102 virtual bool LoadCurrentRow() OVERRIDE; |
2257 | 3103 |
2258 protected: | 3104 protected: |
2259 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { | 3105 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { |
2260 return IndexDataKey::Encode(cursor_options_.database_id, | 3106 return IndexDataKey::Encode(cursor_options_.database_id, |
2261 cursor_options_.object_store_id, | 3107 cursor_options_.object_store_id, |
2262 cursor_options_.index_id, | 3108 cursor_options_.index_id, |
2263 key); | 3109 key); |
2264 } | 3110 } |
2265 virtual std::string EncodeKey(const IndexedDBKey& key, | 3111 virtual std::string EncodeKey(const IndexedDBKey& key, |
2266 const IndexedDBKey& primary_key) OVERRIDE { | 3112 const IndexedDBKey& primary_key) OVERRIDE { |
2267 return IndexDataKey::Encode(cursor_options_.database_id, | 3113 return IndexDataKey::Encode(cursor_options_.database_id, |
2268 cursor_options_.object_store_id, | 3114 cursor_options_.object_store_id, |
2269 cursor_options_.index_id, | 3115 cursor_options_.index_id, |
2270 key, | 3116 key, |
2271 primary_key); | 3117 primary_key); |
2272 } | 3118 } |
2273 | 3119 |
2274 private: | 3120 private: |
2275 explicit IndexCursorImpl(const IndexCursorImpl* other) | 3121 explicit IndexCursorImpl(const IndexCursorImpl* other) |
2276 : IndexedDBBackingStore::Cursor(other), | 3122 : IndexedDBBackingStore::Cursor(other), |
2277 primary_key_(new IndexedDBKey(*other->primary_key_)), | 3123 primary_key_(new IndexedDBKey(*other->primary_key_)), |
2278 current_value_(other->current_value_), | 3124 current_value_(other->current_value_), |
2279 primary_leveldb_key_(other->primary_leveldb_key_) {} | 3125 primary_leveldb_key_(other->primary_leveldb_key_) {} |
2280 | 3126 |
2281 scoped_ptr<IndexedDBKey> primary_key_; | 3127 scoped_ptr<IndexedDBKey> primary_key_; |
2282 std::string current_value_; | 3128 IndexedDBValue current_value_; |
2283 std::string primary_leveldb_key_; | 3129 std::string primary_leveldb_key_; |
2284 }; | 3130 }; |
2285 | 3131 |
2286 bool IndexCursorImpl::LoadCurrentRow() { | 3132 bool IndexCursorImpl::LoadCurrentRow() { |
2287 StringPiece slice(iterator_->Key()); | 3133 StringPiece slice(iterator_->Key()); |
2288 IndexDataKey index_data_key; | 3134 IndexDataKey index_data_key; |
2289 if (!IndexDataKey::Decode(&slice, &index_data_key)) { | 3135 if (!IndexDataKey::Decode(&slice, &index_data_key)) { |
2290 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 3136 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
2291 return false; | 3137 return false; |
2292 } | 3138 } |
2293 | 3139 |
2294 current_key_ = index_data_key.user_key(); | 3140 current_key_ = index_data_key.user_key(); |
2295 DCHECK(current_key_); | 3141 DCHECK(current_key_); |
2296 | 3142 |
2297 slice = StringPiece(iterator_->Value()); | 3143 slice = StringPiece(iterator_->Value()); |
2298 int64 index_data_version; | 3144 int64 index_data_version; |
2299 if (!DecodeVarInt(&slice, &index_data_version)) { | 3145 if (!DecodeVarInt(&slice, &index_data_version)) { |
2300 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 3146 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
2301 return false; | 3147 return false; |
2302 } | 3148 } |
2303 if (!DecodeIDBKey(&slice, &primary_key_)) { | 3149 if (!DecodeIDBKey(&slice, &primary_key_)) { |
2304 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 3150 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
2305 return false; | 3151 return false; |
2306 } | 3152 } |
2307 | 3153 |
| 3154 DCHECK_EQ(index_data_key.DatabaseId(), database_id_); |
2308 primary_leveldb_key_ = | 3155 primary_leveldb_key_ = |
2309 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), | 3156 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), |
2310 index_data_key.ObjectStoreId(), | 3157 index_data_key.ObjectStoreId(), |
2311 *primary_key_); | 3158 *primary_key_); |
2312 | 3159 |
2313 std::string result; | 3160 std::string result; |
2314 bool found = false; | 3161 bool found = false; |
2315 bool ok = transaction_->Get(primary_leveldb_key_, &result, &found); | 3162 bool ok = transaction_->Get(primary_leveldb_key_, &result, &found); |
2316 if (!ok) { | 3163 if (!ok) { |
2317 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 3164 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
(...skipping 13 matching lines...) Expand all Loading... |
2331 if (!DecodeVarInt(&slice, &object_store_data_version)) { | 3178 if (!DecodeVarInt(&slice, &object_store_data_version)) { |
2332 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 3179 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
2333 return false; | 3180 return false; |
2334 } | 3181 } |
2335 | 3182 |
2336 if (object_store_data_version != index_data_version) { | 3183 if (object_store_data_version != index_data_version) { |
2337 transaction_->Remove(iterator_->Key()); | 3184 transaction_->Remove(iterator_->Key()); |
2338 return false; | 3185 return false; |
2339 } | 3186 } |
2340 | 3187 |
2341 current_value_ = slice.as_string(); | 3188 current_value_.bits = slice.as_string(); |
2342 return true; | 3189 return GetBlobInfoForRecord(backing_store_, |
| 3190 transaction_, |
| 3191 database_id_, |
| 3192 primary_leveldb_key_, |
| 3193 ¤t_value_); |
2343 } | 3194 } |
2344 | 3195 |
2345 bool ObjectStoreCursorOptions( | 3196 bool ObjectStoreCursorOptions( |
2346 LevelDBTransaction* transaction, | 3197 LevelDBTransaction* transaction, |
2347 int64 database_id, | 3198 int64 database_id, |
2348 int64 object_store_id, | 3199 int64 object_store_id, |
2349 const IndexedDBKeyRange& range, | 3200 const IndexedDBKeyRange& range, |
2350 indexed_db::CursorDirection direction, | 3201 indexed_db::CursorDirection direction, |
2351 IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) { | 3202 IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) { |
2352 cursor_options->database_id = database_id; | 3203 cursor_options->database_id = database_id; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2488 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreCursor"); | 3339 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreCursor"); |
2489 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 3340 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
2490 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; | 3341 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; |
2491 if (!ObjectStoreCursorOptions(leveldb_transaction, | 3342 if (!ObjectStoreCursorOptions(leveldb_transaction, |
2492 database_id, | 3343 database_id, |
2493 object_store_id, | 3344 object_store_id, |
2494 range, | 3345 range, |
2495 direction, | 3346 direction, |
2496 &cursor_options)) | 3347 &cursor_options)) |
2497 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 3348 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
2498 scoped_ptr<ObjectStoreCursorImpl> cursor( | 3349 scoped_ptr<ObjectStoreCursorImpl> cursor(new ObjectStoreCursorImpl( |
2499 new ObjectStoreCursorImpl(leveldb_transaction, cursor_options)); | 3350 this, leveldb_transaction, database_id, cursor_options)); |
2500 if (!cursor->FirstSeek()) | 3351 if (!cursor->FirstSeek()) |
2501 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 3352 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
2502 | 3353 |
2503 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); | 3354 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); |
2504 } | 3355 } |
2505 | 3356 |
2506 scoped_ptr<IndexedDBBackingStore::Cursor> | 3357 scoped_ptr<IndexedDBBackingStore::Cursor> |
2507 IndexedDBBackingStore::OpenObjectStoreKeyCursor( | 3358 IndexedDBBackingStore::OpenObjectStoreKeyCursor( |
2508 IndexedDBBackingStore::Transaction* transaction, | 3359 IndexedDBBackingStore::Transaction* transaction, |
2509 int64 database_id, | 3360 int64 database_id, |
2510 int64 object_store_id, | 3361 int64 object_store_id, |
2511 const IndexedDBKeyRange& range, | 3362 const IndexedDBKeyRange& range, |
2512 indexed_db::CursorDirection direction) { | 3363 indexed_db::CursorDirection direction) { |
2513 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor"); | 3364 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor"); |
2514 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 3365 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
2515 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; | 3366 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; |
2516 if (!ObjectStoreCursorOptions(leveldb_transaction, | 3367 if (!ObjectStoreCursorOptions(leveldb_transaction, |
2517 database_id, | 3368 database_id, |
2518 object_store_id, | 3369 object_store_id, |
2519 range, | 3370 range, |
2520 direction, | 3371 direction, |
2521 &cursor_options)) | 3372 &cursor_options)) |
2522 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 3373 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
2523 scoped_ptr<ObjectStoreKeyCursorImpl> cursor( | 3374 scoped_ptr<ObjectStoreKeyCursorImpl> cursor(new ObjectStoreKeyCursorImpl( |
2524 new ObjectStoreKeyCursorImpl(leveldb_transaction, cursor_options)); | 3375 this, leveldb_transaction, database_id, cursor_options)); |
2525 if (!cursor->FirstSeek()) | 3376 if (!cursor->FirstSeek()) |
2526 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 3377 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
2527 | 3378 |
2528 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); | 3379 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); |
2529 } | 3380 } |
2530 | 3381 |
2531 scoped_ptr<IndexedDBBackingStore::Cursor> | 3382 scoped_ptr<IndexedDBBackingStore::Cursor> |
2532 IndexedDBBackingStore::OpenIndexKeyCursor( | 3383 IndexedDBBackingStore::OpenIndexKeyCursor( |
2533 IndexedDBBackingStore::Transaction* transaction, | 3384 IndexedDBBackingStore::Transaction* transaction, |
2534 int64 database_id, | 3385 int64 database_id, |
2535 int64 object_store_id, | 3386 int64 object_store_id, |
2536 int64 index_id, | 3387 int64 index_id, |
2537 const IndexedDBKeyRange& range, | 3388 const IndexedDBKeyRange& range, |
2538 indexed_db::CursorDirection direction) { | 3389 indexed_db::CursorDirection direction) { |
2539 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor"); | 3390 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor"); |
2540 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 3391 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
2541 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; | 3392 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; |
2542 if (!IndexCursorOptions(leveldb_transaction, | 3393 if (!IndexCursorOptions(leveldb_transaction, |
2543 database_id, | 3394 database_id, |
2544 object_store_id, | 3395 object_store_id, |
2545 index_id, | 3396 index_id, |
2546 range, | 3397 range, |
2547 direction, | 3398 direction, |
2548 &cursor_options)) | 3399 &cursor_options)) |
2549 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 3400 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
2550 scoped_ptr<IndexKeyCursorImpl> cursor( | 3401 scoped_ptr<IndexKeyCursorImpl> cursor(new IndexKeyCursorImpl( |
2551 new IndexKeyCursorImpl(leveldb_transaction, cursor_options)); | 3402 this, leveldb_transaction, database_id, cursor_options)); |
2552 if (!cursor->FirstSeek()) | 3403 if (!cursor->FirstSeek()) |
2553 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 3404 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
2554 | 3405 |
2555 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); | 3406 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); |
2556 } | 3407 } |
2557 | 3408 |
2558 scoped_ptr<IndexedDBBackingStore::Cursor> | 3409 scoped_ptr<IndexedDBBackingStore::Cursor> |
2559 IndexedDBBackingStore::OpenIndexCursor( | 3410 IndexedDBBackingStore::OpenIndexCursor( |
2560 IndexedDBBackingStore::Transaction* transaction, | 3411 IndexedDBBackingStore::Transaction* transaction, |
2561 int64 database_id, | 3412 int64 database_id, |
2562 int64 object_store_id, | 3413 int64 object_store_id, |
2563 int64 index_id, | 3414 int64 index_id, |
2564 const IndexedDBKeyRange& range, | 3415 const IndexedDBKeyRange& range, |
2565 indexed_db::CursorDirection direction) { | 3416 indexed_db::CursorDirection direction) { |
2566 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor"); | 3417 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor"); |
2567 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 3418 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
2568 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; | 3419 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; |
2569 if (!IndexCursorOptions(leveldb_transaction, | 3420 if (!IndexCursorOptions(leveldb_transaction, |
2570 database_id, | 3421 database_id, |
2571 object_store_id, | 3422 object_store_id, |
2572 index_id, | 3423 index_id, |
2573 range, | 3424 range, |
2574 direction, | 3425 direction, |
2575 &cursor_options)) | 3426 &cursor_options)) |
2576 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 3427 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
2577 scoped_ptr<IndexCursorImpl> cursor( | 3428 scoped_ptr<IndexCursorImpl> cursor(new IndexCursorImpl( |
2578 new IndexCursorImpl(leveldb_transaction, cursor_options)); | 3429 this, leveldb_transaction, database_id, cursor_options)); |
2579 if (!cursor->FirstSeek()) | 3430 if (!cursor->FirstSeek()) |
2580 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 3431 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
2581 | 3432 |
2582 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); | 3433 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); |
2583 } | 3434 } |
2584 | 3435 |
2585 IndexedDBBackingStore::Transaction::Transaction( | 3436 IndexedDBBackingStore::Transaction::Transaction( |
2586 IndexedDBBackingStore* backing_store) | 3437 IndexedDBBackingStore* backing_store) |
2587 : backing_store_(backing_store) {} | 3438 : backing_store_(backing_store), database_id_(-1) {} |
2588 | 3439 |
2589 IndexedDBBackingStore::Transaction::~Transaction() {} | 3440 IndexedDBBackingStore::Transaction::~Transaction() { |
| 3441 BlobChangeMap::iterator iter = blob_change_map_.begin(); |
| 3442 for (; iter != blob_change_map_.end(); ++iter) { |
| 3443 delete iter->second; |
| 3444 } |
| 3445 } |
2590 | 3446 |
2591 void IndexedDBBackingStore::Transaction::Begin() { | 3447 void IndexedDBBackingStore::Transaction::Begin() { |
2592 IDB_TRACE("IndexedDBBackingStore::Transaction::Begin"); | 3448 IDB_TRACE("IndexedDBBackingStore::Transaction::Begin"); |
2593 DCHECK(!transaction_.get()); | 3449 DCHECK(!transaction_.get()); |
2594 transaction_ = new LevelDBTransaction(backing_store_->db_.get()); | 3450 transaction_ = new LevelDBTransaction(backing_store_->db_.get()); |
2595 } | 3451 } |
2596 | 3452 |
2597 bool IndexedDBBackingStore::Transaction::Commit() { | 3453 static GURL getURLFromUUID(const string& uuid) { |
2598 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); | 3454 return GURL("blob:uuid/" + uuid); |
2599 DCHECK(transaction_.get()); | 3455 } |
| 3456 |
| 3457 void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetBlobInfo( |
| 3458 std::vector<IndexedDBBlobInfo>* blob_info) { |
| 3459 blob_info_.clear(); |
| 3460 if (blob_info) |
| 3461 blob_info_.swap(*blob_info); |
| 3462 } |
| 3463 |
| 3464 void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetHandles( |
| 3465 ScopedVector<webkit_blob::BlobDataHandle>* handles) { |
| 3466 handles_.clear(); |
| 3467 if (handles) |
| 3468 handles_.swap(*handles); |
| 3469 } |
| 3470 |
| 3471 bool IndexedDBBackingStore::Transaction::HandleBlobPreTransaction( |
| 3472 BlobEntryKeyValuePairVec* new_blob_entries, |
| 3473 WriteDescriptorVec* new_files_to_write) { |
| 3474 BlobChangeMap::iterator iter = blob_change_map_.begin(); |
| 3475 new_blob_entries->clear(); |
| 3476 new_files_to_write->clear(); |
| 3477 if (iter != blob_change_map_.end()) { |
| 3478 // Create LevelDBTransaction for the name generator seed and add-journal. |
| 3479 scoped_refptr<LevelDBTransaction> pre_transaction = |
| 3480 new LevelDBTransaction(backing_store_->db_.get()); |
| 3481 BlobJournalType journal; |
| 3482 for (; iter != blob_change_map_.end(); ++iter) { |
| 3483 std::vector<IndexedDBBlobInfo>::iterator info_iter; |
| 3484 std::vector<IndexedDBBlobInfo*> new_blob_keys; |
| 3485 for (info_iter = iter->second->mutable_blob_info().begin(); |
| 3486 info_iter != iter->second->mutable_blob_info().end(); |
| 3487 ++info_iter) { |
| 3488 int64 next_blob_key = -1; |
| 3489 bool result = GetBlobKeyGeneratorCurrentNumber( |
| 3490 pre_transaction.get(), database_id_, &next_blob_key); |
| 3491 if (!result || next_blob_key < 0) |
| 3492 return false; |
| 3493 BlobJournalEntryType journal_entry = |
| 3494 std::make_pair(database_id_, next_blob_key); |
| 3495 journal.push_back(journal_entry); |
| 3496 if (info_iter->is_file()) { |
| 3497 new_files_to_write->push_back( |
| 3498 WriteDescriptor(info_iter->file_path(), next_blob_key)); |
| 3499 } else { |
| 3500 new_files_to_write->push_back(WriteDescriptor( |
| 3501 getURLFromUUID(info_iter->uuid()), next_blob_key)); |
| 3502 } |
| 3503 info_iter->set_key(next_blob_key); |
| 3504 new_blob_keys.push_back(&*info_iter); |
| 3505 result = UpdateBlobKeyGeneratorCurrentNumber( |
| 3506 pre_transaction.get(), database_id_, next_blob_key + 1); |
| 3507 if (!result) |
| 3508 return result; |
| 3509 } |
| 3510 BlobEntryKey blob_entry_key; |
| 3511 StringPiece key_piece(iter->second->key()); |
| 3512 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) { |
| 3513 NOTREACHED(); |
| 3514 return false; |
| 3515 } |
| 3516 new_blob_entries->push_back( |
| 3517 std::make_pair(blob_entry_key, EncodeBlobData(new_blob_keys))); |
| 3518 } |
| 3519 UpdatePrimaryJournalWithBlobList(pre_transaction.get(), journal); |
| 3520 if (!pre_transaction->Commit()) |
| 3521 return false; |
| 3522 } |
| 3523 return true; |
| 3524 } |
| 3525 |
| 3526 bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() { |
| 3527 BlobChangeMap::iterator iter = blob_change_map_.begin(); |
| 3528 // Look up all old files to remove as part of the transaction, store their |
| 3529 // names in blobs_to_remove_, and remove their old blob data entries. |
| 3530 if (iter != blob_change_map_.end()) { |
| 3531 scoped_ptr<LevelDBIterator> db_iter = transaction_->CreateIterator(); |
| 3532 for (; iter != blob_change_map_.end(); ++iter) { |
| 3533 BlobEntryKey blob_entry_key; |
| 3534 StringPiece key_piece(iter->second->key()); |
| 3535 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) { |
| 3536 NOTREACHED(); |
| 3537 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); |
| 3538 transaction_ = NULL; |
| 3539 return false; |
| 3540 } |
| 3541 if (database_id_ < 0) |
| 3542 database_id_ = blob_entry_key.database_id(); |
| 3543 else |
| 3544 DCHECK_EQ(database_id_, blob_entry_key.database_id()); |
| 3545 std::string blob_entry_key_bytes = blob_entry_key.Encode(); |
| 3546 db_iter->Seek(blob_entry_key_bytes); |
| 3547 if (db_iter->IsValid() && |
| 3548 !CompareKeys(db_iter->Key(), blob_entry_key_bytes)) { |
| 3549 std::vector<IndexedDBBlobInfo> blob_info; |
| 3550 if (!DecodeBlobData(db_iter->Value().as_string(), &blob_info)) { |
| 3551 INTERNAL_READ_ERROR(TRANSACTION_COMMIT_METHOD); |
| 3552 transaction_ = NULL; |
| 3553 return false; |
| 3554 } |
| 3555 std::vector<IndexedDBBlobInfo>::iterator blob_info_iter; |
| 3556 for (blob_info_iter = blob_info.begin(); |
| 3557 blob_info_iter != blob_info.end(); |
| 3558 ++blob_info_iter) |
| 3559 blobs_to_remove_.push_back( |
| 3560 std::make_pair(database_id_, blob_info_iter->key())); |
| 3561 transaction_->Remove(blob_entry_key_bytes); |
| 3562 } |
| 3563 } |
| 3564 } |
| 3565 return true; |
| 3566 } |
| 3567 |
| 3568 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper |
| 3569 : public IndexedDBBackingStore::BlobWriteCallback { |
| 3570 public: |
| 3571 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction, |
| 3572 scoped_refptr<BlobWriteCallback> callback) |
| 3573 : transaction_(transaction), callback_(callback) {} |
| 3574 virtual void didSucceed() { |
| 3575 callback_->didSucceed(); |
| 3576 transaction_->chained_blob_writer_ = NULL; |
| 3577 } |
| 3578 virtual void didFail() { |
| 3579 callback_->didFail(); |
| 3580 transaction_->chained_blob_writer_ = NULL; |
| 3581 } |
| 3582 |
| 3583 private: |
| 3584 IndexedDBBackingStore::Transaction* transaction_; |
| 3585 scoped_refptr<BlobWriteCallback> callback_; |
| 3586 }; |
| 3587 |
| 3588 void IndexedDBBackingStore::Transaction::WriteNewBlobs( |
| 3589 BlobEntryKeyValuePairVec& new_blob_entries, |
| 3590 WriteDescriptorVec& new_files_to_write, |
| 3591 scoped_refptr<BlobWriteCallback> callback) { |
| 3592 DCHECK_GT(new_files_to_write.size(), 0UL); |
| 3593 DCHECK_GT(database_id_, 0); |
| 3594 BlobEntryKeyValuePairVec::iterator blob_entry_iter; |
| 3595 for (blob_entry_iter = new_blob_entries.begin(); |
| 3596 blob_entry_iter != new_blob_entries.end(); |
| 3597 ++blob_entry_iter) { |
| 3598 // Add the new blob-table entry for each blob to the main transaction, or |
| 3599 // remove any entry that may exist if there's no new one. |
| 3600 if (!blob_entry_iter->second.size()) |
| 3601 transaction_->Remove(blob_entry_iter->first.Encode()); |
| 3602 else |
| 3603 transaction_->Put(blob_entry_iter->first.Encode(), |
| 3604 &blob_entry_iter->second); |
| 3605 } |
| 3606 // Creating the writer will start it going asynchronously. |
| 3607 chained_blob_writer_ = |
| 3608 new ChainedBlobWriterImpl(database_id_, |
| 3609 backing_store_, |
| 3610 new_files_to_write, |
| 3611 new BlobWriteCallbackWrapper(this, callback)); |
| 3612 } |
| 3613 |
| 3614 bool IndexedDBBackingStore::Transaction::SortBlobsToRemove() { |
| 3615 IndexedDBActiveBlobRegistry* registry = |
| 3616 backing_store_->active_blob_registry(); |
| 3617 BlobJournalType::iterator iter; |
| 3618 BlobJournalType primary_journal, live_blob_journal; |
| 3619 for (iter = blobs_to_remove_.begin(); iter != blobs_to_remove_.end(); |
| 3620 ++iter) { |
| 3621 if (registry->MarkDeletedCheckIfUsed(iter->first, iter->second)) |
| 3622 live_blob_journal.push_back(*iter); |
| 3623 else |
| 3624 primary_journal.push_back(*iter); |
| 3625 } |
| 3626 UpdatePrimaryJournalWithBlobList(transaction_.get(), primary_journal); |
| 3627 if (!MergeBlobsIntoLiveBlobJournal(transaction_.get(), live_blob_journal)) |
| 3628 return false; |
| 3629 // To signal how many blobs need attention right now. |
| 3630 blobs_to_remove_.swap(primary_journal); |
| 3631 return true; |
| 3632 } |
| 3633 |
| 3634 bool IndexedDBBackingStore::Transaction::CommitPhaseOne( |
| 3635 scoped_refptr<BlobWriteCallback> callback) { |
| 3636 IDB_TRACE("IndexedDBBackingStore::Transaction::commit"); |
| 3637 DCHECK(transaction_); |
| 3638 DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread()); |
| 3639 |
| 3640 if (!backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode())) { |
| 3641 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); |
| 3642 transaction_ = NULL; |
| 3643 return false; |
| 3644 } |
| 3645 |
| 3646 BlobEntryKeyValuePairVec new_blob_entries; |
| 3647 WriteDescriptorVec new_files_to_write; |
| 3648 // This commits the journal of blob files we're about to add, if any. |
| 3649 if (!HandleBlobPreTransaction(&new_blob_entries, &new_files_to_write)) { |
| 3650 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); |
| 3651 transaction_ = NULL; |
| 3652 return false; |
| 3653 } |
| 3654 |
| 3655 DCHECK(!new_files_to_write.size() || |
| 3656 KeyPrefix::IsValidDatabaseId(database_id_)); |
| 3657 if (!CollectBlobFilesToRemove()) { |
| 3658 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); |
| 3659 transaction_ = NULL; |
| 3660 return false; |
| 3661 } |
| 3662 |
| 3663 if (new_files_to_write.size()) { |
| 3664 // This kicks off the writes of the new blobs, if any. |
| 3665 // This call will zero out new_blob_entries and new_files_to_write. |
| 3666 WriteNewBlobs(new_blob_entries, new_files_to_write, callback); |
| 3667 // Remove the add journal, if any; once the blobs are written, and we |
| 3668 // commit, this will do the cleanup. |
| 3669 ClearBlobJournal(transaction_.get(), BlobJournalKey::Encode()); |
| 3670 } else { |
| 3671 callback->didSucceed(); |
| 3672 } |
| 3673 |
| 3674 return true; |
| 3675 } |
| 3676 |
| 3677 bool IndexedDBBackingStore::Transaction::CommitPhaseTwo() { |
| 3678 if (blobs_to_remove_.size()) |
| 3679 if (!SortBlobsToRemove()) { |
| 3680 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); |
| 3681 transaction_ = NULL; |
| 3682 return false; |
| 3683 } |
| 3684 |
2600 bool result = transaction_->Commit(); | 3685 bool result = transaction_->Commit(); |
2601 transaction_ = NULL; | 3686 transaction_ = NULL; |
| 3687 |
2602 if (!result) | 3688 if (!result) |
2603 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); | 3689 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); |
| 3690 else if (blobs_to_remove_.size()) |
| 3691 backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode()); |
| 3692 |
2604 return result; | 3693 return result; |
2605 } | 3694 } |
2606 | 3695 |
2607 void IndexedDBBackingStore::Transaction::Rollback() { | 3696 void IndexedDBBackingStore::Transaction::Rollback() { |
2608 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); | 3697 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); |
2609 DCHECK(transaction_.get()); | 3698 DCHECK(transaction_.get()); |
| 3699 if (chained_blob_writer_) { |
| 3700 chained_blob_writer_->Abort(); |
| 3701 chained_blob_writer_ = NULL; |
| 3702 } |
2610 transaction_->Rollback(); | 3703 transaction_->Rollback(); |
2611 transaction_ = NULL; | 3704 transaction_ = NULL; |
2612 } | 3705 } |
2613 | 3706 |
| 3707 // This is storing an info, even if empty, even if the previous key had no blob |
| 3708 // info that we know of. It duplicates a bunch of information stored in the |
| 3709 // leveldb transaction, but only w.r.t. the user keys altered--we don't keep the |
| 3710 // changes to exists or index keys here. |
| 3711 void IndexedDBBackingStore::Transaction::PutBlobInfo( |
| 3712 int64 database_id, |
| 3713 int64 object_store_id, |
| 3714 const std::string& key, |
| 3715 std::vector<IndexedDBBlobInfo>* blob_info, |
| 3716 ScopedVector<webkit_blob::BlobDataHandle>* handles) { |
| 3717 DCHECK_GT(key.size(), 0UL); |
| 3718 if (database_id_ < 0) |
| 3719 database_id_ = database_id; |
| 3720 DCHECK_EQ(database_id_, database_id); |
| 3721 |
| 3722 BlobChangeMap::iterator it = blob_change_map_.find(key); |
| 3723 BlobChangeRecord* record = NULL; |
| 3724 if (it == blob_change_map_.end()) { |
| 3725 record = new BlobChangeRecord(); |
| 3726 blob_change_map_[key] = record; |
| 3727 record->set_key(key); |
| 3728 record->set_object_store_id(object_store_id); |
| 3729 } else { |
| 3730 record = it->second; |
| 3731 } |
| 3732 DCHECK_EQ(record->object_store_id(), object_store_id); |
| 3733 record->SetBlobInfo(blob_info); |
| 3734 record->SetHandles(handles); |
| 3735 DCHECK(!handles || !handles->size()); |
| 3736 } |
| 3737 |
| 3738 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( |
| 3739 const GURL& url, |
| 3740 int64_t key) |
| 3741 : is_file_(false), url_(url), key_(key) {} |
| 3742 |
| 3743 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( |
| 3744 const FilePath& file_path, |
| 3745 int64_t key) |
| 3746 : is_file_(true), file_path_(file_path), key_(key) {} |
| 3747 |
2614 } // namespace content | 3748 } // namespace content |
OLD | NEW |