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"
34 class EventChainPreVisitor
;
35 } // namespace mozilla
37 BEGIN_INDEXEDDB_NAMESPACE
39 class AsyncConnectionHelper
;
42 class IndexedDBDatabaseChild
;
43 class IndexedDBTransactionChild
;
44 class IndexedDBTransactionParent
;
45 struct ObjectStoreInfo
;
46 class TransactionThreadPool
;
47 class UpdateRefcountFunction
;
49 class IDBTransactionListener
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
,
64 friend class AsyncConnectionHelper
;
65 friend class CommitHelper
;
66 friend class IndexedDBDatabaseChild
;
67 friend class ThreadObserver
;
68 friend class TransactionThreadPool
;
71 NS_DECL_ISUPPORTS_INHERITED
74 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction
, IDBWrapperCache
)
82 // Only needed for IPC serialization helper, should never be used in code.
94 static already_AddRefed
<IDBTransaction
>
95 Create(IDBDatabase
* aDatabase
,
96 const Sequence
<nsString
>& aObjectStoreNames
,
98 bool aDispatchDelayed
)
100 return CreateInternal(aDatabase
, aObjectStoreNames
, aMode
, aDispatchDelayed
,
105 virtual nsresult
PreHandleEvent(EventChainPreVisitor
& aVisitor
) MOZ_OVERRIDE
;
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
);
126 already_AddRefed
<mozIStorageStatement
>
127 GetCachedStatement(const char (&aQuery
)[N
])
129 return GetCachedStatement(NS_LITERAL_CSTRING(aQuery
));
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
155 IDBDatabase
* Database()
157 NS_ASSERTION(mDatabase
, "This should never be null!");
161 DatabaseInfo
* DBInfo() const
163 return mDatabaseInfo
;
166 already_AddRefed
<IDBObjectStore
>
167 GetOrCreateObjectStore(const nsAString
& aName
,
168 ObjectStoreInfo
* aObjectStoreInfo
,
171 already_AddRefed
<FileInfo
> GetFileInfo(nsIDOMBlob
* aBlob
);
172 void AddFileInfo(nsIDOMBlob
* aBlob
, FileInfo
* aFileInfo
);
174 void ClearCreatedFileInfos();
177 SetActor(IndexedDBTransactionChild
* aActorChild
)
179 NS_ASSERTION(!aActorChild
|| !mActorChild
, "Shouldn't have more than one!");
180 mActorChild
= aActorChild
;
184 SetActor(IndexedDBTransactionParent
* aActorParent
)
186 NS_ASSERTION(!aActorParent
|| !mActorParent
,
187 "Shouldn't have more than one!");
188 mActorParent
= aActorParent
;
191 IndexedDBTransactionChild
*
192 GetActorChild() const
197 IndexedDBTransactionParent
*
198 GetActorParent() const
204 Abort(IDBRequest
* aRequest
);
207 Abort(nsresult aAbortCode
);
215 #ifdef MOZ_ENABLE_PROFILER_SPS
217 GetSerialNumber() const
219 return mSerialNumber
;
225 WrapObject(JSContext
* aCx
) MOZ_OVERRIDE
;
229 GetParentObject() const
235 GetMode(ErrorResult
& aRv
) const;
240 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
247 already_AddRefed
<IDBObjectStore
>
248 ObjectStore(const nsAString
& aName
, ErrorResult
& aRv
);
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
);
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
,
274 bool aDispatchDelayed
,
275 bool aIsVersionChangeTransactionChild
);
277 explicit IDBTransaction(IDBDatabase
* aDatabase
);
280 nsresult
CommitOrRollback();
282 nsRefPtr
<IDBDatabase
> mDatabase
;
283 nsRefPtr
<DatabaseInfo
> mDatabaseInfo
;
284 nsRefPtr
<DOMError
> mError
;
285 nsTArray
<nsString
> mObjectStoreNames
;
286 ReadyState mReadyState
;
288 uint32_t mPendingRequests
;
290 nsInterfaceHashtable
<nsCStringHashKey
, mozIStorageStatement
>
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
;
311 #ifdef MOZ_ENABLE_PROFILER_SPS
312 uint64_t mSerialNumber
;
317 bool mFiredCompleteOrAbort
;
321 class CommitHelper MOZ_FINAL
: public nsIRunnable
324 NS_DECL_THREADSAFE_ISUPPORTS
327 CommitHelper(IDBTransaction
* aTransaction
,
328 IDBTransactionListener
* aListener
,
329 const nsTArray
<nsRefPtr
<IDBObjectStore
> >& mUpdatedObjectStores
);
330 CommitHelper(IDBTransaction
* aTransaction
,
331 nsresult aAbortCode
);
334 bool AddDoomedObject(nsCOMPtr
<T
>& aCOMPtr
)
337 if (!mDoomedObjects
.AppendElement(do_QueryInterface(aCOMPtr
))) {
338 NS_ERROR("Out of memory!");
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
;
368 class UpdateRefcountFunction MOZ_FINAL
: public mozIStorageFunction
370 ~UpdateRefcountFunction()
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());
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
);
422 explicit FileInfoEntry(FileInfo
* aFileInfo
)
423 : mFileInfo(aFileInfo
), mDelta(0), mSavepointDelta(0)
429 nsRefPtr
<FileInfo
> mFileInfo
;
431 int32_t mSavepointDelta
;
439 class DatabaseUpdateFunction
442 DatabaseUpdateFunction(mozIStorageConnection
* aConnection
,
443 UpdateRefcountFunction
* aFunction
)
444 : mConnection(aConnection
), mFunction(aFunction
), mErrorCode(NS_OK
)
447 bool Update(int64_t aId
, int32_t aDelta
);
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
;
466 nsresult
ProcessValue(mozIStorageValueArray
* aValues
,
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
,
479 static PLDHashOperator
480 FileInfoUpdateCallback(const uint64_t& aKey
,
481 FileInfoEntry
* aValue
,
484 static PLDHashOperator
485 RollbackSavepointCallback(const uint64_t& aKey
,
486 FileInfoEntry
* aValue
,
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
;
500 END_INDEXEDDB_NAMESPACE
502 #endif // mozilla_dom_indexeddb_idbtransaction_h__