Bumping manifests a=b2g-bump
[gecko.git] / dom / indexedDB / IDBTransaction.h
blobdb8149323e98bac024b5829081f356f892fd7b66
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_indexeddb_idbtransaction_h__
8 #define mozilla_dom_indexeddb_idbtransaction_h__
10 #include "mozilla/Attributes.h"
11 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
13 #include "mozIStorageConnection.h"
14 #include "mozIStorageStatement.h"
15 #include "mozIStorageFunction.h"
16 #include "mozilla/dom/DOMError.h"
17 #include "nsIRunnable.h"
19 #include "nsAutoPtr.h"
20 #include "nsClassHashtable.h"
21 #include "nsHashKeys.h"
22 #include "nsInterfaceHashtable.h"
23 #include "nsRefPtrHashtable.h"
25 #include "mozilla/dom/IDBTransactionBinding.h"
26 #include "mozilla/dom/indexedDB/IDBDatabase.h"
27 #include "mozilla/dom/indexedDB/IDBWrapperCache.h"
28 #include "mozilla/dom/indexedDB/FileInfo.h"
30 class nsIThread;
31 class nsPIDOMWindow;
33 namespace mozilla {
34 class EventChainPreVisitor;
35 } // namespace mozilla
37 BEGIN_INDEXEDDB_NAMESPACE
39 class AsyncConnectionHelper;
40 class CommitHelper;
41 class IDBRequest;
42 class IndexedDBDatabaseChild;
43 class IndexedDBTransactionChild;
44 class IndexedDBTransactionParent;
45 struct ObjectStoreInfo;
46 class TransactionThreadPool;
47 class UpdateRefcountFunction;
49 class IDBTransactionListener
51 public:
52 NS_IMETHOD_(MozExternalRefCountType) AddRef() = 0;
53 NS_IMETHOD_(MozExternalRefCountType) Release() = 0;
55 // Called just before dispatching the final events on the transaction.
56 virtual nsresult NotifyTransactionPreComplete(IDBTransaction* aTransaction) = 0;
57 // Called just after dispatching the final events on the transaction.
58 virtual nsresult NotifyTransactionPostComplete(IDBTransaction* aTransaction) = 0;
61 class IDBTransaction : public IDBWrapperCache,
62 public nsIRunnable
64 friend class AsyncConnectionHelper;
65 friend class CommitHelper;
66 friend class IndexedDBDatabaseChild;
67 friend class ThreadObserver;
68 friend class TransactionThreadPool;
70 public:
71 NS_DECL_ISUPPORTS_INHERITED
72 NS_DECL_NSIRUNNABLE
74 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, IDBWrapperCache)
76 enum Mode
78 READ_ONLY = 0,
79 READ_WRITE,
80 VERSION_CHANGE,
82 // Only needed for IPC serialization helper, should never be used in code.
83 MODE_INVALID
86 enum ReadyState
88 INITIAL = 0,
89 LOADING,
90 COMMITTING,
91 DONE
94 static already_AddRefed<IDBTransaction>
95 Create(IDBDatabase* aDatabase,
96 const Sequence<nsString>& aObjectStoreNames,
97 Mode aMode,
98 bool aDispatchDelayed)
100 return CreateInternal(aDatabase, aObjectStoreNames, aMode, aDispatchDelayed,
101 false);
104 // nsIDOMEventTarget
105 virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
107 void OnNewRequest();
108 void OnRequestFinished();
109 void OnRequestDisconnected();
111 void RemoveObjectStore(const nsAString& aName);
113 void SetTransactionListener(IDBTransactionListener* aListener);
115 bool StartSavepoint();
116 nsresult ReleaseSavepoint();
117 void RollbackSavepoint();
119 // Only meant to be called on mStorageThread!
120 nsresult GetOrCreateConnection(mozIStorageConnection** aConnection);
122 already_AddRefed<mozIStorageStatement>
123 GetCachedStatement(const nsACString& aQuery);
125 template<int N>
126 already_AddRefed<mozIStorageStatement>
127 GetCachedStatement(const char (&aQuery)[N])
129 return GetCachedStatement(NS_LITERAL_CSTRING(aQuery));
132 bool IsOpen() const;
134 bool IsFinished() const
136 return mReadyState > LOADING;
139 bool IsWriteAllowed() const
141 return mMode == READ_WRITE || mMode == VERSION_CHANGE;
144 bool IsAborted() const
146 return NS_FAILED(mAbortCode);
149 // 'Get' prefix is to avoid name collisions with the enum
150 Mode GetMode()
152 return mMode;
155 IDBDatabase* Database()
157 NS_ASSERTION(mDatabase, "This should never be null!");
158 return mDatabase;
161 DatabaseInfo* DBInfo() const
163 return mDatabaseInfo;
166 already_AddRefed<IDBObjectStore>
167 GetOrCreateObjectStore(const nsAString& aName,
168 ObjectStoreInfo* aObjectStoreInfo,
169 bool aCreating);
171 already_AddRefed<FileInfo> GetFileInfo(nsIDOMBlob* aBlob);
172 void AddFileInfo(nsIDOMBlob* aBlob, FileInfo* aFileInfo);
174 void ClearCreatedFileInfos();
176 void
177 SetActor(IndexedDBTransactionChild* aActorChild)
179 NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
180 mActorChild = aActorChild;
183 void
184 SetActor(IndexedDBTransactionParent* aActorParent)
186 NS_ASSERTION(!aActorParent || !mActorParent,
187 "Shouldn't have more than one!");
188 mActorParent = aActorParent;
191 IndexedDBTransactionChild*
192 GetActorChild() const
194 return mActorChild;
197 IndexedDBTransactionParent*
198 GetActorParent() const
200 return mActorParent;
203 nsresult
204 Abort(IDBRequest* aRequest);
206 nsresult
207 Abort(nsresult aAbortCode);
209 nsresult
210 GetAbortCode() const
212 return mAbortCode;
215 #ifdef MOZ_ENABLE_PROFILER_SPS
216 uint64_t
217 GetSerialNumber() const
219 return mSerialNumber;
221 #endif
223 // nsWrapperCache
224 virtual JSObject*
225 WrapObject(JSContext* aCx) MOZ_OVERRIDE;
227 // WebIDL
228 nsPIDOMWindow*
229 GetParentObject() const
231 return GetOwner();
234 IDBTransactionMode
235 GetMode(ErrorResult& aRv) const;
237 IDBDatabase*
238 Db() const
240 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
241 return mDatabase;
244 DOMError*
245 GetError() const;
247 already_AddRefed<IDBObjectStore>
248 ObjectStore(const nsAString& aName, ErrorResult& aRv);
250 void
251 Abort(ErrorResult& aRv)
253 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
254 aRv = AbortInternal(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR, nullptr);
257 IMPL_EVENT_HANDLER(abort)
258 IMPL_EVENT_HANDLER(complete)
259 IMPL_EVENT_HANDLER(error)
261 already_AddRefed<DOMStringList>
262 GetObjectStoreNames(ErrorResult& aRv);
264 private:
265 nsresult
266 AbortInternal(nsresult aAbortCode,
267 already_AddRefed<mozilla::dom::DOMError> aError);
269 // Should only be called directly through IndexedDBDatabaseChild.
270 static already_AddRefed<IDBTransaction>
271 CreateInternal(IDBDatabase* aDatabase,
272 const Sequence<nsString>& aObjectStoreNames,
273 Mode aMode,
274 bool aDispatchDelayed,
275 bool aIsVersionChangeTransactionChild);
277 explicit IDBTransaction(IDBDatabase* aDatabase);
278 ~IDBTransaction();
280 nsresult CommitOrRollback();
282 nsRefPtr<IDBDatabase> mDatabase;
283 nsRefPtr<DatabaseInfo> mDatabaseInfo;
284 nsRefPtr<DOMError> mError;
285 nsTArray<nsString> mObjectStoreNames;
286 ReadyState mReadyState;
287 Mode mMode;
288 uint32_t mPendingRequests;
290 nsInterfaceHashtable<nsCStringHashKey, mozIStorageStatement>
291 mCachedStatements;
293 nsRefPtr<IDBTransactionListener> mListener;
295 // Only touched on the database thread.
296 nsCOMPtr<mozIStorageConnection> mConnection;
298 // Only touched on the database thread.
299 uint32_t mSavepointCount;
301 nsTArray<nsRefPtr<IDBObjectStore> > mCreatedObjectStores;
302 nsTArray<nsRefPtr<IDBObjectStore> > mDeletedObjectStores;
304 nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
305 nsRefPtrHashtable<nsISupportsHashKey, FileInfo> mCreatedFileInfos;
307 IndexedDBTransactionChild* mActorChild;
308 IndexedDBTransactionParent* mActorParent;
310 nsresult mAbortCode;
311 #ifdef MOZ_ENABLE_PROFILER_SPS
312 uint64_t mSerialNumber;
313 #endif
314 bool mCreating;
316 #ifdef DEBUG
317 bool mFiredCompleteOrAbort;
318 #endif
321 class CommitHelper MOZ_FINAL : public nsIRunnable
323 public:
324 NS_DECL_THREADSAFE_ISUPPORTS
325 NS_DECL_NSIRUNNABLE
327 CommitHelper(IDBTransaction* aTransaction,
328 IDBTransactionListener* aListener,
329 const nsTArray<nsRefPtr<IDBObjectStore> >& mUpdatedObjectStores);
330 CommitHelper(IDBTransaction* aTransaction,
331 nsresult aAbortCode);
333 template<class T>
334 bool AddDoomedObject(nsCOMPtr<T>& aCOMPtr)
336 if (aCOMPtr) {
337 if (!mDoomedObjects.AppendElement(do_QueryInterface(aCOMPtr))) {
338 NS_ERROR("Out of memory!");
339 return false;
341 aCOMPtr = nullptr;
343 return true;
346 private:
347 ~CommitHelper();
349 // Writes new autoincrement counts to database
350 nsresult WriteAutoIncrementCounts();
352 // Updates counts after a successful commit
353 void CommitAutoIncrementCounts();
355 // Reverts counts when a transaction is aborted
356 void RevertAutoIncrementCounts();
358 nsRefPtr<IDBTransaction> mTransaction;
359 nsRefPtr<IDBTransactionListener> mListener;
360 nsCOMPtr<mozIStorageConnection> mConnection;
361 nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
362 nsAutoTArray<nsCOMPtr<nsISupports>, 10> mDoomedObjects;
363 nsAutoTArray<nsRefPtr<IDBObjectStore>, 10> mAutoIncrementObjectStores;
365 nsresult mAbortCode;
368 class UpdateRefcountFunction MOZ_FINAL : public mozIStorageFunction
370 ~UpdateRefcountFunction()
373 public:
374 NS_DECL_THREADSAFE_ISUPPORTS
375 NS_DECL_MOZISTORAGEFUNCTION
377 explicit UpdateRefcountFunction(FileManager* aFileManager)
378 : mFileManager(aFileManager), mInSavepoint(false)
381 void StartSavepoint()
383 MOZ_ASSERT(!mInSavepoint);
384 MOZ_ASSERT(!mSavepointEntriesIndex.Count());
386 mInSavepoint = true;
389 void ReleaseSavepoint()
391 MOZ_ASSERT(mInSavepoint);
393 mSavepointEntriesIndex.Clear();
395 mInSavepoint = false;
398 void RollbackSavepoint()
400 MOZ_ASSERT(mInSavepoint);
402 mInSavepoint = false;
404 mSavepointEntriesIndex.EnumerateRead(RollbackSavepointCallback, nullptr);
406 mSavepointEntriesIndex.Clear();
409 void ClearFileInfoEntries()
411 mFileInfoEntries.Clear();
414 nsresult WillCommit(mozIStorageConnection* aConnection);
415 void DidCommit();
416 void DidAbort();
418 private:
419 class FileInfoEntry
421 public:
422 explicit FileInfoEntry(FileInfo* aFileInfo)
423 : mFileInfo(aFileInfo), mDelta(0), mSavepointDelta(0)
426 ~FileInfoEntry()
429 nsRefPtr<FileInfo> mFileInfo;
430 int32_t mDelta;
431 int32_t mSavepointDelta;
434 enum UpdateType {
435 eIncrement,
436 eDecrement
439 class DatabaseUpdateFunction
441 public:
442 DatabaseUpdateFunction(mozIStorageConnection* aConnection,
443 UpdateRefcountFunction* aFunction)
444 : mConnection(aConnection), mFunction(aFunction), mErrorCode(NS_OK)
447 bool Update(int64_t aId, int32_t aDelta);
448 nsresult ErrorCode()
450 return mErrorCode;
453 private:
454 nsresult UpdateInternal(int64_t aId, int32_t aDelta);
456 nsCOMPtr<mozIStorageConnection> mConnection;
457 nsCOMPtr<mozIStorageStatement> mUpdateStatement;
458 nsCOMPtr<mozIStorageStatement> mSelectStatement;
459 nsCOMPtr<mozIStorageStatement> mInsertStatement;
461 UpdateRefcountFunction* mFunction;
463 nsresult mErrorCode;
466 nsresult ProcessValue(mozIStorageValueArray* aValues,
467 int32_t aIndex,
468 UpdateType aUpdateType);
470 nsresult CreateJournals();
472 nsresult RemoveJournals(const nsTArray<int64_t>& aJournals);
474 static PLDHashOperator
475 DatabaseUpdateCallback(const uint64_t& aKey,
476 FileInfoEntry* aValue,
477 void* aUserArg);
479 static PLDHashOperator
480 FileInfoUpdateCallback(const uint64_t& aKey,
481 FileInfoEntry* aValue,
482 void* aUserArg);
484 static PLDHashOperator
485 RollbackSavepointCallback(const uint64_t& aKey,
486 FileInfoEntry* aValue,
487 void* aUserArg);
489 FileManager* mFileManager;
490 nsClassHashtable<nsUint64HashKey, FileInfoEntry> mFileInfoEntries;
491 nsDataHashtable<nsUint64HashKey, FileInfoEntry*> mSavepointEntriesIndex;
493 nsTArray<int64_t> mJournalsToCreateBeforeCommit;
494 nsTArray<int64_t> mJournalsToRemoveAfterCommit;
495 nsTArray<int64_t> mJournalsToRemoveAfterAbort;
497 bool mInSavepoint;
500 END_INDEXEDDB_NAMESPACE
502 #endif // mozilla_dom_indexeddb_idbtransaction_h__