зеркало из https://github.com/mozilla/gecko-dev.git
Bug 584319 - 'IndexedDB: Out of Memory error and crash when calling moz_indexedDB.open a lot'. r=sicking
This commit is contained in:
Родитель
e8315ce8b9
Коммит
88b443f419
|
@ -172,12 +172,6 @@ AsyncConnectionHelper::Run()
|
|||
NS_ASSERTION(connection, "This should never be null!");
|
||||
}
|
||||
}
|
||||
else if (mDatabase) {
|
||||
rv = mDatabase->GetOrCreateConnection(getter_AddRefs(connection));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ASSERTION(connection, "This should never be null!");
|
||||
}
|
||||
}
|
||||
|
||||
if (connection) {
|
||||
rv = connection->SetProgressHandler(kProgressHandlerGranularity, this,
|
||||
|
|
|
@ -147,14 +147,14 @@ CheckPermissionsHelper::Run()
|
|||
nsRefPtr<AsyncConnectionHelper> helper;
|
||||
helper.swap(mHelper);
|
||||
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
thread.swap(mThread);
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> window;
|
||||
window.swap(mWindow);
|
||||
|
||||
if (permission == nsIPermissionManager::ALLOW_ACTION) {
|
||||
return helper->Dispatch(thread);
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
|
||||
return helper->Dispatch(mgr->IOThread());
|
||||
}
|
||||
|
||||
NS_ASSERTION(permission == nsIPermissionManager::UNKNOWN_ACTION ||
|
||||
|
|
|
@ -63,25 +63,21 @@ public:
|
|||
NS_DECL_NSIOBSERVER
|
||||
|
||||
CheckPermissionsHelper(AsyncConnectionHelper* aHelper,
|
||||
nsIThread* aThread,
|
||||
nsIDOMWindow* aWindow,
|
||||
const nsACString& aASCIIOrigin)
|
||||
: mHelper(aHelper),
|
||||
mThread(aThread),
|
||||
mWindow(aWindow),
|
||||
mASCIIOrigin(aASCIIOrigin),
|
||||
mHasPrompted(PR_FALSE),
|
||||
mPromptResult(0)
|
||||
{
|
||||
NS_ASSERTION(aHelper, "Null pointer!");
|
||||
NS_ASSERTION(aThread, "Null pointer!");
|
||||
NS_ASSERTION(aWindow, "Null pointer!");
|
||||
NS_ASSERTION(!aASCIIOrigin.IsEmpty(), "Empty host!");
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<AsyncConnectionHelper> mHelper;
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
nsCOMPtr<nsIDOMWindow> mWindow;
|
||||
nsCString mASCIIOrigin;
|
||||
PRBool mHasPrompted;
|
||||
|
|
|
@ -81,6 +81,54 @@ EnumerateObjectStoreNames(const nsAString& aKey,
|
|||
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
DatabaseInfo::DatabaseInfo()
|
||||
: id(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DatabaseInfo);
|
||||
}
|
||||
|
||||
DatabaseInfo::~DatabaseInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(DatabaseInfo);
|
||||
}
|
||||
|
||||
IndexInfo::IndexInfo()
|
||||
: id(LL_MININT),
|
||||
unique(false),
|
||||
autoIncrement(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(IndexInfo);
|
||||
}
|
||||
|
||||
IndexInfo::~IndexInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(IndexInfo);
|
||||
}
|
||||
|
||||
ObjectStoreInfo::ObjectStoreInfo()
|
||||
: id(0),
|
||||
autoIncrement(false),
|
||||
databaseId(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ObjectStoreInfo);
|
||||
}
|
||||
|
||||
ObjectStoreInfo::~ObjectStoreInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ObjectStoreInfo);
|
||||
}
|
||||
|
||||
IndexUpdateInfo::IndexUpdateInfo()
|
||||
{
|
||||
MOZ_COUNT_CTOR(IndexUpdateInfo);
|
||||
}
|
||||
IndexUpdateInfo::~IndexUpdateInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(IndexUpdateInfo);
|
||||
}
|
||||
#endif /* NS_BUILD_REFCNT_LOGGING */
|
||||
|
||||
// static
|
||||
bool
|
||||
DatabaseInfo::Get(PRUint32 aId,
|
||||
|
|
|
@ -57,8 +57,13 @@ struct DatabaseInfo
|
|||
|
||||
nsAutoRefCnt referenceCount;
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
DatabaseInfo();
|
||||
~DatabaseInfo();
|
||||
#else
|
||||
DatabaseInfo()
|
||||
: id(0) { }
|
||||
#endif
|
||||
|
||||
static bool Get(PRUint32 aId,
|
||||
DatabaseInfo** aInfo);
|
||||
|
@ -73,8 +78,13 @@ struct DatabaseInfo
|
|||
|
||||
struct IndexInfo
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
IndexInfo();
|
||||
~IndexInfo();
|
||||
#else
|
||||
IndexInfo()
|
||||
: id(LL_MININT), unique(false), autoIncrement(false) { }
|
||||
#endif
|
||||
|
||||
PRInt64 id;
|
||||
nsString name;
|
||||
|
@ -92,8 +102,13 @@ struct ObjectStoreInfo
|
|||
PRUint32 databaseId;
|
||||
nsTArray<IndexInfo> indexes;
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ObjectStoreInfo();
|
||||
~ObjectStoreInfo();
|
||||
#else
|
||||
ObjectStoreInfo()
|
||||
: id(0), autoIncrement(false), databaseId(0) { }
|
||||
#endif
|
||||
|
||||
static bool Get(PRUint32 aDatabaseId,
|
||||
const nsAString& aName,
|
||||
|
@ -107,6 +122,11 @@ struct ObjectStoreInfo
|
|||
|
||||
struct IndexUpdateInfo
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
IndexUpdateInfo();
|
||||
~IndexUpdateInfo();
|
||||
#endif
|
||||
|
||||
IndexInfo info;
|
||||
Key value;
|
||||
};
|
||||
|
|
|
@ -224,14 +224,10 @@ already_AddRefed<IDBDatabase>
|
|||
IDBDatabase::Create(nsIScriptContext* aScriptContext,
|
||||
nsPIDOMWindow* aOwner,
|
||||
DatabaseInfo* aDatabaseInfo,
|
||||
LazyIdleThread* aThread,
|
||||
nsCOMPtr<mozIStorageConnection>& aConnection,
|
||||
const nsACString& aASCIIOrigin)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aDatabaseInfo, "Null pointer!");
|
||||
NS_ASSERTION(aThread, "Null pointer!");
|
||||
NS_ASSERTION(aConnection, "Null pointer!");
|
||||
NS_ASSERTION(!aASCIIOrigin.IsEmpty(), "Empty origin!");
|
||||
|
||||
nsRefPtr<IDBDatabase> db(new IDBDatabase());
|
||||
|
@ -245,16 +241,11 @@ IDBDatabase::Create(nsIScriptContext* aScriptContext,
|
|||
db->mFilePath = aDatabaseInfo->filePath;
|
||||
db->mASCIIOrigin = aASCIIOrigin;
|
||||
|
||||
aThread->SetWeakIdleObserver(db);
|
||||
db->mConnectionThread = aThread;
|
||||
|
||||
db->mConnection.swap(aConnection);
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
|
||||
if (!mgr->RegisterDatabase(db)) {
|
||||
NS_WARNING("Out of memory?");
|
||||
// Either out of memory or shutting down.
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
@ -263,7 +254,8 @@ IDBDatabase::Create(nsIScriptContext* aScriptContext,
|
|||
|
||||
IDBDatabase::IDBDatabase()
|
||||
: mDatabaseId(0),
|
||||
mInvalidated(0)
|
||||
mInvalidated(0),
|
||||
mRegistered(false)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
|
@ -276,17 +268,14 @@ IDBDatabase::IDBDatabase()
|
|||
IDBDatabase::~IDBDatabase()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
if (mgr) {
|
||||
mgr->UnregisterDatabase(this);
|
||||
}
|
||||
|
||||
if (mConnectionThread) {
|
||||
mConnectionThread->SetWeakIdleObserver(nsnull);
|
||||
if (mRegistered) {
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
if (mgr) {
|
||||
mgr->UnregisterDatabase(this);
|
||||
}
|
||||
}
|
||||
|
||||
CloseConnection();
|
||||
|
||||
if (mDatabaseId && !mInvalidated) {
|
||||
DatabaseInfo* info;
|
||||
if (!DatabaseInfo::Get(mDatabaseId, &info)) {
|
||||
|
@ -314,40 +303,6 @@ IDBDatabase::~IDBDatabase()
|
|||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
IDBDatabase::GetOrCreateConnection(mozIStorageConnection** aResult)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (mInvalidated) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (!mConnection) {
|
||||
mConnection = IDBFactory::GetConnection(mFilePath);
|
||||
NS_ENSURE_TRUE(mConnection, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> result(mConnection);
|
||||
result.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
IDBDatabase::CloseConnection()
|
||||
{
|
||||
if (mConnection) {
|
||||
if (mConnectionThread) {
|
||||
NS_ProxyRelease(mConnectionThread, mConnection, PR_TRUE);
|
||||
}
|
||||
else {
|
||||
NS_ERROR("Leaking connection!");
|
||||
mozIStorageConnection* leak;
|
||||
mConnection.forget(&leak);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsQuotaDisabled()
|
||||
{
|
||||
|
@ -415,7 +370,6 @@ IDBDatabase::Invalidate()
|
|||
}
|
||||
|
||||
PR_AtomicSet(&mInvalidated, 1);
|
||||
CloseConnection();
|
||||
|
||||
DatabaseInfo* info;
|
||||
if (!DatabaseInfo::Get(mDatabaseId, &info)) {
|
||||
|
@ -448,7 +402,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBDatabase)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIIDBDatabase)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBDatabase)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
|
@ -653,6 +606,10 @@ IDBDatabase::Transaction(nsIVariant* aStoreNames,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (IndexedDatabaseManager::IsShuttingDown()) {
|
||||
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
|
||||
}
|
||||
|
||||
if (aOptionalArgCount) {
|
||||
if (aMode != nsIIDBTransaction::READ_WRITE &&
|
||||
aMode != nsIIDBTransaction::READ_ONLY &&
|
||||
|
@ -831,19 +788,6 @@ IDBDatabase::ObjectStore(const nsAString& aName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IDBDatabase::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_FALSE(strcmp(aTopic, IDLE_THREAD_TOPIC), NS_ERROR_UNEXPECTED);
|
||||
|
||||
CloseConnection();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint16
|
||||
SetVersionHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
{
|
||||
|
|
|
@ -41,16 +41,13 @@
|
|||
#define mozilla_dom_indexeddb_idbdatabase_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
#include "mozilla/dom/indexedDB/LazyIdleThread.h"
|
||||
|
||||
#include "nsIIDBDatabase.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsDOMLists.h"
|
||||
|
||||
class mozIStorageConnection;
|
||||
class nsIScriptContext;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
|
@ -59,17 +56,17 @@ BEGIN_INDEXEDDB_NAMESPACE
|
|||
class AsyncConnectionHelper;
|
||||
struct DatabaseInfo;
|
||||
class IDBTransaction;
|
||||
class IndexedDatabaseManager;
|
||||
|
||||
class IDBDatabase : public nsDOMEventTargetHelper,
|
||||
public nsIIDBDatabase,
|
||||
public nsIObserver
|
||||
public nsIIDBDatabase
|
||||
{
|
||||
friend class AsyncConnectionHelper;
|
||||
friend class IndexedDatabaseManager;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIIDBDATABASE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase,
|
||||
nsDOMEventTargetHelper)
|
||||
|
@ -78,17 +75,8 @@ public:
|
|||
Create(nsIScriptContext* aScriptContext,
|
||||
nsPIDOMWindow* aOwner,
|
||||
DatabaseInfo* aDatabaseInfo,
|
||||
LazyIdleThread* aThread,
|
||||
nsCOMPtr<mozIStorageConnection>& aConnection,
|
||||
const nsACString& aASCIIOrigin);
|
||||
|
||||
nsIThread* ConnectionThread()
|
||||
{
|
||||
return mConnectionThread;
|
||||
}
|
||||
|
||||
void CloseConnection();
|
||||
|
||||
PRUint32 Id()
|
||||
{
|
||||
return mDatabaseId;
|
||||
|
@ -111,8 +99,7 @@ public:
|
|||
return mOwner;
|
||||
}
|
||||
|
||||
bool
|
||||
IsQuotaDisabled();
|
||||
bool IsQuotaDisabled();
|
||||
|
||||
nsCString& Origin()
|
||||
{
|
||||
|
@ -126,21 +113,13 @@ private:
|
|||
IDBDatabase();
|
||||
~IDBDatabase();
|
||||
|
||||
// Only meant to be called on mStorageThread!
|
||||
nsresult GetOrCreateConnection(mozIStorageConnection** aConnection);
|
||||
|
||||
PRUint32 mDatabaseId;
|
||||
nsString mName;
|
||||
nsString mDescription;
|
||||
nsString mFilePath;
|
||||
nsCString mASCIIOrigin;
|
||||
PRInt32 mInvalidated;
|
||||
|
||||
nsRefPtr<LazyIdleThread> mConnectionThread;
|
||||
|
||||
// Only touched on mStorageThread! These must be destroyed in the
|
||||
// FireCloseConnectionRunnable method.
|
||||
nsCOMPtr<mozIStorageConnection> mConnection;
|
||||
bool mRegistered;
|
||||
|
||||
// Only touched on the main thread.
|
||||
nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;
|
||||
|
|
|
@ -128,30 +128,24 @@ public:
|
|||
OpenDatabaseHelper(IDBRequest* aRequest,
|
||||
const nsAString& aName,
|
||||
const nsAString& aDescription,
|
||||
const nsACString& aASCIIOrigin,
|
||||
LazyIdleThread* aThread)
|
||||
const nsACString& aASCIIOrigin)
|
||||
: AsyncConnectionHelper(static_cast<IDBDatabase*>(nsnull), aRequest),
|
||||
mName(aName), mDescription(aDescription), mASCIIOrigin(aASCIIOrigin),
|
||||
mThread(aThread), mDatabaseId(0)
|
||||
mDatabaseId(0)
|
||||
{ }
|
||||
|
||||
PRUint16 DoDatabaseWork(mozIStorageConnection* aConnection);
|
||||
PRUint16 GetSuccessResult(nsIWritableVariant* aResult);
|
||||
|
||||
private:
|
||||
PRUint16 DoDatabaseWorkInternal(mozIStorageConnection* aConnection);
|
||||
|
||||
// In-params.
|
||||
nsString mName;
|
||||
nsString mDescription;
|
||||
nsCString mASCIIOrigin;
|
||||
nsRefPtr<LazyIdleThread> mThread;
|
||||
|
||||
// Out-params.
|
||||
nsTArray<nsAutoPtr<ObjectStoreInfo> > mObjectStores;
|
||||
nsString mVersion;
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> mConnection;
|
||||
nsString mDatabaseFilePath;
|
||||
PRUint32 mDatabaseId;
|
||||
};
|
||||
|
@ -718,14 +712,11 @@ IDBFactory::Open(const nsAString& aName,
|
|||
nsRefPtr<IDBRequest> request = IDBRequest::Create(this, context, innerWindow);
|
||||
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
|
||||
|
||||
nsRefPtr<LazyIdleThread> thread(new LazyIdleThread(kDefaultThreadTimeoutMS,
|
||||
nsnull));
|
||||
|
||||
nsRefPtr<OpenDatabaseHelper> openHelper =
|
||||
new OpenDatabaseHelper(request, aName, aDescription, origin, thread);
|
||||
new OpenDatabaseHelper(request, aName, aDescription, origin);
|
||||
|
||||
nsRefPtr<CheckPermissionsHelper> permissionHelper =
|
||||
new CheckPermissionsHelper(openHelper, thread, innerWindow, origin);
|
||||
new CheckPermissionsHelper(openHelper, innerWindow, origin);
|
||||
|
||||
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::GetOrCreate();
|
||||
NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE);
|
||||
|
@ -839,30 +830,26 @@ IDBFactory::MakeBoundKeyRange(nsIVariant* aLeft,
|
|||
|
||||
PRUint16
|
||||
OpenDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
{
|
||||
PRUint16 result = DoDatabaseWorkInternal(aConnection);
|
||||
if (result != OK) {
|
||||
mConnection = nsnull;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PRUint16
|
||||
OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
{
|
||||
PRBool correctThread;
|
||||
NS_ASSERTION(NS_SUCCEEDED(mThread->IsOnCurrentThread(&correctThread)) &&
|
||||
NS_ASSERTION(NS_SUCCEEDED(IndexedDatabaseManager::Get()->IOThread()->
|
||||
IsOnCurrentThread(&correctThread)) &&
|
||||
correctThread,
|
||||
"Running on the wrong thread!");
|
||||
}
|
||||
#endif
|
||||
NS_ASSERTION(!aConnection, "Huh?!");
|
||||
|
||||
if (IndexedDatabaseManager::IsShuttingDown()) {
|
||||
return nsIIDBDatabaseException::UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> connection;
|
||||
nsresult rv = CreateDatabaseConnection(mASCIIOrigin, mName, mDescription,
|
||||
mDatabaseFilePath,
|
||||
getter_AddRefs(mConnection));
|
||||
getter_AddRefs(connection));
|
||||
NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseException::UNKNOWN_ERR);
|
||||
|
||||
mDatabaseId = HashString(mDatabaseFilePath);
|
||||
|
@ -872,7 +859,7 @@ OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
|
|||
|
||||
{ // Load object store names and ids.
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT name, id, key_path, auto_increment "
|
||||
"FROM object_store"
|
||||
), getter_AddRefs(stmt));
|
||||
|
@ -910,7 +897,7 @@ OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
|
|||
|
||||
{ // Load index information
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT object_store_id, id, name, key_path, unique_index, "
|
||||
"object_store_autoincrement "
|
||||
"FROM object_store_index"
|
||||
|
@ -951,7 +938,7 @@ OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
|
|||
|
||||
{ // Load version information.
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT version "
|
||||
"FROM database"
|
||||
), getter_AddRefs(stmt));
|
||||
|
@ -975,8 +962,6 @@ OpenDatabaseHelper::DoDatabaseWorkInternal(mozIStorageConnection* aConnection)
|
|||
PRUint16
|
||||
OpenDatabaseHelper::GetSuccessResult(nsIWritableVariant* aResult)
|
||||
{
|
||||
NS_ASSERTION(mConnection, "Should have a connection!");
|
||||
|
||||
DatabaseInfo* dbInfo;
|
||||
if (DatabaseInfo::Get(mDatabaseId, &dbInfo)) {
|
||||
NS_ASSERTION(dbInfo->referenceCount, "Bad reference count!");
|
||||
|
@ -1064,10 +1049,10 @@ OpenDatabaseHelper::GetSuccessResult(nsIWritableVariant* aResult)
|
|||
|
||||
nsRefPtr<IDBDatabase> db =
|
||||
IDBDatabase::Create(mRequest->ScriptContext(), mRequest->Owner(), dbInfo,
|
||||
mThread, mConnection, mASCIIOrigin);
|
||||
NS_ASSERTION(db, "This can't fail!");
|
||||
|
||||
NS_ASSERTION(!mConnection, "Should have swapped out!");
|
||||
mASCIIOrigin);
|
||||
if (!db) {
|
||||
return nsIIDBDatabaseException::UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
aResult->SetAsISupports(static_cast<nsPIDOMEventTarget*>(db));
|
||||
return OK;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "nsHashKeys.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
|
||||
class mozIStorageConnection;
|
||||
class mozIStorageStatement;
|
||||
class nsIThread;
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ using namespace mozilla::services;
|
|||
|
||||
namespace {
|
||||
|
||||
bool gShutdown = false;
|
||||
PRInt32 gShutdown = 0;
|
||||
|
||||
// Does not hold a reference.
|
||||
IndexedDatabaseManager* gInstance = nsnull;
|
||||
|
@ -116,7 +116,7 @@ IndexedDatabaseManager::GetOrCreate()
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (gShutdown) {
|
||||
if (IsShuttingDown()) {
|
||||
NS_ERROR("Calling GetOrCreateInstance() after shutdown!");
|
||||
return nsnull;
|
||||
}
|
||||
|
@ -153,7 +153,8 @@ IndexedDatabaseManager::GetOrCreate()
|
|||
|
||||
// Make a lazy thread for any IO we need (like clearing or enumerating the
|
||||
// contents of indexedDB database directories).
|
||||
instance->mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS);
|
||||
instance->mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
|
||||
LazyIdleThread::ManualShutdown);
|
||||
|
||||
// The observer service will hold our last reference, don't AddRef here.
|
||||
gInstance = instance;
|
||||
|
@ -187,7 +188,7 @@ IndexedDatabaseManager::RegisterDatabase(IDBDatabase* aDatabase)
|
|||
NS_ASSERTION(aDatabase, "Null pointer!");
|
||||
|
||||
// Don't allow any new databases to be created after shutdown.
|
||||
if (gShutdown) {
|
||||
if (IsShuttingDown()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -205,6 +206,8 @@ IndexedDatabaseManager::RegisterDatabase(IDBDatabase* aDatabase)
|
|||
NS_WARNING("Out of memory?");
|
||||
return false;
|
||||
}
|
||||
|
||||
aDatabase->mRegistered = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -287,6 +290,13 @@ IndexedDatabaseManager::WaitForClearAndDispatch(const nsACString& aOrigin,
|
|||
return NS_DispatchToCurrentThread(aRunnable);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
IndexedDatabaseManager::IsShuttingDown()
|
||||
{
|
||||
return !!gShutdown;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(IndexedDatabaseManager, nsIIndexedDatabaseManager,
|
||||
nsIObserver)
|
||||
|
||||
|
@ -445,9 +455,11 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject,
|
|||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID)) {
|
||||
// Setting this flag prevents the servic from being recreated and prevents
|
||||
// Setting this flag prevents the service from being recreated and prevents
|
||||
// further databases from being created.
|
||||
gShutdown = true;
|
||||
if (PR_AtomicSet(&gShutdown, 1)) {
|
||||
NS_ERROR("Shutdown more than once?!");
|
||||
}
|
||||
|
||||
// Make sure to join with our IO thread.
|
||||
if (NS_FAILED(mIOThread->Shutdown())) {
|
||||
|
|
|
@ -80,6 +80,14 @@ public:
|
|||
nsresult WaitForClearAndDispatch(const nsACString& aOrigin,
|
||||
nsIRunnable* aRunnable);
|
||||
|
||||
nsIThread* IOThread()
|
||||
{
|
||||
NS_ASSERTION(mIOThread, "This should never be null!");
|
||||
return mIOThread;
|
||||
}
|
||||
|
||||
static bool IsShuttingDown();
|
||||
|
||||
private:
|
||||
IndexedDatabaseManager();
|
||||
~IndexedDatabaseManager();
|
||||
|
|
|
@ -64,6 +64,7 @@ USING_INDEXEDDB_NAMESPACE
|
|||
using mozilla::MutexAutoLock;
|
||||
|
||||
LazyIdleThread::LazyIdleThread(PRUint32 aIdleTimeoutMS,
|
||||
ShutdownMethod aShutdownMethod,
|
||||
nsIObserver* aIdleObserver)
|
||||
: mMutex("LazyIdleThread::mMutex"),
|
||||
mOwningThread(NS_GetCurrentThread()),
|
||||
|
@ -71,6 +72,7 @@ LazyIdleThread::LazyIdleThread(PRUint32 aIdleTimeoutMS,
|
|||
mIdleTimeoutMS(aIdleTimeoutMS),
|
||||
mPendingEventCount(0),
|
||||
mIdleNotificationCount(0),
|
||||
mShutdownMethod(aShutdownMethod),
|
||||
mShutdown(PR_FALSE),
|
||||
mThreadIsShuttingDown(PR_FALSE),
|
||||
mIdleTimeoutEnabled(PR_TRUE)
|
||||
|
@ -172,7 +174,7 @@ LazyIdleThread::EnsureThread()
|
|||
|
||||
nsresult rv;
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
if (mShutdownMethod == AutomaticShutdown && NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -257,7 +259,7 @@ LazyIdleThread::ShutdownThread()
|
|||
nsresult rv;
|
||||
|
||||
if (mThread) {
|
||||
if (NS_IsMainThread()) {
|
||||
if (mShutdownMethod == AutomaticShutdown && NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
NS_WARN_IF_FALSE(obs, "Failed to get observer service!");
|
||||
|
@ -504,8 +506,10 @@ LazyIdleThread::Observe(nsISupports* /* aSubject */,
|
|||
const PRUnichar* /* aData */)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ENSURE_FALSE(strcmp("xpcom-shutdown-threads", aTopic),
|
||||
NS_ERROR_UNEXPECTED);
|
||||
NS_ASSERTION(mShutdownMethod == AutomaticShutdown,
|
||||
"Should not receive notifications if not AutomaticShutdown!");
|
||||
NS_ASSERTION(!strcmp("xpcom-shutdown-threads", aTopic), "Bad topic!");
|
||||
|
||||
Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -72,11 +72,17 @@ public:
|
|||
NS_DECL_NSITHREADOBSERVER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
enum ShutdownMethod {
|
||||
AutomaticShutdown = 0,
|
||||
ManualShutdown
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new LazyIdleThread that will destroy its thread after the given
|
||||
* number of milliseconds.
|
||||
*/
|
||||
LazyIdleThread(PRUint32 aIdleTimeoutMS,
|
||||
ShutdownMethod aShutdownMethod = AutomaticShutdown,
|
||||
nsIObserver* aIdleObserver = nsnull);
|
||||
|
||||
/**
|
||||
|
@ -191,6 +197,13 @@ private:
|
|||
*/
|
||||
PRUint32 mIdleNotificationCount;
|
||||
|
||||
/**
|
||||
* Whether or not the thread should automatically shutdown. If the owner
|
||||
* specified ManualShutdown at construction time then the owner should take
|
||||
* care to call Shutdown() manually when appropriate.
|
||||
*/
|
||||
ShutdownMethod mShutdownMethod;
|
||||
|
||||
/**
|
||||
* Only accessed on the owning thread. Set to true when Shutdown() has been
|
||||
* called and prevents EnsureThread() from recreating mThread.
|
||||
|
|
Загрузка…
Ссылка в новой задаче