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

Side by Side Diff: third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp

Issue 2314933005: Align IndexedDB metadata rollback on transaction abort to spec. (Closed)
Patch Set: Rebased. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 #include "public/platform/modules/indexeddb/WebIDBKeyRange.h" 48 #include "public/platform/modules/indexeddb/WebIDBKeyRange.h"
49 #include <memory> 49 #include <memory>
50 #include <v8.h> 50 #include <v8.h>
51 51
52 using blink::WebBlobInfo; 52 using blink::WebBlobInfo;
53 using blink::WebIDBCallbacks; 53 using blink::WebIDBCallbacks;
54 using blink::WebIDBCursor; 54 using blink::WebIDBCursor;
55 using blink::WebIDBDatabase; 55 using blink::WebIDBDatabase;
56 using blink::WebVector; 56 using blink::WebVector;
57 57
58
58 namespace blink { 59 namespace blink {
59 60
60 IDBObjectStore::IDBObjectStore(const IDBObjectStoreMetadata& metadata, IDBTransa ction* transaction) 61 namespace {
61 : m_metadata(metadata) 62 using IndexKeys = HeapVector<Member<IDBKey>>;
63 }
64
65 IDBObjectStore::IDBObjectStore(RefPtr<IDBObjectStoreMetadata> metadata, IDBTrans action* transaction)
66 : m_metadata(std::move(metadata))
62 , m_transaction(transaction) 67 , m_transaction(transaction)
63 { 68 {
64 ASSERT(m_transaction); 69 DCHECK(m_transaction);
70 DCHECK(m_metadata.get());
65 } 71 }
66 72
67 DEFINE_TRACE(IDBObjectStore) 73 DEFINE_TRACE(IDBObjectStore)
68 { 74 {
69 visitor->trace(m_transaction); 75 visitor->trace(m_transaction);
70 visitor->trace(m_indexMap); 76 visitor->trace(m_indexMap);
71 visitor->trace(m_createdIndexes);
72 } 77 }
73 78
74 void IDBObjectStore::setName(const String& name, ExceptionState& exceptionState) 79 void IDBObjectStore::setName(const String& newName, ExceptionState& exceptionSta te)
75 { 80 {
76 if (!RuntimeEnabledFeatures::indexedDBExperimentalEnabled()) 81 if (!RuntimeEnabledFeatures::indexedDBExperimentalEnabled())
77 return; 82 return;
78 83
79 IDB_TRACE("IDBObjectStore::setName"); 84 IDB_TRACE("IDBObjectStore::setName");
80 if (!m_transaction->isVersionChange()) { 85 if (!m_transaction->isVersionChange()) {
81 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage); 86 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage);
82 return; 87 return;
83 } 88 }
84 if (isDeleted()) { 89 if (isDeleted()) {
85 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectS toreDeletedErrorMessage); 90 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectS toreDeletedErrorMessage);
86 return; 91 return;
87 } 92 }
88 if (m_transaction->isFinished() || m_transaction->isFinishing()) { 93 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
89 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase:: transactionFinishedErrorMessage); 94 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase:: transactionFinishedErrorMessage);
90 return; 95 return;
91 } 96 }
92 if (!m_transaction->isActive()) { 97 if (!m_transaction->isActive()) {
93 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase:: transactionInactiveErrorMessage); 98 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase:: transactionInactiveErrorMessage);
94 return; 99 return;
95 } 100 }
96 101
97 if (m_metadata.name == name) 102 if (name() == newName)
98 return; 103 return;
99 if (m_transaction->db()->containsObjectStore(name)) { 104 if (m_transaction->db()->containsObjectStore(newName)) {
100 exceptionState.throwDOMException(ConstraintError, IDBDatabase::objectSto reNameTakenErrorMessage); 105 exceptionState.throwDOMException(ConstraintError, IDBDatabase::objectSto reNameTakenErrorMessage);
101 return; 106 return;
102 } 107 }
103 if (!backendDB()) { 108 if (!backendDB()) {
104 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage); 109 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage);
105 return; 110 return;
106 } 111 }
107 112
108 backendDB()->renameObjectStore(m_transaction->id(), id(), name); 113 m_transaction->db()->renameObjectStore(id(), newName);
109 m_transaction->objectStoreRenamed(m_metadata.name, name);
110 m_metadata.name = name;
111
112 // The name inside the database's version of the object store metadata is us ed by IDBDatabase.objectStoreNames().
113 // If the transaction is aborted, this name will be reverted when the metada ta is overwritten with the previousMetadata in IDBTransaction.
114 m_transaction->db()->objectStoreRenamed(id(), name);
115 } 114 }
116 115
117 ScriptValue IDBObjectStore::keyPath(ScriptState* scriptState) const 116 ScriptValue IDBObjectStore::keyPath(ScriptState* scriptState) const
118 { 117 {
119 return ScriptValue::from(scriptState, m_metadata.keyPath); 118 return ScriptValue::from(scriptState, metadata().own.keyPath);
120 } 119 }
121 120
122 DOMStringList* IDBObjectStore::indexNames() const 121 DOMStringList* IDBObjectStore::indexNames() const
123 { 122 {
124 IDB_TRACE("IDBObjectStore::indexNames"); 123 IDB_TRACE("IDBObjectStore::indexNames");
125 DOMStringList* indexNames = DOMStringList::create(DOMStringList::IndexedDB); 124 DOMStringList* indexNames = DOMStringList::create(DOMStringList::IndexedDB);
126 for (const auto& it : m_metadata.indexes) 125 for (const auto& it : metadata().indexes)
127 indexNames->append(it.value.name); 126 indexNames->append(it.value->name);
128 indexNames->sort(); 127 indexNames->sort();
129 return indexNames; 128 return indexNames;
130 } 129 }
131 130
132 IDBRequest* IDBObjectStore::get(ScriptState* scriptState, const ScriptValue& key , ExceptionState& exceptionState) 131 IDBRequest* IDBObjectStore::get(ScriptState* scriptState, const ScriptValue& key , ExceptionState& exceptionState)
133 { 132 {
134 IDB_TRACE("IDBObjectStore::get"); 133 IDB_TRACE("IDBObjectStore::get");
135 if (isDeleted()) { 134 if (isDeleted()) {
136 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectS toreDeletedErrorMessage); 135 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectS toreDeletedErrorMessage);
137 return nullptr; 136 return nullptr;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 if (!backendDB()) { 257 if (!backendDB()) {
259 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage); 258 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage);
260 return nullptr; 259 return nullptr;
261 } 260 }
262 261
263 IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); 262 IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
264 backendDB()->getAll(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, range, maxCount, true, WebIDBCallbacksImpl::create(request).release()); 263 backendDB()->getAll(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, range, maxCount, true, WebIDBCallbacksImpl::create(request).release());
265 return request; 264 return request;
266 } 265 }
267 266
268 static void generateIndexKeysForValue(v8::Isolate* isolate, const IDBIndexMetada ta& indexMetadata, const ScriptValue& objectValue, IDBObjectStore::IndexKeys* in dexKeys) 267 static void generateIndexKeysForValue(v8::Isolate* isolate, const IDBIndexMetada ta& indexMetadata, const ScriptValue& objectValue, IndexKeys* indexKeys)
269 { 268 {
270 ASSERT(indexKeys); 269 ASSERT(indexKeys);
271 NonThrowableExceptionState exceptionState; 270 NonThrowableExceptionState exceptionState;
272 IDBKey* indexKey = ScriptValue::to<IDBKey*>(isolate, objectValue, exceptionS tate, indexMetadata.keyPath); 271 IDBKey* indexKey = ScriptValue::to<IDBKey*>(isolate, objectValue, exceptionS tate, indexMetadata.keyPath);
273 272
274 if (!indexKey) 273 if (!indexKey)
275 return; 274 return;
276 275
277 if (!indexMetadata.multiEntry || indexKey->getType() != IDBKey::ArrayType) { 276 if (!indexMetadata.multiEntry || indexKey->getType() != IDBKey::ArrayType) {
278 if (!indexKey->isValid()) 277 if (!indexKey->isValid())
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 Vector<WebBlobInfo> blobInfo; 332 Vector<WebBlobInfo> blobInfo;
334 RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::seria lize(isolate, value.v8Value(), nullptr, &blobInfo, exceptionState); 333 RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::seria lize(isolate, value.v8Value(), nullptr, &blobInfo, exceptionState);
335 if (exceptionState.hadException()) 334 if (exceptionState.hadException())
336 return nullptr; 335 return nullptr;
337 336
338 // Keys that need to be extracted must be taken from a clone so that 337 // Keys that need to be extracted must be taken from a clone so that
339 // side effects (i.e. getters) are not triggered. Construct the 338 // side effects (i.e. getters) are not triggered. Construct the
340 // clone lazily since the operation may be expensive. 339 // clone lazily since the operation may be expensive.
341 ScriptValue clone; 340 ScriptValue clone;
342 341
343 const IDBKeyPath& keyPath = m_metadata.keyPath; 342 const IDBKeyPath& keyPath = metadata().own.keyPath;
344 const bool usesInLineKeys = !keyPath.isNull(); 343 const bool usesInLineKeys = !keyPath.isNull();
345 const bool hasKeyGenerator = autoIncrement(); 344 const bool hasKeyGenerator = autoIncrement();
346 345
347 if (putMode != WebIDBPutModeCursorUpdate && usesInLineKeys && key) { 346 if (putMode != WebIDBPutModeCursorUpdate && usesInLineKeys && key) {
348 exceptionState.throwDOMException(DataError, "The object store uses in-li ne keys and the key parameter was provided."); 347 exceptionState.throwDOMException(DataError, "The object store uses in-li ne keys and the key parameter was provided.");
349 return nullptr; 348 return nullptr;
350 } 349 }
351 350
352 // This test logically belongs in IDBCursor, but must operate on the cloned value. 351 // This test logically belongs in IDBCursor, but must operate on the cloned value.
353 if (putMode == WebIDBPutModeCursorUpdate && usesInLineKeys) { 352 if (putMode == WebIDBPutModeCursorUpdate && usesInLineKeys) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 return nullptr; 394 return nullptr;
396 } 395 }
397 396
398 if (!backendDB()) { 397 if (!backendDB()) {
399 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage); 398 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage);
400 return nullptr; 399 return nullptr;
401 } 400 }
402 401
403 Vector<int64_t> indexIds; 402 Vector<int64_t> indexIds;
404 HeapVector<IndexKeys> indexKeys; 403 HeapVector<IndexKeys> indexKeys;
405 for (const auto& it : m_metadata.indexes) { 404 for (const auto& it : metadata().indexes) {
406 if (clone.isEmpty()) 405 if (clone.isEmpty())
407 clone = deserializeScriptValue(scriptState, serializedValue.get(), & blobInfo); 406 clone = deserializeScriptValue(scriptState, serializedValue.get(), & blobInfo);
408 IndexKeys keys; 407 IndexKeys keys;
409 generateIndexKeysForValue(scriptState->isolate(), it.value, clone, &keys ); 408 generateIndexKeysForValue(scriptState->isolate(), *it.value, clone, &key s);
410 indexIds.append(it.key); 409 indexIds.append(it.key);
411 indexKeys.append(keys); 410 indexKeys.append(keys);
412 } 411 }
413 412
414 IDBRequest* request = IDBRequest::create(scriptState, source, m_transaction. get()); 413 IDBRequest* request = IDBRequest::create(scriptState, source, m_transaction. get());
415 Vector<char> wireBytes; 414 Vector<char> wireBytes;
416 serializedValue->toWireBytes(wireBytes); 415 serializedValue->toWireBytes(wireBytes);
417 RefPtr<SharedBuffer> valueBuffer = SharedBuffer::adoptVector(wireBytes); 416 RefPtr<SharedBuffer> valueBuffer = SharedBuffer::adoptVector(wireBytes);
418 417
419 backendDB()->put(m_transaction->id(), id(), WebData(valueBuffer), blobInfo, key, static_cast<WebIDBPutMode>(putMode), WebIDBCallbacksImpl::create(request).r elease(), indexIds, indexKeys); 418 backendDB()->put(m_transaction->id(), id(), WebData(valueBuffer), blobInfo, key, static_cast<WebIDBPutMode>(putMode), WebIDBCallbacksImpl::create(request).r elease(), indexIds, indexKeys);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 } 486 }
488 487
489 namespace { 488 namespace {
490 // This class creates the index keys for a given index by extracting 489 // This class creates the index keys for a given index by extracting
491 // them from the SerializedScriptValue, for all the existing values in 490 // them from the SerializedScriptValue, for all the existing values in
492 // the objectStore. It only needs to be kept alive by virtue of being 491 // the objectStore. It only needs to be kept alive by virtue of being
493 // a listener on an IDBRequest object, in the same way that JavaScript 492 // a listener on an IDBRequest object, in the same way that JavaScript
494 // cursor success handlers are kept alive. 493 // cursor success handlers are kept alive.
495 class IndexPopulator final : public EventListener { 494 class IndexPopulator final : public EventListener {
496 public: 495 public:
497 static IndexPopulator* create(ScriptState* scriptState, IDBDatabase* databas e, int64_t transactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMe tadata) 496 static IndexPopulator* create(ScriptState* scriptState, IDBDatabase* databas e, int64_t transactionId, int64_t objectStoreId, RefPtr<const IDBIndexMetadata> indexMetadata)
498 { 497 {
499 return new IndexPopulator(scriptState, database, transactionId, objectSt oreId, indexMetadata); 498 return new IndexPopulator(scriptState, database, transactionId, objectSt oreId, std::move(indexMetadata));
500 } 499 }
501 500
502 bool operator==(const EventListener& other) const override 501 bool operator==(const EventListener& other) const override
503 { 502 {
504 return this == &other; 503 return this == &other;
505 } 504 }
506 505
507 DEFINE_INLINE_VIRTUAL_TRACE() 506 DEFINE_INLINE_VIRTUAL_TRACE()
508 { 507 {
509 visitor->trace(m_database); 508 visitor->trace(m_database);
510 EventListener::trace(visitor); 509 EventListener::trace(visitor);
511 } 510 }
512 511
513 private: 512 private:
514 IndexPopulator(ScriptState* scriptState, IDBDatabase* database, int64_t tran sactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) 513 IndexPopulator(ScriptState* scriptState, IDBDatabase* database, int64_t tran sactionId, int64_t objectStoreId, RefPtr<const IDBIndexMetadata> indexMetadata)
515 : EventListener(CPPEventListenerType) 514 : EventListener(CPPEventListenerType)
516 , m_scriptState(scriptState) 515 , m_scriptState(scriptState)
517 , m_database(database) 516 , m_database(database)
518 , m_transactionId(transactionId) 517 , m_transactionId(transactionId)
519 , m_objectStoreId(objectStoreId) 518 , m_objectStoreId(objectStoreId)
520 , m_indexMetadata(indexMetadata) 519 , m_indexMetadata(std::move(indexMetadata))
521 { 520 {
521 DCHECK(m_indexMetadata.get());
522 } 522 }
523 523
524 const IDBIndexMetadata& indexMetadata() { return *m_indexMetadata; }
525
524 void handleEvent(ExecutionContext* executionContext, Event* event) override 526 void handleEvent(ExecutionContext* executionContext, Event* event) override
525 { 527 {
526 ASSERT(m_scriptState->getExecutionContext() == executionContext); 528 ASSERT(m_scriptState->getExecutionContext() == executionContext);
527 ASSERT(event->type() == EventTypeNames::success); 529 ASSERT(event->type() == EventTypeNames::success);
528 EventTarget* target = event->target(); 530 EventTarget* target = event->target();
529 IDBRequest* request = static_cast<IDBRequest*>(target); 531 IDBRequest* request = static_cast<IDBRequest*>(target);
530 532
531 if (!m_database->backend()) // If database is stopped? 533 if (!m_database->backend()) // If database is stopped?
532 return; 534 return;
533 535
534 IDBAny* cursorAny = request->resultAsAny(); 536 IDBAny* cursorAny = request->resultAsAny();
535 IDBCursorWithValue* cursor = nullptr; 537 IDBCursorWithValue* cursor = nullptr;
536 if (cursorAny->getType() == IDBAny::IDBCursorWithValueType) 538 if (cursorAny->getType() == IDBAny::IDBCursorWithValueType)
537 cursor = cursorAny->idbCursorWithValue(); 539 cursor = cursorAny->idbCursorWithValue();
538 540
539 Vector<int64_t> indexIds; 541 Vector<int64_t> indexIds;
540 indexIds.append(m_indexMetadata.id); 542 indexIds.append(indexMetadata().id);
541 if (cursor && !cursor->isDeleted()) { 543 if (cursor && !cursor->isDeleted()) {
542 cursor->continueFunction(nullptr, nullptr, ASSERT_NO_EXCEPTION); 544 cursor->continueFunction(nullptr, nullptr, ASSERT_NO_EXCEPTION);
543 545
544 IDBKey* primaryKey = cursor->idbPrimaryKey(); 546 IDBKey* primaryKey = cursor->idbPrimaryKey();
545 ScriptValue value = cursor->value(m_scriptState.get()); 547 ScriptValue value = cursor->value(m_scriptState.get());
546 548
547 IDBObjectStore::IndexKeys indexKeys; 549 IndexKeys indexKeys;
548 generateIndexKeysForValue(m_scriptState->isolate(), m_indexMetadata, value, &indexKeys); 550 generateIndexKeysForValue(m_scriptState->isolate(), indexMetadata(), value, &indexKeys);
549 551
550 HeapVector<IDBObjectStore::IndexKeys> indexKeysList; 552 HeapVector<IndexKeys> indexKeysList;
551 indexKeysList.append(indexKeys); 553 indexKeysList.append(indexKeys);
552 554
553 m_database->backend()->setIndexKeys(m_transactionId, m_objectStoreId , primaryKey, indexIds, indexKeysList); 555 m_database->backend()->setIndexKeys(m_transactionId, m_objectStoreId , primaryKey, indexIds, indexKeysList);
554 } else { 556 } else {
555 // Now that we are done indexing, tell the backend to go 557 // Now that we are done indexing, tell the backend to go
556 // back to processing tasks of type NormalTask. 558 // back to processing tasks of type NormalTask.
557 m_database->backend()->setIndexesReady(m_transactionId, m_objectStor eId, indexIds); 559 m_database->backend()->setIndexesReady(m_transactionId, m_objectStor eId, indexIds);
558 m_database.clear(); 560 m_database.clear();
559 } 561 }
560 562
561 } 563 }
562 564
563 RefPtr<ScriptState> m_scriptState; 565 RefPtr<ScriptState> m_scriptState;
564 Member<IDBDatabase> m_database; 566 Member<IDBDatabase> m_database;
565 const int64_t m_transactionId; 567 const int64_t m_transactionId;
566 const int64_t m_objectStoreId; 568 const int64_t m_objectStoreId;
567 const IDBIndexMetadata m_indexMetadata; 569 RefPtr<const IDBIndexMetadata> m_indexMetadata;
568 }; 570 };
569 } // namespace 571 } // namespace
570 572
571 IDBIndex* IDBObjectStore::createIndex(ScriptState* scriptState, const String& na me, const IDBKeyPath& keyPath, const IDBIndexParameters& options, ExceptionState & exceptionState) 573 IDBIndex* IDBObjectStore::createIndex(ScriptState* scriptState, const String& na me, const IDBKeyPath& keyPath, const IDBIndexParameters& options, ExceptionState & exceptionState)
572 { 574 {
573 IDB_TRACE("IDBObjectStore::createIndex"); 575 IDB_TRACE("IDBObjectStore::createIndex");
574 if (!m_transaction->isVersionChange()) { 576 if (!m_transaction->isVersionChange()) {
575 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage); 577 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage);
576 return nullptr; 578 return nullptr;
577 } 579 }
(...skipping 19 matching lines...) Expand all
597 } 599 }
598 if (keyPath.getType() == IDBKeyPath::ArrayType && options.multiEntry()) { 600 if (keyPath.getType() == IDBKeyPath::ArrayType && options.multiEntry()) {
599 exceptionState.throwDOMException(InvalidAccessError, "The keyPath argume nt was an array and the multiEntry option is true."); 601 exceptionState.throwDOMException(InvalidAccessError, "The keyPath argume nt was an array and the multiEntry option is true.");
600 return nullptr; 602 return nullptr;
601 } 603 }
602 if (!backendDB()) { 604 if (!backendDB()) {
603 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage); 605 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage);
604 return nullptr; 606 return nullptr;
605 } 607 }
606 608
607 int64_t indexId = m_metadata.maxIndexId + 1; 609 int64_t indexId = m_metadata->own.maxIndexId + 1;
610 DCHECK(indexId != IDBIndexMetadata::InvalidId);
608 backendDB()->createIndex(m_transaction->id(), id(), indexId, name, keyPath, options.unique(), options.multiEntry()); 611 backendDB()->createIndex(m_transaction->id(), id(), indexId, name, keyPath, options.unique(), options.multiEntry());
609 612
610 ++m_metadata.maxIndexId; 613 ++m_metadata->own.maxIndexId;
611 614
612 IDBIndexMetadata metadata(name, indexId, keyPath, options.unique(), options. multiEntry()); 615 RefPtr<IDBIndexMetadata> indexMetadata = adoptRef(new IDBIndexMetadata(
613 IDBIndex* index = IDBIndex::create(metadata, this, m_transaction.get()); 616 name, indexId, keyPath, options.unique(), options.multiEntry()));
617 IDBIndex* index = IDBIndex::create(indexMetadata, this, m_transaction.get()) ;
614 m_indexMap.set(name, index); 618 m_indexMap.set(name, index);
615 m_createdIndexes.add(index); 619 m_metadata->indexes.set(indexId, indexMetadata);
616 m_metadata.indexes.set(indexId, metadata);
617 m_transaction->db()->indexCreated(id(), metadata);
618 620
619 ASSERT(!exceptionState.hadException()); 621 ASSERT(!exceptionState.hadException());
620 if (exceptionState.hadException()) 622 if (exceptionState.hadException())
621 return nullptr; 623 return nullptr;
622 624
623 IDBRequest* indexRequest = openCursor(scriptState, nullptr, WebIDBCursorDire ctionNext, WebIDBTaskTypePreemptive); 625 IDBRequest* indexRequest = openCursor(scriptState, nullptr, WebIDBCursorDire ctionNext, WebIDBTaskTypePreemptive);
624 indexRequest->preventPropagation(); 626 indexRequest->preventPropagation();
625 627
626 // This is kept alive by being the success handler of the request, which is in turn kept alive by the owning transaction. 628 // This is kept alive by being the success handler of the request, which is in turn kept alive by the owning transaction.
627 IndexPopulator* indexPopulator = IndexPopulator::create(scriptState, transac tion()->db(), m_transaction->id(), id(), metadata); 629 IndexPopulator* indexPopulator = IndexPopulator::create(scriptState, transac tion()->db(), m_transaction->id(), id(), std::move(indexMetadata));
628 indexRequest->setOnsuccess(indexPopulator); 630 indexRequest->setOnsuccess(indexPopulator);
629 return index; 631 return index;
630 } 632 }
631 633
632 IDBIndex* IDBObjectStore::index(const String& name, ExceptionState& exceptionSta te) 634 IDBIndex* IDBObjectStore::index(const String& name, ExceptionState& exceptionSta te)
633 { 635 {
634 IDB_TRACE("IDBObjectStore::index"); 636 IDB_TRACE("IDBObjectStore::index");
635 if (isDeleted()) { 637 if (isDeleted()) {
636 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectS toreDeletedErrorMessage); 638 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectS toreDeletedErrorMessage);
637 return nullptr; 639 return nullptr;
638 } 640 }
639 if (m_transaction->isFinished() || m_transaction->isFinishing()) { 641 if (m_transaction->isFinished() || m_transaction->isFinishing()) {
640 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transac tionFinishedErrorMessage); 642 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transac tionFinishedErrorMessage);
641 return nullptr; 643 return nullptr;
642 } 644 }
643 645
644 IDBIndexMap::iterator it = m_indexMap.find(name); 646 IndexMap::iterator it = m_indexMap.find(name);
645 if (it != m_indexMap.end()) 647 if (it != m_indexMap.end())
646 return it->value; 648 return it->value;
647 649
648 int64_t indexId = findIndexId(name); 650 int64_t indexId = findIndexId(name);
649 if (indexId == IDBIndexMetadata::InvalidId) { 651 if (indexId == IDBIndexMetadata::InvalidId) {
650 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchIndex ErrorMessage); 652 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchIndex ErrorMessage);
651 return nullptr; 653 return nullptr;
652 } 654 }
653 655
654 const IDBIndexMetadata* indexMetadata(nullptr); 656 DCHECK(metadata().indexes.contains(indexId));
655 for (const auto& it : m_metadata.indexes) { 657 RefPtr<IDBIndexMetadata> indexMetadata = metadata().indexes.get(indexId);
656 if (it.value.name == name) { 658 DCHECK(indexMetadata.get());
657 indexMetadata = &it.value; 659 IDBIndex* index = IDBIndex::create(std::move(indexMetadata), this, m_transac tion.get());
658 break;
659 }
660 }
661 ASSERT(indexMetadata);
662 ASSERT(indexMetadata->id != IDBIndexMetadata::InvalidId);
663
664 IDBIndex* index = IDBIndex::create(*indexMetadata, this, m_transaction.get() );
665 m_indexMap.set(name, index); 660 m_indexMap.set(name, index);
666 return index; 661 return index;
667 } 662 }
668 663
669 void IDBObjectStore::deleteIndex(const String& name, ExceptionState& exceptionSt ate) 664 void IDBObjectStore::deleteIndex(const String& name, ExceptionState& exceptionSt ate)
670 { 665 {
671 IDB_TRACE("IDBObjectStore::deleteIndex"); 666 IDB_TRACE("IDBObjectStore::deleteIndex");
672 if (!m_transaction->isVersionChange()) { 667 if (!m_transaction->isVersionChange()) {
673 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage); 668 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVers ionChangeTransactionErrorMessage);
674 return; 669 return;
(...skipping 15 matching lines...) Expand all
690 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchIndex ErrorMessage); 685 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchIndex ErrorMessage);
691 return; 686 return;
692 } 687 }
693 if (!backendDB()) { 688 if (!backendDB()) {
694 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage); 689 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage);
695 return; 690 return;
696 } 691 }
697 692
698 backendDB()->deleteIndex(m_transaction->id(), id(), indexId); 693 backendDB()->deleteIndex(m_transaction->id(), id(), indexId);
699 694
700 m_metadata.indexes.remove(indexId); 695 m_metadata->indexes.remove(indexId);
701 m_transaction->db()->indexDeleted(id(), indexId); 696 IndexMap::iterator it = m_indexMap.find(name);
702 IDBIndexMap::iterator it = m_indexMap.find(name);
703 if (it != m_indexMap.end()) { 697 if (it != m_indexMap.end()) {
698 m_transaction->indexDeleted(it->value);
704 it->value->markDeleted(); 699 it->value->markDeleted();
705 m_indexMap.remove(name); 700 m_indexMap.remove(name);
706 } 701 }
707 } 702 }
708 703
709 IDBRequest* IDBObjectStore::openCursor(ScriptState* scriptState, const ScriptVal ue& range, const String& directionString, ExceptionState& exceptionState) 704 IDBRequest* IDBObjectStore::openCursor(ScriptState* scriptState, const ScriptVal ue& range, const String& directionString, ExceptionState& exceptionState)
710 { 705 {
711 IDB_TRACE("IDBObjectStore::openCursor"); 706 IDB_TRACE("IDBObjectStore::openCursor");
712 if (isDeleted()) { 707 if (isDeleted()) {
713 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectS toreDeletedErrorMessage); 708 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectS toreDeletedErrorMessage);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 if (!backendDB()) { 795 if (!backendDB()) {
801 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage); 796 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databas eClosedErrorMessage);
802 return nullptr; 797 return nullptr;
803 } 798 }
804 799
805 IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); 800 IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get());
806 backendDB()->count(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, k eyRange, WebIDBCallbacksImpl::create(request).release()); 801 backendDB()->count(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, k eyRange, WebIDBCallbacksImpl::create(request).release());
807 return request; 802 return request;
808 } 803 }
809 804
810 void IDBObjectStore::abort() 805 void IDBObjectStore::markDeleted()
811 { 806 {
812 for (auto& index : m_createdIndexes) 807 m_deleted = true;
808 m_metadata->indexes.clear();
809
810 for (auto& it : m_indexMap) {
811 IDBIndex* index = it.value;
813 index->markDeleted(); 812 index->markDeleted();
813 }
814 } 814 }
815 815
816 void IDBObjectStore::transactionFinished() 816 void IDBObjectStore::transactionFinished()
817 { 817 {
818 ASSERT(m_transaction->isFinished()); 818 DCHECK(m_transaction->isFinished());
819 819
820 // Break reference cycles. 820 // Remove our references to IDBIndex instances, so Oilpan can
821 // TODO(jsbell): This can be removed c/o Oilpan. 821 // garbage-collect the instances that are not referenced in JavaScript.
822 m_indexMap.clear(); 822 m_indexMap.clear();
823 m_createdIndexes.clear();
824 } 823 }
825 824
826 void IDBObjectStore::indexRenamed(int64_t indexId, const String& newName) 825 void IDBObjectStore::revertMetadata(RefPtr<IDBObjectStoreMetadata> oldMetadata)
826 {
827 DCHECK(m_transaction->isVersionChange());
828 DCHECK(!m_transaction->isActive());
829 DCHECK(oldMetadata.get());
830 DCHECK(id() == oldMetadata->own.id);
831
832 // Index IDs are allocated sequentially, so we can tell if an index was
833 // created in this transaction by comparing its ID with the object store's
834 // maximum index ID at the time when the transaction was started.
835 const int64_t oldMaxIndexId = oldMetadata->own.maxIndexId;
836 for (auto& it : m_indexMap) {
837 IDBIndex* index = it.value;
838 const int64_t indexId = index->id();
839
840 if (indexId >= oldMaxIndexId) {
841 // The index was created by this transaction. According to the spec,
842 // its metadata will remain as-is. We just need to look up the
843 // index's IDBIndex instance, and mark it as deleted.
844 DCHECK(!oldMetadata->indexes.contains(indexId));
845 index->markDeleted();
846 continue;
847 }
848
849 // The index was created in a previous transaction. We need to revert
850 // its metadata. The index might have been deleted, so we
851 // unconditionally reset the deletion marker. We could find out if the
852 // index was deleted by looking up the index ID in the store's metadata,
853 // but that would be more work than the unconditional reset.
854 DCHECK(oldMetadata->indexes.contains(indexId));
855 RefPtr<IDBIndexMetadata> oldIndexMetadata = oldMetadata->indexes.get(ind exId);
856 index->revertMetadata(std::move(oldIndexMetadata));
857 }
858 m_metadata = std::move(oldMetadata);
859
860 // An object store's metadata will only get reverted if the index was in the
861 // database when the versionchange transaction started.
862 m_deleted = false;
863 }
864
865 void IDBObjectStore::revertDeletedIndexMetadata(IDBIndex& deletedIndex)
866 {
867 DCHECK(m_transaction->isVersionChange());
868 DCHECK(!m_transaction->isActive());
869 DCHECK(deletedIndex.objectStore() == this);
870 DCHECK(deletedIndex.isDeleted());
871
872 const int64_t indexId = deletedIndex.id();
873 DCHECK(m_metadata->indexes.contains(indexId)) << "The object store's metadat a was not correctly reverted";
874 RefPtr<IDBIndexMetadata> oldIndexMetadata = m_metadata->indexes.get(indexId) ;
875 deletedIndex.revertMetadata(std::move(oldIndexMetadata));
876 }
877
878 void IDBObjectStore::renameIndex(int64_t indexId, const String& newName)
827 { 879 {
828 DCHECK(m_transaction->isVersionChange()); 880 DCHECK(m_transaction->isVersionChange());
829 DCHECK(m_transaction->isActive()); 881 DCHECK(m_transaction->isActive());
830 882
831 IDBObjectStoreMetadata::IndexMap::iterator metadataIterator = m_metadata.ind exes.find(indexId); 883 auto metadataIterator = m_metadata->indexes.find(indexId);
832 DCHECK(metadataIterator != m_metadata.indexes.end()) << "Invalid indexId"; 884 DCHECK(metadataIterator != m_metadata->indexes.end()) << "Invalid indexId";
833 const String& oldName = metadataIterator->value.name; 885 const String& oldName = metadataIterator->value->name;
834 886
835 DCHECK(m_indexMap.contains(oldName)) << "The index had to be accessed in ord er to be renamed."; 887 DCHECK(m_indexMap.contains(oldName)) << "The index had to be accessed in ord er to be renamed.";
836 DCHECK(!m_indexMap.contains(newName)); 888 DCHECK(!m_indexMap.contains(newName));
837 IDBIndexMap::iterator it = m_indexMap.find(oldName); 889 IDBIndex* index = m_indexMap.take(oldName);
838 m_indexMap.set(newName, it->value); 890 m_indexMap.set(newName, index);
839 m_indexMap.remove(oldName);
840 891
841 metadataIterator->value.name = newName; 892 metadataIterator->value->name = newName;
842 } 893 }
843 894
844 int64_t IDBObjectStore::findIndexId(const String& name) const 895 int64_t IDBObjectStore::findIndexId(const String& name) const
845 { 896 {
846 for (const auto& it : m_metadata.indexes) { 897 for (const auto& it : metadata().indexes) {
847 if (it.value.name == name) { 898 if (it.value->name == name) {
848 ASSERT(it.key != IDBIndexMetadata::InvalidId); 899 ASSERT(it.key != IDBIndexMetadata::InvalidId);
849 return it.key; 900 return it.key;
850 } 901 }
851 } 902 }
852 return IDBIndexMetadata::InvalidId; 903 return IDBIndexMetadata::InvalidId;
853 } 904 }
854 905
855 WebIDBDatabase* IDBObjectStore::backendDB() const 906 WebIDBDatabase* IDBObjectStore::backendDB() const
856 { 907 {
857 return m_transaction->backendDB(); 908 return m_transaction->backendDB();
858 } 909 }
859 910
860 } // namespace blink 911 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698