mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-29 01:00:41 +00:00
Bug 429986 - Provide an option for database access to be asynchronous.
This adds a method to mozIStorageStatement to allow for a statement to execute asynchronously and report to a callback. For writes, this can move fsyncs, which can be painful, off of the main thread. r=vlad sr=shaver
This commit is contained in:
parent
3da654e7c2
commit
35ba2ed351
@ -60,6 +60,9 @@ XPIDLSRCS = \
|
||||
mozIStorageValueArray.idl \
|
||||
mozIStorageResultSet.idl \
|
||||
mozIStorageRow.idl \
|
||||
mozIStorageError.idl \
|
||||
mozIStorageStatementCallback.idl \
|
||||
mozIStoragePendingStatement.idl \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
170
storage/public/mozIStorageError.idl
Normal file
170
storage/public/mozIStorageError.idl
Normal file
@ -0,0 +1,170 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(1f350f96-7023-434a-8864-40a1c493aac1)]
|
||||
interface mozIStorageError : nsISupports {
|
||||
|
||||
/**
|
||||
* General SQL error or missing database.
|
||||
*/
|
||||
const long ERROR = 1;
|
||||
|
||||
/**
|
||||
* Internal logic error.
|
||||
*/
|
||||
const long INTERNAL = 2;
|
||||
|
||||
/**
|
||||
* Access permission denied.
|
||||
*/
|
||||
const long PERM = 3;
|
||||
|
||||
/**
|
||||
* A callback routine requested an abort.
|
||||
*/
|
||||
const long ABORT = 4;
|
||||
|
||||
/**
|
||||
* The database file is locked.
|
||||
*/
|
||||
const long BUSY = 5;
|
||||
|
||||
/**
|
||||
* A table in the database is locked.
|
||||
*/
|
||||
const long LOCKED = 6;
|
||||
|
||||
/**
|
||||
* An allocation failed.
|
||||
*/
|
||||
const long NOMEM = 7;
|
||||
|
||||
/**
|
||||
* Attempt to write to a readonly database.
|
||||
*/
|
||||
const long READONLY = 8;
|
||||
|
||||
/**
|
||||
* Operation was terminated by an interrupt.
|
||||
*/
|
||||
const long INTERRUPT = 9;
|
||||
|
||||
/**
|
||||
* Some kind of disk I/O error occurred.
|
||||
*/
|
||||
const long IOERR = 10;
|
||||
|
||||
/**
|
||||
* The database disk image is malformed.
|
||||
*/
|
||||
const long CORRUPT = 11;
|
||||
|
||||
/**
|
||||
* An insertion failed because the database is full.
|
||||
*/
|
||||
const long FULL = 13;
|
||||
|
||||
/**
|
||||
* Unable to open the database file.
|
||||
*/
|
||||
const long CANTOPEN = 14;
|
||||
|
||||
/**
|
||||
* The database is empty.
|
||||
*/
|
||||
const long EMPTY = 16;
|
||||
|
||||
/**
|
||||
* The database scheme changed.
|
||||
*/
|
||||
const long SCHEMA = 17;
|
||||
|
||||
/**
|
||||
* A string or blob exceeds the size limit.
|
||||
*/
|
||||
const long TOOBIG = 18;
|
||||
|
||||
/**
|
||||
* Abort due to a constraint violation.
|
||||
*/
|
||||
const long CONSTRAINT = 19;
|
||||
|
||||
/**
|
||||
* Data type mismatch.
|
||||
*/
|
||||
const long MISMATCH = 20;
|
||||
|
||||
/**
|
||||
* Library used incorrectly.
|
||||
*/
|
||||
const long MISUSE = 21;
|
||||
|
||||
/**
|
||||
* Uses OS features not supported on the host system.
|
||||
*/
|
||||
const long NOLFS = 22;
|
||||
|
||||
/**
|
||||
* Authorization denied.
|
||||
*/
|
||||
const long AUTH = 23;
|
||||
|
||||
/**
|
||||
* Auxiliary database format error.
|
||||
*/
|
||||
const long FORMAT = 24;
|
||||
|
||||
/**
|
||||
* File opened that is not a database file.
|
||||
*/
|
||||
const long NOTADB = 26;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates what type of error occurred.
|
||||
*/
|
||||
readonly attribute long result;
|
||||
|
||||
/**
|
||||
* An error string the gives more details, if available.
|
||||
*/
|
||||
readonly attribute AUTF8String message;
|
||||
};
|
50
storage/public/mozIStoragePendingStatement.idl
Normal file
50
storage/public/mozIStoragePendingStatement.idl
Normal file
@ -0,0 +1,50 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(5c458b3a-8648-45dd-a9a0-c321949cd864)]
|
||||
interface mozIStoragePendingStatement : nsISupports {
|
||||
|
||||
/**
|
||||
* Cancels a pending statement. This may fail because the statement has
|
||||
* already completed.
|
||||
*/
|
||||
void cancel();
|
||||
};
|
@ -1,5 +1,6 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
@ -42,10 +43,12 @@
|
||||
interface mozIStorageConnection;
|
||||
interface mozIStorageDataSet;
|
||||
interface nsISimpleEnumerator;
|
||||
interface mozIStorageStatementCallback;
|
||||
interface mozIStoragePendingStatement;
|
||||
|
||||
[ptr] native sqlite3stmtptr(struct sqlite3_stmt);
|
||||
|
||||
[scriptable, uuid(4101bda7-6ec8-4a72-bbf8-6569af0030ea)]
|
||||
[scriptable, uuid(4a712295-d076-4007-9c78-8c0e15373b9f)]
|
||||
interface mozIStorageStatement : mozIStorageValueArray {
|
||||
/**
|
||||
* Finalizes a statement so you can successfully close a database connection.
|
||||
@ -149,6 +152,19 @@ interface mozIStorageStatement : mozIStorageValueArray {
|
||||
*/
|
||||
boolean executeStep();
|
||||
|
||||
/**
|
||||
* Execute a query asynchronously using any currently bound parameters. This
|
||||
* statement can be reused immediately, and reset does not need to be called.
|
||||
*
|
||||
* @param aCallback [optional]
|
||||
* The callback object that will be notified of progress, errors, and
|
||||
* completion.
|
||||
* @returns an object that can be used to cancel the statements execution.
|
||||
*/
|
||||
mozIStoragePendingStatement executeAsync(
|
||||
[optional] in mozIStorageStatementCallback aCallback
|
||||
);
|
||||
|
||||
/**
|
||||
* The current state. Row getters are only valid while
|
||||
* the statement is in the "executing" state.
|
||||
|
81
storage/public/mozIStorageStatementCallback.idl
Normal file
81
storage/public/mozIStorageStatementCallback.idl
Normal file
@ -0,0 +1,81 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface mozIStorageResultSet;
|
||||
interface mozIStorageError;
|
||||
|
||||
[scriptable, uuid(29383d00-d8c4-4ddd-9f8b-c2feb0f2fcfa)]
|
||||
interface mozIStorageStatementCallback : nsISupports {
|
||||
|
||||
/**
|
||||
* Called when some result is obtained from the database. This function can
|
||||
* be called more than once with a different storageIResultSet each time for
|
||||
* any given asynchronous statement.
|
||||
*
|
||||
* @param aResultSet
|
||||
* The result set containing the data from the database.
|
||||
*/
|
||||
void handleResult(in mozIStorageResultSet aResultSet);
|
||||
|
||||
/**
|
||||
* Called when some error occurs while executing the statement. This function
|
||||
* may be called more than once with a different storageIError each time for
|
||||
* any given asynchronous statement.
|
||||
*
|
||||
* @param aError
|
||||
* An object containing information about the error.
|
||||
*/
|
||||
void handleError(in mozIStorageError aError);
|
||||
|
||||
/**
|
||||
* Called when the statement has finished executing. This function will only
|
||||
* be called once for any given asynchronous statement.
|
||||
*
|
||||
* @param aReason
|
||||
* Indicates if the statement is no longer executing because it either
|
||||
* finished (REASON_FINISHED), was canceled (REASON_CANCELED), or
|
||||
* a fatal error occurred (REASON_ERROR).
|
||||
*/
|
||||
const unsigned short REASON_FINISHED = 0;
|
||||
const unsigned short REASON_CANCELED = 1;
|
||||
const unsigned short REASON_ERROR = 2;
|
||||
void handleCompletion(in unsigned short aReason);
|
||||
};
|
@ -58,6 +58,7 @@ REQUIRES = xpcom \
|
||||
sqlite3 \
|
||||
js \
|
||||
xpconnect \
|
||||
necko \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
@ -69,6 +70,9 @@ CPPSRCS = \
|
||||
mozStorageUnicodeFunctions.cpp \
|
||||
mozStorageRow.cpp \
|
||||
mozStorageResultSet.cpp \
|
||||
mozStorageError.cpp \
|
||||
mozStorageBackground.cpp \
|
||||
mozStorageEvents.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
125
storage/src/mozStorageBackground.cpp
Normal file
125
storage/src/mozStorageBackground.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIThreadPool.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
#include "mozStorageCID.h"
|
||||
#include "mozIStorageService.h"
|
||||
#include "mozStorageConnection.h"
|
||||
#include "mozStorageBackground.h"
|
||||
|
||||
namespace {
|
||||
class ThreadShutdownObserver : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
ThreadShutdownObserver(nsIThreadPool *aThreadPool) :
|
||||
mThreadPool(aThreadPool)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Observe(nsISupports *, const char *aTopic, const PRUnichar *)
|
||||
{
|
||||
if (!strcmp(aTopic, "xpcom-shutdown-threads")) {
|
||||
(void)mThreadPool->Shutdown();
|
||||
mThreadPool = nsnull;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
ThreadShutdownObserver() { }
|
||||
nsCOMPtr<nsIThreadPool> mThreadPool;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(ThreadShutdownObserver, nsIObserver)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Public Methods
|
||||
|
||||
mozStorageBackground *mozStorageBackground::mSingleton = nsnull;
|
||||
|
||||
mozStorageBackground *
|
||||
mozStorageBackground::getService()
|
||||
{
|
||||
return mozStorageBackground::mSingleton;
|
||||
}
|
||||
|
||||
mozStorageBackground::mozStorageBackground()
|
||||
{
|
||||
mozStorageBackground::mSingleton = this;
|
||||
}
|
||||
|
||||
mozStorageBackground::~mozStorageBackground()
|
||||
{
|
||||
(void)mThreadPool->Shutdown();
|
||||
mozStorageBackground::mSingleton = nsnull;
|
||||
}
|
||||
|
||||
nsIEventTarget *
|
||||
mozStorageBackground::target()
|
||||
{
|
||||
return mThreadPool;
|
||||
}
|
||||
|
||||
nsresult
|
||||
mozStorageBackground::initialize()
|
||||
{
|
||||
// Create the thread pool
|
||||
mThreadPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID);
|
||||
NS_ENSURE_TRUE(mThreadPool, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Create the observer, and register it with the observer service
|
||||
mObserver = new ThreadShutdownObserver(mThreadPool);
|
||||
NS_ENSURE_TRUE(mObserver, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIObserverService> os =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
NS_ENSURE_TRUE(os, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsresult rv = os->AddObserver(mObserver, "xpcom-shutdown-threads", PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
91
storage/src/mozStorageBackground.h
Normal file
91
storage/src/mozStorageBackground.h
Normal file
@ -0,0 +1,91 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _mozStorageBackground_h_
|
||||
#define _mozStorageBackground_h_
|
||||
|
||||
#include "nsClassHashtable.h"
|
||||
class mozStorageConnection;
|
||||
class nsIThreadPool;
|
||||
class nsIEventTarget;
|
||||
class nsIObserver;
|
||||
|
||||
/**
|
||||
* This class managed the connections used in the background for
|
||||
* asynchronous operations. There is a one-to-one mapping of calling thread
|
||||
* connections to background ones. Additionally, it manages the background
|
||||
* thread pool used for asynchronous database calls.
|
||||
*
|
||||
* @note This class is threadsafe.
|
||||
*/
|
||||
class mozStorageBackground
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @returns the background event target that all events to be ran on the
|
||||
* background should be dispatched to.
|
||||
*/
|
||||
nsIEventTarget *target();
|
||||
|
||||
/**
|
||||
* Initializes this object. Creates the background thread pool.
|
||||
*/
|
||||
nsresult initialize();
|
||||
|
||||
/**
|
||||
* Obtains a singleton service of this class.
|
||||
*
|
||||
* @returns a mozStorageBackground object.
|
||||
*/
|
||||
static mozStorageBackground *getService();
|
||||
|
||||
mozStorageBackground();
|
||||
~mozStorageBackground();
|
||||
|
||||
private:
|
||||
|
||||
nsCOMPtr<nsIThreadPool> mThreadPool;
|
||||
|
||||
static mozStorageBackground *mSingleton;
|
||||
|
||||
nsCOMPtr<nsIObserver> mObserver;
|
||||
};
|
||||
|
||||
#endif // _mozStorageBackground_h_
|
72
storage/src/mozStorageError.cpp
Normal file
72
storage/src/mozStorageError.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozStorageError.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// mozStorageError
|
||||
|
||||
/**
|
||||
* Note: This object is only ever accessed on one thread at a time. It it not
|
||||
* threadsafe, but it does need threadsafe AddRef and Release.
|
||||
*/
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(mozStorageError, mozIStorageError)
|
||||
|
||||
mozStorageError::mozStorageError(int aResult, const char *aMessage) :
|
||||
mResult(aResult)
|
||||
, mMessage(aMessage)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// mozIStorageError
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozStorageError::GetResult(PRInt32 *_result)
|
||||
{
|
||||
*_result = mResult;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozStorageError::GetMessage(nsACString &_message)
|
||||
{
|
||||
_message = mMessage;
|
||||
return NS_OK;
|
||||
}
|
59
storage/src/mozStorageError.h
Normal file
59
storage/src/mozStorageError.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __mozStorageError_h__
|
||||
#define __mozStorageError_h__
|
||||
|
||||
#include "mozIStorageError.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class mozStorageError : public mozIStorageError
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGEERROR
|
||||
|
||||
mozStorageError(int aResult, const char *aMessage);
|
||||
|
||||
private:
|
||||
int mResult;
|
||||
nsCString mMessage;
|
||||
};
|
||||
|
||||
#endif // __mozStorageError_h__
|
545
storage/src/mozStorageEvents.cpp
Normal file
545
storage/src/mozStorageEvents.cpp
Normal file
@ -0,0 +1,545 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
#include "mozIStorageStatementCallback.h"
|
||||
#include "mozIStoragePendingStatement.h"
|
||||
#include "mozStorageStatement.h"
|
||||
#include "mozStorageResultSet.h"
|
||||
#include "mozStorageRow.h"
|
||||
#include "mozStorageBackground.h"
|
||||
#include "mozStorageError.h"
|
||||
#include "mozStorageEvents.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Asynchronous Statement Execution
|
||||
|
||||
/**
|
||||
* Enum used to describe the state of execution.
|
||||
*/
|
||||
enum ExecutionState {
|
||||
PENDING = -1
|
||||
, COMPLETED = mozIStorageStatementCallback::REASON_FINISHED
|
||||
, CANCELED = mozIStorageStatementCallback::REASON_CANCELED
|
||||
, ERROR = mozIStorageStatementCallback::REASON_ERROR
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface used to cancel pending events.
|
||||
*/
|
||||
class iCancelable : public nsISupports
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Tells an event to cancel itself.
|
||||
*/
|
||||
virtual void cancel() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface used to notify of event completion.
|
||||
*/
|
||||
class iCompletionNotifier : public nsISupports
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Called when an event is completed and no longer needs to be tracked.
|
||||
*
|
||||
* @param aEvent
|
||||
* The event that has finished.
|
||||
*/
|
||||
virtual void completed(iCancelable *aEvent) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies a callback with a result set.
|
||||
*/
|
||||
class CallbackResultNotifier : public nsIRunnable
|
||||
, public iCancelable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
CallbackResultNotifier(mozIStorageStatementCallback *aCallback,
|
||||
mozIStorageResultSet *aResults,
|
||||
iCompletionNotifier *aNotifier) :
|
||||
mCallback(aCallback)
|
||||
, mResults(aResults)
|
||||
, mCompletionNotifier(aNotifier)
|
||||
, mCanceled(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (!mCanceled)
|
||||
(void)mCallback->HandleResult(mResults);
|
||||
|
||||
// Notify owner AsyncExecute that we have completed
|
||||
mCompletionNotifier->completed(this);
|
||||
// It is likely that the completion notifier holds a reference to us as
|
||||
// well, so we release our reference to it here to avoid cycles.
|
||||
mCompletionNotifier = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual void cancel()
|
||||
{
|
||||
// Atomically set our status so we know to not run.
|
||||
PR_AtomicSet(&mCanceled, PR_TRUE);
|
||||
}
|
||||
private:
|
||||
CallbackResultNotifier() { }
|
||||
|
||||
mozIStorageStatementCallback *mCallback;
|
||||
nsCOMPtr<mozIStorageResultSet> mResults;
|
||||
nsRefPtr<iCompletionNotifier> mCompletionNotifier;
|
||||
PRInt32 mCanceled;
|
||||
};
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(
|
||||
CallbackResultNotifier,
|
||||
nsIRunnable
|
||||
)
|
||||
|
||||
/**
|
||||
* Notifies the calling thread that an error has occurred.
|
||||
*/
|
||||
class ErrorNotifier : public nsIRunnable
|
||||
, public iCancelable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
ErrorNotifier(mozIStorageStatementCallback *aCallback,
|
||||
mozIStorageError *aErrorObj,
|
||||
iCompletionNotifier *aCompletionNotifier) :
|
||||
mCallback(aCallback)
|
||||
, mErrorObj(aErrorObj)
|
||||
, mCanceled(PR_FALSE)
|
||||
, mCompletionNotifier(aCompletionNotifier)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (!mCanceled)
|
||||
(void)mCallback->HandleError(mErrorObj);
|
||||
|
||||
mCompletionNotifier->completed(this);
|
||||
// It is likely that the completion notifier holds a reference to us as
|
||||
// well, so we release our reference to it here to avoid cycles.
|
||||
mCompletionNotifier = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual void cancel()
|
||||
{
|
||||
// Atomically set our status so we know to not run.
|
||||
PR_AtomicSet(&mCanceled, PR_TRUE);
|
||||
}
|
||||
|
||||
static inline iCancelable *Dispatch(nsIThread *aCallingThread,
|
||||
mozIStorageStatementCallback *aCallback,
|
||||
iCompletionNotifier *aCompletionNotifier,
|
||||
int aResult,
|
||||
const char *aMessage)
|
||||
{
|
||||
nsCOMPtr<mozIStorageError> errorObj(new mozStorageError(aResult, aMessage));
|
||||
if (!errorObj)
|
||||
return nsnull;
|
||||
|
||||
ErrorNotifier *notifier =
|
||||
new ErrorNotifier(aCallback, errorObj, aCompletionNotifier);
|
||||
(void)aCallingThread->Dispatch(notifier, NS_DISPATCH_NORMAL);
|
||||
return notifier;
|
||||
}
|
||||
private:
|
||||
ErrorNotifier() { }
|
||||
|
||||
mozIStorageStatementCallback *mCallback;
|
||||
nsCOMPtr<mozIStorageError> mErrorObj;
|
||||
PRInt32 mCanceled;
|
||||
nsRefPtr<iCompletionNotifier> mCompletionNotifier;
|
||||
};
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(
|
||||
ErrorNotifier,
|
||||
nsIRunnable
|
||||
)
|
||||
|
||||
/**
|
||||
* Notifies the calling thread that the statement has finished executing.
|
||||
*/
|
||||
class CompletionNotifier : public nsIRunnable
|
||||
, public iCancelable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
/**
|
||||
* This takes ownership of the callback and statement. Both are released
|
||||
* on the thread this is dispatched to (which should always be the calling
|
||||
* thread).
|
||||
*/
|
||||
CompletionNotifier(mozIStorageStatementCallback *aCallback,
|
||||
ExecutionState aReason,
|
||||
mozIStorageStatement *aStatement,
|
||||
iCompletionNotifier *aCompletionNotifier) :
|
||||
mCallback(aCallback)
|
||||
, mReason(aReason)
|
||||
, mStatement(aStatement)
|
||||
, mCompletionNotifier(aCompletionNotifier)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
NS_RELEASE(mStatement);
|
||||
if (mCallback) {
|
||||
(void)mCallback->HandleCompletion(mReason);
|
||||
NS_RELEASE(mCallback);
|
||||
}
|
||||
|
||||
mCompletionNotifier->completed(this);
|
||||
// It is likely that the completion notifier holds a reference to us as
|
||||
// well, so we release our reference to it here to avoid cycles.
|
||||
mCompletionNotifier = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual void cancel()
|
||||
{
|
||||
// Update our reason so the completion notifier knows what is up.
|
||||
mReason = CANCELED;
|
||||
}
|
||||
|
||||
private:
|
||||
CompletionNotifier() { }
|
||||
|
||||
mozIStorageStatementCallback *mCallback;
|
||||
ExecutionState mReason;
|
||||
mozIStorageStatement *mStatement;
|
||||
nsRefPtr<iCompletionNotifier> mCompletionNotifier;
|
||||
};
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(
|
||||
CompletionNotifier,
|
||||
nsIRunnable
|
||||
)
|
||||
|
||||
/**
|
||||
* Executes a statement asynchronously in the background.
|
||||
*/
|
||||
class AsyncExecute : public nsIRunnable
|
||||
, public mozIStoragePendingStatement
|
||||
, public iCompletionNotifier
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
/**
|
||||
* This takes ownership of both the statement and the callback.
|
||||
*/
|
||||
AsyncExecute(mozStorageStatement *aStatement,
|
||||
mozIStorageStatementCallback *aCallback) :
|
||||
mStatement(aStatement)
|
||||
, mCallback(aCallback)
|
||||
, mCallingThread(do_GetCurrentThread())
|
||||
, mState(PENDING)
|
||||
, mStateMutex(nsAutoLock::NewLock("AsyncExecute::mStateMutex"))
|
||||
, mPendingEventsMutex(nsAutoLock::NewLock("AsyncExecute::mPendingEventsMutex"))
|
||||
{
|
||||
}
|
||||
|
||||
nsresult initialize()
|
||||
{
|
||||
NS_ENSURE_TRUE(mStateMutex, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(mPendingEventsMutex, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ADDREF(mStatement);
|
||||
NS_IF_ADDREF(mCallback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
// do not run if we have been canceled
|
||||
{
|
||||
nsAutoLock mutex(mStateMutex);
|
||||
if (mState == CANCELED)
|
||||
return Complete();
|
||||
}
|
||||
|
||||
// Execute the statement, giving the callback results
|
||||
// XXX better chunking of results?
|
||||
nsresult rv;
|
||||
while (PR_TRUE) {
|
||||
PRBool hasResults;
|
||||
rv = mStatement->ExecuteStep(&hasResults);
|
||||
// Break out if we have no more results
|
||||
if (NS_SUCCEEDED(rv) && !hasResults)
|
||||
break;
|
||||
|
||||
// Some errors are not fatal, but we still need to report them
|
||||
if (NS_FAILED(rv)) {
|
||||
// Get the real result code
|
||||
sqlite3 *db = sqlite3_db_handle(mStatement->NativeStatement());
|
||||
int err = sqlite3_errcode(db);
|
||||
if (err == SQLITE_BUSY) {
|
||||
// Yield, and try again
|
||||
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set error state
|
||||
{
|
||||
nsAutoLock mutex(mStateMutex);
|
||||
mState = ERROR;
|
||||
}
|
||||
|
||||
// Notify
|
||||
iCancelable *cancelable = ErrorNotifier::Dispatch(
|
||||
mCallingThread, mCallback, this, err, sqlite3_errmsg(db)
|
||||
);
|
||||
if (cancelable) {
|
||||
nsAutoLock mutex(mPendingEventsMutex);
|
||||
(void)mPendingEvents.AppendObject(cancelable);
|
||||
}
|
||||
|
||||
// And complete
|
||||
return Complete();
|
||||
}
|
||||
|
||||
// Check to see if we have been canceled
|
||||
{
|
||||
nsAutoLock mutex(mStateMutex);
|
||||
if (mState == CANCELED)
|
||||
return Complete();
|
||||
}
|
||||
|
||||
// If we do not have a callback, but are getting results, we should stop
|
||||
// now since all this work isn't going to accomplish anything
|
||||
if (!mCallback) {
|
||||
nsAutoLock mutex(mStateMutex);
|
||||
mState = COMPLETED;
|
||||
return Complete();
|
||||
}
|
||||
|
||||
// Build result object
|
||||
nsRefPtr<mozStorageResultSet> results(new mozStorageResultSet());
|
||||
if (!results)
|
||||
break;
|
||||
|
||||
nsRefPtr<mozStorageRow> row(new mozStorageRow());
|
||||
if (!row)
|
||||
break;
|
||||
|
||||
rv = row->initialize(mStatement->NativeStatement());
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
rv = results->add(row);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
// Notify caller
|
||||
nsRefPtr<CallbackResultNotifier> notifier =
|
||||
new CallbackResultNotifier(mCallback, results, this);
|
||||
if (!notifier)
|
||||
break;
|
||||
|
||||
nsresult status = mCallingThread->Dispatch(notifier, NS_DISPATCH_NORMAL);
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
nsAutoLock mutex(mPendingEventsMutex);
|
||||
(void)mPendingEvents.AppendObject(notifier);
|
||||
}
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
// This is a fatal error :(
|
||||
|
||||
// Update state
|
||||
{
|
||||
nsAutoLock mutex(mStateMutex);
|
||||
mState = ERROR;
|
||||
}
|
||||
|
||||
// Notify
|
||||
iCancelable *cancelable = ErrorNotifier::Dispatch(
|
||||
mCallingThread, mCallback, this, mozIStorageError::ERROR, ""
|
||||
);
|
||||
if (cancelable) {
|
||||
nsAutoLock mutex(mPendingEventsMutex);
|
||||
(void)mPendingEvents.AppendObject(cancelable);
|
||||
}
|
||||
}
|
||||
|
||||
// No more results, so update state if needed
|
||||
{
|
||||
nsAutoLock mutex(mStateMutex);
|
||||
if (mState == PENDING)
|
||||
mState = COMPLETED;
|
||||
|
||||
// Notify about completion
|
||||
return Complete();
|
||||
}
|
||||
}
|
||||
|
||||
static PRBool cancelEnumerator(iCancelable *aCancelable, void *)
|
||||
{
|
||||
(void)aCancelable->cancel();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHOD Cancel()
|
||||
{
|
||||
// Check and update our state
|
||||
{
|
||||
nsAutoLock mutex(mStateMutex);
|
||||
NS_ENSURE_TRUE(mState == PENDING || mState == COMPLETED,
|
||||
NS_ERROR_UNEXPECTED);
|
||||
mState = CANCELED;
|
||||
}
|
||||
|
||||
// Cancel all our pending events on the calling thread
|
||||
{
|
||||
nsAutoLock mutex(mPendingEventsMutex);
|
||||
(void)mPendingEvents.EnumerateForwards(&AsyncExecute::cancelEnumerator,
|
||||
nsnull);
|
||||
mPendingEvents.Clear();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual void completed(iCancelable *aCancelable)
|
||||
{
|
||||
nsAutoLock mutex(mPendingEventsMutex);
|
||||
(void)mPendingEvents.RemoveObject(aCancelable);
|
||||
}
|
||||
|
||||
private:
|
||||
AsyncExecute() { }
|
||||
|
||||
~AsyncExecute()
|
||||
{
|
||||
NS_ASSERTION(mPendingEvents.Count() == 0, "Still pending events!");
|
||||
nsAutoLock::DestroyLock(mStateMutex);
|
||||
nsAutoLock::DestroyLock(mPendingEventsMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies callback about completion, and does any necessary cleanup.
|
||||
* @note: When calling this function, mStateMutex must be held.
|
||||
*/
|
||||
nsresult Complete()
|
||||
{
|
||||
// Reset the statement
|
||||
(void)mStatement->Reset();
|
||||
|
||||
// Notify about completion
|
||||
NS_ASSERTION(mState != PENDING,
|
||||
"Still in a pending state when calling Complete!");
|
||||
nsRefPtr<CompletionNotifier> completionEvent =
|
||||
new CompletionNotifier(mCallback, mState, mStatement, this);
|
||||
nsresult rv = mCallingThread->Dispatch(completionEvent, NS_DISPATCH_NORMAL);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoLock mutex(mPendingEventsMutex);
|
||||
(void)mPendingEvents.AppendObject(completionEvent);
|
||||
}
|
||||
|
||||
// We no longer own mCallback or mStatement (the CompletionNotifier takes
|
||||
// ownership), so null them out
|
||||
mCallback = nsnull;
|
||||
mStatement = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mozStorageStatement *mStatement;
|
||||
mozIStorageStatementCallback *mCallback;
|
||||
nsCOMPtr<nsIThread> mCallingThread;
|
||||
|
||||
/**
|
||||
* Indicates the state the object is currently in.
|
||||
*/
|
||||
ExecutionState mState;
|
||||
|
||||
/**
|
||||
* Mutex to protect mState.
|
||||
*/
|
||||
PRLock *mStateMutex;
|
||||
|
||||
/**
|
||||
* Stores a list of pending events that have not yet completed on the
|
||||
* calling thread.
|
||||
*/
|
||||
nsCOMArray<iCancelable> mPendingEvents;
|
||||
|
||||
/**
|
||||
* Mutex to protect mPendingEvents.
|
||||
*/
|
||||
PRLock *mPendingEventsMutex;
|
||||
};
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(
|
||||
AsyncExecute,
|
||||
nsIRunnable,
|
||||
mozIStoragePendingStatement
|
||||
)
|
||||
|
||||
nsresult
|
||||
NS_executeAsync(mozStorageStatement *aStatement,
|
||||
mozIStorageStatementCallback *aCallback,
|
||||
mozIStoragePendingStatement **_stmt)
|
||||
{
|
||||
// Create our event to run in the background
|
||||
nsRefPtr<AsyncExecute> event(new AsyncExecute(aStatement, aCallback));
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = event->initialize();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Dispatch it to the background
|
||||
nsIEventTarget *target = mozStorageBackground::getService()->target();
|
||||
rv = target->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Return it as the pending statement object
|
||||
NS_ADDREF(*_stmt = event);
|
||||
return NS_OK;
|
||||
}
|
66
storage/src/mozStorageEvents.h
Normal file
66
storage/src/mozStorageEvents.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _mozStorageEvents_h_
|
||||
#define _mozStorageEvents_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "mozStorageBackground.h"
|
||||
class mozStorageStatement;
|
||||
class mozIStorageStatementCallback;
|
||||
class mozIStoragePendingStatement;
|
||||
|
||||
/**
|
||||
* Executes a statement in the background, and passes results back to the
|
||||
* caller.
|
||||
*
|
||||
* @param aStatement
|
||||
* The statement to execute in the background.
|
||||
* @param aCallback
|
||||
* The callback that is notified of results, completion, and errors.
|
||||
* @param _stmt
|
||||
* The handle to control the execution of the statement.
|
||||
*/
|
||||
nsresult NS_executeAsync(
|
||||
mozStorageStatement *aStatement,
|
||||
mozIStorageStatementCallback *aCallback,
|
||||
mozIStoragePendingStatement **_stmt
|
||||
);
|
||||
|
||||
#endif // _mozStorageEvents_h_
|
@ -121,6 +121,9 @@ mozStorageService::Init()
|
||||
if (!mLock)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = mBackground.initialize();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This makes multiple connections to the same database share the same pager
|
||||
// cache. We do not need to lock here with mLock because this function is
|
||||
// only ever called from mozStorageService::GetSingleton, which will only
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "prlock.h"
|
||||
|
||||
#include "mozIStorageService.h"
|
||||
#include "mozStorageBackground.h"
|
||||
|
||||
class mozStorageConnection;
|
||||
|
||||
@ -76,6 +77,11 @@ private:
|
||||
* can ensure that the state of sqlite3_enable_shared_cache is sane.
|
||||
*/
|
||||
PRLock *mLock;
|
||||
|
||||
/**
|
||||
* The background service needs to stay around just as long as this does.
|
||||
*/
|
||||
mozStorageBackground mBackground;
|
||||
protected:
|
||||
nsCOMPtr<nsIFile> mProfileStorageFile;
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsError.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsMemory.h"
|
||||
@ -49,6 +50,7 @@
|
||||
#include "mozStorageStatement.h"
|
||||
#include "mozStorageValueArray.h"
|
||||
#include "mozStorage.h"
|
||||
#include "mozStorageEvents.h"
|
||||
|
||||
#include "prlog.h"
|
||||
|
||||
@ -456,8 +458,6 @@ mozStorageStatement::ExecuteStep(PRBool *_retval)
|
||||
if (!mDBConnection || !mDBStatement)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
int srv = sqlite3_step (mDBStatement);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
@ -493,6 +493,35 @@ mozStorageStatement::ExecuteStep(PRBool *_retval)
|
||||
return ConvertResultCode(srv);
|
||||
}
|
||||
|
||||
/* nsICancelable executeAsync([optional] in storageIStatementCallback aCallback); */
|
||||
nsresult
|
||||
mozStorageStatement::ExecuteAsync(mozIStorageStatementCallback *aCallback,
|
||||
mozIStoragePendingStatement **_stmt)
|
||||
{
|
||||
// Clone this statement
|
||||
nsRefPtr<mozStorageStatement> stmt(new mozStorageStatement());
|
||||
NS_ENSURE_TRUE(stmt, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCAutoString sql(sqlite3_sql(mDBStatement));
|
||||
nsresult rv = stmt->Initialize(mDBConnection, sql);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Transfer the bindings
|
||||
int rc = sqlite3_transfer_bindings(mDBStatement, stmt->mDBStatement);
|
||||
if (rc != SQLITE_OK)
|
||||
return ConvertResultCode(rc);
|
||||
|
||||
// Dispatch to the background.
|
||||
rv = NS_executeAsync(stmt, aCallback, _stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Reset this statement.
|
||||
rv = Reset();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript,notxpcom] sqlite3stmtptr getNativeStatementPointer(); */
|
||||
sqlite3_stmt*
|
||||
mozStorageStatement::GetNativeStatementPointer()
|
||||
|
@ -48,6 +48,8 @@
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
class mozStorageConnection;
|
||||
|
||||
class mozStorageStatement : public mozIStorageStatement
|
||||
{
|
||||
public:
|
||||
@ -70,6 +72,12 @@ public:
|
||||
nsresult Initialize(mozStorageConnection *aDBConnection,
|
||||
const nsACString &aSQLStatement);
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the native statement pointer.
|
||||
*/
|
||||
inline sqlite3_stmt *NativeStatement() { return mDBStatement; }
|
||||
|
||||
private:
|
||||
~mozStorageStatement();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user