dom/src/storage/DOMStorageDBThread.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.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef DOMStorageDBThread_h___
     7 #define DOMStorageDBThread_h___
     9 #include "prthread.h"
    10 #include "prinrval.h"
    11 #include "nsTArray.h"
    12 #include "mozilla/Monitor.h"
    13 #include "mozilla/storage/StatementCache.h"
    14 #include "nsString.h"
    15 #include "nsCOMPtr.h"
    16 #include "nsClassHashtable.h"
    17 #include "nsIFile.h"
    19 class mozIStorageConnection;
    21 namespace mozilla {
    22 namespace dom {
    24 class DOMStorageCacheBridge;
    25 class DOMStorageUsageBridge;
    26 class DOMStorageUsage;
    28 typedef mozilla::storage::StatementCache<mozIStorageStatement> StatementCache;
    30 // Interface used by the cache to post operations to the asynchronous
    31 // database thread or process.
    32 class DOMStorageDBBridge
    33 {
    34 public:
    35   DOMStorageDBBridge();
    36   virtual ~DOMStorageDBBridge() {}
    38   // Ensures the database engine is started
    39   virtual nsresult Init() = 0;
    41   // Releases the database and disallows its usage
    42   virtual nsresult Shutdown() = 0;
    44   // Asynchronously fills the cache with data from the database for first use.
    45   // When |aPriority| is true, the preload operation is scheduled as the first one.
    46   // This method is responsible to keep hard reference to the cache for the time of
    47   // the preload or, when preload cannot be performed, call LoadDone() immediately.
    48   virtual void AsyncPreload(DOMStorageCacheBridge* aCache, bool aPriority = false) = 0;
    50   // Asynchronously fill the |usage| object with actual usage of data by its scope.
    51   // The scope is eTLD+1 tops, never deeper subdomains.
    52   virtual void AsyncGetUsage(DOMStorageUsageBridge* aUsage) = 0;
    54   // Synchronously fills the cache, when |aForceSync| is false and cache already got some
    55   // data before, the method waits for the running preload to finish
    56   virtual void SyncPreload(DOMStorageCacheBridge* aCache, bool aForceSync = false) = 0;
    58   // Called when an existing key is modified in the storage, schedules update to the database
    59   virtual nsresult AsyncAddItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue) = 0;
    61   // Called when an existing key is modified in the storage, schedules update to the database
    62   virtual nsresult AsyncUpdateItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue) = 0;
    64   // Called when an item is removed from the storage, schedules delete of the key
    65   virtual nsresult AsyncRemoveItem(DOMStorageCacheBridge* aCache, const nsAString& aKey) = 0;
    67   // Called when the whole storage is cleared by the DOM API, schedules delete of the scope
    68   virtual nsresult AsyncClear(DOMStorageCacheBridge* aCache) = 0;
    70   // Called when chrome deletes e.g. cookies, schedules delete of the whole database
    71   virtual void AsyncClearAll() = 0;
    73   // Called when only a domain and its subdomains or an app data is about to clear
    74   virtual void AsyncClearMatchingScope(const nsACString& aScope) = 0;
    76   // Forces scheduled DB operations to be early flushed to the disk
    77   virtual void AsyncFlush() = 0;
    79   // Check whether the scope has any data stored on disk and is thus allowed to preload
    80   virtual bool ShouldPreloadScope(const nsACString& aScope) = 0;
    82   // Get the complete list of scopes having data
    83   virtual void GetScopesHavingData(InfallibleTArray<nsCString>* aScopes) = 0;
    84 };
    86 // The implementation of the the database engine, this directly works
    87 // with the sqlite or any other db API we are based on
    88 // This class is resposible for collecting and processing asynchronous 
    89 // DB operations over caches (DOMStorageCache) communicating though 
    90 // DOMStorageCacheBridge interface class
    91 class DOMStorageDBThread MOZ_FINAL : public DOMStorageDBBridge
    92 {
    93 public:
    94   class PendingOperations;
    96   // Representation of a singe database task, like adding and removing keys,
    97   // (pre)loading the whole origin data, cleaning.
    98   class DBOperation
    99   {
   100   public:
   101     typedef enum {
   102       // Only operation that reads data from the database
   103       opPreload,
   104       // The same as opPreload, just executed with highest priority
   105       opPreloadUrgent,
   107       // Load usage of a scope
   108       opGetUsage,
   110       // Operations invoked by the DOM content API
   111       opAddItem,
   112       opUpdateItem,
   113       opRemoveItem,
   114       opClear,
   116       // Operations invoked by chrome
   117       opClearAll,
   118       opClearMatchingScope,
   119     } OperationType;
   121     DBOperation(const OperationType aType,
   122                 DOMStorageCacheBridge* aCache = nullptr,
   123                 const nsAString& aKey = EmptyString(),
   124                 const nsAString& aValue = EmptyString());
   125     DBOperation(const OperationType aType,
   126                 DOMStorageUsageBridge* aUsage);
   127     DBOperation(const OperationType aType,
   128                 const nsACString& aScope);
   129     ~DBOperation();
   131     // Executes the operation, doesn't necessarity have to be called on the I/O thread
   132     void PerformAndFinalize(DOMStorageDBThread* aThread);
   134     // Finalize the operation, i.e. do any internal cleanup and finish calls
   135     void Finalize(nsresult aRv);
   137     // The operation type
   138     OperationType Type() { return mType; }
   140     // The operation scope (=origin)
   141     const nsCString Scope();
   143     // |Scope + key| the operation is working with
   144     const nsCString Target();
   146   private:
   147     // The operation implementation body
   148     nsresult Perform(DOMStorageDBThread* aThread);
   150     friend class PendingOperations;
   151     OperationType mType;
   152     nsRefPtr<DOMStorageCacheBridge> mCache;
   153     nsRefPtr<DOMStorageUsageBridge> mUsage;
   154     nsString mKey;
   155     nsString mValue;
   156     nsCString mScope;
   157   };
   159   // Encapsulation of collective and coalescing logic for all pending operations
   160   // except preloads that are handled separately as priority operations
   161   class PendingOperations {
   162   public:
   163     PendingOperations();
   165     // Method responsible for coalescing redundant update operations with the same
   166     // |Target()| or clear operations with the same or matching |Scope()|
   167     void Add(DBOperation* aOperation);
   169     // True when there are some scheduled operations to flush on disk
   170     bool HasTasks();
   172     // Moves collected operations to a local flat list to allow execution of the operation
   173     // list out of the thread lock
   174     bool Prepare();
   176     // Executes the previously |Prepared()'ed| list of operations, retuns result, but doesn't
   177     // handle it in any way in case of a failure
   178     nsresult Execute(DOMStorageDBThread* aThread);
   180     // Finalizes the pending operation list, returns false when too many operations failed
   181     // to flush what indicates a long standing issue with the database access.
   182     bool Finalize(nsresult aRv);
   184     // true when a clear that deletes the given |scope| is among the pending operations;
   185     // when a preload for that scope is being scheduled, it must be finished right away
   186     bool IsScopeClearPending(const nsACString& aScope);
   188     // Checks whether there is a pending update (or clear, actually) operation for this scope.
   189     bool IsScopeUpdatePending(const nsACString& aScope);
   191   private:
   192     // Returns true iff new operation is of type newType and there is a pending 
   193     // operation of type pendingType for the same key (target).
   194     bool CheckForCoalesceOpportunity(DBOperation* aNewOp,
   195                                      DBOperation::OperationType aPendingType,
   196                                      DBOperation::OperationType aNewType);
   198     // List of all clearing operations, executed first
   199     nsClassHashtable<nsCStringHashKey, DBOperation> mClears;
   201     // List of all update/insert operations, executed as second
   202     nsClassHashtable<nsCStringHashKey, DBOperation> mUpdates;
   204     // Collection of all tasks, valid only between Prepare() and Execute()
   205     nsTArray<nsAutoPtr<DBOperation> > mExecList;
   207     // Number of failing flush attempts
   208     uint32_t mFlushFailureCount;
   209   };
   211 public:
   212   DOMStorageDBThread();
   213   virtual ~DOMStorageDBThread() {}
   215   virtual nsresult Init();
   216   virtual nsresult Shutdown();
   218   virtual void AsyncPreload(DOMStorageCacheBridge* aCache, bool aPriority = false)
   219     { InsertDBOp(new DBOperation(aPriority ? DBOperation::opPreloadUrgent : DBOperation::opPreload, aCache)); }
   221   virtual void SyncPreload(DOMStorageCacheBridge* aCache, bool aForce = false);
   223   virtual void AsyncGetUsage(DOMStorageUsageBridge * aUsage)
   224     { InsertDBOp(new DBOperation(DBOperation::opGetUsage, aUsage)); }
   226   virtual nsresult AsyncAddItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue)
   227     { return InsertDBOp(new DBOperation(DBOperation::opAddItem, aCache, aKey, aValue)); }
   229   virtual nsresult AsyncUpdateItem(DOMStorageCacheBridge* aCache, const nsAString& aKey, const nsAString& aValue)
   230     { return InsertDBOp(new DBOperation(DBOperation::opUpdateItem, aCache, aKey, aValue)); }
   232   virtual nsresult AsyncRemoveItem(DOMStorageCacheBridge* aCache, const nsAString& aKey)
   233     { return InsertDBOp(new DBOperation(DBOperation::opRemoveItem, aCache, aKey)); }
   235   virtual nsresult AsyncClear(DOMStorageCacheBridge* aCache)
   236     { return InsertDBOp(new DBOperation(DBOperation::opClear, aCache)); }
   238   virtual void AsyncClearAll()
   239     { InsertDBOp(new DBOperation(DBOperation::opClearAll)); }
   241   virtual void AsyncClearMatchingScope(const nsACString& aScope)
   242     { InsertDBOp(new DBOperation(DBOperation::opClearMatchingScope, aScope)); }
   244   virtual void AsyncFlush();
   246   virtual bool ShouldPreloadScope(const nsACString& aScope);
   247   virtual void GetScopesHavingData(InfallibleTArray<nsCString>* aScopes);
   249 private:
   250   nsCOMPtr<nsIFile> mDatabaseFile;
   251   PRThread* mThread;
   253   // The monitor we drive the thread with
   254   Monitor mMonitor;
   256   // Flag to stop, protected by the monitor
   257   bool mStopIOThread;
   259   // Whether WAL is enabled
   260   bool mWALModeEnabled;
   262   // Whether DB has already been open, avoid races between main thread reads
   263   // and pending DB init in the background I/O thread
   264   bool mDBReady;
   266   // State of the database initiation
   267   nsresult mStatus;
   269   // List of scopes having data, for optimization purposes only
   270   nsTHashtable<nsCStringHashKey> mScopesHavingData;
   272   StatementCache mWorkerStatements;
   273   StatementCache mReaderStatements;
   275   // Connection used by the worker thread for all read and write ops
   276   nsCOMPtr<mozIStorageConnection> mWorkerConnection;
   278   // Connection used only on the main thread for sync read operations
   279   nsCOMPtr<mozIStorageConnection> mReaderConnection;
   281   // Time the first pending operation has been added to the pending operations
   282   // list
   283   PRIntervalTime mDirtyEpoch;
   285   // Flag to force immediate flush of all pending operations
   286   bool mFlushImmediately;
   288   // List of preloading operations, in chronological or priority order.
   289   // Executed prioritly over pending update operations.
   290   nsTArray<DBOperation*> mPreloads;
   292   // Collector of pending update operations
   293   PendingOperations mPendingTasks;
   295   // Counter of calls for thread priority rising.
   296   int32_t mPriorityCounter;
   298   // Helper to direct an operation to one of the arrays above;
   299   // also checks IsScopeClearPending for preloads
   300   nsresult InsertDBOp(DBOperation* aOperation);
   302   // Opens the database, first thing we do after start of the thread.
   303   nsresult OpenDatabaseConnection();
   304   nsresult InitDatabase();
   305   nsresult ShutdownDatabase();
   307   // Tries to establish WAL mode
   308   nsresult SetJournalMode(bool aIsWal);
   309   nsresult TryJournalMode();
   311   // Sets the threshold for auto-checkpointing the WAL.
   312   nsresult ConfigureWALBehavior();
   314   void SetHigherPriority();
   315   void SetDefaultPriority();
   317   // Ensures we flush pending tasks in some reasonble time
   318   void ScheduleFlush();
   320   // Called when flush of pending tasks is being executed
   321   void UnscheduleFlush();
   323   // This method is used for two purposes:
   324   // 1. as a value passed to monitor.Wait() method
   325   // 2. as in indicator that flush has to be performed
   326   //
   327   // Return:
   328   // - PR_INTERVAL_NO_TIMEOUT when no pending tasks are scheduled
   329   // - larger then zero when tasks have been scheduled, but it is
   330   //   still not time to perform the flush ; it is actual interval
   331   //   time to wait until the flush has to happen
   332   // - 0 when it is time to do the flush
   333   PRIntervalTime TimeUntilFlush();
   335   // Notifies to the main thread that flush has completed
   336   void NotifyFlushCompletion();
   338   // Thread loop
   339   static void ThreadFunc(void* aArg);
   340   void ThreadFunc();
   341 };
   343 } // ::dom
   344 } // ::mozilla
   346 #endif /* DOMStorageDBThread_h___ */

mercurial