bug 1498165 - Add common multistore behaviour to ScalarBase r=janerik
☠☠ backed out by 507698ccab9b ☠ ☠
authorChris H-C <chutten@mozilla.com>
Tue, 20 Nov 2018 15:06:21 +0000
changeset 503784 2427211409152fd03f82f3778d314d53cd4f8515
parent 503783 a6fd8299991243e3c2d5fede292a890659108bd0
child 503785 97f08187a60baef92ee398d3f598bdb2c6bebf23
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjanerik
bugs1498165
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1498165 - Add common multistore behaviour to ScalarBase r=janerik ScalarBase needs to transform from store names to indices and provide storage and logic for which stores have values. Depends on D12128 Differential Revision: https://phabricator.services.mozilla.com/D12129
toolkit/components/telemetry/core/TelemetryScalar.cpp
--- a/toolkit/components/telemetry/core/TelemetryScalar.cpp
+++ b/toolkit/components/telemetry/core/TelemetryScalar.cpp
@@ -326,16 +326,26 @@ ScalarInfo::expiration() const
 
 /**
  * The base scalar object, that serves as a common ancestor for storage
  * purposes.
  */
 class ScalarBase
 {
 public:
+  explicit ScalarBase(const BaseScalarInfo& aInfo)
+    : mStoreCount(aInfo.storeCount())
+    , mStoreOffset(aInfo.storeOffset())
+    , mStoreHasValue(mStoreCount)
+  {
+    mStoreHasValue.SetLength(mStoreCount);
+    for (auto& val: mStoreHasValue) {
+      val = false;
+    }
+  };
   virtual ~ScalarBase() = default;
 
   // Set, Add and SetMaximum functions as described in the Telemetry IDL.
   virtual ScalarResult SetValue(nsIVariant* aValue) = 0;
   virtual ScalarResult AddValue(nsIVariant* aValue) { return ScalarResult::OperationNotSupported; }
   virtual ScalarResult SetMaximum(nsIVariant* aValue) { return ScalarResult::OperationNotSupported; }
 
   // Convenience methods used by the C++ API.
@@ -344,38 +354,106 @@ public:
   virtual void SetValue(bool aValue) { mozilla::Unused << HandleUnsupported(); }
   virtual void AddValue(uint32_t aValue) { mozilla::Unused << HandleUnsupported(); }
   virtual void SetMaximum(uint32_t aValue) { mozilla::Unused << HandleUnsupported(); }
 
   // GetValue is used to get the value of the scalar when persisting it to JS.
   virtual nsresult GetValue(const nsACString& aStoreName, nsCOMPtr<nsIVariant>& aResult) const = 0;
 
   // To measure the memory stats.
+  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
 
+protected:
+  bool HasValueInStore(size_t aStoreIndex) const;
+  void ClearValueInStore(size_t aStoreIndex);
+  void SetValueInStores();
+  nsresult StoreIndex(const nsACString& aStoreName, size_t* aStoreIndex) const;
+
 private:
   ScalarResult HandleUnsupported() const;
+
+  const uint32_t mStoreCount;
+  const uint16_t mStoreOffset;
+  nsTArray<bool> mStoreHasValue;
 };
 
 ScalarResult
 ScalarBase::HandleUnsupported() const
 {
   MOZ_ASSERT(false, "This operation is not support for this scalar type.");
   return ScalarResult::OperationNotSupported;
 }
 
