storage/public/StatementCache.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef mozilla_storage_StatementCache_h
michael@0 8 #define mozilla_storage_StatementCache_h
michael@0 9
michael@0 10 #include "mozIStorageConnection.h"
michael@0 11 #include "mozIStorageStatement.h"
michael@0 12 #include "mozIStorageAsyncStatement.h"
michael@0 13
michael@0 14 #include "nsAutoPtr.h"
michael@0 15 #include "nsHashKeys.h"
michael@0 16 #include "nsInterfaceHashtable.h"
michael@0 17
michael@0 18 namespace mozilla {
michael@0 19 namespace storage {
michael@0 20
michael@0 21 /**
michael@0 22 * Class used to cache statements (mozIStorageStatement or
michael@0 23 * mozIStorageAsyncStatement).
michael@0 24 */
michael@0 25 template<typename StatementType>
michael@0 26 class StatementCache {
michael@0 27 public:
michael@0 28 /**
michael@0 29 * Constructor for the cache.
michael@0 30 *
michael@0 31 * @note a connection can have more than one cache.
michael@0 32 *
michael@0 33 * @param aConnection
michael@0 34 * A reference to the nsCOMPtr for the connection this cache is to be
michael@0 35 * used for. This nsCOMPtr must at least live as long as this class,
michael@0 36 * otherwise crashes will happen.
michael@0 37 */
michael@0 38 StatementCache(nsCOMPtr<mozIStorageConnection>& aConnection)
michael@0 39 : mConnection(aConnection)
michael@0 40 {
michael@0 41 }
michael@0 42
michael@0 43 /**
michael@0 44 * Obtains a cached statement. If this statement is not yet created, it will
michael@0 45 * be created and stored for later use.
michael@0 46 *
michael@0 47 * @param aQuery
michael@0 48 * The SQL string (either a const char [] or nsACString) to get a
michael@0 49 * cached query for.
michael@0 50 * @return the cached statement, or null upon error.
michael@0 51 */
michael@0 52 inline
michael@0 53 already_AddRefed<StatementType>
michael@0 54 GetCachedStatement(const nsACString& aQuery)
michael@0 55 {
michael@0 56 nsCOMPtr<StatementType> stmt;
michael@0 57 if (!mCachedStatements.Get(aQuery, getter_AddRefs(stmt))) {
michael@0 58 stmt = CreateStatement(aQuery);
michael@0 59 NS_ENSURE_TRUE(stmt, nullptr);
michael@0 60
michael@0 61 mCachedStatements.Put(aQuery, stmt);
michael@0 62 }
michael@0 63 return stmt.forget();
michael@0 64 }
michael@0 65
michael@0 66 template<int N>
michael@0 67 MOZ_ALWAYS_INLINE already_AddRefed<StatementType>
michael@0 68 GetCachedStatement(const char (&aQuery)[N])
michael@0 69 {
michael@0 70 nsDependentCString query(aQuery, N - 1);
michael@0 71 return GetCachedStatement(query);
michael@0 72 }
michael@0 73
michael@0 74 /**
michael@0 75 * Finalizes all cached statements so the database can be safely closed. The
michael@0 76 * behavior of this cache is unspecified after this method is called.
michael@0 77 */
michael@0 78 inline
michael@0 79 void
michael@0 80 FinalizeStatements()
michael@0 81 {
michael@0 82 (void)mCachedStatements.Enumerate(FinalizeCachedStatements, nullptr);
michael@0 83
michael@0 84 // Clear the cache at this time too!
michael@0 85 (void)mCachedStatements.Clear();
michael@0 86 }
michael@0 87
michael@0 88 private:
michael@0 89 inline
michael@0 90 already_AddRefed<StatementType>
michael@0 91 CreateStatement(const nsACString& aQuery);
michael@0 92 static
michael@0 93 PLDHashOperator
michael@0 94 FinalizeCachedStatements(const nsACString& aKey,
michael@0 95 nsCOMPtr<StatementType>& aStatement,
michael@0 96 void*)
michael@0 97 {
michael@0 98 (void)aStatement->Finalize();
michael@0 99 return PL_DHASH_NEXT;
michael@0 100 }
michael@0 101
michael@0 102 nsInterfaceHashtable<nsCStringHashKey, StatementType> mCachedStatements;
michael@0 103 nsCOMPtr<mozIStorageConnection>& mConnection;
michael@0 104 };
michael@0 105
michael@0 106 template< >
michael@0 107 inline
michael@0 108 already_AddRefed<mozIStorageStatement>
michael@0 109 StatementCache<mozIStorageStatement>::CreateStatement(const nsACString& aQuery)
michael@0 110 {
michael@0 111 NS_ENSURE_TRUE(mConnection, nullptr);
michael@0 112
michael@0 113 nsCOMPtr<mozIStorageStatement> stmt;
michael@0 114 nsresult rv = mConnection->CreateStatement(aQuery, getter_AddRefs(stmt));
michael@0 115 if (NS_FAILED(rv)) {
michael@0 116 nsCString error;
michael@0 117 error.AppendLiteral("The statement '");
michael@0 118 error.Append(aQuery);
michael@0 119 error.AppendLiteral("' failed to compile with the error message '");
michael@0 120 nsCString msg;
michael@0 121 (void)mConnection->GetLastErrorString(msg);
michael@0 122 error.Append(msg);
michael@0 123 error.AppendLiteral("'.");
michael@0 124 NS_ERROR(error.get());
michael@0 125 }
michael@0 126 NS_ENSURE_SUCCESS(rv, nullptr);
michael@0 127
michael@0 128 return stmt.forget();
michael@0 129 }
michael@0 130
michael@0 131 template< >
michael@0 132 inline
michael@0 133 already_AddRefed<mozIStorageAsyncStatement>
michael@0 134 StatementCache<mozIStorageAsyncStatement>::CreateStatement(const nsACString& aQuery)
michael@0 135 {
michael@0 136 NS_ENSURE_TRUE(mConnection, nullptr);
michael@0 137
michael@0 138 nsCOMPtr<mozIStorageAsyncStatement> stmt;
michael@0 139 nsresult rv = mConnection->CreateAsyncStatement(aQuery, getter_AddRefs(stmt));
michael@0 140 NS_ENSURE_SUCCESS(rv, nullptr);
michael@0 141
michael@0 142 return stmt.forget();
michael@0 143 }
michael@0 144
michael@0 145 } // namespace storage
michael@0 146 } // namespace mozilla
michael@0 147
michael@0 148 #endif // mozilla_storage_StatementCache_h

mercurial