DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (e9d6d0965bc6)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_localstorage_LSSnapshot_h
#define mozilla_dom_localstorage_LSSnapshot_h

#include "LSValue.h"

#include "nsCOMPtr.h"
#include "nsDataHashtable.h"
#include "nsIRunnable.h"
#include "nsHashKeys.h"
#include "nsIRunnable.h"
#include "nsTHashtable.h"

class nsITimer;

namespace mozilla {
namespace dom {

class LSDatabase;
class LSNotifyInfo;
class LSSnapshotChild;
class LSSnapshotInitInfo;
class LSWriteAndNotifyInfo;
class SnapshotWriteOptimizer;

template <typename> class Optional;


class LSSnapshot final : public nsIRunnable {
 public:
  /**
   * The LoadState expresses what subset of information a snapshot has from the
   * authoritative Datastore in the parent process.  The initial snapshot is
   * populated heuristically based on the size of the keys and size of the items
   * (inclusive of the key value; item is key+value, not just value) of the
   * entire datastore relative to the configured prefill limit (via pref
   * "dom.storage.snapshot_prefill" exposed as gSnapshotPrefill in bytes).
   *
   * If there's less data than the limit, we send both keys and values and end
   * up as AllOrderedItems.  If there's enough room for all the keys but not
   * all the values, we end up as AllOrderedKeys with as many values present as
   * would fit.  If there's not enough room for all the keys, then we end up as
   * Partial with as many key-value pairs as will fit.
   *
   * The state AllUnorderedItems can only be reached by code getting items one
   * by one.
   */
  enum class LoadState {
    /**
     * Class constructed, Init(LSSnapshotInitInfo) has not been invoked yet.
     */
    Initial,
    /**
     * Some keys and their values are known.
     */
    Partial,
    /**
     * All the keys are known in order, but some values are unknown.
     */
    AllOrderedKeys,
    /**
     * All keys and their values are known, but in an arbitrary order.
     */
    AllUnorderedItems,
    /**
     * All keys and their values are known and are present in their canonical
     * order.  This is everything, and is the preferred case.  The initial
     * population will send this info when the size of all items is less than
     * the prefill threshold.
     *
     * mValues will contain all keys and values, mLoadedItems and mUnknownItems
     * are unused.
     */
    AllOrderedItems,
    EndGuard
  };

 private:
  RefPtr<LSSnapshot> mSelfRef;

  RefPtr<LSDatabase> mDatabase;

  nsCOMPtr<nsITimer> mTimer;

  LSSnapshotChild* mActor;

  nsTHashtable<nsStringHashKey> mLoadedItems;
  nsTHashtable<nsStringHashKey> mUnknownItems;
  nsDataHashtable<nsStringHashKey, nsString> mValues;
  nsAutoPtr<SnapshotWriteOptimizer> mWriteOptimizer;
  nsAutoPtr<nsTArray<LSWriteAndNotifyInfo>> mWriteAndNotifyInfos;

  uint32_t mInitLength;
  uint32_t mLength;
  int64_t mExactUsage;
  int64_t mPeakUsage;

  LoadState mLoadState;

  bool mHasOtherProcessObservers;
  bool mExplicit;
  bool mHasPendingStableStateCallback;
  bool mHasPendingTimerCallback;
  bool mDirty;

#ifdef DEBUG
  bool mInitialized;
  bool mSentFinish;
#endif

 public:
  explicit LSSnapshot(LSDatabase* aDatabase);

  void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(LSSnapshot); }

  void SetActor(LSSnapshotChild* aActor);

  void ClearActor() {
    AssertIsOnOwningThread();
    MOZ_ASSERT(mActor);

    mActor = nullptr;
  }

  bool Explicit() const { return mExplicit; }

  nsresult Init(const nsAString& aKey, const LSSnapshotInitInfo& aInitInfo,
                bool aExplicit);

  nsresult GetLength(uint32_t* aResult);

  nsresult GetKey(uint32_t aIndex, nsAString& aResult);

  nsresult GetItem(const nsAString& aKey, nsAString& aResult);

  nsresult GetKeys(nsTArray<nsString>& aKeys);

  nsresult SetItem(const nsAString& aKey, const nsAString& aValue,
                   LSNotifyInfo& aNotifyInfo);

  nsresult RemoveItem(const nsAString& aKey, LSNotifyInfo& aNotifyInfo);

  nsresult Clear(LSNotifyInfo& aNotifyInfo);

  void MarkDirty();

  nsresult End();

 private:
  ~LSSnapshot();

  void ScheduleStableStateCallback();

  void MaybeScheduleStableStateCallback();

  nsresult GetItemInternal(const nsAString& aKey,
                           const Optional<nsString>& aValue,
                           nsAString& aResult);

  nsresult EnsureAllKeys();

  nsresult UpdateUsage(int64_t aDelta);

  nsresult Checkpoint();

  nsresult Finish();

  void CancelTimer();

  static void TimerCallback(nsITimer* aTimer, void* aClosure);

  NS_DECL_ISUPPORTS
  NS_DECL_NSIRUNNABLE
};

}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_localstorage_LSSnapshot_h