Loading browser/components/search/nsSearchService.js +11 −1 Original line number Diff line number Diff line Loading @@ -2726,7 +2726,17 @@ var engineMetadataService = { file.append("search.sqlite"); var dbService = Cc["@mozilla.org/storage/service;1"]. getService(Ci.mozIStorageService); try { this.mDB = dbService.openDatabase(file); } catch (ex) { if (ex.result == 0x8052000b) { /* NS_ERROR_FILE_CORRUPTED */ // delete and try again file.remove(false); this.mDB = dbService.openDatabase(file); } else { throw ex; } } try { this.mDB.createTable("engine_data", engineDataTable); Loading dom/src/storage/nsDOMStorageDB.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,12 @@ nsDOMStorageDB::Init() service = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = service->OpenDatabase(storageFile, getter_AddRefs(mConnection)); if (rv == NS_ERROR_FILE_CORRUPTED) { // delete the db and try opening again rv = storageFile->Remove(PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); rv = service->OpenDatabase(storageFile, getter_AddRefs(mConnection)); } NS_ENSURE_SUCCESS(rv, rv); PRBool exists; Loading storage/src/mozStorageAsyncIO.cpp +84 −0 Original line number Diff line number Diff line Loading @@ -363,6 +363,12 @@ struct AsyncMessage AsyncMessage* mNext; }; struct AsyncMessageBarrierData { PRLock *mLock; PRCondVar *mCondVar; }; // Possible values of AsyncMessage.mOp #define ASYNC_WRITE 1 #define ASYNC_SYNC 2 Loading @@ -373,6 +379,7 @@ struct AsyncMessage #define ASYNC_DELETE 7 #define ASYNC_OPENEXCLUSIVE 8 #define ASYNC_SYNCDIRECTORY 9 #define ASYNC_BARRIER 10 // replacements for the sqlite OS routines static int AsyncOpenReadWrite(const char *aName, OsFile **aFile, int *aReadOnly); Loading @@ -396,6 +403,8 @@ static int AsyncUnlock(OsFile* aFile, int aLockType); static int AsyncCheckReservedLock(OsFile* aFile); static int AsyncLockState(OsFile* aFile); static int AsyncBarrier(PRLock* aLock, PRCondVar* aCondVar); // backend for all the open functions static int AsyncOpenFile(const char *aName, AsyncOsFile **aFile, OsFile *aBaseRead, PRBool aOpenForWriting); Loading Loading @@ -537,6 +546,56 @@ mozStorageService::InitStorageAsyncIO() return NS_OK; } // mozstorageService::FlushAsyncIO // // This function will grab the async lock and process all // remaining async operations that are in the queue on the current // thread. Call this when you need to make sure that an operation // has taken place, e.g. that a file has been closed. nsresult mozStorageService::FlushAsyncIO() { AsyncMessage *message = 0; int rc; // single threaded? nothing to do. if (!AsyncWriteThreadInstance) return NS_OK; PRLock *flushLock = PR_NewLock(); if (!flushLock) return NS_ERROR_OUT_OF_MEMORY; PRCondVar *flushCond = PR_NewCondVar(flushLock); if (!flushCond) { PR_DestroyLock(flushLock); return NS_ERROR_OUT_OF_MEMORY; } PR_Lock(flushLock); rc = AsyncBarrier(flushLock, flushCond); if (rc == SQLITE_OK) { // the async thread will notify us once it reaches // the ASYNC_BARRIER operation; only wait if // adding the barrier worked, otherwise just unlock // and return the error PR_WaitCondVar(flushCond, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(flushLock); PR_DestroyCondVar(flushCond); PR_DestroyLock(flushLock); if (rc == SQLITE_NOMEM) return NS_ERROR_OUT_OF_MEMORY; else if (rc != SQLITE_OK) return NS_ERROR_FAILURE; return NS_OK; } // mozStorageService::FinishAsyncIO // Loading Loading @@ -1275,6 +1334,23 @@ AsyncLockState(OsFile* aFile) return SQLITE_OK; } // AsyncBarrier // // This is used to notify a waiting thread that this point in the async // queue has been reached. Note that this is not a sqlite redirected IO // function int // static AsyncBarrier(PRLock* aLock, PRCondVar* aCondVar) { AsyncMessageBarrierData bd; bd.mLock = aLock; bd.mCondVar = aCondVar; return AppendNewAsyncMessage(nsnull, ASYNC_BARRIER, 0, sizeof(AsyncMessageBarrierData), (const char*) &bd); } // ProcessOneMessage // Loading Loading @@ -1385,6 +1461,14 @@ ProcessOneMessage(AsyncMessage* aMessage) break; } case ASYNC_BARRIER: { AsyncMessageBarrierData *bd = (AsyncMessageBarrierData*) aMessage->mBuf; PR_Lock(bd->mLock); PR_NotifyCondVar(bd->mCondVar); PR_Unlock(bd->mLock); break; } default: NS_NOTREACHED("Illegal value for AsyncMessage.mOp"); } Loading storage/src/mozStorageConnection.cpp +61 −13 Original line number Diff line number Diff line Loading @@ -73,7 +73,31 @@ mozStorageConnection::~mozStorageConnection() if (srv != SQLITE_OK) { NS_WARNING("sqlite3_close failed. There are probably outstanding statements!"); } // make sure it really got closed ((mozStorageService*)(mStorageService.get()))->FlushAsyncIO(); } } // convert a sqlite srv to an nsresult static nsresult ConvertResultCode (int srv) { switch (srv) { case SQLITE_OK: return NS_OK; case SQLITE_CORRUPT: case SQLITE_NOTADB: return NS_ERROR_FILE_CORRUPTED; case SQLITE_PERM: case SQLITE_CANTOPEN: return NS_ERROR_FILE_ACCESS_DENIED; case SQLITE_BUSY: return NS_ERROR_FILE_IS_LOCKED; } // generic error return NS_ERROR_FAILURE; } #ifdef PR_LOGGING Loading Loading @@ -109,7 +133,7 @@ mozStorageConnection::Initialize(nsIFile *aDatabaseFile) } if (srv != SQLITE_OK) { mDBConn = nsnull; return NS_ERROR_FAILURE; // XXX error code return ConvertResultCode(srv); } #ifdef PR_LOGGING Loading @@ -119,6 +143,35 @@ mozStorageConnection::Initialize(nsIFile *aDatabaseFile) sqlite3_trace (mDBConn, tracefunc, nsnull); #endif /* Execute a dummy statement to force the db open, and to verify * whether it's valid or not */ sqlite3_stmt *stmt = nsnull; nsCString query("SELECT * FROM sqlite_master"); srv = sqlite3_prepare (mDBConn, query.get(), query.Length(), &stmt, nsnull); if (srv == SQLITE_OK) { srv = sqlite3_step(stmt); if (srv == SQLITE_DONE || srv == SQLITE_ROW) srv = SQLITE_OK; } else { stmt = nsnull; } if (stmt != nsnull) sqlite3_finalize (stmt); if (srv != SQLITE_OK) { sqlite3_close (mDBConn); mDBConn = nsnull; // make sure it really got closed ((mozStorageService*)(mStorageService.get()))->FlushAsyncIO(); return ConvertResultCode(srv); } mFunctions = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; Loading Loading @@ -199,7 +252,7 @@ mozStorageConnection::CreateStatement(const nsACString& aSQLStatement, nsresult rv = statement->Initialize (this, aSQLStatement); if (NS_FAILED(rv)) { NS_RELEASE(statement); return NS_ERROR_FAILURE; // XXX error code return rv; } *_retval = statement; Loading @@ -215,7 +268,7 @@ mozStorageConnection::ExecuteSimpleSQL(const nsACString& aSQLStatement) NULL, NULL, NULL); if (srv != SQLITE_OK) { HandleSqliteError(nsPromiseFlatCString(aSQLStatement).get()); return NS_ERROR_FAILURE; // XXX error code return ConvertResultCode(srv); } return NS_OK; Loading @@ -234,7 +287,7 @@ mozStorageConnection::TableExists(const nsACString& aSQLStatement, PRBool *_retv int srv = sqlite3_prepare (mDBConn, query.get(), query.Length(), &stmt, nsnull); if (srv != SQLITE_OK) { HandleSqliteError(query.get()); return NS_ERROR_FAILURE; // XXX error code return ConvertResultCode(srv); } PRBool exists = PR_FALSE; Loading Loading @@ -269,7 +322,7 @@ mozStorageConnection::IndexExists(const nsACString& aIndexName, PRBool* _retval) int srv = sqlite3_prepare(mDBConn, query.get(), query.Length(), &stmt, nsnull); if (srv != SQLITE_OK) { HandleSqliteError(query.get()); return NS_ERROR_FAILURE; // XXX error code return ConvertResultCode(srv); } PRBool exists = PR_FALSE; Loading Loading @@ -381,10 +434,7 @@ mozStorageConnection::CreateTable(/*const nsID& aID,*/ PR_smprintf_free(buf); if (srv != SQLITE_OK) { return NS_ERROR_FAILURE; // XXX SQL_ERROR_TABLE_EXISTS } return NS_OK; return ConvertResultCode(srv); } /** Loading Loading @@ -433,7 +483,7 @@ mozStorageConnection::CreateFunction(const char *aFunctionName, nsnull); if (srv != SQLITE_OK) { HandleSqliteError(nsnull); return NS_ERROR_FAILURE; return ConvertResultCode(srv); } rv = mFunctions->AppendElement (aFunction, PR_FALSE); Loading @@ -450,9 +500,7 @@ nsresult mozStorageConnection::Preload() { int srv = sqlite3Preload(mDBConn); if (srv != SQLITE_OK) return NS_ERROR_FAILURE; return NS_OK; return ConvertResultCode(srv); } /** Loading storage/src/mozStorageService.h +5 −0 Original line number Diff line number Diff line Loading @@ -48,9 +48,13 @@ #include "mozIStorageService.h" class mozStorageConnection; class mozStorageService : public mozIStorageService, public nsIObserver { friend class mozStorageConnection; public: mozStorageService(); Loading @@ -71,6 +75,7 @@ protected: nsCOMPtr<nsIFile> mProfileStorageFile; nsresult InitStorageAsyncIO(); nsresult FlushAsyncIO(); nsresult FinishAsyncIO(); void FreeLocks(); }; Loading Loading
browser/components/search/nsSearchService.js +11 −1 Original line number Diff line number Diff line Loading @@ -2726,7 +2726,17 @@ var engineMetadataService = { file.append("search.sqlite"); var dbService = Cc["@mozilla.org/storage/service;1"]. getService(Ci.mozIStorageService); try { this.mDB = dbService.openDatabase(file); } catch (ex) { if (ex.result == 0x8052000b) { /* NS_ERROR_FILE_CORRUPTED */ // delete and try again file.remove(false); this.mDB = dbService.openDatabase(file); } else { throw ex; } } try { this.mDB.createTable("engine_data", engineDataTable); Loading
dom/src/storage/nsDOMStorageDB.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,12 @@ nsDOMStorageDB::Init() service = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = service->OpenDatabase(storageFile, getter_AddRefs(mConnection)); if (rv == NS_ERROR_FILE_CORRUPTED) { // delete the db and try opening again rv = storageFile->Remove(PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); rv = service->OpenDatabase(storageFile, getter_AddRefs(mConnection)); } NS_ENSURE_SUCCESS(rv, rv); PRBool exists; Loading
storage/src/mozStorageAsyncIO.cpp +84 −0 Original line number Diff line number Diff line Loading @@ -363,6 +363,12 @@ struct AsyncMessage AsyncMessage* mNext; }; struct AsyncMessageBarrierData { PRLock *mLock; PRCondVar *mCondVar; }; // Possible values of AsyncMessage.mOp #define ASYNC_WRITE 1 #define ASYNC_SYNC 2 Loading @@ -373,6 +379,7 @@ struct AsyncMessage #define ASYNC_DELETE 7 #define ASYNC_OPENEXCLUSIVE 8 #define ASYNC_SYNCDIRECTORY 9 #define ASYNC_BARRIER 10 // replacements for the sqlite OS routines static int AsyncOpenReadWrite(const char *aName, OsFile **aFile, int *aReadOnly); Loading @@ -396,6 +403,8 @@ static int AsyncUnlock(OsFile* aFile, int aLockType); static int AsyncCheckReservedLock(OsFile* aFile); static int AsyncLockState(OsFile* aFile); static int AsyncBarrier(PRLock* aLock, PRCondVar* aCondVar); // backend for all the open functions static int AsyncOpenFile(const char *aName, AsyncOsFile **aFile, OsFile *aBaseRead, PRBool aOpenForWriting); Loading Loading @@ -537,6 +546,56 @@ mozStorageService::InitStorageAsyncIO() return NS_OK; } // mozstorageService::FlushAsyncIO // // This function will grab the async lock and process all // remaining async operations that are in the queue on the current // thread. Call this when you need to make sure that an operation // has taken place, e.g. that a file has been closed. nsresult mozStorageService::FlushAsyncIO() { AsyncMessage *message = 0; int rc; // single threaded? nothing to do. if (!AsyncWriteThreadInstance) return NS_OK; PRLock *flushLock = PR_NewLock(); if (!flushLock) return NS_ERROR_OUT_OF_MEMORY; PRCondVar *flushCond = PR_NewCondVar(flushLock); if (!flushCond) { PR_DestroyLock(flushLock); return NS_ERROR_OUT_OF_MEMORY; } PR_Lock(flushLock); rc = AsyncBarrier(flushLock, flushCond); if (rc == SQLITE_OK) { // the async thread will notify us once it reaches // the ASYNC_BARRIER operation; only wait if // adding the barrier worked, otherwise just unlock // and return the error PR_WaitCondVar(flushCond, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(flushLock); PR_DestroyCondVar(flushCond); PR_DestroyLock(flushLock); if (rc == SQLITE_NOMEM) return NS_ERROR_OUT_OF_MEMORY; else if (rc != SQLITE_OK) return NS_ERROR_FAILURE; return NS_OK; } // mozStorageService::FinishAsyncIO // Loading Loading @@ -1275,6 +1334,23 @@ AsyncLockState(OsFile* aFile) return SQLITE_OK; } // AsyncBarrier // // This is used to notify a waiting thread that this point in the async // queue has been reached. Note that this is not a sqlite redirected IO // function int // static AsyncBarrier(PRLock* aLock, PRCondVar* aCondVar) { AsyncMessageBarrierData bd; bd.mLock = aLock; bd.mCondVar = aCondVar; return AppendNewAsyncMessage(nsnull, ASYNC_BARRIER, 0, sizeof(AsyncMessageBarrierData), (const char*) &bd); } // ProcessOneMessage // Loading Loading @@ -1385,6 +1461,14 @@ ProcessOneMessage(AsyncMessage* aMessage) break; } case ASYNC_BARRIER: { AsyncMessageBarrierData *bd = (AsyncMessageBarrierData*) aMessage->mBuf; PR_Lock(bd->mLock); PR_NotifyCondVar(bd->mCondVar); PR_Unlock(bd->mLock); break; } default: NS_NOTREACHED("Illegal value for AsyncMessage.mOp"); } Loading
storage/src/mozStorageConnection.cpp +61 −13 Original line number Diff line number Diff line Loading @@ -73,7 +73,31 @@ mozStorageConnection::~mozStorageConnection() if (srv != SQLITE_OK) { NS_WARNING("sqlite3_close failed. There are probably outstanding statements!"); } // make sure it really got closed ((mozStorageService*)(mStorageService.get()))->FlushAsyncIO(); } } // convert a sqlite srv to an nsresult static nsresult ConvertResultCode (int srv) { switch (srv) { case SQLITE_OK: return NS_OK; case SQLITE_CORRUPT: case SQLITE_NOTADB: return NS_ERROR_FILE_CORRUPTED; case SQLITE_PERM: case SQLITE_CANTOPEN: return NS_ERROR_FILE_ACCESS_DENIED; case SQLITE_BUSY: return NS_ERROR_FILE_IS_LOCKED; } // generic error return NS_ERROR_FAILURE; } #ifdef PR_LOGGING Loading Loading @@ -109,7 +133,7 @@ mozStorageConnection::Initialize(nsIFile *aDatabaseFile) } if (srv != SQLITE_OK) { mDBConn = nsnull; return NS_ERROR_FAILURE; // XXX error code return ConvertResultCode(srv); } #ifdef PR_LOGGING Loading @@ -119,6 +143,35 @@ mozStorageConnection::Initialize(nsIFile *aDatabaseFile) sqlite3_trace (mDBConn, tracefunc, nsnull); #endif /* Execute a dummy statement to force the db open, and to verify * whether it's valid or not */ sqlite3_stmt *stmt = nsnull; nsCString query("SELECT * FROM sqlite_master"); srv = sqlite3_prepare (mDBConn, query.get(), query.Length(), &stmt, nsnull); if (srv == SQLITE_OK) { srv = sqlite3_step(stmt); if (srv == SQLITE_DONE || srv == SQLITE_ROW) srv = SQLITE_OK; } else { stmt = nsnull; } if (stmt != nsnull) sqlite3_finalize (stmt); if (srv != SQLITE_OK) { sqlite3_close (mDBConn); mDBConn = nsnull; // make sure it really got closed ((mozStorageService*)(mStorageService.get()))->FlushAsyncIO(); return ConvertResultCode(srv); } mFunctions = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; Loading Loading @@ -199,7 +252,7 @@ mozStorageConnection::CreateStatement(const nsACString& aSQLStatement, nsresult rv = statement->Initialize (this, aSQLStatement); if (NS_FAILED(rv)) { NS_RELEASE(statement); return NS_ERROR_FAILURE; // XXX error code return rv; } *_retval = statement; Loading @@ -215,7 +268,7 @@ mozStorageConnection::ExecuteSimpleSQL(const nsACString& aSQLStatement) NULL, NULL, NULL); if (srv != SQLITE_OK) { HandleSqliteError(nsPromiseFlatCString(aSQLStatement).get()); return NS_ERROR_FAILURE; // XXX error code return ConvertResultCode(srv); } return NS_OK; Loading @@ -234,7 +287,7 @@ mozStorageConnection::TableExists(const nsACString& aSQLStatement, PRBool *_retv int srv = sqlite3_prepare (mDBConn, query.get(), query.Length(), &stmt, nsnull); if (srv != SQLITE_OK) { HandleSqliteError(query.get()); return NS_ERROR_FAILURE; // XXX error code return ConvertResultCode(srv); } PRBool exists = PR_FALSE; Loading Loading @@ -269,7 +322,7 @@ mozStorageConnection::IndexExists(const nsACString& aIndexName, PRBool* _retval) int srv = sqlite3_prepare(mDBConn, query.get(), query.Length(), &stmt, nsnull); if (srv != SQLITE_OK) { HandleSqliteError(query.get()); return NS_ERROR_FAILURE; // XXX error code return ConvertResultCode(srv); } PRBool exists = PR_FALSE; Loading Loading @@ -381,10 +434,7 @@ mozStorageConnection::CreateTable(/*const nsID& aID,*/ PR_smprintf_free(buf); if (srv != SQLITE_OK) { return NS_ERROR_FAILURE; // XXX SQL_ERROR_TABLE_EXISTS } return NS_OK; return ConvertResultCode(srv); } /** Loading Loading @@ -433,7 +483,7 @@ mozStorageConnection::CreateFunction(const char *aFunctionName, nsnull); if (srv != SQLITE_OK) { HandleSqliteError(nsnull); return NS_ERROR_FAILURE; return ConvertResultCode(srv); } rv = mFunctions->AppendElement (aFunction, PR_FALSE); Loading @@ -450,9 +500,7 @@ nsresult mozStorageConnection::Preload() { int srv = sqlite3Preload(mDBConn); if (srv != SQLITE_OK) return NS_ERROR_FAILURE; return NS_OK; return ConvertResultCode(srv); } /** Loading
storage/src/mozStorageService.h +5 −0 Original line number Diff line number Diff line Loading @@ -48,9 +48,13 @@ #include "mozIStorageService.h" class mozStorageConnection; class mozStorageService : public mozIStorageService, public nsIObserver { friend class mozStorageConnection; public: mozStorageService(); Loading @@ -71,6 +75,7 @@ protected: nsCOMPtr<nsIFile> mProfileStorageFile; nsresult InitStorageAsyncIO(); nsresult FlushAsyncIO(); nsresult FinishAsyncIO(); void FreeLocks(); }; Loading