+bool
+ScalarBase::HasValueInStore(size_t aStoreIndex) const
+{
+  MOZ_ASSERT(aStoreIndex < mStoreHasValue.Length(),
+             "Invalid scalar store index.");
+  return mStoreHasValue[aStoreIndex];
+}
+
+void
+ScalarBase::ClearValueInStore(size_t aStoreIndex)
+{
+  MOZ_ASSERT(aStoreIndex < mStoreHasValue.Length(),
+             "Invalid scalar store index to clear.");
+  mStoreHasValue[aStoreIndex] = false;
+}
+
+void
+ScalarBase::SetValueInStores()
+{
+  for (auto& val: mStoreHasValue) {
+    val = true;
+  }
+}
+
+nsresult
+ScalarBase::StoreIndex(const nsACString& aStoreName, size_t* aStoreIndex) const
+{
+  if (mStoreCount == 1 && mStoreOffset == UINT16_MAX) {
+    // This Scalar is only in the "main" store.
+    if (aStoreName.EqualsLiteral("main")) {
+      *aStoreIndex = 0;
+      return NS_OK;
+    }
+    return NS_ERROR_FAILURE;
+  }
+
+  // Multiple stores. Linear scan to find one that matches aStoreName.
+  for (uint32_t i = 0; i < mStoreCount; ++i) {
+    uint32_t stringIndex = gScalarStoresTable[mStoreOffset + i];
+    if (aStoreName.EqualsASCII(&gScalarsStringTable[stringIndex])) {
+      *aStoreIndex = i;
+      return NS_OK;
+    }
+  }
+  return NS_ERROR_FAILURE;
+}
+
+size_t
+ScalarBase::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+{
+  return mStoreHasValue.ShallowSizeOfExcludingThis(aMallocSizeOf);
+}
+
 /**
  * The implementation for the unsigned int scalar type.
  */
 class ScalarUnsigned : public ScalarBase
 {
 public:
   using ScalarBase::SetValue;
 
-  ScalarUnsigned() : mStorage(0) {};
+  ScalarUnsigned(const BaseScalarInfo& aInfo)
+    : ScalarBase(aInfo)
+    , mStorage(0)
+  {};
+
   ~ScalarUnsigned() override = default;
 
   ScalarResult SetValue(nsIVariant* aValue) final;
   void SetValue(uint32_t aValue) final;
   ScalarResult AddValue(nsIVariant* aValue) final;
   void AddValue(uint32_t aValue) final;
   ScalarResult SetMaximum(nsIVariant* aValue) final;
   void SetMaximum(uint32_t aValue) final;
@@ -504,17 +582,21 @@ ScalarUnsigned::CheckInput(nsIVariant* a
 /**
  * The implementation for the string scalar type.
  */
 class ScalarString : public ScalarBase
 {
 public:
   using ScalarBase::SetValue;
 
-  ScalarString() : mStorage(EmptyString()) {};
+  ScalarString(const BaseScalarInfo& aInfo)
+    : ScalarBase(aInfo)
+    , mStorage(EmptyString())
+  {};
+
   ~ScalarString() override = default;
 
   ScalarResult SetValue(nsIVariant* aValue) final;
   ScalarResult SetValue(const nsAString& aValue) final;
   nsresult GetValue(const nsACString& aStoreName, nsCOMPtr<nsIVariant>& aResult) const final;
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const final;
 
 private:
@@ -583,17 +665,21 @@ ScalarString::SizeOfIncludingThis(mozill
 /**
  * The implementation for the boolean scalar type.
  */
 class ScalarBoolean : public ScalarBase
 {
 public:
   using ScalarBase::SetValue;
 
-  ScalarBoolean() : mStorage(false) {};
+  ScalarBoolean(const BaseScalarInfo& aInfo)
+    : ScalarBase(aInfo)
+    , mStorage(false)
+  {};
+
   ~ScalarBoolean() override = default;
 
   ScalarResult SetValue(nsIVariant* aValue) final;
   void SetValue(bool aValue) final;
   nsresult GetValue(const nsACString& aStoreName, nsCOMPtr<nsIVariant>& aResult) const final;
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const final;
 
 private:
@@ -654,28 +740,28 @@ ScalarBoolean::SizeOfIncludingThis(mozil
 /**
  * Allocate a scalar class given the scalar info.
  *
  * @param aInfo The informations for the scalar coming from the definition file.
  * @return nullptr if the scalar type is unknown, otherwise a valid pointer to the
  *         scalar type.
  */
 ScalarBase*
-internal_ScalarAllocate(uint32_t aScalarKind)
+internal_ScalarAllocate(const BaseScalarInfo& aInfo)
 {
   ScalarBase* scalar = nullptr;
-  switch (aScalarKind) {
+  switch (aInfo.kind) {
   case nsITelemetry::SCALAR_TYPE_COUNT:
-    scalar = new ScalarUnsigned();
+    scalar = new ScalarUnsigned(aInfo);
     break;
   case nsITelemetry::SCALAR_TYPE_STRING:
-    scalar = new ScalarString();
+    scalar = new ScalarString(aInfo);
     break;
   case nsITelemetry::SCALAR_TYPE_BOOLEAN:
-    scalar = new ScalarBoolean();
+    scalar = new ScalarBoolean(aInfo);
     break;
   default:
     MOZ_ASSERT(false, "Invalid scalar type");
   }
   return scalar;
 }
 
 /**
@@ -905,17 +991,17 @@ KeyedScalar::GetScalarForKey(const Stati
       return ScalarResult::TooManyKeys;
     }
 
     scalarExceed->AddValue(locker, NS_ConvertUTF8toUTF16(mScalarInfo.name()), 1);
 
     return ScalarResult::TooManyKeys;
   }
 
-  scalar = internal_ScalarAllocate(mScalarInfo.kind);
+  scalar = internal_ScalarAllocate(mScalarInfo);
   if (!scalar) {
     return ScalarResult::InvalidType;
   }
 
   mScalarKeys.Put(utf8Key, scalar);
 
   *aRet = scalar;
   return ScalarResult::Ok;
@@ -1293,17 +1379,17 @@ internal_GetScalarByEnum(const StaticMut
   }
 
   // The scalar storage wasn't already allocated. Check if the scalar is expired and
   // then allocate the storage, if needed.
   if (IsExpiredVersion(info.expiration())) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  scalar = internal_ScalarAllocate(info.kind);
+  scalar = internal_ScalarAllocate(info);
   if (!scalar) {
     return NS_ERROR_INVALID_ARG;
   }
 
   scalarStorage->Put(aId.id, scalar);
   *aRet = scalar;
   return NS_OK;
 }