LCOV - app.info - storage/src/StorageBaseStatementInternal.cpp

LCOV - code coverage report
| Current view: | directory - storage/src - StorageBaseStatementInternal.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 65 | 63 | 96.9 %
| Date: | 2012-04-21 | Functions: | 14 | 14 | 100.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
           2                 :  * vim: sw=2 ts=2 sts=2 expandtab
           3                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is mozilla.org code.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is the Mozilla Foundation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2010
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Andrew Sutherland <asutherland@asutherland.org>
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : #include "StorageBaseStatementInternal.h"
          40                 :
          41                 : #include "nsProxyRelease.h"
          42                 :
          43                 : #include "mozStorageBindingParamsArray.h"
          44                 : #include "mozStorageStatementData.h"
          45                 : #include "mozStorageAsyncStatementExecution.h"
          46                 :
          47                 : namespace mozilla {
          48                 : namespace storage {
          49                 :
          50                 : ////////////////////////////////////////////////////////////////////////////////
          51                 : //// Local Classes
          52                 :
          53                 : /**
          54                 :  * Used to finalize an asynchronous statement on the background thread.
          55                 :  */
          56                 : class AsyncStatementFinalizer : public nsRunnable
          57           34920 : {
          58                 : public:
          59                 :   /**
          60                 :    * Constructor for the event.
          61                 :    *
          62                 :    * @param aStatement
          63                 :    *        We need the AsyncStatement to be able to get at the sqlite3_stmt;
          64                 :    *        we only access/create it on the async thread.
          65                 :    * @param aConnection
          66                 :    *        We need the connection to know what thread to release the statement
          67                 :    *        on.  We release the statement on that thread since releasing the
          68                 :    *        statement might end up releasing the connection too.
          69                 :    */
          70            8730 :   AsyncStatementFinalizer(StorageBaseStatementInternal *aStatement,
          71                 :                           Connection *aConnection)
          72                 :   : mStatement(aStatement)
          73            8730 :   , mConnection(aConnection)
          74                 :   {
          75            8730 :   }
          76                 :
          77            8730 :   NS_IMETHOD Run()
          78                 :   {
          79            8730 :     if (mStatement->mAsyncStatement) {
          80            8717 :       (void)::sqlite3_finalize(mStatement->mAsyncStatement);
          81            8717 :       mStatement->mAsyncStatement = nsnull;
          82                 :     }
          83            8730 :     (void)::NS_ProxyRelease(mConnection->threadOpenedOn, mStatement);
          84            8730 :     return NS_OK;
          85                 :   }
          86                 : private:
          87                 :   nsRefPtr<StorageBaseStatementInternal> mStatement;
          88                 :   nsRefPtr<Connection> mConnection;
          89                 : };
          90                 :
          91                 : /**
          92                 :  * Finalize a sqlite3_stmt on the background thread for a statement whose
          93                 :  * destructor was invoked and the statement was non-null.
          94                 :  */
          95                 : class LastDitchSqliteStatementFinalizer : public nsRunnable
          96            3912 : {
          97                 : public:
          98                 :   /**
          99                 :    * Event constructor.
         100                 :    *
         101                 :    * @param aConnection
         102                 :    *        Used to keep the connection alive.  If we failed to do this, it
         103                 :    *        is possible that the statement going out of scope invoking us
         104                 :    *        might have the last reference to the connection and so trigger
         105                 :    *        an attempt to close the connection which is doomed to fail
         106                 :    *        (because the asynchronous execution thread must exist which will
         107                 :    *        trigger the failure case).
         108                 :    * @param aStatement
         109                 :    *        The sqlite3_stmt to finalize.  This object takes ownership /
         110                 :    *        responsibility for the instance and all other references to it
         111                 :    *        should be forgotten.
         112                 :    */
         113             978 :   LastDitchSqliteStatementFinalizer(nsRefPtr<Connection> &aConnection,
         114                 :                                     sqlite3_stmt *aStatement)
         115                 :   : mConnection(aConnection)
         116             978 :   , mAsyncStatement(aStatement)
         117                 :   {
         118             978 :     NS_PRECONDITION(aConnection, "You must provide a Connection");
         119             978 :   }
         120                 :
         121             978 :   NS_IMETHOD Run()
         122                 :   {
         123             978 :     (void)::sqlite3_finalize(mAsyncStatement);
         124             978 :     mAsyncStatement = nsnull;
         125                 :
         126                 :     // Because of our ambiguous nsISupports we cannot use the NS_ProxyRelease
         127                 :     // template helpers.
         128             978 :     Connection *rawConnection = nsnull;
         129             978 :     mConnection.swap(rawConnection);
         130                 :     (void)::NS_ProxyRelease(
         131                 :       rawConnection->threadOpenedOn,
         132             978 :       NS_ISUPPORTS_CAST(mozIStorageConnection *, rawConnection));
         133             978 :     return NS_OK;
         134                 :   }
         135                 : private:
         136                 :   nsRefPtr<Connection> mConnection;
         137                 :   sqlite3_stmt *mAsyncStatement;
         138                 : };
         139                 :
         140                 : ////////////////////////////////////////////////////////////////////////////////
         141                 : //// StorageBaseStatementInternal
         142                 :
         143           59572 : StorageBaseStatementInternal::StorageBaseStatementInternal()
         144           59572 : : mAsyncStatement(NULL)
         145                 : {
         146           59572 : }
         147                 :
         148                 : void
         149            8730 : StorageBaseStatementInternal::asyncFinalize()
         150                 : {
         151            8730 :   nsIEventTarget *target = mDBConnection->getAsyncExecutionTarget();
         152            8730 :   if (!target) {
         153                 :     // If we cannot get the background thread, we have to assume it has been
         154                 :     // shutdown (or is in the process of doing so).  As a result, we should
         155                 :     // just finalize it here and now.
         156               0 :     destructorAsyncFinalize();
         157                 :   }
         158                 :   else {
         159                 :     nsCOMPtr<nsIRunnable> event =
         160           26190 :       new AsyncStatementFinalizer(this, mDBConnection);
         161                 :
         162                 :     // If the dispatching did not go as planned, finalize now.
         163            8730 :     if (NS_FAILED(target->Dispatch(event, NS_DISPATCH_NORMAL))) {
         164               0 :       destructorAsyncFinalize();
         165                 :     }
         166                 :   }
         167            8730 : }
         168                 :
         169                 : void
         170            5888 : StorageBaseStatementInternal::destructorAsyncFinalize()
         171                 : {
         172            5888 :   if (!mAsyncStatement)
         173            4717 :     return;
         174                 :
         175            1171 :   nsIEventTarget *target = mDBConnection->getAsyncExecutionTarget();
         176            1171 :   if (target) {
         177                 :     nsCOMPtr<nsIRunnable> event =
         178            1956 :       new LastDitchSqliteStatementFinalizer(mDBConnection, mAsyncStatement);
         179             978 :     if (NS_SUCCEEDED(target->Dispatch(event, NS_DISPATCH_NORMAL))) {
         180             978 :       mAsyncStatement = nsnull;
         181                 :       return;
         182                 :     }
         183                 :   }
         184                 :   // (no async thread remains or we could not dispatch to it)
         185             193 :   (void)::sqlite3_finalize(mAsyncStatement);
         186             193 :   mAsyncStatement = nsnull;
         187                 : }
         188                 :
         189                 : NS_IMETHODIMP
         190          120652 : StorageBaseStatementInternal::NewBindingParamsArray(
         191                 :   mozIStorageBindingParamsArray **_array
         192                 : )
         193                 : {
         194          241304 :   nsCOMPtr<mozIStorageBindingParamsArray> array = new BindingParamsArray(this);
         195          120652 :   NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
         196                 :
         197          120652 :   array.forget(_array);
         198          120652 :   return NS_OK;
         199                 : }
         200                 :
         201                 : NS_IMETHODIMP
         202           37270 : StorageBaseStatementInternal::ExecuteAsync(
         203                 :   mozIStorageStatementCallback *aCallback,
         204                 :   mozIStoragePendingStatement **_stmt
         205                 : )
         206                 : {
         207                 :   // We used to call Connection::ExecuteAsync but it takes a
         208                 :   // mozIStorageBaseStatement signature because it is also a public API.  Since
         209                 :   // our 'this' has no static concept of mozIStorageBaseStatement and Connection
         210                 :   // would just QI it back across to a StorageBaseStatementInternal and the
         211                 :   // actual logic is very simple, we now roll our own.
         212           74540 :   nsTArray<StatementData> stmts(1);
         213           74540 :   StatementData data;
         214           37270 :   nsresult rv = getAsynchronousStatementData(data);
         215           37270 :   NS_ENSURE_SUCCESS(rv, rv);
         216           37269 :   NS_ENSURE_TRUE(stmts.AppendElement(data), NS_ERROR_OUT_OF_MEMORY);
         217                 :
         218                 :   // Dispatch to the background
         219                 :   return AsyncExecuteStatements::execute(stmts, mDBConnection, aCallback,
         220           37269 :                                          _stmt);
         221                 : }
         222                 :
         223                 : NS_IMETHODIMP
         224             100 : StorageBaseStatementInternal::EscapeStringForLIKE(
         225                 :   const nsAString &aValue,
         226                 :   const PRUnichar aEscapeChar,
         227                 :   nsAString &_escapedString
         228                 : )
         229                 : {
         230             100 :   const PRUnichar MATCH_ALL('%');
         231             100 :   const PRUnichar MATCH_ONE('_');
         232                 :
         233             100 :   _escapedString.Truncate(0);
         234                 :
         235            1186 :   for (PRUint32 i = 0; i < aValue.Length(); i++) {
         236            2168 :     if (aValue[i] == aEscapeChar || aValue[i] == MATCH_ALL ||
         237            1082 :         aValue[i] == MATCH_ONE) {
         238               6 :       _escapedString += aEscapeChar;
         239                 :     }
         240            1086 :     _escapedString += aValue[i];
         241                 :   }
         242             100 :   return NS_OK;
         243                 : }
         244                 :
         245                 : } // namespace storage
         246                 : } // namespace mozilla

Generated by: LCOV version 1.7