forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			243 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 | |
|  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
 | |
|  * This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef mozStorageAsyncStatementExecution_h
 | |
| #define mozStorageAsyncStatementExecution_h
 | |
| 
 | |
| #include "nscore.h"
 | |
| #include "nsTArray.h"
 | |
| #include "mozilla/Mutex.h"
 | |
| #include "mozilla/TimeStamp.h"
 | |
| #include "mozilla/Attributes.h"
 | |
| #include "nsThreadUtils.h"
 | |
| 
 | |
| #include "SQLiteMutex.h"
 | |
| #include "mozIStoragePendingStatement.h"
 | |
| #include "mozIStorageStatementCallback.h"
 | |
| #include "mozStorageHelper.h"
 | |
| 
 | |
| struct sqlite3_stmt;
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace storage {
 | |
| 
 | |
| class Connection;
 | |
| class ResultSet;
 | |
| class StatementData;
 | |
| }  // namespace storage
 | |
| }  // namespace mozilla
 | |
| 
 | |
| namespace mozilla::storage {
 | |
| class AsyncExecuteStatements final : public Runnable,
 | |
|                                      public mozIStoragePendingStatement {
 | |
|  public:
 | |
|   NS_DECL_ISUPPORTS_INHERITED
 | |
|   NS_DECL_NSIRUNNABLE
 | |
|   NS_DECL_MOZISTORAGEPENDINGSTATEMENT
 | |
| 
 | |
|   /**
 | |
|    * Describes the state of execution.
 | |
|    */
 | |
|   enum ExecutionState {
 | |
|     PENDING = -1,
 | |
|     COMPLETED = mozIStorageStatementCallback::REASON_FINISHED,
 | |
|     CANCELED = mozIStorageStatementCallback::REASON_CANCELED,
 | |
|     ERROR = mozIStorageStatementCallback::REASON_ERROR
 | |
|   };
 | |
| 
 | |
|   typedef nsTArray<StatementData> StatementDataArray;
 | |
| 
 | |
|   /**
 | |
|    * Executes a statement in the background, and passes results back to the
 | |
|    * caller.
 | |
|    *
 | |
|    * @param aStatements
 | |
|    *        The statements to execute and possibly bind in the background.
 | |
|    *        Ownership is transfered from the caller.
 | |
|    * @param aConnection
 | |
|    *        The connection that created the statements to execute.
 | |
|    * @param aNativeConnection
 | |
|    *        The native Sqlite connection that created the statements to execute.
 | |
|    * @param aCallback
 | |
|    *        The callback that is notified of results, completion, and errors.
 | |
|    * @param _stmt
 | |
|    *        The handle to control the execution of the statements.
 | |
|    */
 | |
|   static nsresult execute(StatementDataArray&& aStatements,
 | |
|                           Connection* aConnection, sqlite3* aNativeConnection,
 | |
|                           mozIStorageStatementCallback* aCallback,
 | |
|                           mozIStoragePendingStatement** _stmt);
 | |
| 
 | |
|   /**
 | |
|    * Indicates when events on the calling thread should run or not.  Certain
 | |
|    * events posted back to the calling thread should call this see if they
 | |
|    * should run or not.
 | |
|    *
 | |
|    * @pre mMutex is not held
 | |
|    *
 | |
|    * @returns true if the event should notify still, false otherwise.
 | |
|    */
 | |
|   bool shouldNotify();
 | |
| 
 | |
|   /**
 | |
|    * Used by notifyComplete(), notifyError() and notifyResults() to notify on
 | |
|    * the calling thread.
 | |
|    */
 | |
|   nsresult notifyCompleteOnCallingThread();
 | |
|   nsresult notifyErrorOnCallingThread(mozIStorageError* aError);
 | |
|   nsresult notifyResultsOnCallingThread(ResultSet* aResultSet);
 | |
| 
 | |
|  private:
 | |
|   AsyncExecuteStatements(StatementDataArray&& aStatements,
 | |
|                          Connection* aConnection, sqlite3* aNativeConnection,
 | |
|                          mozIStorageStatementCallback* aCallback);
 | |
|   ~AsyncExecuteStatements();
 | |
| 
 | |
|   /**
 | |
|    * Binds and then executes a given statement until completion, an error
 | |
|    * occurs, or we are canceled.  If aLastStatement is true, we should set
 | |
|    * mState accordingly.
 | |
|    *
 | |
|    * @pre mMutex is not held
 | |
|    *
 | |
|    * @param aData
 | |
|    *        The StatementData to bind, execute, and then process.
 | |
|    * @param aLastStatement
 | |
|    *        Indicates if this is the last statement or not.  If it is, we have
 | |
|    *        to set the proper state.
 | |
|    * @returns true if we should continue to process statements, false otherwise.
 | |
|    */
 | |
|   bool bindExecuteAndProcessStatement(StatementData& aData,
 | |
|                                       bool aLastStatement);
 | |
| 
 | |
|   /**
 | |
|    * Executes a given statement until completion, an error occurs, or we are
 | |
|    * canceled.  If aLastStatement is true, we should set mState accordingly.
 | |
|    *
 | |
|    * @pre mMutex is not held
 | |
|    *
 | |
|    * @param aData
 | |
|    *        The StatementData to execute, and then process.
 | |
|    * @param aLastStatement
 | |
|    *        Indicates if this is the last statement or not.  If it is, we have
 | |
|    *        to set the proper state.
 | |
|    * @returns true if we should continue to process statements, false otherwise.
 | |
|    */
 | |
|   bool executeAndProcessStatement(StatementData& aData, bool aLastStatement);
 | |
| 
 | |
|   /**
 | |
|    * Executes a statement to completion, properly handling any error conditions.
 | |
|    *
 | |
|    * @pre mMutex is not held
 | |
|    *
 | |
|    * @param aData
 | |
|    *        The StatementData to execute to completion.
 | |
|    * @returns true if results were obtained, false otherwise.
 | |
|    */
 | |
|   bool executeStatement(StatementData& aData);
 | |
| 
 | |
|   /**
 | |
|    * Builds a result set up with a row from a given statement.  If we meet the
 | |
|    * right criteria, go ahead and notify about this results too.
 | |
|    *
 | |
|    * @pre mMutex is not held
 | |
|    *
 | |
|    * @param aStatement
 | |
|    *        The statement to get the row data from.
 | |
|    */
 | |
|   nsresult buildAndNotifyResults(sqlite3_stmt* aStatement);
 | |
| 
 | |
|   /**
 | |
|    * Notifies callback about completion, and does any necessary cleanup.
 | |
|    *
 | |
|    * @pre mMutex is not held
 | |
|    */
 | |
|   nsresult notifyComplete();
 | |
| 
 | |
|   /**
 | |
|    * Notifies callback about an error.
 | |
|    *
 | |
|    * @pre mMutex is not held
 | |
|    * @pre mDBMutex is not held
 | |
|    *
 | |
|    * @param aErrorCode
 | |
|    *        The error code defined in mozIStorageError for the error.
 | |
|    * @param aMessage
 | |
|    *        The error string, if any.
 | |
|    * @param aError
 | |
|    *        The error object to notify the caller with.
 | |
|    */
 | |
|   nsresult notifyError(int32_t aErrorCode, const char* aMessage);
 | |
|   nsresult notifyError(mozIStorageError* aError);
 | |
| 
 | |
|   /**
 | |
|    * Notifies the callback about a result set.
 | |
|    *
 | |
|    * @pre mMutex is not held
 | |
|    */
 | |
|   nsresult notifyResults();
 | |
| 
 | |
|   /**
 | |
|    * Tests whether the current statements should be wrapped in an explicit
 | |
|    * transaction.
 | |
|    *
 | |
|    * @return true if an explicit transaction is needed, false otherwise.
 | |
|    */
 | |
|   bool statementsNeedTransaction();
 | |
| 
 | |
|   StatementDataArray mStatements;
 | |
|   RefPtr<Connection> mConnection;
 | |
|   sqlite3* mNativeConnection;
 | |
|   bool mHasTransaction;
 | |
|   // Note, this may not be a threadsafe object - never addref/release off
 | |
|   // the calling thread.  We take a reference when this is created, and
 | |
|   // release it in the CompletionNotifier::Run() call back to this thread.
 | |
|   nsCOMPtr<mozIStorageStatementCallback> mCallback;
 | |
|   nsCOMPtr<nsIThread> mCallingThread;
 | |
|   RefPtr<ResultSet> mResultSet;
 | |
| 
 | |
|   /**
 | |
|    * The maximum amount of time we want to wait between results.  Defined by
 | |
|    * MAX_MILLISECONDS_BETWEEN_RESULTS and set at construction.
 | |
|    */
 | |
|   const TimeDuration mMaxWait;
 | |
| 
 | |
|   /**
 | |
|    * The start time since our last set of results.
 | |
|    */
 | |
|   TimeStamp mIntervalStart;
 | |
| 
 | |
|   /**
 | |
|    * Indicates our state of execution.
 | |
|    */
 | |
|   ExecutionState mState;
 | |
| 
 | |
|   /**
 | |
|    * Indicates if we should try to cancel at a cancelation point.
 | |
|    */
 | |
|   bool mCancelRequested;
 | |
| 
 | |
|   /**
 | |
|    * This is the mutex that protects our state from changing between threads.
 | |
|    * This includes the following variables:
 | |
|    *   - mCancelRequested is only set on the calling thread while the lock is
 | |
|    *     held.  It is always read from within the lock on the background thread,
 | |
|    *     but not on the calling thread (see shouldNotify for why).
 | |
|    */
 | |
|   Mutex& mMutex;
 | |
| 
 | |
|   /**
 | |
|    * The wrapped SQLite recursive connection mutex.  We use it whenever we call
 | |
|    * sqlite3_step and care about having reliable error messages.  By taking it
 | |
|    * prior to the call and holding it until the point where we no longer care
 | |
|    * about the error message, the user gets reliable error messages.
 | |
|    */
 | |
|   SQLiteMutex& mDBMutex;
 | |
| };
 | |
| 
 | |
| }  // namespace mozilla::storage
 | |
| 
 | |
| #endif  // mozStorageAsyncStatementExecution_h
 | 
