This is an automated email from the ASF dual-hosted git repository.

mzhu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git

commit 8d372e14b0240aa5735a7c0cf36e03e7b3344bd1
Author: Meng Zhu <[email protected]>
AuthorDate: Tue May 28 16:27:16 2019 +0200

    Added methods to subtract `ResourceQuantities` from `ResourceLimits`.
    
    This patch also makes `ResourceLimits` a friend class of
    `ResourceQuantities` to achieve one-pass operation complexities.
    
    Also added unit test.
    
    Review: https://reviews.apache.org/r/70735
---
 src/common/resource_quantities.cpp      | 44 +++++++++++++++++++++++++++++++++
 src/common/resource_quantities.hpp      |  8 ++++++
 src/tests/resource_quantities_tests.cpp | 34 +++++++++++++++++++++++++
 3 files changed, 86 insertions(+)

diff --git a/src/common/resource_quantities.cpp 
b/src/common/resource_quantities.cpp
index 40c7ef1..f79b678 100644
--- a/src/common/resource_quantities.cpp
+++ b/src/common/resource_quantities.cpp
@@ -517,6 +517,7 @@ bool ResourceLimits::operator!=(const ResourceLimits& that) 
const
 }
 
 
+// TODO(mzhu): Given the friendship, optimize this to be one pass.
 bool ResourceLimits::contains(const ResourceQuantities& quantities) const
 {
   foreachpair (const string& name, const Value::Scalar& quantity, quantities) {
@@ -531,6 +532,49 @@ bool ResourceLimits::contains(const ResourceQuantities& 
quantities) const
 }
 
 
+ResourceLimits& ResourceLimits::operator-=(const ResourceQuantities& 
quantities)
+{
+  size_t limitsIndex = 0u;
+  size_t quantitiesIndex = 0u;
+
+  // Since both limits and quantities are sorted in alphabetical order, we can
+  // walk them at the same time.
+  while (limitsIndex < size() && quantitiesIndex < quantities.size()) {
+    pair<string, Value::Scalar>& limit = limits.at(limitsIndex);
+    const pair<string, Value::Scalar>& quantity =
+      quantities.quantities.at(quantitiesIndex);
+
+    if (limit.first < quantity.first) {
+      // Item exists in limits but not in quantities i.e.
+      // finite limit minus zero quantity.
+      ++limitsIndex;
+    } else if (limit.first > quantity.first) {
+      // Item exists in quantities but not in limits i.e.
+      // infinite limit minus finite quantity.
+      ++quantitiesIndex;
+    } else {
+      // Item exists in both limits and quantities i.e.
+      // finite limits minus finite quantity.
+      limit.second = std::max(limit.second - quantity.second,
+                              Value::Scalar());
+      ++limitsIndex;
+      ++quantitiesIndex;
+    }
+  }
+
+  return *this;
+}
+
+
+ResourceLimits ResourceLimits::operator-(
+    const ResourceQuantities& quantities) const
+{
+  ResourceLimits result = *this;
+  result -= quantities;
+  return result;
+}
+
+
 void ResourceLimits::set(
     const std::string& name, const Value::Scalar& scalar)
 {
diff --git a/src/common/resource_quantities.hpp 
b/src/common/resource_quantities.hpp
index 718ce14..538256b 100644
--- a/src/common/resource_quantities.hpp
+++ b/src/common/resource_quantities.hpp
@@ -29,6 +29,9 @@
 namespace mesos {
 namespace internal {
 
+// Forward declaration.
+class ResourceLimits;
+
 
 // An efficient collection of resource quantities. All values are guaranteed
 // to be positive and finite.
@@ -144,6 +147,8 @@ public:
   ResourceQuantities operator-(const ResourceQuantities& quantities) const;
 
 private:
+  friend class ResourceLimits;
+
   void add(const std::string& name, const Value::Scalar& scalar);
   void add(const std::string& name, double value);
 
@@ -238,6 +243,9 @@ public:
 
   bool contains(const ResourceQuantities& quantities) const;
 
+  ResourceLimits& operator-=(const ResourceQuantities& quantities);
+  ResourceLimits operator-(const ResourceQuantities& quantities) const;
+
 private:
   // Set the limit of the resource with `name` to `scalar`.
   // Note, the existing limit of the resource will be overwritten.
diff --git a/src/tests/resource_quantities_tests.cpp 
b/src/tests/resource_quantities_tests.cpp
index ebe53be..f018c8a 100644
--- a/src/tests/resource_quantities_tests.cpp
+++ b/src/tests/resource_quantities_tests.cpp
@@ -542,6 +542,40 @@ TEST(LimitsTest, ContainsQuantities)
 }
 
 
+TEST(LimitsTest, SubtractQuantities)
+{
+  auto limits = [](const string& resourceLimitsString) {
+    return CHECK_NOTERROR(ResourceLimits::fromString(resourceLimitsString));
+  };
+
+  auto subtract = [](const string& resourceLimitsString,
+                     const string& resourceQuantitiesString) {
+    ResourceLimits limits =
+      CHECK_NOTERROR(ResourceLimits::fromString(resourceLimitsString));
+    ResourceQuantities quantities =
+      CHECK_NOTERROR(ResourceQuantities::fromString(resourceQuantitiesString));
+
+    return limits - quantities;
+  };
+
+  EXPECT_EQ(limits(""), subtract("", ""));
+  EXPECT_EQ(limits(""), subtract("", "cpus:10"));
+
+  EXPECT_EQ(limits("cpus:1"), subtract("cpus:1", ""));
+
+  EXPECT_EQ(limits("cpus:0"), subtract("cpus:1", "cpus:1"));
+  EXPECT_EQ(limits("cpus:0"), subtract("cpus:1", "cpus:2"));
+
+  EXPECT_EQ(limits("cpus:0;mem:10"), subtract("cpus:1;mem:10", "cpus:1"));
+  EXPECT_EQ(
+      limits("cpus:0;mem:10"), subtract("cpus:1;mem:10", "cpus:1;disk:10"));
+
+  EXPECT_EQ(
+      limits("cpus:0;mem:5"),
+      subtract("cpus:1;mem:10", "cpus:1;mem:5;disk:10"));
+}
+
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

Reply via email to