mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Don't allow writers to starve
This commit is contained in:
parent
d2fb9aee66
commit
438b20ac44
@ -384,6 +384,8 @@ IDBObjectStoreRequest::GetName(nsAString& aName)
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
aName.Assign(mName);
|
aName.Assign(mName);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -393,6 +395,8 @@ IDBObjectStoreRequest::GetKeyPath(nsAString& aKeyPath)
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
aKeyPath.Assign(mKeyPath);
|
aKeyPath.Assign(mKeyPath);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -402,6 +406,8 @@ IDBObjectStoreRequest::GetIndexNames(nsIDOMDOMStringList** aIndexNames)
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
nsRefPtr<nsDOMStringList> list(new nsDOMStringList());
|
nsRefPtr<nsDOMStringList> list(new nsDOMStringList());
|
||||||
#if 0
|
#if 0
|
||||||
PRUint32 count = mIndexes.Length();
|
PRUint32 count = mIndexes.Length();
|
||||||
@ -419,6 +425,8 @@ IDBObjectStoreRequest::Get(nsIVariant* aKey,
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
Key key;
|
Key key;
|
||||||
nsresult rv = GetKeyFromVariant(aKey, key);
|
nsresult rv = GetKeyFromVariant(aKey, key);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
@ -446,6 +454,9 @@ IDBObjectStoreRequest::GetAll(nsIIDBKeyRange* aKeyRange,
|
|||||||
nsIIDBRequest** _retval)
|
nsIIDBRequest** _retval)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
@ -457,6 +468,8 @@ IDBObjectStoreRequest::Add(nsIVariant* /* aValue */,
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
if (mMode != nsIIDBTransaction::READ_WRITE) {
|
if (mMode != nsIIDBTransaction::READ_WRITE) {
|
||||||
return NS_ERROR_OBJECT_IS_IMMUTABLE;
|
return NS_ERROR_OBJECT_IS_IMMUTABLE;
|
||||||
}
|
}
|
||||||
@ -493,6 +506,8 @@ IDBObjectStoreRequest::Modify(nsIVariant* /* aValue */,
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
if (mMode != nsIIDBTransaction::READ_WRITE) {
|
if (mMode != nsIIDBTransaction::READ_WRITE) {
|
||||||
return NS_ERROR_OBJECT_IS_IMMUTABLE;
|
return NS_ERROR_OBJECT_IS_IMMUTABLE;
|
||||||
}
|
}
|
||||||
@ -529,6 +544,8 @@ IDBObjectStoreRequest::AddOrModify(nsIVariant* /* aValue */,
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
if (mMode != nsIIDBTransaction::READ_WRITE) {
|
if (mMode != nsIIDBTransaction::READ_WRITE) {
|
||||||
return NS_ERROR_OBJECT_IS_IMMUTABLE;
|
return NS_ERROR_OBJECT_IS_IMMUTABLE;
|
||||||
}
|
}
|
||||||
@ -564,6 +581,8 @@ IDBObjectStoreRequest::Remove(nsIVariant* aKey,
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
if (mMode != nsIIDBTransaction::READ_WRITE) {
|
if (mMode != nsIIDBTransaction::READ_WRITE) {
|
||||||
return NS_ERROR_OBJECT_IS_IMMUTABLE;
|
return NS_ERROR_OBJECT_IS_IMMUTABLE;
|
||||||
}
|
}
|
||||||
@ -598,6 +617,10 @@ IDBObjectStoreRequest::OpenCursor(nsIIDBKeyRange* aRange,
|
|||||||
nsIIDBRequest** _retval)
|
nsIIDBRequest** _retval)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
|
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,6 +631,9 @@ IDBObjectStoreRequest::CreateIndex(const nsAString& aName,
|
|||||||
nsIIDBRequest** _retval)
|
nsIIDBRequest** _retval)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
@ -617,6 +643,9 @@ IDBObjectStoreRequest::Index(const nsAString& aName,
|
|||||||
nsIIDBIndexRequest** _retval)
|
nsIIDBIndexRequest** _retval)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
@ -626,6 +655,9 @@ IDBObjectStoreRequest::RemoveIndex(const nsAString& aName,
|
|||||||
nsIIDBRequest** _retval)
|
nsIIDBRequest** _retval)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(mTransaction->TransactionIsOpen());
|
||||||
|
|
||||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
@ -638,14 +670,19 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
|||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
bool mayOverwrite = mOverwrite;
|
bool mayOverwrite = mOverwrite;
|
||||||
|
bool unsetKey = mKey.IsUnset();
|
||||||
|
|
||||||
if (mKey.IsUnset()) {
|
if (unsetKey) {
|
||||||
NS_ASSERTION(mAutoIncrement, "Must have a key for non-autoIncrement!");
|
NS_ASSERTION(mAutoIncrement, "Must have a key for non-autoIncrement!");
|
||||||
|
|
||||||
// Will need to add first and then set the key later.
|
// Will need to add first and then set the key later.
|
||||||
mayOverwrite = false;
|
mayOverwrite = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mAutoIncrement && !unsetKey) {
|
||||||
|
mayOverwrite = true;
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageStatement> stmt =
|
nsCOMPtr<mozIStorageStatement> stmt =
|
||||||
mTransaction->AddStatement(mCreate, mayOverwrite, mAutoIncrement);
|
mTransaction->AddStatement(mCreate, mayOverwrite, mAutoIncrement);
|
||||||
NS_ENSURE_TRUE(stmt, nsIIDBDatabaseException::UNKNOWN_ERR);
|
NS_ENSURE_TRUE(stmt, nsIIDBDatabaseException::UNKNOWN_ERR);
|
||||||
@ -678,8 +715,6 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mAutoIncrement && mCreate && !mOverwrite) {
|
if (mAutoIncrement && mCreate && !mOverwrite) {
|
||||||
bool unsetKey = mKey.IsUnset();
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRInt64 oldKey = unsetKey ? 0 : mKey.IntValue();
|
PRInt64 oldKey = unsetKey ? 0 : mKey.IntValue();
|
||||||
#endif
|
#endif
|
||||||
|
@ -441,6 +441,9 @@ NS_IMETHODIMP
|
|||||||
IDBTransactionRequest::GetDb(nsIIDBDatabase** aDB)
|
IDBTransactionRequest::GetDb(nsIIDBDatabase** aDB)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
NS_ADDREF(*aDB = mDatabase);
|
NS_ADDREF(*aDB = mDatabase);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -449,6 +452,9 @@ NS_IMETHODIMP
|
|||||||
IDBTransactionRequest::GetReadyState(PRUint16* aReadyState)
|
IDBTransactionRequest::GetReadyState(PRUint16* aReadyState)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
*aReadyState = mReadyState;
|
*aReadyState = mReadyState;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -457,6 +463,9 @@ NS_IMETHODIMP
|
|||||||
IDBTransactionRequest::GetMode(PRUint16* aMode)
|
IDBTransactionRequest::GetMode(PRUint16* aMode)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
*aMode = mMode;
|
*aMode = mMode;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -466,6 +475,8 @@ IDBTransactionRequest::GetObjectStoreNames(nsIDOMDOMStringList** aObjectStores)
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
nsRefPtr<nsDOMStringList> list(new nsDOMStringList());
|
nsRefPtr<nsDOMStringList> list(new nsDOMStringList());
|
||||||
PRUint32 count = mObjectStoreNames.Length();
|
PRUint32 count = mObjectStoreNames.Length();
|
||||||
for (PRUint32 index = 0; index < count; index++) {
|
for (PRUint32 index = 0; index < count; index++) {
|
||||||
@ -481,6 +492,8 @@ IDBTransactionRequest::ObjectStore(const nsAString& aName,
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
ObjectStoreInfo* info = nsnull;
|
ObjectStoreInfo* info = nsnull;
|
||||||
|
|
||||||
PRUint32 count = mObjectStoreNames.Length();
|
PRUint32 count = mObjectStoreNames.Length();
|
||||||
@ -512,6 +525,8 @@ IDBTransactionRequest::Abort()
|
|||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
NS_WARNING("Abort doesn't actually do anything yet! Fix me now!");
|
NS_WARNING("Abort doesn't actually do anything yet! Fix me now!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> runnable =
|
nsCOMPtr<nsIRunnable> runnable =
|
||||||
IDBEvent::CreateGenericEventRunnable(NS_LITERAL_STRING(ABORT_EVT_STR),
|
IDBEvent::CreateGenericEventRunnable(NS_LITERAL_STRING(ABORT_EVT_STR),
|
||||||
this);
|
this);
|
||||||
@ -527,6 +542,9 @@ NS_IMETHODIMP
|
|||||||
IDBTransactionRequest::GetOncomplete(nsIDOMEventListener** aOncomplete)
|
IDBTransactionRequest::GetOncomplete(nsIDOMEventListener** aOncomplete)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
return GetInnerEventListener(mOnCompleteListener, aOncomplete);
|
return GetInnerEventListener(mOnCompleteListener, aOncomplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,6 +552,9 @@ NS_IMETHODIMP
|
|||||||
IDBTransactionRequest::SetOncomplete(nsIDOMEventListener* aOncomplete)
|
IDBTransactionRequest::SetOncomplete(nsIDOMEventListener* aOncomplete)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
return RemoveAddEventListener(NS_LITERAL_STRING(COMPLETE_EVT_STR),
|
return RemoveAddEventListener(NS_LITERAL_STRING(COMPLETE_EVT_STR),
|
||||||
mOnCompleteListener, aOncomplete);
|
mOnCompleteListener, aOncomplete);
|
||||||
}
|
}
|
||||||
@ -542,6 +563,9 @@ NS_IMETHODIMP
|
|||||||
IDBTransactionRequest::GetOnabort(nsIDOMEventListener** aOnabort)
|
IDBTransactionRequest::GetOnabort(nsIDOMEventListener** aOnabort)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
return GetInnerEventListener(mOnAbortListener, aOnabort);
|
return GetInnerEventListener(mOnAbortListener, aOnabort);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,6 +573,9 @@ NS_IMETHODIMP
|
|||||||
IDBTransactionRequest::SetOnabort(nsIDOMEventListener* aOnabort)
|
IDBTransactionRequest::SetOnabort(nsIDOMEventListener* aOnabort)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
return RemoveAddEventListener(NS_LITERAL_STRING(ABORT_EVT_STR),
|
return RemoveAddEventListener(NS_LITERAL_STRING(ABORT_EVT_STR),
|
||||||
mOnAbortListener, aOnabort);
|
mOnAbortListener, aOnabort);
|
||||||
}
|
}
|
||||||
@ -557,6 +584,9 @@ NS_IMETHODIMP
|
|||||||
IDBTransactionRequest::GetOntimeout(nsIDOMEventListener** aOntimeout)
|
IDBTransactionRequest::GetOntimeout(nsIDOMEventListener** aOntimeout)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
return GetInnerEventListener(mOnTimeoutListener, aOntimeout);
|
return GetInnerEventListener(mOnTimeoutListener, aOntimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,6 +594,9 @@ NS_IMETHODIMP
|
|||||||
IDBTransactionRequest::SetOntimeout(nsIDOMEventListener* aOntimeout)
|
IDBTransactionRequest::SetOntimeout(nsIDOMEventListener* aOntimeout)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
NS_ENSURE_STATE(TransactionIsOpen());
|
||||||
|
|
||||||
return RemoveAddEventListener(NS_LITERAL_STRING(TIMEOUT_EVT_STR),
|
return RemoveAddEventListener(NS_LITERAL_STRING(TIMEOUT_EVT_STR),
|
||||||
mOnTimeoutListener, aOntimeout);
|
mOnTimeoutListener, aOntimeout);
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,11 @@ public:
|
|||||||
|
|
||||||
void CloseConnection();
|
void CloseConnection();
|
||||||
|
|
||||||
|
bool TransactionIsOpen() {
|
||||||
|
return mReadyState == nsIIDBTransaction::INITIAL ||
|
||||||
|
mReadyState == nsIIDBTransaction::LOADING;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IDBTransactionRequest();
|
IDBTransactionRequest();
|
||||||
~IDBTransactionRequest();
|
~IDBTransactionRequest();
|
||||||
|
@ -151,9 +151,10 @@ CreateTables(mozIStorageConnection* aDBConn)
|
|||||||
// Table `ai_object_data`
|
// Table `ai_object_data`
|
||||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
"CREATE TABLE ai_object_data ("
|
"CREATE TABLE ai_object_data ("
|
||||||
"id INTEGER PRIMARY KEY, "
|
"id INTEGER, "
|
||||||
"object_store_id INTEGER NOT NULL, "
|
"object_store_id INTEGER NOT NULL, "
|
||||||
"data TEXT NOT NULL, "
|
"data TEXT NOT NULL, "
|
||||||
|
"PRIMARY KEY (id), "
|
||||||
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
|
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
|
||||||
"CASCADE"
|
"CASCADE"
|
||||||
");"
|
");"
|
||||||
|
@ -67,10 +67,11 @@ bool gShutdown = false;
|
|||||||
|
|
||||||
struct TransactionObjectStoreInfo
|
struct TransactionObjectStoreInfo
|
||||||
{
|
{
|
||||||
TransactionObjectStoreInfo() : writing(false) { }
|
TransactionObjectStoreInfo() : writing(false), writerWaiting(false) { }
|
||||||
|
|
||||||
nsString objectStoreName;
|
nsString objectStoreName;
|
||||||
bool writing;
|
bool writing;
|
||||||
|
bool writerWaiting;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
@ -311,7 +312,7 @@ TransactionThreadPool::TransactionCanRun(IDBTransactionRequest* aTransaction,
|
|||||||
for (PRUint32 transactionIndex = 0;
|
for (PRUint32 transactionIndex = 0;
|
||||||
transactionIndex < transactionCount;
|
transactionIndex < transactionCount;
|
||||||
transactionIndex++) {
|
transactionIndex++) {
|
||||||
const TransactionInfo& transactionInfo =
|
TransactionInfo& transactionInfo =
|
||||||
transactionsInProgress->ElementAt(transactionIndex);
|
transactionsInProgress->ElementAt(transactionIndex);
|
||||||
|
|
||||||
if (transactionInfo.transaction == aTransaction) {
|
if (transactionInfo.transaction == aTransaction) {
|
||||||
@ -321,14 +322,14 @@ TransactionThreadPool::TransactionCanRun(IDBTransactionRequest* aTransaction,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not our transaction, see if the objectStores overlap.
|
// Not our transaction, see if the objectStores overlap.
|
||||||
const nsTArray<TransactionObjectStoreInfo>& objectStoreInfoArray =
|
nsTArray<TransactionObjectStoreInfo>& objectStoreInfoArray =
|
||||||
transactionInfo.objectStoreInfo;
|
transactionInfo.objectStoreInfo;
|
||||||
|
|
||||||
PRUint32 objectStoreCount = objectStoreInfoArray.Length();
|
PRUint32 objectStoreCount = objectStoreInfoArray.Length();
|
||||||
for (PRUint32 objectStoreIndex = 0;
|
for (PRUint32 objectStoreIndex = 0;
|
||||||
objectStoreIndex < objectStoreCount;
|
objectStoreIndex < objectStoreCount;
|
||||||
objectStoreIndex++) {
|
objectStoreIndex++) {
|
||||||
const TransactionObjectStoreInfo& objectStoreInfo =
|
TransactionObjectStoreInfo& objectStoreInfo =
|
||||||
objectStoreInfoArray[objectStoreIndex];
|
objectStoreInfoArray[objectStoreIndex];
|
||||||
|
|
||||||
if (objectStoreNames.Contains(objectStoreInfo.objectStoreName)) {
|
if (objectStoreNames.Contains(objectStoreInfo.objectStoreName)) {
|
||||||
@ -336,12 +337,13 @@ TransactionThreadPool::TransactionCanRun(IDBTransactionRequest* aTransaction,
|
|||||||
switch (mode) {
|
switch (mode) {
|
||||||
case nsIIDBTransaction::READ_WRITE: {
|
case nsIIDBTransaction::READ_WRITE: {
|
||||||
// Someone else is reading or writing to this table, we can't
|
// Someone else is reading or writing to this table, we can't
|
||||||
// run now.
|
// run now. Mark that we're waiting for it though.
|
||||||
|
objectStoreInfo.writerWaiting = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
case nsIIDBTransaction::READ_ONLY: {
|
case nsIIDBTransaction::READ_ONLY: {
|
||||||
if (objectStoreInfo.writing) {
|
if (objectStoreInfo.writing || objectStoreInfo.writerWaiting) {
|
||||||
// Someone else is writing to this table, we can't run now.
|
// Someone else is writing to this table, we can't run now.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ _TEST_FILES = \
|
|||||||
test_readonly_transactions.html \
|
test_readonly_transactions.html \
|
||||||
test_remove_objectStore.html \
|
test_remove_objectStore.html \
|
||||||
test_setVersion.html \
|
test_setVersion.html \
|
||||||
|
test_writer_starvation.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_TEST_FILES)
|
libs:: $(_TEST_FILES)
|
||||||
|
@ -53,6 +53,15 @@
|
|||||||
|
|
||||||
is(event.result, key2, "modify gave the same key back");
|
is(event.result, key2, "modify gave the same key back");
|
||||||
|
|
||||||
|
key2 = 100;
|
||||||
|
|
||||||
|
request = objectStore.add({}, key2);
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield;
|
||||||
|
|
||||||
|
is(event.result, key2, "modify gave the same key back");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objectStore.addOrModify({});
|
objectStore.addOrModify({});
|
||||||
ok(false, "addOrModify with no key should throw!");
|
ok(false, "addOrModify with no key should throw!");
|
||||||
|
106
dom/indexedDB/test/test_writer_starvation.html
Normal file
106
dom/indexedDB/test/test_writer_starvation.html
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Indexed Database Property Test</title>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
|
||||||
|
<script type="text/javascript;version=1.7">
|
||||||
|
function testSteps()
|
||||||
|
{
|
||||||
|
const READ_ONLY = Components.interfaces.nsIIDBTransaction.READ_ONLY;
|
||||||
|
const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
|
||||||
|
|
||||||
|
const name = window.location.pathname;
|
||||||
|
const description = "My Test Database";
|
||||||
|
|
||||||
|
let request = indexedDB.open(name, description);
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
let event = yield;
|
||||||
|
|
||||||
|
let db = event.result;
|
||||||
|
|
||||||
|
request = db.createObjectStore("foo", "", true);
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
let event = yield;
|
||||||
|
|
||||||
|
is(event.transaction.mode, READ_WRITE, "Correct mode");
|
||||||
|
|
||||||
|
request = event.result.add({});
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield;
|
||||||
|
|
||||||
|
let key = event.result;
|
||||||
|
ok(key, "Got a key");
|
||||||
|
|
||||||
|
SimpleTest.executeSoon(function() { testGenerator.next(); });
|
||||||
|
yield;
|
||||||
|
|
||||||
|
let objectStore = db.objectStore("foo");
|
||||||
|
|
||||||
|
let continueReading = true;
|
||||||
|
let readerCount = 0;
|
||||||
|
let callbackCount = 0;
|
||||||
|
let finalCallbackCount = 0;
|
||||||
|
|
||||||
|
// Generate a bunch of reads right away without returning to the event
|
||||||
|
// loop.
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
readerCount++;
|
||||||
|
request = objectStore.get(key);
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = function(event) {
|
||||||
|
callbackCount++;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
while (continueReading) {
|
||||||
|
readerCount++;
|
||||||
|
request = db.objectStore("foo").get(key);
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = function(event) {
|
||||||
|
is(event.transaction.mode, READ_ONLY, "Correct mode");
|
||||||
|
callbackCount++;
|
||||||
|
if (callbackCount == 100) {
|
||||||
|
request = db.objectStore("foo", READ_WRITE).add({}, readerCount);
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = function(event) {
|
||||||
|
continueReading = false;
|
||||||
|
finalCallbackCount = callbackCount;
|
||||||
|
ok(event.result == callbackCount,
|
||||||
|
"write callback came before later reads");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SimpleTest.executeSoon(function() { testGenerator.next(); });
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (callbackCount < readerCount) {
|
||||||
|
SimpleTest.executeSoon(function() { testGenerator.next(); });
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
|
||||||
|
is(callbackCount, readerCount, "All requests accounted for");
|
||||||
|
ok(callbackCount > finalCallbackCount, "More readers after writer");
|
||||||
|
|
||||||
|
finishTest();
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="runTest();"></body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user