storage/public/mozStorageHelper.h

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef MOZSTORAGEHELPER_H
michael@0 7 #define MOZSTORAGEHELPER_H
michael@0 8
michael@0 9 #include "nsAutoPtr.h"
michael@0 10
michael@0 11 #include "mozIStorageAsyncConnection.h"
michael@0 12 #include "mozIStorageConnection.h"
michael@0 13 #include "mozIStorageStatement.h"
michael@0 14 #include "nsError.h"
michael@0 15
michael@0 16 /**
michael@0 17 * This class wraps a transaction inside a given C++ scope, guaranteeing that
michael@0 18 * the transaction will be completed even if you have an exception or
michael@0 19 * return early.
michael@0 20 *
michael@0 21 * aCommitOnComplete controls whether the transaction is committed or rolled
michael@0 22 * back when it goes out of scope. A common use is to create an instance with
michael@0 23 * commitOnComplete = FALSE (rollback), then call Commit on this object manually
michael@0 24 * when your function completes successfully.
michael@0 25 *
michael@0 26 * Note that nested transactions are not supported by sqlite, so if a transaction
michael@0 27 * is already in progress, this object does nothing. Note that in this case,
michael@0 28 * you may not get the transaction type you ask for, and you won't be able
michael@0 29 * to rollback.
michael@0 30 *
michael@0 31 * Note: This class is templatized to be also usable with internal data
michael@0 32 * structures. External users of this class should generally use
michael@0 33 * |mozStorageTransaction| instead.
michael@0 34 */
michael@0 35 template<typename T, typename U>
michael@0 36 class mozStorageTransactionBase
michael@0 37 {
michael@0 38 public:
michael@0 39 mozStorageTransactionBase(T* aConnection,
michael@0 40 bool aCommitOnComplete,
michael@0 41 int32_t aType = mozIStorageConnection::TRANSACTION_DEFERRED)
michael@0 42 : mConnection(aConnection),
michael@0 43 mHasTransaction(false),
michael@0 44 mCommitOnComplete(aCommitOnComplete),
michael@0 45 mCompleted(false)
michael@0 46 {
michael@0 47 // We won't try to get a transaction if one is already in progress.
michael@0 48 if (mConnection)
michael@0 49 mHasTransaction = NS_SUCCEEDED(mConnection->BeginTransactionAs(aType));
michael@0 50 }
michael@0 51 ~mozStorageTransactionBase()
michael@0 52 {
michael@0 53 if (mConnection && mHasTransaction && ! mCompleted) {
michael@0 54 if (mCommitOnComplete)
michael@0 55 mConnection->CommitTransaction();
michael@0 56 else
michael@0 57 mConnection->RollbackTransaction();
michael@0 58 }
michael@0 59 }
michael@0 60
michael@0 61 /**
michael@0 62 * Commits the transaction if one is in progress. If one is not in progress,
michael@0 63 * this is a NOP since the actual owner of the transaction outside of our
michael@0 64 * scope is in charge of finally comitting or rolling back the transaction.
michael@0 65 */
michael@0 66 nsresult Commit()
michael@0 67 {
michael@0 68 if (!mConnection || mCompleted)
michael@0 69 return NS_OK; // no connection, or already done
michael@0 70 mCompleted = true;
michael@0 71 if (! mHasTransaction)
michael@0 72 return NS_OK; // transaction not ours, ignore
michael@0 73 nsresult rv = mConnection->CommitTransaction();
michael@0 74 if (NS_SUCCEEDED(rv))
michael@0 75 mHasTransaction = false;
michael@0 76
michael@0 77 return rv;
michael@0 78 }
michael@0 79
michael@0 80 /**
michael@0 81 * Rolls back the transaction in progress. You should only call this function
michael@0 82 * if this object has a real transaction (HasTransaction() = true) because
michael@0 83 * otherwise, there is no transaction to roll back.
michael@0 84 */
michael@0 85 nsresult Rollback()
michael@0 86 {
michael@0 87 if (!mConnection || mCompleted)
michael@0 88 return NS_OK; // no connection, or already done
michael@0 89 mCompleted = true;
michael@0 90 if (! mHasTransaction)
michael@0 91 return NS_ERROR_FAILURE;
michael@0 92
michael@0 93 // It is possible that a rollback will return busy, so we busy wait...
michael@0 94 nsresult rv = NS_OK;
michael@0 95 do {
michael@0 96 rv = mConnection->RollbackTransaction();
michael@0 97 if (rv == NS_ERROR_STORAGE_BUSY)
michael@0 98 (void)PR_Sleep(PR_INTERVAL_NO_WAIT);
michael@0 99 } while (rv == NS_ERROR_STORAGE_BUSY);
michael@0 100
michael@0 101 if (NS_SUCCEEDED(rv))
michael@0 102 mHasTransaction = false;
michael@0 103
michael@0 104 return rv;
michael@0 105 }
michael@0 106
michael@0 107 /**
michael@0 108 * Returns whether this object wraps a real transaction. False means that
michael@0 109 * this object doesn't do anything because there was already a transaction in
michael@0 110 * progress when it was created.
michael@0 111 */
michael@0 112 bool HasTransaction()
michael@0 113 {
michael@0 114 return mHasTransaction;
michael@0 115 }
michael@0 116
michael@0 117 /**
michael@0 118 * This sets the default action (commit or rollback) when this object goes
michael@0 119 * out of scope.
michael@0 120 */
michael@0 121 void SetDefaultAction(bool aCommitOnComplete)
michael@0 122 {
michael@0 123 mCommitOnComplete = aCommitOnComplete;
michael@0 124 }
michael@0 125
michael@0 126 protected:
michael@0 127 U mConnection;
michael@0 128 bool mHasTransaction;
michael@0 129 bool mCommitOnComplete;
michael@0 130 bool mCompleted;
michael@0 131 };
michael@0 132
michael@0 133 /**
michael@0 134 * An instance of the mozStorageTransaction<> family dedicated
michael@0 135 * to |mozIStorageConnection|.
michael@0 136 */
michael@0 137 typedef mozStorageTransactionBase<mozIStorageConnection,
michael@0 138 nsCOMPtr<mozIStorageConnection> >
michael@0 139 mozStorageTransaction;
michael@0 140
michael@0 141
michael@0 142
michael@0 143 /**
michael@0 144 * This class wraps a statement so that it is guaraneed to be reset when
michael@0 145 * this object goes out of scope.
michael@0 146 *
michael@0 147 * Note that this always just resets the statement. If the statement doesn't
michael@0 148 * need resetting, the reset operation is inexpensive.
michael@0 149 */
michael@0 150 class MOZ_STACK_CLASS mozStorageStatementScoper
michael@0 151 {
michael@0 152 public:
michael@0 153 mozStorageStatementScoper(mozIStorageStatement* aStatement)
michael@0 154 : mStatement(aStatement)
michael@0 155 {
michael@0 156 }
michael@0 157 ~mozStorageStatementScoper()
michael@0 158 {
michael@0 159 if (mStatement)
michael@0 160 mStatement->Reset();
michael@0 161 }
michael@0 162
michael@0 163 /**
michael@0 164 * Call this to make the statement not reset. You might do this if you know
michael@0 165 * that the statement has been reset.
michael@0 166 */
michael@0 167 void Abandon()
michael@0 168 {
michael@0 169 mStatement = nullptr;
michael@0 170 }
michael@0 171
michael@0 172 protected:
michael@0 173 nsCOMPtr<mozIStorageStatement> mStatement;
michael@0 174 };
michael@0 175
michael@0 176 // Use this to make queries uniquely identifiable in telemetry
michael@0 177 // statistics, especially PRAGMAs. We don't include __LINE__ so that
michael@0 178 // queries are stable in the face of source code changes.
michael@0 179 #define MOZ_STORAGE_UNIQUIFY_QUERY_STR "/* " __FILE__ " */ "
michael@0 180
michael@0 181 #endif /* MOZSTORAGEHELPER_H */

mercurial