dom/indexedDB/IDBTransaction.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
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_dom_indexeddb_idbtransaction_h__
michael@0 8 #define mozilla_dom_indexeddb_idbtransaction_h__
michael@0 9
michael@0 10 #include "mozilla/Attributes.h"
michael@0 11 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
michael@0 12
michael@0 13 #include "mozIStorageConnection.h"
michael@0 14 #include "mozIStorageStatement.h"
michael@0 15 #include "mozIStorageFunction.h"
michael@0 16 #include "mozilla/dom/DOMError.h"
michael@0 17 #include "nsIRunnable.h"
michael@0 18
michael@0 19 #include "nsAutoPtr.h"
michael@0 20 #include "nsClassHashtable.h"
michael@0 21 #include "nsHashKeys.h"
michael@0 22 #include "nsInterfaceHashtable.h"
michael@0 23 #include "nsRefPtrHashtable.h"
michael@0 24
michael@0 25 #include "mozilla/dom/IDBTransactionBinding.h"
michael@0 26 #include "mozilla/dom/indexedDB/IDBDatabase.h"
michael@0 27 #include "mozilla/dom/indexedDB/IDBWrapperCache.h"
michael@0 28 #include "mozilla/dom/indexedDB/FileInfo.h"
michael@0 29
michael@0 30 class nsIThread;
michael@0 31 class nsPIDOMWindow;
michael@0 32
michael@0 33 namespace mozilla {
michael@0 34 class EventChainPreVisitor;
michael@0 35 } // namespace mozilla
michael@0 36
michael@0 37 BEGIN_INDEXEDDB_NAMESPACE
michael@0 38
michael@0 39 class AsyncConnectionHelper;
michael@0 40 class CommitHelper;
michael@0 41 class IDBRequest;
michael@0 42 class IndexedDBDatabaseChild;
michael@0 43 class IndexedDBTransactionChild;
michael@0 44 class IndexedDBTransactionParent;
michael@0 45 struct ObjectStoreInfo;
michael@0 46 class TransactionThreadPool;
michael@0 47 class UpdateRefcountFunction;
michael@0 48
michael@0 49 class IDBTransactionListener
michael@0 50 {
michael@0 51 public:
michael@0 52 NS_IMETHOD_(MozExternalRefCountType) AddRef() = 0;
michael@0 53 NS_IMETHOD_(MozExternalRefCountType) Release() = 0;
michael@0 54
michael@0 55 // Called just before dispatching the final events on the transaction.
michael@0 56 virtual nsresult NotifyTransactionPreComplete(IDBTransaction* aTransaction) = 0;
michael@0 57 // Called just after dispatching the final events on the transaction.
michael@0 58 virtual nsresult NotifyTransactionPostComplete(IDBTransaction* aTransaction) = 0;
michael@0 59 };
michael@0 60
michael@0 61 class IDBTransaction : public IDBWrapperCache,
michael@0 62 public nsIRunnable
michael@0 63 {
michael@0 64 friend class AsyncConnectionHelper;
michael@0 65 friend class CommitHelper;
michael@0 66 friend class IndexedDBDatabaseChild;
michael@0 67 friend class ThreadObserver;
michael@0 68 friend class TransactionThreadPool;
michael@0 69
michael@0 70 public:
michael@0 71 NS_DECL_ISUPPORTS_INHERITED
michael@0 72 NS_DECL_NSIRUNNABLE
michael@0 73
michael@0 74 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, IDBWrapperCache)
michael@0 75
michael@0 76 enum Mode
michael@0 77 {
michael@0 78 READ_ONLY = 0,
michael@0 79 READ_WRITE,
michael@0 80 VERSION_CHANGE,
michael@0 81
michael@0 82 // Only needed for IPC serialization helper, should never be used in code.
michael@0 83 MODE_INVALID
michael@0 84 };
michael@0 85
michael@0 86 enum ReadyState
michael@0 87 {
michael@0 88 INITIAL = 0,
michael@0 89 LOADING,
michael@0 90 COMMITTING,
michael@0 91 DONE
michael@0 92 };
michael@0 93
michael@0 94 static already_AddRefed<IDBTransaction>
michael@0 95 Create(IDBDatabase* aDatabase,
michael@0 96 const Sequence<nsString>& aObjectStoreNames,
michael@0 97 Mode aMode,
michael@0 98 bool aDispatchDelayed)
michael@0 99 {
michael@0 100 return CreateInternal(aDatabase, aObjectStoreNames, aMode, aDispatchDelayed,
michael@0 101 false);
michael@0 102 }
michael@0 103
michael@0 104 // nsIDOMEventTarget
michael@0 105 virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
michael@0 106
michael@0 107 void OnNewRequest();
michael@0 108 void OnRequestFinished();
michael@0 109 void OnRequestDisconnected();
michael@0 110
michael@0 111 void RemoveObjectStore(const nsAString& aName);
michael@0 112
michael@0 113 void SetTransactionListener(IDBTransactionListener* aListener);
michael@0 114
michael@0 115 bool StartSavepoint();
michael@0 116 nsresult ReleaseSavepoint();
michael@0 117 void RollbackSavepoint();
michael@0 118
michael@0 119 // Only meant to be called on mStorageThread!
michael@0 120 nsresult GetOrCreateConnection(mozIStorageConnection** aConnection);
michael@0 121
michael@0 122 already_AddRefed<mozIStorageStatement>
michael@0 123 GetCachedStatement(const nsACString& aQuery);
michael@0 124
michael@0 125 template<int N>
michael@0 126 already_AddRefed<mozIStorageStatement>
michael@0 127 GetCachedStatement(const char (&aQuery)[N])
michael@0 128 {
michael@0 129 return GetCachedStatement(NS_LITERAL_CSTRING(aQuery));
michael@0 130 }
michael@0 131
michael@0 132 bool IsOpen() const;
michael@0 133
michael@0 134 bool IsFinished() const
michael@0 135 {
michael@0 136 return mReadyState > LOADING;
michael@0 137 }
michael@0 138
michael@0 139 bool IsWriteAllowed() const
michael@0 140 {
michael@0 141 return mMode == READ_WRITE || mMode == VERSION_CHANGE;
michael@0 142 }
michael@0 143
michael@0 144 bool IsAborted() const
michael@0 145 {
michael@0 146 return NS_FAILED(mAbortCode);
michael@0 147 }
michael@0 148
michael@0 149 // 'Get' prefix is to avoid name collisions with the enum
michael@0 150 Mode GetMode()
michael@0 151 {
michael@0 152 return mMode;
michael@0 153 }
michael@0 154
michael@0 155 IDBDatabase* Database()
michael@0 156 {
michael@0 157 NS_ASSERTION(mDatabase, "This should never be null!");
michael@0 158 return mDatabase;
michael@0 159 }
michael@0 160
michael@0 161 DatabaseInfo* DBInfo() const
michael@0 162 {
michael@0 163 return mDatabaseInfo;
michael@0 164 }
michael@0 165
michael@0 166 already_AddRefed<IDBObjectStore>
michael@0 167 GetOrCreateObjectStore(const nsAString& aName,
michael@0 168 ObjectStoreInfo* aObjectStoreInfo,
michael@0 169 bool aCreating);
michael@0 170
michael@0 171 already_AddRefed<FileInfo> GetFileInfo(nsIDOMBlob* aBlob);
michael@0 172 void AddFileInfo(nsIDOMBlob* aBlob, FileInfo* aFileInfo);
michael@0 173
michael@0 174 void ClearCreatedFileInfos();
michael@0 175
michael@0 176 void
michael@0 177 SetActor(IndexedDBTransactionChild* aActorChild)
michael@0 178 {
michael@0 179 NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
michael@0 180 mActorChild = aActorChild;
michael@0 181 }
michael@0 182
michael@0 183 void
michael@0 184 SetActor(IndexedDBTransactionParent* aActorParent)
michael@0 185 {
michael@0 186 NS_ASSERTION(!aActorParent || !mActorParent,
michael@0 187 "Shouldn't have more than one!");
michael@0 188 mActorParent = aActorParent;
michael@0 189 }
michael@0 190
michael@0 191 IndexedDBTransactionChild*
michael@0 192 GetActorChild() const
michael@0 193 {
michael@0 194 return mActorChild;
michael@0 195 }
michael@0 196
michael@0 197 IndexedDBTransactionParent*
michael@0 198 GetActorParent() const
michael@0 199 {
michael@0 200 return mActorParent;
michael@0 201 }
michael@0 202
michael@0 203 nsresult
michael@0 204 Abort(IDBRequest* aRequest);
michael@0 205
michael@0 206 nsresult
michael@0 207 Abort(nsresult aAbortCode);
michael@0 208
michael@0 209 nsresult
michael@0 210 GetAbortCode() const
michael@0 211 {
michael@0 212 return mAbortCode;
michael@0 213 }
michael@0 214
michael@0 215 #ifdef MOZ_ENABLE_PROFILER_SPS
michael@0 216 uint64_t
michael@0 217 GetSerialNumber() const
michael@0 218 {
michael@0 219 return mSerialNumber;
michael@0 220 }
michael@0 221 #endif
michael@0 222
michael@0 223 // nsWrapperCache
michael@0 224 virtual JSObject*
michael@0 225 WrapObject(JSContext* aCx) MOZ_OVERRIDE;
michael@0 226
michael@0 227 // WebIDL
michael@0 228 nsPIDOMWindow*
michael@0 229 GetParentObject() const
michael@0 230 {
michael@0 231 return GetOwner();
michael@0 232 }
michael@0 233
michael@0 234 IDBTransactionMode
michael@0 235 GetMode(ErrorResult& aRv) const;
michael@0 236
michael@0 237 IDBDatabase*
michael@0 238 Db() const
michael@0 239 {
michael@0 240 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 241 return mDatabase;
michael@0 242 }
michael@0 243
michael@0 244 DOMError*
michael@0 245 GetError(ErrorResult& aRv);
michael@0 246
michael@0 247 already_AddRefed<IDBObjectStore>
michael@0 248 ObjectStore(const nsAString& aName, ErrorResult& aRv);
michael@0 249
michael@0 250 void
michael@0 251 Abort(ErrorResult& aRv)
michael@0 252 {
michael@0 253 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 254 aRv = AbortInternal(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR, nullptr);
michael@0 255 }
michael@0 256
michael@0 257 IMPL_EVENT_HANDLER(abort)
michael@0 258 IMPL_EVENT_HANDLER(complete)
michael@0 259 IMPL_EVENT_HANDLER(error)
michael@0 260
michael@0 261 already_AddRefed<DOMStringList>
michael@0 262 GetObjectStoreNames(ErrorResult& aRv);
michael@0 263
michael@0 264 private:
michael@0 265 nsresult
michael@0 266 AbortInternal(nsresult aAbortCode,
michael@0 267 already_AddRefed<mozilla::dom::DOMError> aError);
michael@0 268
michael@0 269 // Should only be called directly through IndexedDBDatabaseChild.
michael@0 270 static already_AddRefed<IDBTransaction>
michael@0 271 CreateInternal(IDBDatabase* aDatabase,
michael@0 272 const Sequence<nsString>& aObjectStoreNames,
michael@0 273 Mode aMode,
michael@0 274 bool aDispatchDelayed,
michael@0 275 bool aIsVersionChangeTransactionChild);
michael@0 276
michael@0 277 IDBTransaction(IDBDatabase* aDatabase);
michael@0 278 ~IDBTransaction();
michael@0 279
michael@0 280 nsresult CommitOrRollback();
michael@0 281
michael@0 282 nsRefPtr<IDBDatabase> mDatabase;
michael@0 283 nsRefPtr<DatabaseInfo> mDatabaseInfo;
michael@0 284 nsRefPtr<DOMError> mError;
michael@0 285 nsTArray<nsString> mObjectStoreNames;
michael@0 286 ReadyState mReadyState;
michael@0 287 Mode mMode;
michael@0 288 uint32_t mPendingRequests;
michael@0 289
michael@0 290 nsInterfaceHashtable<nsCStringHashKey, mozIStorageStatement>
michael@0 291 mCachedStatements;
michael@0 292
michael@0 293 nsRefPtr<IDBTransactionListener> mListener;
michael@0 294
michael@0 295 // Only touched on the database thread.
michael@0 296 nsCOMPtr<mozIStorageConnection> mConnection;
michael@0 297
michael@0 298 // Only touched on the database thread.
michael@0 299 uint32_t mSavepointCount;
michael@0 300
michael@0 301 nsTArray<nsRefPtr<IDBObjectStore> > mCreatedObjectStores;
michael@0 302 nsTArray<nsRefPtr<IDBObjectStore> > mDeletedObjectStores;
michael@0 303
michael@0 304 nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
michael@0 305 nsRefPtrHashtable<nsISupportsHashKey, FileInfo> mCreatedFileInfos;
michael@0 306
michael@0 307 IndexedDBTransactionChild* mActorChild;
michael@0 308 IndexedDBTransactionParent* mActorParent;
michael@0 309
michael@0 310 nsresult mAbortCode;
michael@0 311 #ifdef MOZ_ENABLE_PROFILER_SPS
michael@0 312 uint64_t mSerialNumber;
michael@0 313 #endif
michael@0 314 bool mCreating;
michael@0 315
michael@0 316 #ifdef DEBUG
michael@0 317 bool mFiredCompleteOrAbort;
michael@0 318 #endif
michael@0 319 };
michael@0 320
michael@0 321 class CommitHelper MOZ_FINAL : public nsIRunnable
michael@0 322 {
michael@0 323 public:
michael@0 324 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 325 NS_DECL_NSIRUNNABLE
michael@0 326
michael@0 327 CommitHelper(IDBTransaction* aTransaction,
michael@0 328 IDBTransactionListener* aListener,
michael@0 329 const nsTArray<nsRefPtr<IDBObjectStore> >& mUpdatedObjectStores);
michael@0 330 CommitHelper(IDBTransaction* aTransaction,
michael@0 331 nsresult aAbortCode);
michael@0 332 ~CommitHelper();
michael@0 333
michael@0 334 template<class T>
michael@0 335 bool AddDoomedObject(nsCOMPtr<T>& aCOMPtr)
michael@0 336 {
michael@0 337 if (aCOMPtr) {
michael@0 338 if (!mDoomedObjects.AppendElement(do_QueryInterface(aCOMPtr))) {
michael@0 339 NS_ERROR("Out of memory!");
michael@0 340 return false;
michael@0 341 }
michael@0 342 aCOMPtr = nullptr;
michael@0 343 }
michael@0 344 return true;
michael@0 345 }
michael@0 346
michael@0 347 private:
michael@0 348 // Writes new autoincrement counts to database
michael@0 349 nsresult WriteAutoIncrementCounts();
michael@0 350
michael@0 351 // Updates counts after a successful commit
michael@0 352 void CommitAutoIncrementCounts();
michael@0 353
michael@0 354 // Reverts counts when a transaction is aborted
michael@0 355 void RevertAutoIncrementCounts();
michael@0 356
michael@0 357 nsRefPtr<IDBTransaction> mTransaction;
michael@0 358 nsRefPtr<IDBTransactionListener> mListener;
michael@0 359 nsCOMPtr<mozIStorageConnection> mConnection;
michael@0 360 nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
michael@0 361 nsAutoTArray<nsCOMPtr<nsISupports>, 10> mDoomedObjects;
michael@0 362 nsAutoTArray<nsRefPtr<IDBObjectStore>, 10> mAutoIncrementObjectStores;
michael@0 363
michael@0 364 nsresult mAbortCode;
michael@0 365 };
michael@0 366
michael@0 367 class UpdateRefcountFunction MOZ_FINAL : public mozIStorageFunction
michael@0 368 {
michael@0 369 public:
michael@0 370 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 371 NS_DECL_MOZISTORAGEFUNCTION
michael@0 372
michael@0 373 UpdateRefcountFunction(FileManager* aFileManager)
michael@0 374 : mFileManager(aFileManager), mInSavepoint(false)
michael@0 375 { }
michael@0 376
michael@0 377 ~UpdateRefcountFunction()
michael@0 378 { }
michael@0 379
michael@0 380 void StartSavepoint()
michael@0 381 {
michael@0 382 MOZ_ASSERT(!mInSavepoint);
michael@0 383 MOZ_ASSERT(!mSavepointEntriesIndex.Count());
michael@0 384
michael@0 385 mInSavepoint = true;
michael@0 386 }
michael@0 387
michael@0 388 void ReleaseSavepoint()
michael@0 389 {
michael@0 390 MOZ_ASSERT(mInSavepoint);
michael@0 391
michael@0 392 mSavepointEntriesIndex.Clear();
michael@0 393
michael@0 394 mInSavepoint = false;
michael@0 395 }
michael@0 396
michael@0 397 void RollbackSavepoint()
michael@0 398 {
michael@0 399 MOZ_ASSERT(mInSavepoint);
michael@0 400
michael@0 401 mInSavepoint = false;
michael@0 402
michael@0 403 mSavepointEntriesIndex.EnumerateRead(RollbackSavepointCallback, nullptr);
michael@0 404
michael@0 405 mSavepointEntriesIndex.Clear();
michael@0 406 }
michael@0 407
michael@0 408 void ClearFileInfoEntries()
michael@0 409 {
michael@0 410 mFileInfoEntries.Clear();
michael@0 411 }
michael@0 412
michael@0 413 nsresult WillCommit(mozIStorageConnection* aConnection);
michael@0 414 void DidCommit();
michael@0 415 void DidAbort();
michael@0 416
michael@0 417 private:
michael@0 418 class FileInfoEntry
michael@0 419 {
michael@0 420 public:
michael@0 421 FileInfoEntry(FileInfo* aFileInfo)
michael@0 422 : mFileInfo(aFileInfo), mDelta(0), mSavepointDelta(0)
michael@0 423 { }
michael@0 424
michael@0 425 ~FileInfoEntry()
michael@0 426 { }
michael@0 427
michael@0 428 nsRefPtr<FileInfo> mFileInfo;
michael@0 429 int32_t mDelta;
michael@0 430 int32_t mSavepointDelta;
michael@0 431 };
michael@0 432
michael@0 433 enum UpdateType {
michael@0 434 eIncrement,
michael@0 435 eDecrement
michael@0 436 };
michael@0 437
michael@0 438 class DatabaseUpdateFunction
michael@0 439 {
michael@0 440 public:
michael@0 441 DatabaseUpdateFunction(mozIStorageConnection* aConnection,
michael@0 442 UpdateRefcountFunction* aFunction)
michael@0 443 : mConnection(aConnection), mFunction(aFunction), mErrorCode(NS_OK)
michael@0 444 { }
michael@0 445
michael@0 446 bool Update(int64_t aId, int32_t aDelta);
michael@0 447 nsresult ErrorCode()
michael@0 448 {
michael@0 449 return mErrorCode;
michael@0 450 }
michael@0 451
michael@0 452 private:
michael@0 453 nsresult UpdateInternal(int64_t aId, int32_t aDelta);
michael@0 454
michael@0 455 nsCOMPtr<mozIStorageConnection> mConnection;
michael@0 456 nsCOMPtr<mozIStorageStatement> mUpdateStatement;
michael@0 457 nsCOMPtr<mozIStorageStatement> mSelectStatement;
michael@0 458 nsCOMPtr<mozIStorageStatement> mInsertStatement;
michael@0 459
michael@0 460 UpdateRefcountFunction* mFunction;
michael@0 461
michael@0 462 nsresult mErrorCode;
michael@0 463 };
michael@0 464
michael@0 465 nsresult ProcessValue(mozIStorageValueArray* aValues,
michael@0 466 int32_t aIndex,
michael@0 467 UpdateType aUpdateType);
michael@0 468
michael@0 469 nsresult CreateJournals();
michael@0 470
michael@0 471 nsresult RemoveJournals(const nsTArray<int64_t>& aJournals);
michael@0 472
michael@0 473 static PLDHashOperator
michael@0 474 DatabaseUpdateCallback(const uint64_t& aKey,
michael@0 475 FileInfoEntry* aValue,
michael@0 476 void* aUserArg);
michael@0 477
michael@0 478 static PLDHashOperator
michael@0 479 FileInfoUpdateCallback(const uint64_t& aKey,
michael@0 480 FileInfoEntry* aValue,
michael@0 481 void* aUserArg);
michael@0 482
michael@0 483 static PLDHashOperator
michael@0 484 RollbackSavepointCallback(const uint64_t& aKey,
michael@0 485 FileInfoEntry* aValue,
michael@0 486 void* aUserArg);
michael@0 487
michael@0 488 FileManager* mFileManager;
michael@0 489 nsClassHashtable<nsUint64HashKey, FileInfoEntry> mFileInfoEntries;
michael@0 490 nsDataHashtable<nsUint64HashKey, FileInfoEntry*> mSavepointEntriesIndex;
michael@0 491
michael@0 492 nsTArray<int64_t> mJournalsToCreateBeforeCommit;
michael@0 493 nsTArray<int64_t> mJournalsToRemoveAfterCommit;
michael@0 494 nsTArray<int64_t> mJournalsToRemoveAfterAbort;
michael@0 495
michael@0 496 bool mInSavepoint;
michael@0 497 };
michael@0 498
michael@0 499 END_INDEXEDDB_NAMESPACE
michael@0 500
michael@0 501 #endif // mozilla_dom_indexeddb_idbtransaction_h__

mercurial