storage/public/mozStorageHelper.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/storage/public/mozStorageHelper.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,181 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef MOZSTORAGEHELPER_H
    1.10 +#define MOZSTORAGEHELPER_H
    1.11 +
    1.12 +#include "nsAutoPtr.h"
    1.13 +
    1.14 +#include "mozIStorageAsyncConnection.h"
    1.15 +#include "mozIStorageConnection.h"
    1.16 +#include "mozIStorageStatement.h"
    1.17 +#include "nsError.h"
    1.18 +
    1.19 +/**
    1.20 + * This class wraps a transaction inside a given C++ scope, guaranteeing that
    1.21 + * the transaction will be completed even if you have an exception or
    1.22 + * return early.
    1.23 + *
    1.24 + * aCommitOnComplete controls whether the transaction is committed or rolled
    1.25 + * back when it goes out of scope. A common use is to create an instance with
    1.26 + * commitOnComplete = FALSE (rollback), then call Commit on this object manually
    1.27 + * when your function completes successfully.
    1.28 + *
    1.29 + * Note that nested transactions are not supported by sqlite, so if a transaction
    1.30 + * is already in progress, this object does nothing. Note that in this case,
    1.31 + * you may not get the transaction type you ask for, and you won't be able
    1.32 + * to rollback.
    1.33 + *
    1.34 + * Note: This class is templatized to be also usable with internal data
    1.35 + * structures. External users of this class should generally use
    1.36 + * |mozStorageTransaction| instead.
    1.37 + */
    1.38 +template<typename T, typename U>
    1.39 +class mozStorageTransactionBase
    1.40 +{
    1.41 +public:
    1.42 +  mozStorageTransactionBase(T* aConnection,
    1.43 +                            bool aCommitOnComplete,
    1.44 +                            int32_t aType = mozIStorageConnection::TRANSACTION_DEFERRED)
    1.45 +    : mConnection(aConnection),
    1.46 +      mHasTransaction(false),
    1.47 +      mCommitOnComplete(aCommitOnComplete),
    1.48 +      mCompleted(false)
    1.49 +  {
    1.50 +    // We won't try to get a transaction if one is already in progress.
    1.51 +    if (mConnection)
    1.52 +      mHasTransaction = NS_SUCCEEDED(mConnection->BeginTransactionAs(aType));
    1.53 +  }
    1.54 +  ~mozStorageTransactionBase()
    1.55 +  {
    1.56 +    if (mConnection && mHasTransaction && ! mCompleted) {
    1.57 +      if (mCommitOnComplete)
    1.58 +        mConnection->CommitTransaction();
    1.59 +      else
    1.60 +        mConnection->RollbackTransaction();
    1.61 +    }
    1.62 +  }
    1.63 +
    1.64 +  /**
    1.65 +   * Commits the transaction if one is in progress. If one is not in progress,
    1.66 +   * this is a NOP since the actual owner of the transaction outside of our
    1.67 +   * scope is in charge of finally comitting or rolling back the transaction.
    1.68 +   */
    1.69 +  nsresult Commit()
    1.70 +  {
    1.71 +    if (!mConnection || mCompleted)
    1.72 +      return NS_OK; // no connection, or already done
    1.73 +    mCompleted = true;
    1.74 +    if (! mHasTransaction)
    1.75 +      return NS_OK; // transaction not ours, ignore
    1.76 +    nsresult rv = mConnection->CommitTransaction();
    1.77 +    if (NS_SUCCEEDED(rv))
    1.78 +      mHasTransaction = false;
    1.79 +
    1.80 +    return rv;
    1.81 +  }
    1.82 +
    1.83 +  /**
    1.84 +   * Rolls back the transaction in progress. You should only call this function
    1.85 +   * if this object has a real transaction (HasTransaction() = true) because
    1.86 +   * otherwise, there is no transaction to roll back.
    1.87 +   */
    1.88 +  nsresult Rollback()
    1.89 +  {
    1.90 +    if (!mConnection || mCompleted)
    1.91 +      return NS_OK; // no connection, or already done
    1.92 +    mCompleted = true;
    1.93 +    if (! mHasTransaction)
    1.94 +      return NS_ERROR_FAILURE;
    1.95 +
    1.96 +    // It is possible that a rollback will return busy, so we busy wait...
    1.97 +    nsresult rv = NS_OK;
    1.98 +    do {
    1.99 +      rv = mConnection->RollbackTransaction();
   1.100 +      if (rv == NS_ERROR_STORAGE_BUSY)
   1.101 +        (void)PR_Sleep(PR_INTERVAL_NO_WAIT);
   1.102 +    } while (rv == NS_ERROR_STORAGE_BUSY);
   1.103 +
   1.104 +    if (NS_SUCCEEDED(rv))
   1.105 +      mHasTransaction = false;
   1.106 +
   1.107 +    return rv;
   1.108 +  }
   1.109 +
   1.110 +  /**
   1.111 +   * Returns whether this object wraps a real transaction. False means that
   1.112 +   * this object doesn't do anything because there was already a transaction in
   1.113 +   * progress when it was created.
   1.114 +   */
   1.115 +  bool HasTransaction()
   1.116 +  {
   1.117 +    return mHasTransaction;
   1.118 +  }
   1.119 +
   1.120 +  /**
   1.121 +   * This sets the default action (commit or rollback) when this object goes
   1.122 +   * out of scope.
   1.123 +   */
   1.124 +  void SetDefaultAction(bool aCommitOnComplete)
   1.125 +  {
   1.126 +    mCommitOnComplete = aCommitOnComplete;
   1.127 +  }
   1.128 +
   1.129 +protected:
   1.130 +  U mConnection;
   1.131 +  bool mHasTransaction;
   1.132 +  bool mCommitOnComplete;
   1.133 +  bool mCompleted;
   1.134 +};
   1.135 +
   1.136 +/**
   1.137 + * An instance of the mozStorageTransaction<> family dedicated
   1.138 + * to |mozIStorageConnection|.
   1.139 + */
   1.140 +typedef mozStorageTransactionBase<mozIStorageConnection,
   1.141 +                                  nsCOMPtr<mozIStorageConnection> >
   1.142 +mozStorageTransaction;
   1.143 +
   1.144 +
   1.145 +
   1.146 +/**
   1.147 + * This class wraps a statement so that it is guaraneed to be reset when
   1.148 + * this object goes out of scope.
   1.149 + *
   1.150 + * Note that this always just resets the statement. If the statement doesn't
   1.151 + * need resetting, the reset operation is inexpensive.
   1.152 + */
   1.153 +class MOZ_STACK_CLASS mozStorageStatementScoper
   1.154 +{
   1.155 +public:
   1.156 +  mozStorageStatementScoper(mozIStorageStatement* aStatement)
   1.157 +      : mStatement(aStatement)
   1.158 +  {
   1.159 +  }
   1.160 +  ~mozStorageStatementScoper()
   1.161 +  {
   1.162 +    if (mStatement)
   1.163 +      mStatement->Reset();
   1.164 +  }
   1.165 +
   1.166 +  /**
   1.167 +   * Call this to make the statement not reset. You might do this if you know
   1.168 +   * that the statement has been reset.
   1.169 +   */
   1.170 +  void Abandon()
   1.171 +  {
   1.172 +    mStatement = nullptr;
   1.173 +  }
   1.174 +
   1.175 +protected:
   1.176 +  nsCOMPtr<mozIStorageStatement> mStatement;
   1.177 +};
   1.178 +
   1.179 +// Use this to make queries uniquely identifiable in telemetry
   1.180 +// statistics, especially PRAGMAs.  We don't include __LINE__ so that
   1.181 +// queries are stable in the face of source code changes.
   1.182 +#define MOZ_STORAGE_UNIQUIFY_QUERY_STR "/* " __FILE__ " */ "
   1.183 +
   1.184 +#endif /* MOZSTORAGEHELPER_H */

mercurial