Changeset 192749 in webkit


Ignore:
Timestamp:
Nov 23, 2015, 11:48:50 AM (10 years ago)
Author:
beidson@apple.com
Message:

Modern IDB: When a transaction is aborted, call onerror handlers for all in-progress requests.
https://bugs.webkit.org/show_bug.cgi?id=151550

Reviewed by Alex Christensen.

Source/WebCore:

Test: storage/indexeddb/modern/abort-requests-cancelled.html

storage/indexeddb/modern/idbtransaction-objectstore-failures.html (with changes)
storage/indexeddb/modern/index-5.html (with changes)
Various (currently skipped) legacy IDB tests.

  • Modules/indexeddb/client/IDBDatabaseImpl.cpp:

(WebCore::IDBClient::IDBDatabase::transaction):
(WebCore::IDBClient::IDBDatabase::startVersionChangeTransaction):
(WebCore::IDBClient::IDBDatabase::didStartTransaction):
(WebCore::IDBClient::IDBDatabase::willCommitTransaction):
(WebCore::IDBClient::IDBDatabase::didCommitTransaction):
(WebCore::IDBClient::IDBDatabase::willAbortTransaction):
(WebCore::IDBClient::IDBDatabase::didAbortTransaction):
(WebCore::IDBClient::IDBDatabase::didCommitOrAbortTransaction):

  • Modules/indexeddb/client/IDBTransactionImpl.cpp:

(WebCore::IDBClient::IDBTransaction::abort):
(WebCore::IDBClient::IDBTransaction::abortOnServerAndCancelRequests):
(WebCore::IDBClient::IDBTransaction::didCreateObjectStoreOnServer):
(WebCore::IDBClient::IDBTransaction::didCreateIndexOnServer):
(WebCore::IDBClient::IDBTransaction::didGetRecordOnServer):
(WebCore::IDBClient::IDBTransaction::didDeleteObjectStoreOnServer):
(WebCore::IDBClient::IDBTransaction::didDeleteIndexOnServer):
(WebCore::IDBClient::IDBTransaction::immediateAbort): Deleted.
(WebCore::IDBClient::IDBTransaction::abortOnServer): Deleted.

  • Modules/indexeddb/client/IDBTransactionImpl.h:
  • Modules/indexeddb/server/MemoryIDBBackingStore.cpp:

(WebCore::IDBServer::MemoryIDBBackingStore::abortTransaction):
(WebCore::IDBServer::MemoryIDBBackingStore::commitTransaction):

  • Modules/indexeddb/shared/IDBError.cpp:

(WebCore::idbErrorName):
(WebCore::idbErrorDescription):

  • Modules/indexeddb/shared/IDBError.h:
  • Modules/indexeddb/shared/IDBResourceIdentifier.cpp:

(WebCore::IDBResourceIdentifier::loggingString):

  • Modules/indexeddb/shared/IDBResourceIdentifier.h:

LayoutTests:

  • storage/indexeddb/modern/abort-requests-cancelled-expected.txt: Added.
  • storage/indexeddb/modern/abort-requests-cancelled.html: Added.
  • storage/indexeddb/modern/idbtransaction-objectstore-failures-expected.txt:
  • storage/indexeddb/modern/idbtransaction-objectstore-failures.html:
  • storage/indexeddb/modern/index-5-expected.txt:
  • storage/indexeddb/modern/index-5.html:
