You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2014/11/19 09:54:10 UTC
[5/9] mesos git commit: Re-organized the functions in C++ Resources.
Re-organized the functions in C++ Resources.
Review: https://reviews.apache.org/r/28078
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/bdf2d9d4
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/bdf2d9d4
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/bdf2d9d4
Branch: refs/heads/master
Commit: bdf2d9d410aeda6733a3d1ccdcd61ae7e89dac4a
Parents: 7ff4920
Author: Jie Yu <yu...@gmail.com>
Authored: Fri Nov 14 10:14:24 2014 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Nov 19 00:14:25 2014 -0800
----------------------------------------------------------------------
include/mesos/resources.hpp | 154 ++++-----
src/common/resources.cpp | 697 ++++++++++++++++++++-------------------
2 files changed, 428 insertions(+), 423 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/bdf2d9d4/include/mesos/resources.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/resources.hpp b/include/mesos/resources.hpp
index 0e37170..c2ba597 100644
--- a/include/mesos/resources.hpp
+++ b/include/mesos/resources.hpp
@@ -19,6 +19,7 @@
#ifndef __RESOURCES_HPP__
#define __RESOURCES_HPP__
+#include <iostream>
#include <string>
#include <mesos/mesos.hpp>
@@ -26,6 +27,7 @@
#include <stout/bytes.hpp>
#include <stout/option.hpp>
+#include <stout/try.hpp>
/**
@@ -50,28 +52,66 @@
* names is a no-op.
*/
-
namespace mesos {
-
bool operator == (const Resource& left, const Resource& right);
bool operator != (const Resource& left, const Resource& right);
+
+
bool operator <= (const Resource& left, const Resource& right);
-Resource operator + (const Resource& left, const Resource& right);
-Resource operator - (const Resource& left, const Resource& right);
+
+
Resource& operator += (Resource& left, const Resource& right);
+Resource operator + (const Resource& left, const Resource& right);
Resource& operator -= (Resource& left, const Resource& right);
+Resource operator - (const Resource& left, const Resource& right);
+
+
// Return true iff both Resources have the same name, type, and role.
bool matches(const Resource& left, const Resource& right);
-std::ostream& operator << (std::ostream& stream, const Resource& resource);
-
// TODO(bmahler): Ensure that the underlying resources are kept
// in a flattened state: MESOS-1714.
class Resources
{
public:
+ /**
+ * Parses the value and returns a Resource with the given name and role.
+ */
+ static Try<Resource> parse(
+ const std::string& name,
+ const std::string& value,
+ const std::string& role);
+
+ /**
+ * Parses resources in the form "name:value (role);name:value...".
+ * Any name/value pair that doesn't specify a role is assigned to defaultRole.
+ */
+ static Try<Resources> parse(
+ const std::string& s,
+ const std::string& defaultRole = "*");
+
+ /**
+ * Returns true iff this resource has a name, a valid type, i.e. scalar,
+ * range, or set, and has the appropriate value set for its type.
+ */
+ static bool isValid(const Resource& resource);
+
+ /**
+ * Returns true iff this resource is valid and allocatable. In particular,
+ * a scalar is allocatable if it's value is greater than zero, a ranges
+ * is allocatable if there is at least one valid range in it, and a set
+ * is allocatable if it has at least one item.
+ */
+ static bool isAllocatable(const Resource& resource);
+
+ /**
+ * Returns true iff this resource is zero valued, i.e. is zero for scalars,
+ * has a range size of zero for ranges, and has no items for sets.
+ */
+ static bool isZero(const Resource& resource);
+
Resources() {}
/*implicit*/
@@ -95,57 +135,16 @@ public:
return *this;
}
- /**
- * Returns a Resources object with only the allocatable resources.
- */
- Resources allocatable() const;
-
size_t size() const
{
return resources.size();
}
/**
- * Using this operator makes it easy to copy a resources object into
- * a protocol buffer field.
+ * Returns all resources in this object that are marked with the
+ * specified role.
*/
- operator const google::protobuf::RepeatedPtrField<Resource>& () const
- {
- return resources;
- }
-
- bool operator == (const Resources& that) const;
-
- bool operator != (const Resources& that) const
- {
- return !(*this == that);
- }
-
- bool operator <= (const Resources& that) const;
-
- Resources operator + (const Resources& that) const;
-
- Resources operator - (const Resources& that) const;
-
- Resources& operator += (const Resources& that);
-
- Resources& operator -= (const Resources& that);
-
- Resources operator + (const Resource& that) const;
-
- Resources operator - (const Resource& that) const;
-
- Resources& operator += (const Resource& that)
- {
- *this = *this + that;
- return *this;
- }
-
- Resources& operator -= (const Resource& that)
- {
- *this = *this - that;
- return *this;
- }
+ Resources extract(const std::string& role) const;
/**
* Returns a Resources object with the same amount of each resource
@@ -155,12 +154,6 @@ public:
Resources flatten(const std::string& role = "*") const;
/**
- * Returns all resources in this object that are marked with the
- * specified role.
- */
- Resources extract(const std::string& role) const;
-
- /**
* Finds a number of resources equal to toFind in these Resources
* and returns them marked with appropriate roles. For each resource
* type, resources are first taken from the specified role, then
@@ -185,6 +178,11 @@ public:
template <typename T>
T get(const std::string& name, const T& t) const;
+ /**
+ * Returns a Resources object with only the allocatable resources.
+ */
+ Resources allocatable() const;
+
// Helpers to get known resource types.
// TODO(vinod): Fix this when we make these types as first class protobufs.
Option<double> cpus() const;
@@ -215,46 +213,32 @@ public:
const_iterator end() const { return resources.end(); }
/**
- * Parses the value and returns a Resource with the given name and role.
+ * Using this operator makes it easy to copy a resources object into
+ * a protocol buffer field.
*/
- static Try<Resource> parse(
- const std::string& name,
- const std::string& value,
- const std::string& role);
+ operator const google::protobuf::RepeatedPtrField<Resource>& () const;
- /**
- * Parses resources in the form "name:value (role);name:value...".
- * Any name/value pair that doesn't specify a role is assigned to defaultRole.
- */
- static Try<Resources> parse(
- const std::string& s,
- const std::string& defaultRole = "*");
+ bool operator == (const Resources& that) const;
+ bool operator != (const Resources& that) const;
- /**
- * Returns true iff this resource has a name, a valid type, i.e. scalar,
- * range, or set, and has the appropriate value set for its type.
- */
- static bool isValid(const Resource& resource);
+ bool operator <= (const Resources& that) const;
- /**
- * Returns true iff this resource is valid and allocatable. In particular,
- * a scalar is allocatable if it's value is greater than zero, a ranges
- * is allocatable if there is at least one valid range in it, and a set
- * is allocatable if it has at least one item.
- */
- static bool isAllocatable(const Resource& resource);
+ Resources operator + (const Resource& that) const;
+ Resources operator + (const Resources& that) const;
+ Resources& operator += (const Resource& that);
+ Resources& operator += (const Resources& that);
- /**
- * Returns true iff this resource is zero valued, i.e. is zero for scalars,
- * has a range size of zero for ranges, and has no items for sets.
- */
- static bool isZero(const Resource& resource);
+ Resources operator - (const Resource& that) const;
+ Resources operator - (const Resources& that) const;
+ Resources& operator -= (const Resource& that);
+ Resources& operator -= (const Resources& that);
private:
google::protobuf::RepeatedPtrField<Resource> resources;
};
+std::ostream& operator << (std::ostream& stream, const Resource& resource);
std::ostream& operator << (std::ostream& stream, const Resources& resources);
http://git-wip-us.apache.org/repos/asf/mesos/blob/bdf2d9d4/src/common/resources.cpp
----------------------------------------------------------------------
diff --git a/src/common/resources.cpp b/src/common/resources.cpp
index e9a0c85..1ffebbb 100644
--- a/src/common/resources.cpp
+++ b/src/common/resources.cpp
@@ -18,7 +18,6 @@
#include <stdint.h>
-#include <iostream>
#include <vector>
#include <glog/logging.h>
@@ -28,7 +27,6 @@
#include <stout/foreach.hpp>
#include <stout/strings.hpp>
-#include <stout/try.hpp>
using std::ostream;
using std::string;
@@ -59,14 +57,6 @@ bool operator != (const Resource& left, const Resource& right)
}
-bool matches(const Resource& left, const Resource& right)
-{
- return left.name() == right.name() &&
- left.type() == right.type() &&
- left.role() == right.role();
-}
-
-
bool operator <= (const Resource& left, const Resource& right)
{
if (matches(left, right)) {
@@ -83,39 +73,37 @@ bool operator <= (const Resource& left, const Resource& right)
}
-Resource operator + (const Resource& left, const Resource& right)
+Resource& operator += (Resource& left, const Resource& right)
{
- Resource result = left;
-
if (matches(left, right)) {
if (left.type() == Value::SCALAR) {
- result.mutable_scalar()->MergeFrom(left.scalar() + right.scalar());
+ left.mutable_scalar()->MergeFrom(left.scalar() + right.scalar());
} else if (left.type() == Value::RANGES) {
- result.mutable_ranges()->Clear();
- result.mutable_ranges()->MergeFrom(left.ranges() + right.ranges());
+ left.mutable_ranges()->Clear();
+ left.mutable_ranges()->MergeFrom(left.ranges() + right.ranges());
} else if (left.type() == Value::SET) {
- result.mutable_set()->Clear();
- result.mutable_set()->MergeFrom(left.set() + right.set());
+ left.mutable_set()->Clear();
+ left.mutable_set()->MergeFrom(left.set() + right.set());
}
}
- return result;
+ return left;
}
-Resource operator - (const Resource& left, const Resource& right)
+Resource operator + (const Resource& left, const Resource& right)
{
Resource result = left;
if (matches(left, right)) {
if (left.type() == Value::SCALAR) {
- result.mutable_scalar()->MergeFrom(left.scalar() - right.scalar());
+ result.mutable_scalar()->MergeFrom(left.scalar() + right.scalar());
} else if (left.type() == Value::RANGES) {
result.mutable_ranges()->Clear();
- result.mutable_ranges()->MergeFrom(left.ranges() - right.ranges());
+ result.mutable_ranges()->MergeFrom(left.ranges() + right.ranges());
} else if (left.type() == Value::SET) {
result.mutable_set()->Clear();
- result.mutable_set()->MergeFrom(left.set() - right.set());
+ result.mutable_set()->MergeFrom(left.set() + right.set());
}
}
@@ -123,17 +111,17 @@ Resource operator - (const Resource& left, const Resource& right)
}
-Resource& operator += (Resource& left, const Resource& right)
+Resource& operator -= (Resource& left, const Resource& right)
{
if (matches(left, right)) {
if (left.type() == Value::SCALAR) {
- left.mutable_scalar()->MergeFrom(left.scalar() + right.scalar());
+ left.mutable_scalar()->MergeFrom(left.scalar() - right.scalar());
} else if (left.type() == Value::RANGES) {
left.mutable_ranges()->Clear();
- left.mutable_ranges()->MergeFrom(left.ranges() + right.ranges());
+ left.mutable_ranges()->MergeFrom(left.ranges() - right.ranges());
} else if (left.type() == Value::SET) {
left.mutable_set()->Clear();
- left.mutable_set()->MergeFrom(left.set() + right.set());
+ left.mutable_set()->MergeFrom(left.set() - right.set());
}
}
@@ -141,188 +129,223 @@ Resource& operator += (Resource& left, const Resource& right)
}
-Resource& operator -= (Resource& left, const Resource& right)
+Resource operator - (const Resource& left, const Resource& right)
{
+ Resource result = left;
+
if (matches(left, right)) {
if (left.type() == Value::SCALAR) {
- left.mutable_scalar()->MergeFrom(left.scalar() - right.scalar());
+ result.mutable_scalar()->MergeFrom(left.scalar() - right.scalar());
} else if (left.type() == Value::RANGES) {
- left.mutable_ranges()->Clear();
- left.mutable_ranges()->MergeFrom(left.ranges() - right.ranges());
+ result.mutable_ranges()->Clear();
+ result.mutable_ranges()->MergeFrom(left.ranges() - right.ranges());
} else if (left.type() == Value::SET) {
- left.mutable_set()->Clear();
- left.mutable_set()->MergeFrom(left.set() - right.set());
+ result.mutable_set()->Clear();
+ result.mutable_set()->MergeFrom(left.set() - right.set());
}
}
- return left;
+ return result;
}
-ostream& operator << (ostream& stream, const Resource& resource)
+bool matches(const Resource& left, const Resource& right)
{
- stream << resource.name() << "(" << resource.role() << "):";
+ return left.name() == right.name() &&
+ left.type() == right.type() &&
+ left.role() == right.role();
+}
- switch (resource.type()) {
- case Value::SCALAR: stream << resource.scalar(); break;
- case Value::RANGES: stream << resource.ranges(); break;
- case Value::SET: stream << resource.set(); break;
- default:
- LOG(FATAL) << "Unexpected Value type: " << resource.type();
- break;
+
+Try<Resource> Resources::parse(
+ const string& name,
+ const string& text,
+ const string& role)
+{
+ Resource resource;
+ Try<Value> result = internal::values::parse(text);
+
+ if (result.isError()) {
+ return Error("Failed to parse resource " + name +
+ " text " + text +
+ " error " + result.error());
+ } else{
+ Value value = result.get();
+ resource.set_name(name);
+ resource.set_role(role);
+
+ if (value.type() == Value::RANGES) {
+ resource.set_type(Value::RANGES);
+ resource.mutable_ranges()->MergeFrom(value.ranges());
+ } else if (value.type() == Value::SET) {
+ resource.set_type(Value::SET);
+ resource.mutable_set()->MergeFrom(value.set());
+ } else if (value.type() == Value::SCALAR) {
+ resource.set_type(Value::SCALAR);
+ resource.mutable_scalar()->MergeFrom(value.scalar());
+ } else {
+ return Error("Bad type for resource " + name +
+ " text " + text +
+ " type " + Value::Type_Name(value.type()));
+ }
}
- return stream;
+ return resource;
}
-Resources Resources::allocatable() const
+Try<Resources> Resources::parse(const string& s, const string& defaultRole)
{
- Resources result;
+ Resources resources;
- foreach (const Resource& resource, resources) {
- if (isAllocatable(resource)) {
- result.resources.Add()->MergeFrom(resource);
+ vector<string> tokens = strings::tokenize(s, ";");
+
+ foreach (const string& token, tokens) {
+ vector<string> pair = strings::tokenize(token, ":");
+ if (pair.size() != 2) {
+ return Error("Bad value for resources, missing or extra ':' in " + token);
+ }
+
+ string name;
+ string role;
+ size_t openParen = pair[0].find("(");
+ if (openParen == string::npos) {
+ name = strings::trim(pair[0]);
+ role = defaultRole;
+ } else {
+ size_t closeParen = pair[0].find(")");
+ if (closeParen == string::npos || closeParen < openParen) {
+ return Error("Bad value for resources, mismatched parentheses in " +
+ token);
+ }
+
+ name = strings::trim(pair[0].substr(0, openParen));
+ role = strings::trim(pair[0].substr(openParen + 1,
+ closeParen - openParen - 1));
+ }
+
+ Try<Resource> resource = Resources::parse(name, pair[1], role);
+ if (resource.isError()) {
+ return Error(resource.error());
}
+ resources += resource.get();
}
- return result;
+ return resources;
}
-bool Resources::operator == (const Resources& that) const
+bool Resources::isValid(const Resource& resource)
{
- if (size() != that.size()) {
+ if (!resource.has_name() ||
+ resource.name() == "" ||
+ !resource.has_type() ||
+ !Value::Type_IsValid(resource.type())) {
return false;
}
- foreach (const Resource& resource, resources) {
- Option<Resource> option = that.get(resource);
- if (option.isNone()) {
- return false;
- } else {
- if (!(resource == option.get())) {
- return false;
- }
- }
+ if (resource.type() == Value::SCALAR) {
+ return resource.has_scalar();
+ } else if (resource.type() == Value::RANGES) {
+ return resource.has_ranges();
+ } else if (resource.type() == Value::SET) {
+ return resource.has_set();
+ } else if (resource.type() == Value::TEXT) {
+ // Resources doesn't support text.
+ return false;
}
- return true;
+ return false;
}
-bool Resources::operator <= (const Resources& that) const
+bool Resources::isAllocatable(const Resource& resource)
{
- foreach (const Resource& resource, resources) {
- Option<Resource> option = that.get(resource);
- if (option.isNone()) {
- if (!isZero(resource)) {
+ if (isValid(resource)) {
+ if (resource.type() == Value::SCALAR) {
+ if (resource.scalar().value() <= 0) {
return false;
}
- } else {
- if (!(resource <= option.get())) {
+ } else if (resource.type() == Value::RANGES) {
+ if (resource.ranges().range_size() == 0) {
+ return false;
+ } else {
+ for (int i = 0; i < resource.ranges().range_size(); i++) {
+ const Value::Range& range = resource.ranges().range(i);
+
+ // Ensure the range make sense (isn't inverted).
+ if (range.begin() > range.end()) {
+ return false;
+ }
+
+ // Ensure ranges don't overlap (but not necessarily coalesced).
+ for (int j = i + 1; j < resource.ranges().range_size(); j++) {
+ if (range.begin() <= resource.ranges().range(j).begin() &&
+ resource.ranges().range(j).begin() <= range.end()) {
+ return false;
+ }
+ }
+ }
+ }
+ } else if (resource.type() == Value::SET) {
+ if (resource.set().item_size() == 0) {
return false;
+ } else {
+ for (int i = 0; i < resource.set().item_size(); i++) {
+ const string& item = resource.set().item(i);
+
+ // Ensure no duplicates.
+ for (int j = i + 1; j < resource.set().item_size(); j++) {
+ if (item == resource.set().item(j)) {
+ return false;
+ }
+ }
+ }
}
}
+
+ return true;
}
- return true;
+ return false;
}
-Resources Resources::operator + (const Resources& that) const
+bool Resources::isZero(const Resource& resource)
{
- Resources result(*this);
-
- foreach (const Resource& resource, that.resources) {
- result += resource;
+ if (resource.type() == Value::SCALAR) {
+ return resource.scalar().value() == 0;
+ } else if (resource.type() == Value::RANGES) {
+ return resource.ranges().range_size() == 0;
+ } else if (resource.type() == Value::SET) {
+ return resource.set().item_size() == 0;
}
- return result;
+ return false;
}
-Resources Resources::operator - (const Resources& that) const
+Resources Resources::extract(const string& role) const
{
- Resources result(*this);
+ Resources r;
- foreach (const Resource& resource, that.resources) {
- result -= resource;
+ foreach (const Resource& resource, resources) {
+ if (resource.role() == role) {
+ r += resource;
+ }
}
- return result;
+ return r;
}
-Resources& Resources::operator += (const Resources& that)
+Resources Resources::flatten(const string& role) const
{
- foreach (const Resource& resource, that.resources) {
- *this += resource;
- }
-
- return *this;
-}
+ Resources flattened;
-
-Resources& Resources::operator -= (const Resources& that)
-{
- foreach (const Resource& resource, that.resources) {
- *this -= resource;
- }
-
- return *this;
-}
-
-
-Resources Resources::operator + (const Resource& that) const
-{
- Resources result;
-
- bool added = false;
-
- foreach (const Resource& resource, resources) {
- if (matches(resource, that)) {
- result.resources.Add()->MergeFrom(resource + that);
- added = true;
- } else {
- result.resources.Add()->MergeFrom(resource);
- }
- }
-
- if (!added) {
- result.resources.Add()->MergeFrom(that);
- }
-
- return result;
-}
-
-
-Resources Resources::operator - (const Resource& that) const
-{
- Resources result;
-
- foreach (const Resource& resource, resources) {
- if (matches(resource, that)) {
- Resource r = resource - that;
- if (!isZero(r)) {
- result.resources.Add()->MergeFrom(r);
- }
- } else {
- result.resources.Add()->MergeFrom(resource);
- }
- }
-
- return result;
-}
-
-
-Resources Resources::flatten(const string& role) const
-{
- Resources flattened;
-
- foreach (const Resource& r, resources) {
- Resource toRemove = r;
- toRemove.set_role(role);
+ foreach (const Resource& r, resources) {
+ Resource toRemove = r;
+ toRemove.set_role(role);
bool found = false;
for (int i = 0; i < flattened.resources.size(); i++) {
@@ -344,20 +367,6 @@ Resources Resources::flatten(const string& role) const
}
-Resources Resources::extract(const string& role) const
-{
- Resources r;
-
- foreach (const Resource& resource, resources) {
- if (resource.role() == role) {
- r += resource;
- }
- }
-
- return r;
-}
-
-
Option<Resources> Resources::find(
const Resources& toFind,
const string& role) const
@@ -439,6 +448,92 @@ Option<Resources> Resources::getAll(const Resource& r) const
}
+template <>
+Value::Scalar Resources::get(
+ const string& name,
+ const Value::Scalar& scalar) const
+{
+ Value::Scalar total;
+ bool found = false;
+
+ foreach (const Resource& resource, resources) {
+ if (resource.name() == name &&
+ resource.type() == Value::SCALAR) {
+ total += resource.scalar();
+ found = true;
+ }
+ }
+
+ if (found) {
+ return total;
+ }
+
+ return scalar;
+}
+
+
+template <>
+Value::Ranges Resources::get(
+ const string& name,
+ const Value::Ranges& ranges) const
+{
+ Value::Ranges total;
+ bool found = false;
+
+ foreach (const Resource& resource, resources) {
+ if (resource.name() == name &&
+ resource.type() == Value::RANGES) {
+ total += resource.ranges();
+ found = true;
+ }
+ }
+
+ if (found) {
+ return total;
+ }
+
+ return ranges;
+}
+
+
+template <>
+Value::Set Resources::get(
+ const string& name,
+ const Value::Set& set) const
+{
+ Value::Set total;
+ bool found = false;
+
+ foreach (const Resource& resource, resources) {
+ if (resource.name() == name &&
+ resource.type() == Value::SET) {
+ total += resource.set();
+ found = true;
+ }
+ }
+
+ if (found) {
+ return total;
+ }
+
+ return set;
+}
+
+
+Resources Resources::allocatable() const
+{
+ Resources result;
+
+ foreach (const Resource& resource, resources) {
+ if (isAllocatable(resource)) {
+ result.resources.Add()->MergeFrom(resource);
+ }
+ }
+
+ return result;
+}
+
+
Option<double> Resources::cpus() const
{
double total= 0;
@@ -573,249 +668,176 @@ Option<Value::Ranges> Resources::ephemeral_ports() const
}
-Try<Resource> Resources::parse(
- const string& name,
- const string& text,
- const string& role)
+Resources::operator const google::protobuf::RepeatedPtrField<Resource>& () const
{
- Resource resource;
- Try<Value> result = internal::values::parse(text);
+ return resources;
+}
- if (result.isError()) {
- return Error("Failed to parse resource " + name +
- " text " + text +
- " error " + result.error());
- } else{
- Value value = result.get();
- resource.set_name(name);
- resource.set_role(role);
- if (value.type() == Value::RANGES) {
- resource.set_type(Value::RANGES);
- resource.mutable_ranges()->MergeFrom(value.ranges());
- } else if (value.type() == Value::SET) {
- resource.set_type(Value::SET);
- resource.mutable_set()->MergeFrom(value.set());
- } else if (value.type() == Value::SCALAR) {
- resource.set_type(Value::SCALAR);
- resource.mutable_scalar()->MergeFrom(value.scalar());
- } else {
- return Error("Bad type for resource " + name +
- " text " + text +
- " type " + Value::Type_Name(value.type()));
+bool Resources::operator == (const Resources& that) const
+{
+ if (size() != that.size()) {
+ return false;
+ }
+
+ foreach (const Resource& resource, resources) {
+ Option<Resource> option = that.get(resource);
+ if (option.isNone()) {
+ return false;
+ } else {
+ if (!(resource == option.get())) {
+ return false;
+ }
}
}
- return resource;
+ return true;
}
-Try<Resources> Resources::parse(const string& s, const string& defaultRole)
+bool Resources::operator != (const Resources& that) const
{
- Resources resources;
+ return !(*this == that);
+}
- vector<string> tokens = strings::tokenize(s, ";");
- foreach (const string& token, tokens) {
- vector<string> pair = strings::tokenize(token, ":");
- if (pair.size() != 2) {
- return Error("Bad value for resources, missing or extra ':' in " + token);
- }
-
- string name;
- string role;
- size_t openParen = pair[0].find("(");
- if (openParen == string::npos) {
- name = strings::trim(pair[0]);
- role = defaultRole;
+bool Resources::operator <= (const Resources& that) const
+{
+ foreach (const Resource& resource, resources) {
+ Option<Resource> option = that.get(resource);
+ if (option.isNone()) {
+ if (!isZero(resource)) {
+ return false;
+ }
} else {
- size_t closeParen = pair[0].find(")");
- if (closeParen == string::npos || closeParen < openParen) {
- return Error("Bad value for resources, mismatched parentheses in " +
- token);
+ if (!(resource <= option.get())) {
+ return false;
}
-
- name = strings::trim(pair[0].substr(0, openParen));
- role = strings::trim(pair[0].substr(openParen + 1,
- closeParen - openParen - 1));
}
-
- Try<Resource> resource = Resources::parse(name, pair[1], role);
- if (resource.isError()) {
- return Error(resource.error());
- }
- resources += resource.get();
}
- return resources;
+ return true;
}
-bool Resources::isValid(const Resource& resource)
+Resources Resources::operator + (const Resource& that) const
{
- if (!resource.has_name() ||
- resource.name() == "" ||
- !resource.has_type() ||
- !Value::Type_IsValid(resource.type())) {
- return false;
+ Resources result;
+
+ bool added = false;
+
+ foreach (const Resource& resource, resources) {
+ if (matches(resource, that)) {
+ result.resources.Add()->MergeFrom(resource + that);
+ added = true;
+ } else {
+ result.resources.Add()->MergeFrom(resource);
+ }
}
- if (resource.type() == Value::SCALAR) {
- return resource.has_scalar();
- } else if (resource.type() == Value::RANGES) {
- return resource.has_ranges();
- } else if (resource.type() == Value::SET) {
- return resource.has_set();
- } else if (resource.type() == Value::TEXT) {
- // Resources doesn't support text.
- return false;
+ if (!added) {
+ result.resources.Add()->MergeFrom(that);
}
- return false;
+ return result;
}
-bool Resources::isAllocatable(const Resource& resource)
+Resources Resources::operator + (const Resources& that) const
{
- if (isValid(resource)) {
- if (resource.type() == Value::SCALAR) {
- if (resource.scalar().value() <= 0) {
- return false;
- }
- } else if (resource.type() == Value::RANGES) {
- if (resource.ranges().range_size() == 0) {
- return false;
- } else {
- for (int i = 0; i < resource.ranges().range_size(); i++) {
- const Value::Range& range = resource.ranges().range(i);
-
- // Ensure the range make sense (isn't inverted).
- if (range.begin() > range.end()) {
- return false;
- }
+ Resources result(*this);
- // Ensure ranges don't overlap (but not necessarily coalesced).
- for (int j = i + 1; j < resource.ranges().range_size(); j++) {
- if (range.begin() <= resource.ranges().range(j).begin() &&
- resource.ranges().range(j).begin() <= range.end()) {
- return false;
- }
- }
- }
- }
- } else if (resource.type() == Value::SET) {
- if (resource.set().item_size() == 0) {
- return false;
- } else {
- for (int i = 0; i < resource.set().item_size(); i++) {
- const std::string& item = resource.set().item(i);
+ foreach (const Resource& resource, that.resources) {
+ result += resource;
+ }
- // Ensure no duplicates.
- for (int j = i + 1; j < resource.set().item_size(); j++) {
- if (item == resource.set().item(j)) {
- return false;
- }
- }
- }
- }
- }
+ return result;
+}
- return true;
- }
- return false;
+Resources& Resources::operator += (const Resource& that)
+{
+ *this = *this + that;
+ return *this;
}
-bool Resources::isZero(const Resource& resource)
+Resources& Resources::operator += (const Resources& that)
{
- if (resource.type() == Value::SCALAR) {
- return resource.scalar().value() == 0;
- } else if (resource.type() == Value::RANGES) {
- return resource.ranges().range_size() == 0;
- } else if (resource.type() == Value::SET) {
- return resource.set().item_size() == 0;
+ foreach (const Resource& resource, that.resources) {
+ *this += resource;
}
- return false;
+ return *this;
}
-template <>
-Value::Scalar Resources::get(
- const std::string& name,
- const Value::Scalar& scalar) const
+Resources Resources::operator - (const Resource& that) const
{
- Value::Scalar total;
- bool found = false;
+ Resources result;
foreach (const Resource& resource, resources) {
- if (resource.name() == name &&
- resource.type() == Value::SCALAR) {
- total += resource.scalar();
- found = true;
+ if (matches(resource, that)) {
+ Resource r = resource - that;
+ if (!isZero(r)) {
+ result.resources.Add()->MergeFrom(r);
+ }
+ } else {
+ result.resources.Add()->MergeFrom(resource);
}
}
- if (found) {
- return total;
+ return result;
+}
+
+
+Resources Resources::operator - (const Resources& that) const
+{
+ Resources result(*this);
+
+ foreach (const Resource& resource, that.resources) {
+ result -= resource;
}
- return scalar;
+ return result;
}
-template <>
-Value::Ranges Resources::get(
- const std::string& name,
- const Value::Ranges& ranges) const
+Resources& Resources::operator -= (const Resource& that)
{
- Value::Ranges total;
- bool found = false;
+ *this = *this - that;
+ return *this;
+}
- foreach (const Resource& resource, resources) {
- if (resource.name() == name &&
- resource.type() == Value::RANGES) {
- total += resource.ranges();
- found = true;
- }
- }
- if (found) {
- return total;
+Resources& Resources::operator -= (const Resources& that)
+{
+ foreach (const Resource& resource, that.resources) {
+ *this -= resource;
}
- return ranges;
+ return *this;
}
-template <>
-Value::Set Resources::get(
- const std::string& name,
- const Value::Set& set) const
+ostream& operator << (ostream& stream, const Resource& resource)
{
- Value::Set total;
- bool found = false;
-
- foreach (const Resource& resource, resources) {
- if (resource.name() == name &&
- resource.type() == Value::SET) {
- total += resource.set();
- found = true;
- }
- }
+ stream << resource.name() << "(" << resource.role() << "):";
- if (found) {
- return total;
+ switch (resource.type()) {
+ case Value::SCALAR: stream << resource.scalar(); break;
+ case Value::RANGES: stream << resource.ranges(); break;
+ case Value::SET: stream << resource.set(); break;
+ default:
+ LOG(FATAL) << "Unexpected Value type: " << resource.type();
+ break;
}
- return set;
+ return stream;
}
-std::ostream& operator << (
- std::ostream& stream,
- const Resources& resources)
+ostream& operator << (ostream& stream, const Resources& resources)
{
mesos::Resources::const_iterator it = resources.begin();
@@ -829,5 +851,4 @@ std::ostream& operator << (
return stream;
}
-
} // namespace mesos {