nsresult TransactionThreadPool::Dispatch(IDBTransaction* aTransaction, nsIRunnable* aRunnable, bool aFinish, nsIRunnable* aFinishRunnable) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aTransaction, "Null pointer!"); NS_ASSERTION(aRunnable, "Null pointer!"); if (aTransaction->mDatabase->IsInvalidated() && !aFinish) { return NS_ERROR_NOT_AVAILABLE; } bool canRun; TransactionQueue* existingQueue; nsresult rv = TransactionCanRun(aTransaction, &canRun, &existingQueue); NS_ENSURE_SUCCESS(rv, rv); if (!canRun) { QueuedDispatchInfo* info = mDelayedDispatchQueue.AppendElement(); NS_ENSURE_TRUE(info, NS_ERROR_OUT_OF_MEMORY); info->transaction = aTransaction; info->runnable = aRunnable; info->finish = aFinish; info->finishRunnable = aFinishRunnable; return NS_OK; } if (existingQueue) { existingQueue->Dispatch(aRunnable); if (aFinish) { existingQueue->Finish(aFinishRunnable); } return NS_OK; } nsIAtom* databaseId = aTransaction->mDatabase->Id(); #ifdef DEBUG if (aTransaction->mMode == IDBTransaction::VERSION_CHANGE) { NS_ASSERTION(!mTransactionsInProgress.Get(databaseId, nsnull), "Shouldn't have anything in progress!"); } #endif DatabaseTransactionInfo* dbTransactionInfo; nsAutoPtr<DatabaseTransactionInfo> autoDBTransactionInfo; if (!mTransactionsInProgress.Get(databaseId, &dbTransactionInfo)) { // Make a new struct for this transaction. autoDBTransactionInfo = new DatabaseTransactionInfo(); dbTransactionInfo = autoDBTransactionInfo; } const nsTArray<nsString>& objectStoreNames = aTransaction->mObjectStoreNames; nsTArray<nsString>& storesInUse = aTransaction->mMode == nsIIDBTransaction::READ_WRITE ? dbTransactionInfo->storesWriting : dbTransactionInfo->storesReading; if (!storesInUse.AppendElements(objectStoreNames)) { NS_WARNING("Out of memory!"); return NS_ERROR_OUT_OF_MEMORY; } nsTArray<TransactionInfo>& transactionInfoArray = dbTransactionInfo->transactions; TransactionInfo* transactionInfo = transactionInfoArray.AppendElement(); NS_ENSURE_TRUE(transactionInfo, NS_ERROR_OUT_OF_MEMORY); transactionInfo->transaction = aTransaction; transactionInfo->queue = new TransactionQueue(aTransaction, aRunnable); if (aFinish) { transactionInfo->queue->Finish(aFinishRunnable); } if (!transactionInfo->objectStoreNames.AppendElements(objectStoreNames)) { NS_WARNING("Out of memory!"); return NS_ERROR_OUT_OF_MEMORY; } if (autoDBTransactionInfo) { if (!mTransactionsInProgress.Put(databaseId, autoDBTransactionInfo)) { NS_WARNING("Failed to put!"); return NS_ERROR_OUT_OF_MEMORY; } autoDBTransactionInfo.forget(); } return mThreadPool->Dispatch(transactionInfo->queue, NS_DISPATCH_NORMAL); }