Location:
trunk
Files:
2 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r192748 r192749  
     12015-11-23  Brady Eidson  <beidson@apple.com>
     2
     3        Modern IDB: When a transaction is aborted, call onerror handlers for all in-progress requests.
     4        https://bugs.webkit.org/show_bug.cgi?id=151550
     5
     6        Reviewed by Alex Christensen.
     7
     8        * storage/indexeddb/modern/abort-requests-cancelled-expected.txt: Added.
     9        * storage/indexeddb/modern/abort-requests-cancelled.html: Added.
     10        * storage/indexeddb/modern/idbtransaction-objectstore-failures-expected.txt:
     11        * storage/indexeddb/modern/idbtransaction-objectstore-failures.html:
     12        * storage/indexeddb/modern/index-5-expected.txt:
     13        * storage/indexeddb/modern/index-5.html:
     14
    1152015-11-23  Brady Eidson  <beidson@apple.com>
    216
  • trunk/LayoutTests/storage/indexeddb/modern/idbtransaction-objectstore-failures-expected.txt

    r191645 r192749  
    66ALERT: Caught attempt to access non-existant object store on the transaction
    77ALERT: Caught attempt to access valid object store on a transaction that is already finishing
    8 ALERT: First version change transaction abort
     8ALERT: put failed (because transaction was aborted)
     9ALERT: First version change transaction unexpected error - [object Event]
    910ALERT: Done
    1011This tests some obvious failures that can happen while calling transaction.objectStore()
  • trunk/LayoutTests/storage/indexeddb/modern/idbtransaction-objectstore-failures.html

    r191645 r192749  
    3131    var putRequest = os1.put("bar", "foo");
    3232   
    33     putRequest.onerror = function(event) {
    34         alert("put unexpectedly failed - " + event);
    35         done();
     33    putRequest.onerror = function() {
     34        alert("put failed (because transaction was aborted)");
    3635    }
    3736   
  • trunk/LayoutTests/storage/indexeddb/modern/index-5-expected.txt

    r192618 r192749  
    22(The index creation should fail).
    33Initial upgrade needed: Old version - 0 New version - 1
     4Error getting cursor count
     5Error opening or iterating cursor
    46Initial upgrade versionchange transaction aborted (expected because index creation failed, and that should've caused transaction abort)
    57Done
  • trunk/LayoutTests/storage/indexeddb/modern/index-5.html

    r192618 r192749  
    3030        log("Count is: " + countRequest.result);
    3131    }
     32    countRequest.onerror = function(e) {
     33        log("Error getting cursor count");
     34        e.stopPropagation();
     35    }
    3236
    3337    var cursorRequest = index.openCursor();
     
    4246    }
    4347    cursorRequest.onerror = function(e) {
    44         log("Unexpected error opening or iterating cursor");
    45         logCursor(cursorRequest.result);
    46         done();
     48        log("Error opening or iterating cursor");
     49        e.stopPropagation();
    4750    }
    4851}
  • trunk/Source/WebCore/ChangeLog

    r192748 r192749  
     12015-11-23  Brady Eidson  <beidson@apple.com>
     2
     3        Modern IDB: When a transaction is aborted, call onerror handlers for all in-progress requests.
     4        https://bugs.webkit.org/show_bug.cgi?id=151550
     5
     6        Reviewed by Alex Christensen.
     7
     8        Test: storage/indexeddb/modern/abort-requests-cancelled.html
     9              storage/indexeddb/modern/idbtransaction-objectstore-failures.html (with changes)
     10              storage/indexeddb/modern/index-5.html (with changes)
     11              Various (currently skipped) legacy IDB tests.
     12
     13        * Modules/indexeddb/client/IDBDatabaseImpl.cpp:
     14        (WebCore::IDBClient::IDBDatabase::transaction):
     15        (WebCore::IDBClient::IDBDatabase::startVersionChangeTransaction):
     16        (WebCore::IDBClient::IDBDatabase::didStartTransaction):
     17        (WebCore::IDBClient::IDBDatabase::willCommitTransaction):
     18        (WebCore::IDBClient::IDBDatabase::didCommitTransaction):
     19        (WebCore::IDBClient::IDBDatabase::willAbortTransaction):
     20        (WebCore::IDBClient::IDBDatabase::didAbortTransaction):
     21        (WebCore::IDBClient::IDBDatabase::didCommitOrAbortTransaction):
     22       
     23        * Modules/indexeddb/client/IDBTransactionImpl.cpp:
     24        (WebCore::IDBClient::IDBTransaction::abort):
     25        (WebCore::IDBClient::IDBTransaction::abortOnServerAndCancelRequests):
     26        (WebCore::IDBClient::IDBTransaction::didCreateObjectStoreOnServer):
     27        (WebCore::IDBClient::IDBTransaction::didCreateIndexOnServer):
     28        (WebCore::IDBClient::IDBTransaction::didGetRecordOnServer):
     29        (WebCore::IDBClient::IDBTransaction::didDeleteObjectStoreOnServer):
     30        (WebCore::IDBClient::IDBTransaction::didDeleteIndexOnServer):
     31        (WebCore::IDBClient::IDBTransaction::immediateAbort): Deleted.
     32        (WebCore::IDBClient::IDBTransaction::abortOnServer): Deleted.
     33        * Modules/indexeddb/client/IDBTransactionImpl.h:
     34       
     35        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
     36        (WebCore::IDBServer::MemoryIDBBackingStore::abortTransaction):
     37        (WebCore::IDBServer::MemoryIDBBackingStore::commitTransaction):
     38       
     39        * Modules/indexeddb/shared/IDBError.cpp:
     40        (WebCore::idbErrorName):
     41        (WebCore::idbErrorDescription):
     42        * Modules/indexeddb/shared/IDBError.h:
     43       
     44        * Modules/indexeddb/shared/IDBResourceIdentifier.cpp:
     45        (WebCore::IDBResourceIdentifier::loggingString):
     46        * Modules/indexeddb/shared/IDBResourceIdentifier.h:
     47
    1482015-11-23  Brady Eidson  <beidson@apple.com>
    249
  • trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.cpp

    r192748 r192749  
    172172    auto transaction = IDBTransaction::create(*this, info);
    173173
     174    LOG(IndexedDB, "IDBDatabase::transaction - Added active transaction %s", info.identifier().loggingString().utf8().data());
     175
    174176    m_activeTransactions.set(info.identifier(), &transaction.get());
    175177
     
    242244Ref<IDBTransaction> IDBDatabase::startVersionChangeTransaction(const IDBTransactionInfo& info, IDBOpenDBRequest& request)
    243245{
    244     LOG(IndexedDB, "IDBDatabase::startVersionChangeTransaction");
     246    LOG(IndexedDB, "IDBDatabase::startVersionChangeTransaction %s", info.identifier().loggingString().utf8().data());
    245247
    246248    ASSERT(!m_versionChangeTransaction);
     
    257259void IDBDatabase::didStartTransaction(IDBTransaction& transaction)
    258260{
    259     LOG(IndexedDB, "IDBDatabase::didStartTransaction");
     261    LOG(IndexedDB, "IDBDatabase::didStartTransaction %s", transaction.info().identifier().loggingString().utf8().data());
    260262    ASSERT(!m_versionChangeTransaction);
    261263
     264    // It is possible for the client to have aborted a transaction before the server replies back that it has started.
     265    if (m_abortingTransactions.contains(transaction.info().identifier()))
     266        return;
     267
    262268    m_activeTransactions.set(transaction.info().identifier(), &transaction);
    263269}
     
    265271void IDBDatabase::willCommitTransaction(IDBTransaction& transaction)
    266272{
    267     LOG(IndexedDB, "IDBDatabase::willCommitTransaction");
     273    LOG(IndexedDB, "IDBDatabase::willCommitTransaction %s", transaction.info().identifier().loggingString().utf8().data());
    268274
    269275    auto refTransaction = m_activeTransactions.take(transaction.info().identifier());
     
    274280void IDBDatabase::didCommitTransaction(IDBTransaction& transaction)
    275281{
    276     LOG(IndexedDB, "IDBDatabase::didCommitTransaction");
     282    LOG(IndexedDB, "IDBDatabase::didCommitTransaction %s", transaction.info().identifier().loggingString().utf8().data());
    277283
    278284    if (m_versionChangeTransaction == &transaction)
     
    284290void IDBDatabase::willAbortTransaction(IDBTransaction& transaction)
    285291{
    286     LOG(IndexedDB, "IDBDatabase::willAbortTransaction");
     292    LOG(IndexedDB, "IDBDatabase::willAbortTransaction %s", transaction.info().identifier().loggingString().utf8().data());
    287293
    288294    auto refTransaction = m_activeTransactions.take(transaction.info().identifier());
     
    293299void IDBDatabase::didAbortTransaction(IDBTransaction& transaction)
    294300{
    295     LOG(IndexedDB, "IDBDatabase::didAbortTransaction");
     301    LOG(IndexedDB, "IDBDatabase::didAbortTransaction %s", transaction.info().identifier().loggingString().utf8().data());
    296302
    297303    if (transaction.isVersionChange()) {
     
    305311void IDBDatabase::didCommitOrAbortTransaction(IDBTransaction& transaction)
    306312{
    307     LOG(IndexedDB, "IDBDatabase::didCommitOrAbortTransaction");
     313    LOG(IndexedDB, "IDBDatabase::didCommitOrAbortTransaction %s", transaction.info().identifier().loggingString().utf8().data());
    308314
    309315    if (m_versionChangeTransaction == &transaction)
  • trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp

    r192720 r192749  
    166166}
    167167
    168 void IDBTransaction::immediateAbort()
    169 {
    170     LOG(IndexedDB, "IDBTransaction::immediateAbort");
    171 
    172     if (isFinishedOrFinishing())
    173         return;
     168void IDBTransaction::abort(ExceptionCode& ec)
     169{
     170    LOG(IndexedDB, "IDBTransaction::abort");
     171
     172    if (isFinishedOrFinishing()) {
     173        ec = INVALID_STATE_ERR;
     174        return;
     175    }
    174176
    175177    m_state = IndexedDB::TransactionState::Aborting;
    176178    m_database->willAbortTransaction(*this);
    177179
    178     auto operation = createTransactionOperation(*this, nullptr, &IDBTransaction::abortOnServer);
    179     abortOnServer(*operation);
    180 }
    181 
    182 void IDBTransaction::abort(ExceptionCode& ec)
    183 {
    184     LOG(IndexedDB, "IDBTransaction::abort");
    185 
    186     if (isFinishedOrFinishing()) {
    187         ec = INVALID_STATE_ERR;
    188         return;
    189     }
    190 
    191     m_state = IndexedDB::TransactionState::Aborting;
    192     m_database->willAbortTransaction(*this);
    193 
    194     auto operation = createTransactionOperation(*this, nullptr, &IDBTransaction::abortOnServer);
    195     scheduleOperation(WTF::move(operation));
    196 }
    197 
    198 void IDBTransaction::abortOnServer(TransactionOperation&)
    199 {
    200     LOG(IndexedDB, "IDBTransaction::abortOnServer");
     180    m_abortQueue.swap(m_transactionOperationQueue);
     181
     182    auto operation = createTransactionOperation(*this, nullptr, &IDBTransaction::abortOnServerAndCancelRequests);
     183    scheduleOperation(WTF::move(operation));
     184}
     185
     186void IDBTransaction::abortOnServerAndCancelRequests(TransactionOperation&)
     187{
     188    LOG(IndexedDB, "IDBTransaction::abortOnServerAndCancelRequests");
     189
     190    ASSERT(m_transactionOperationQueue.isEmpty());
     191
    201192    serverConnection().abortTransaction(*this);
     193
     194    IDBError error(IDBExceptionCode::AbortError);
     195    for (auto& operation : m_abortQueue)
     196        operation->completed(IDBResultData::error(operation->identifier(), error));
     197
     198    // Since we're aborting, this abortOnServerAndCancelRequests() operation should be the only
     199    // in-progress operation, and it should be impossible to have queued any further operations.
     200    ASSERT(m_transactionOperationMap.size() == 1);
     201    ASSERT(m_transactionOperationQueue.isEmpty());
    202202}
    203203
     
    427427    LOG(IndexedDB, "IDBTransaction::didCreateObjectStoreOnServer");
    428428
    429     ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::CreateObjectStoreSuccess);
     429    ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::CreateObjectStoreSuccess || resultData.type() == IDBResultType::Error);
    430430}
    431431
     
    459459        return;
    460460
    461     // If index creation failed, the transaction is aborted.
    462     immediateAbort();
     461    ASSERT(resultData.type() == IDBResultType::Error);
     462
     463    // This operation might have failed because the transaction is already aborting.
     464    if (m_state == IndexedDB::TransactionState::Aborting)
     465        return;
     466
     467    // Otherwise, failure to create an index forced abortion of the transaction.
     468    ExceptionCode ec;
     469    abort(ec);
    463470}
    464471
     
    585592{
    586593    LOG(IndexedDB, "IDBTransaction::didGetRecordOnServer");
     594
     595    if (resultData.type() == IDBResultType::Error) {
     596        request.requestCompleted(resultData);
     597        return;
     598    }
     599
     600    ASSERT(resultData.type() == IDBResultType::GetRecordSuccess);
    587601
    588602    const IDBGetResult& result = resultData.getResult();
     
    761775{
    762776    LOG(IndexedDB, "IDBTransaction::didDeleteObjectStoreOnServer");
    763     ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteObjectStoreSuccess);
     777    ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteObjectStoreSuccess || resultData.type() == IDBResultType::Error);
    764778}
    765779
     
    785799{
    786800    LOG(IndexedDB, "IDBTransaction::didDeleteIndexOnServer");
    787     ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteIndexSuccess);
     801    ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteIndexSuccess || resultData.type() == IDBResultType::Error);
    788802}
    789803
  • trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h

    r192748 r192749  
    143143
    144144    void commitOnServer(TransactionOperation&);
    145     void abortOnServer(TransactionOperation&);
     145    void abortOnServerAndCancelRequests(TransactionOperation&);
    146146
    147147    void createObjectStoreOnServer(TransactionOperation&, const IDBObjectStoreInfo&);
     
    183183    void scheduleOperationTimer();
    184184
    185     void immediateAbort();
    186 
    187185    Ref<IDBDatabase> m_database;
    188186    IDBTransactionInfo m_info;
     
    200198
    201199    Deque<RefPtr<TransactionOperation>> m_transactionOperationQueue;
     200    Deque<RefPtr<TransactionOperation>> m_abortQueue;
    202201    HashMap<IDBResourceIdentifier, RefPtr<TransactionOperation>> m_transactionOperationMap;
    203202
  • trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp

    r192645 r192749  
    9696IDBError MemoryIDBBackingStore::abortTransaction(const IDBResourceIdentifier& transactionIdentifier)
    9797{
    98     LOG(IndexedDB, "MemoryIDBBackingStore::abortTransaction");
     98    LOG(IndexedDB, "MemoryIDBBackingStore::abortTransaction - %s", transactionIdentifier.loggingString().utf8().data());
    9999
    100100    auto transaction = m_transactions.take(transactionIdentifier);
     
    109109IDBError MemoryIDBBackingStore::commitTransaction(const IDBResourceIdentifier& transactionIdentifier)
    110110{
    111     LOG(IndexedDB, "MemoryIDBBackingStore::commitTransaction");
     111    LOG(IndexedDB, "MemoryIDBBackingStore::commitTransaction - %s", transactionIdentifier.loggingString().utf8().data());
    112112
    113113    auto transaction = m_transactions.take(transactionIdentifier);
  • trunk/Source/WebCore/Modules/indexeddb/shared/IDBError.cpp

    r191635 r192749  
    6868        return entry;
    6969    }
     70    case IDBExceptionCode::AbortError: {
     71        static NeverDestroyed<String> entry = ASCIILiteral("AbortError");
     72        return entry;
     73    }
    7074    case IDBExceptionCode::None:
    7175        RELEASE_ASSERT_NOT_REACHED();
     
    108112    case IDBExceptionCode::DataCloneError: {
    109113        static NeverDestroyed<String> entry = ASCIILiteral("Data being stored could not be cloned by the structured cloning algorithm.");
     114        return entry;
     115    }
     116    case IDBExceptionCode::AbortError: {
     117        static NeverDestroyed<String> entry = ASCIILiteral("Transaction was aborted");
    110118        return entry;
    111119    }
  • trunk/Source/WebCore/Modules/indexeddb/shared/IDBError.h

    r191635 r192749  
    4545    InvalidStateError,
    4646    DataCloneError,
     47    AbortError,
    4748};
    4849
  • trunk/Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.cpp

    r191114 r192749  
    9595}
    9696
     97#ifndef NDEBUG
     98String IDBResourceIdentifier::loggingString() const
     99{
     100    return String::format("<%" PRIu64", %" PRIu64">", m_idbConnectionIdentifier, m_resourceNumber);
     101}
     102#endif
    97103} // namespace WebCore
    98104
  • trunk/Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.h

    r191114 r192749  
    7373    IDBResourceIdentifier isolatedCopy() const;
    7474
     75#ifndef NDEBUG
     76    String loggingString() const;
     77#endif
     78
    7579private:
    7680    IDBResourceIdentifier() = delete;
Note: See TracChangeset for help on using the changeset viewer.