[ https://issues.apache.org/jira/browse/MESOS-3404?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14952863#comment-14952863 ]
Benjamin Bannier commented on MESOS-3404: ----------------------------------------- Here is the full list of duplicates found by duplo(-fork), {code} % duplo src/v1/*cpp src/common/*cpp {code} ---- {code} src/v1/attributes.cpp(30) src/v1/resources.cpp(38) using std::string; using std::vector; namespace mesos { namespace v1 { src/v1/attributes.cpp(29) src/v1/values.cpp(41) using std::ostream; using std::string; using std::vector; namespace mesos { namespace v1 { src/v1/attributes.cpp(26) src/common/attributes.cpp(26) #include <stout/foreach.hpp> #include <stout/strings.hpp> using std::ostream; using std::string; using std::vector; namespace mesos { src/v1/attributes.cpp(36) src/common/attributes.cpp(36) std::ostream& operator<<(std::ostream& stream, const Attribute& attribute) stream << attribute.name() << "="; switch (attribute.type()) { case Value::SCALAR: stream << attribute.scalar(); break; case Value::RANGES: stream << attribute.ranges(); break; case Value::SET: stream << attribute.set(); break; case Value::TEXT: stream << attribute.text(); break; default: LOG(FATAL) << "Unexpected Value type: " << attribute.type(); break; return stream; bool Attributes::operator==(const Attributes& that) const if (size() != that.size()) { return false; foreach (const Attribute& attribute, attributes) { Option<Attribute> maybeAttribute = that.get(attribute); if (maybeAttribute.isNone()) { return false; const Attribute& thatAttribute = maybeAttribute.get(); switch (attribute.type()) { case Value::SCALAR: if (!(attribute.scalar() == thatAttribute.scalar())) { return false; break; case Value::RANGES: if (!(attribute.ranges() == thatAttribute.ranges())) { return false; break; case Value::TEXT: if (!(attribute.text() == thatAttribute.text())) { return false; break; case Value::SET: LOG(FATAL) << "Sets not supported for attributes"; return true; const Option<Attribute> Attributes::get(const Attribute& thatAttribute) const foreach (const Attribute& attribute, attributes) { if (attribute.name() == thatAttribute.name() && attribute.type() == thatAttribute.type()) { return attribute; return None(); Attribute Attributes::parse(const string& name, const string& text) Attribute attribute; Try<Value> result = internal::values::parse(text); if (result.isError()) { LOG(FATAL) << "Failed to parse attribute " << name << " text " << text << " error " << result.error(); } else { Value value = result.get(); attribute.set_name(name); if (value.type() == Value::RANGES) { attribute.set_type(Value::RANGES); attribute.mutable_ranges()->MergeFrom(value.ranges()); } else if (value.type() == Value::TEXT) { attribute.set_type(Value::TEXT); attribute.mutable_text()->MergeFrom(value.text()); } else if (value.type() == Value::SCALAR) { attribute.set_type(Value::SCALAR); attribute.mutable_scalar()->MergeFrom(value.scalar()); } else { LOG(FATAL) << "Bad type for attribute " << name << " text " << text << " type " << value.type(); return attribute; Attributes Attributes::parse(const string& s) Attributes attributes; vector<string> tokens = strings::tokenize(s, ";\n"); for (size_t i = 0; i < tokens.size(); i++) { const vector<string>& pairs = strings::split(tokens[i], ":", 2); if (pairs.size() != 2 || pairs[0].empty() || pairs[1].empty()) { LOG(FATAL) << "Invalid attribute key:value pair '" << tokens[i] << "'"; attributes.add(parse(pairs[0], pairs[1])); return attributes; bool Attributes::isValid(const Attribute& attribute) if (!attribute.has_name() || attribute.name() == "" || !attribute.has_type() || !Value::Type_IsValid(attribute.type())) { return false; if (attribute.type() == Value::SCALAR) { return attribute.has_scalar(); } else if (attribute.type() == Value::RANGES) { return attribute.has_ranges(); } else if (attribute.type() == Value::TEXT) { return attribute.has_text(); } else if (attribute.type() == Value::SET) { return false; return false; template <> Value::Scalar Attributes::get( const string& name, const Value::Scalar& scalar) const foreach (const Attribute& attribute, attributes) { if (attribute.name() == name && attribute.type() == Value::SCALAR) { return attribute.scalar(); return scalar; template <> Value::Ranges Attributes::get( const string& name, const Value::Ranges& ranges) const foreach (const Attribute& attribute, attributes) { if (attribute.name() == name && attribute.type() == Value::RANGES) { return attribute.ranges(); return ranges; template <> Value::Text Attributes::get( const string& name, const Value::Text& text) const foreach (const Attribute& attribute, attributes) { if (attribute.name() == name && attribute.type() == Value::TEXT) { return attribute.text(); return text; src/v1/attributes.cpp(29) src/common/values.cpp(41) using std::ostream; using std::string; using std::vector; namespace mesos { src/v1/mesos.cpp(270) src/v1/values.cpp(310) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(240) src/v1/values.cpp(310) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(206) src/v1/values.cpp(310) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/v1/values.cpp(310) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/v1/values.cpp(409) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(161) src/v1/values.cpp(310) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/v1/values.cpp(434) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(240) src/v1/values.cpp(409) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(240) src/v1/values.cpp(434) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(206) src/v1/values.cpp(409) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/v1/values.cpp(310) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(206) src/v1/values.cpp(434) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/v1/values.cpp(409) found = true; break; if (!found) { return false; src/v1/mesos.cpp(161) src/v1/values.cpp(409) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/v1/values.cpp(434) found = true; break; if (!found) { return false; src/v1/mesos.cpp(39) src/v1/values.cpp(310) found = true; break; if (!found) { return false; src/v1/mesos.cpp(161) src/v1/values.cpp(434) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/v1/values.cpp(409) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(104) src/v1/values.cpp(434) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(39) src/v1/values.cpp(409) found = true; break; if (!found) { return false; src/v1/mesos.cpp(39) src/v1/values.cpp(434) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/common/type_utils.cpp(163) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/common/type_utils.cpp(242) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(206) src/common/type_utils.cpp(181) found = true; break; if (!found) { return false; src/v1/mesos.cpp(240) src/common/type_utils.cpp(208) found = true; break; if (!found) { return false; src/v1/mesos.cpp(206) src/common/type_utils.cpp(163) found = true; break; if (!found) { return false; src/v1/mesos.cpp(161) src/common/type_utils.cpp(106) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/common/type_utils.cpp(41) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/common/type_utils.cpp(208) found = true; break; if (!found) { return false; src/v1/mesos.cpp(240) src/common/type_utils.cpp(181) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/common/type_utils.cpp(106) found = true; break; if (!found) { return false; src/v1/mesos.cpp(240) src/common/type_utils.cpp(163) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/common/type_utils.cpp(181) found = true; break; if (!found) { return false; src/v1/mesos.cpp(206) src/common/type_utils.cpp(106) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/common/type_utils.cpp(163) found = true; break; if (!found) { return false; src/v1/mesos.cpp(161) src/common/type_utils.cpp(41) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/common/type_utils.cpp(41) found = true; break; if (!found) { return false; src/v1/mesos.cpp(240) src/common/type_utils.cpp(106) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(206) src/common/type_utils.cpp(41) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/common/type_utils.cpp(106) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(240) src/common/type_utils.cpp(41) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/common/type_utils.cpp(41) found = true; break; if (!found) { return false; src/v1/mesos.cpp(28) src/common/type_utils.cpp(30) bool operator==(const CommandInfo& left, const CommandInfo& right) if (left.uris().size() != right.uris().size()) { return false; for (int i = 0; i < left.uris().size(); i++) { bool found = false; for (int j = 0; j < right.uris().size(); j++) { if (left.uris().Get(i) == right.uris().Get(j)) { found = true; break; if (!found) { return false; if (left.arguments().size() != right.arguments().size()) { return false; for (int i = 0; i < left.arguments().size(); i++) { if (left.arguments().Get(i) != right.arguments().Get(i)) { return false; return left.environment() == right.environment() && left.value() == right.value() && left.user() == right.user() && left.shell() == right.shell(); bool operator==(const CommandInfo::URI& left, const CommandInfo::URI& right) return left.value() == right.value() && left.executable() == right.executable() && left.extract() == right.extract(); bool operator==(const Credential& left, const Credential& right) return left.principal() == right.principal() && left.secret() == right.secret(); bool operator==( const Environment::Variable& left, const Environment::Variable& right) return left.name() == right.name() && left.value() == right.value(); bool operator==(const Environment& left, const Environment& right) if (left.variables().size() != right.variables().size()) { return false; for (int i = 0; i < left.variables().size(); i++) { bool found = false; for (int j = 0; j < right.variables().size(); j++) { if (left.variables().Get(i) == right.variables().Get(j)) { found = true; break; if (!found) { return false; return true; bool operator==(const Volume& left, const Volume& right) return left.container_path() == right.container_path() && left.host_path() == right.host_path() && left.mode() == right.mode(); bool operator==(const URL& left, const URL& right) return left.SerializeAsString() == right.SerializeAsString(); bool operator==( const ContainerInfo::DockerInfo::PortMapping& left, const ContainerInfo::DockerInfo::PortMapping& right) return left.host_port() == right.host_port() && left.container_port() == right.container_port() && left.protocol() == right.protocol(); bool operator==(const Parameter& left, const Parameter& right) return left.key() == right.key() && left.value() == right.value(); bool operator==( const ContainerInfo::DockerInfo& left, const ContainerInfo::DockerInfo& right) if (left.port_mappings().size() != right.port_mappings().size()) { return false; for (int i = 0; i < left.port_mappings().size(); i++) { bool found = false; for (int j = 0; j < right.port_mappings().size(); j++) { if (left.port_mappings().Get(i) == right.port_mappings().Get(j)) { found = true; break; if (!found) { return false; if (left.parameters().size() != right.parameters().size()) { return false; for (int i = 0; i < left.parameters().size(); i++) { bool found = false; for (int j = 0; j < right.parameters().size(); j++) { if (left.parameters().Get(i) == right.parameters().Get(j)) { found = true; break; if (!found) { return false; return left.image() == right.image() && left.network() == right.network() && left.privileged() == right.privileged() && left.force_pull_image() == right.force_pull_image(); bool operator==(const ContainerInfo& left, const ContainerInfo& right) if (left.volumes().size() != right.volumes().size()) { return false; for (int i = 0; i < left.volumes().size(); i++) { bool found = false; for (int j = 0; j < right.volumes().size(); j++) { if (left.volumes().Get(i) == right.volumes().Get(j)) { found = true; break; if (!found) { return false; return left.type() == right.type() && left.hostname() == right.hostname() && left.docker() == right.docker(); bool operator==(const Port& left, const Port& right) return left.number() == right.number() && left.name() == right.name() && left.protocol() == right.protocol(); bool operator==(const Ports& left, const Ports& right) if (left.ports().size() != right.ports().size()) { return false; for (int i = 0; i < left.ports().size(); i++) { bool found = false; for (int j = 0; j < right.ports().size(); j++) { if (left.ports().Get(i) == right.ports().Get(j)) { found = true; break; if (!found) { return false; return true; bool operator==(const Label& left, const Label& right) return left.key() == right.key() && left.value() == right.value(); bool operator==(const Labels& left, const Labels& right) if (left.labels().size() != right.labels().size()) { return false; for (int i = 0; i < left.labels().size(); i++) { bool found = false; for (int j = 0; j < right.labels().size(); j++) { if (left.labels().Get(i) == right.labels().Get(j)) { found = true; break; if (!found) { return false; return true; bool operator==(const DiscoveryInfo& left, const DiscoveryInfo& right) return left.visibility() == right.visibility() && left.name() == right.name() && left.environment() == right.environment() && left.location() == right.location() && left.version() == right.version() && left.ports() == right.ports() && left.labels() == right.labels(); bool operator==(const ExecutorInfo& left, const ExecutorInfo& right) return left.executor_id() == right.executor_id() && left.data() == right.data() && Resources(left.resources()) == Resources(right.resources()) && left.command() == right.command() && left.framework_id() == right.framework_id() && left.name() == right.name() && left.source() == right.source() && left.container() == right.container() && left.discovery() == right.discovery(); bool operator==(const MasterInfo& left, const MasterInfo& right) return left.id() == right.id() && left.ip() == right.ip() && left.port() == right.port() && left.pid() == right.pid() && left.hostname() == right.hostname() && left.version() == right.version(); bool operator==( const ResourceStatistics& left, const ResourceStatistics& right) return left.SerializeAsString() == right.SerializeAsString(); src/v1/mesos.cpp(330) src/common/type_utils.cpp(332) return left.hostname() == right.hostname() && Resources(left.resources()) == Resources(right.resources()) && Attributes(left.attributes()) == Attributes(right.attributes()) && left.id() == right.id() && src/v1/mesos.cpp(334) src/common/type_utils.cpp(337) left.port() == right.port(); bool operator==(const TaskStatus& left, const TaskStatus& right) return left.task_id() == right.task_id() && left.state() == right.state() && left.data() == right.data() && left.message() == right.message() && src/v1/mesos.cpp(346) src/common/type_utils.cpp(349) left.timestamp() == right.timestamp() && left.executor_id() == right.executor_id() && left.healthy() == right.healthy() && left.source() == right.source() && left.reason() == right.reason() && left.uuid() == right.uuid(); bool operator!=(const TaskStatus& left, const TaskStatus& right) return !(left == right); src/v1/mesos.cpp(161) src/common/type_utils.cpp(181) found = true; break; if (!found) { return false; src/v1/mesos.cpp(240) src/common/type_utils.cpp(272) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(179) src/common/type_utils.cpp(208) found = true; break; if (!found) { return false; src/v1/mesos.cpp(206) src/common/type_utils.cpp(242) found = true; break; if (!found) { return false; src/v1/mesos.cpp(161) src/common/type_utils.cpp(208) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/common/type_utils.cpp(163) found = true; break; if (!found) { return false; src/v1/mesos.cpp(39) src/common/type_utils.cpp(106) found = true; break; if (!found) { return false; src/v1/mesos.cpp(206) src/common/type_utils.cpp(272) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/common/type_utils.cpp(242) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/common/type_utils.cpp(181) found = true; break; if (!found) { return false; src/v1/mesos.cpp(161) src/common/type_utils.cpp(242) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/common/type_utils.cpp(272) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/common/type_utils.cpp(208) found = true; break; if (!found) { return false; src/v1/mesos.cpp(161) src/common/type_utils.cpp(272) found = true; break; if (!found) { return false; src/v1/mesos.cpp(39) src/common/type_utils.cpp(163) found = true; break; if (!found) { return false; src/v1/mesos.cpp(39) src/common/type_utils.cpp(181) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/common/type_utils.cpp(242) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(39) src/common/type_utils.cpp(208) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/common/type_utils.cpp(272) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(39) src/common/type_utils.cpp(242) found = true; break; if (!found) { return false; src/v1/mesos.cpp(39) src/common/type_utils.cpp(272) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/common/values.cpp(310) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(240) src/common/values.cpp(310) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(206) src/common/values.cpp(310) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/common/values.cpp(310) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/common/values.cpp(409) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(161) src/common/values.cpp(310) found = true; break; if (!found) { return false; src/v1/mesos.cpp(270) src/common/values.cpp(434) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(240) src/common/values.cpp(409) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(240) src/common/values.cpp(434) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(206) src/common/values.cpp(409) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/common/values.cpp(310) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(206) src/common/values.cpp(434) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/common/values.cpp(409) found = true; break; if (!found) { return false; src/v1/mesos.cpp(161) src/common/values.cpp(409) found = true; break; if (!found) { return false; src/v1/mesos.cpp(179) src/common/values.cpp(434) found = true; break; if (!found) { return false; src/v1/mesos.cpp(39) src/common/values.cpp(310) found = true; break; if (!found) { return false; src/v1/mesos.cpp(161) src/common/values.cpp(434) found = true; break; if (!found) { return false; src/v1/mesos.cpp(104) src/common/values.cpp(409) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(104) src/common/values.cpp(434) found = true; break; if (!found) { return false; return true; src/v1/mesos.cpp(39) src/common/values.cpp(409) found = true; break; if (!found) { return false; src/v1/mesos.cpp(39) src/common/values.cpp(434) found = true; break; if (!found) { return false; src/v1/resources.cpp(38) src/v1/values.cpp(42) using std::string; using std::vector; namespace mesos { namespace v1 { src/v1/resources.cpp(37) src/common/http.cpp(37) using std::set; using std::string; using std::vector; namespace mesos { src/v1/resources.cpp(18) src/common/resources.cpp(18) #include <stdint.h> #include <set> #include <string> #include <vector> #include <glog/logging.h> src/v1/resources.cpp(30) src/common/resources.cpp(30) #include <stout/foreach.hpp> #include <stout/hashmap.hpp> #include <stout/lambda.hpp> #include <stout/strings.hpp> using std::map; using std::ostream; using std::set; using std::string; using std::vector; namespace mesos { src/v1/resources.cpp(49) src/common/resources.cpp(48) bool operator==( const Resource::ReservationInfo& left, const Resource::ReservationInfo& right) return left.principal() == right.principal(); bool operator!=( const Resource::ReservationInfo& left, const Resource::ReservationInfo& right) return !(left == right); bool operator==(const Resource::DiskInfo& left, const Resource::DiskInfo& right) if (left.has_persistence() != right.has_persistence()) { return false; if (left.has_persistence()) { return left.persistence().id() == right.persistence().id(); return true; bool operator!=(const Resource::DiskInfo& left, const Resource::DiskInfo& right) return !(left == right); bool operator==(const Resource& left, const Resource& right) if (left.name() != right.name() || left.type() != right.type() || left.role() != right.role()) { return false; if (left.has_reservation() != right.has_reservation()) { return false; if (left.has_reservation() && left.reservation() != right.reservation()) { return false; if (left.has_disk() != right.has_disk()) { return false; if (left.has_disk() && left.disk() != right.disk()) { return false; if (left.has_revocable() != right.has_revocable()) { return false; if (left.type() == Value::SCALAR) { return left.scalar() == right.scalar(); } else if (left.type() == Value::RANGES) { return left.ranges() == right.ranges(); } else if (left.type() == Value::SET) { return left.set() == right.set(); } else { return false; bool operator!=(const Resource& left, const Resource& right) return !(left == right); namespace internal { static bool addable(const Resource& left, const Resource& right) if (left.name() != right.name() || left.type() != right.type() || left.role() != right.role()) { return false; if (left.has_reservation() != right.has_reservation()) { return false; if (left.has_reservation() && left.reservation() != right.reservation()) { return false; if (left.has_disk() != right.has_disk()) { return false; if (left.has_disk() && left.disk() != right.disk()) { return false; if (left.has_disk() && left.disk().has_persistence()) { return false; if (left.has_revocable() != right.has_revocable()) { return false; return true; static bool subtractable(const Resource& left, const Resource& right) if (left.name() != right.name() || left.type() != right.type() || left.role() != right.role()) { return false; if (left.has_reservation() != right.has_reservation()) { return false; if (left.has_reservation() && left.reservation() != right.reservation()) { return false; if (left.has_disk() != right.has_disk()) { return false; if (left.has_disk() && left.disk() != right.disk()) { return false; if (left.has_disk() && left.disk().has_persistence() && left != right) { return false; if (left.has_revocable() != right.has_revocable()) { return false; return true; static bool contains(const Resource& left, const Resource& right) if (!subtractable(left, right)) { return false; if (left.type() == Value::SCALAR) { return right.scalar() <= left.scalar(); } else if (left.type() == Value::RANGES) { return right.ranges() <= left.ranges(); } else if (left.type() == Value::SET) { return right.set() <= left.set(); } else { return false; Resource& operator+=(Resource& left, const Resource& right) if (left.type() == Value::SCALAR) { *left.mutable_scalar() += right.scalar(); } else if (left.type() == Value::RANGES) { *left.mutable_ranges() += right.ranges(); } else if (left.type() == Value::SET) { *left.mutable_set() += right.set(); return left; Resource operator+(const Resource& left, const Resource& right) Resource result = left; result += right; return result; Resource& operator-=(Resource& left, const Resource& right) if (left.type() == Value::SCALAR) { *left.mutable_scalar() -= right.scalar(); } else if (left.type() == Value::RANGES) { *left.mutable_ranges() -= right.ranges(); } else if (left.type() == Value::SET) { *left.mutable_set() -= right.set(); return left; Resource operator-(const Resource& left, const Resource& right) Resource result = left; result -= right; return result; Try<Resource> Resources::parse( const string& name, const string& value, const string& role) Try<Value> result = internal::values::parse(value); if (result.isError()) { return Error( "Failed to parse resource " + name + " value " + value + " error " + result.error()); Resource resource; Value _value = result.get(); resource.set_name(name); resource.set_role(role); if (_value.type() == Value::SCALAR) { resource.set_type(Value::SCALAR); resource.mutable_scalar()->CopyFrom(_value.scalar()); } else if (_value.type() == Value::RANGES) { resource.set_type(Value::RANGES); resource.mutable_ranges()->CopyFrom(_value.ranges()); } else if (_value.type() == Value::SET) { resource.set_type(Value::SET); resource.mutable_set()->CopyFrom(_value.set()); } else { return Error( "Bad type for resource " + name + " value " + value + " type " + Value::Type_Name(_value.type())); return resource; Try<Resources> Resources::parse( const string& text, const string& defaultRole) Resources resources; hashmap<string, Value_Type> nameTypes; foreach (const string& token, strings::tokenize(text, ";")) { 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()); if (nameTypes.contains(name) && nameTypes[name] != resource.get().type()) { return Error( "Resources with the same name ('" + name + "') but different types " "are not allowed"); } else if (!nameTypes.contains(name)) { nameTypes[name] = resource.get().type(); resources += resource.get(); return resources; Option<Error> Resources::validate(const Resource& resource) if (resource.name().empty()) { return Error("Empty resource name"); if (!Value::Type_IsValid(resource.type())) { return Error("Invalid resource type"); if (resource.type() == Value::SCALAR) { if (!resource.has_scalar() || resource.has_ranges() || resource.has_set()) { return Error("Invalid scalar resource"); if (resource.scalar().value() < 0) { return Error("Invalid scalar resource: value < 0"); } else if (resource.type() == Value::RANGES) { if (resource.has_scalar() || !resource.has_ranges() || resource.has_set()) { return Error("Invalid ranges resource"); for (int i = 0; i < resource.ranges().range_size(); i++) { const Value::Range& range = resource.ranges().range(i); if (range.begin() > range.end()) { return Error("Invalid ranges resource: begin > end"); 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 Error("Invalid ranges resource: overlapping ranges"); } else if (resource.type() == Value::SET) { if (resource.has_scalar() || resource.has_ranges() || !resource.has_set()) { return Error("Invalid set resource"); for (int i = 0; i < resource.set().item_size(); i++) { const string& item = resource.set().item(i); for (int j = i + 1; j < resource.set().item_size(); j++) { if (item == resource.set().item(j)) { return Error("Invalid set resource: duplicated elements"); } else { return Error("Unsupported resource type"); if (resource.has_disk() && resource.name() != "disk") { return Error( "DiskInfo should not be set for " + resource.name() + " resource"); if (resource.role() == "*" && resource.has_reservation()) { return Error( "Invalid reservation: role \"*\" cannot be dynamically reserved"); return None(); Option<Error> Resources::validate( const google::protobuf::RepeatedPtrField<Resource>& resources) foreach (const Resource& resource, resources) { Option<Error> error = validate(resource); if (error.isSome()) { return Error( "Resource '" + stringify(resource) + "' is invalid: " + error.get().message); return None(); bool Resources::isEmpty(const Resource& 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; } else { return false; bool Resources::isPersistentVolume(const Resource& resource) return resource.has_disk() && resource.disk().has_persistence(); bool Resources::isReserved( const Resource& resource, const Option<std::string>& role) if (role.isSome()) { return !isUnreserved(resource) && role.get() == resource.role(); } else { return !isUnreserved(resource); bool Resources::isUnreserved(const Resource& resource) return resource.role() == "*" && !resource.has_reservation(); bool Resources::isDynamicallyReserved(const Resource& resource) return resource.has_reservation(); bool Resources::isRevocable(const Resource& resource) return resource.has_revocable(); Resources::Resources(const Resource& resource) *this += resource; Resources::Resources(const vector<Resource>& _resources) foreach (const Resource& resource, _resources) { *this += resource; Resources::Resources( const google::protobuf::RepeatedPtrField<Resource>& _resources) foreach (const Resource& resource, _resources) { *this += resource; bool Resources::contains(const Resources& that) const Resources remaining = *this; foreach (const Resource& resource, that.resources) { if (!remaining._contains(resource)) { return false; remaining -= resource; return true; bool Resources::contains(const Resource& that) const return validate(that).isNone() && _contains(that); Resources Resources::filter( const lambda::function<bool(const Resource&)>& predicate) const Resources result; foreach (const Resource& resource, resources) { if (predicate(resource)) { result += resource; return result; hashmap<string, Resources> Resources::reserved() const hashmap<string, Resources> result; foreach (const Resource& resource, resources) { if (isReserved(resource)) { result[resource.role()] += resource; return result; Resources Resources::reserved(const string& role) const return filter(lambda::bind(isReserved, lambda::_1, role)); Resources Resources::unreserved() const return filter(isUnreserved); Resources Resources::persistentVolumes() const return filter(isPersistentVolume); Resources Resources::revocable() const return filter(isRevocable); Resources Resources::flatten( const string& role, const Option<Resource::ReservationInfo>& reservation) const Resources flattened; foreach (Resource resource, resources) { resource.set_role(role); if (reservation.isNone()) { resource.clear_reservation(); } else { resource.mutable_reservation()->CopyFrom(reservation.get()); flattened += resource; return flattened; static bool any(const Resource&) { return true; } Option<Resources> Resources::find(const Resource& target) const Resources found; Resources total = *this; Resources remaining = Resources(target).flatten(); vector<lambda::function<bool(const Resource&)>> predicates = { lambda::bind(isReserved, lambda::_1, target.role()), isUnreserved, any foreach (const auto& predicate, predicates) { foreach (const Resource& resource, total.filter(predicate)) { Resources flattened = Resources(resource).flatten(); if (flattened.contains(remaining)) { if (!resource.has_reservation()) { return found + remaining.flatten(resource.role()); } else { return found + remaining.flatten(resource.role(), resource.reservation()); } else if (remaining.contains(flattened)) { found += resource; total -= resource; remaining -= flattened; break; return None(); Option<Resources> Resources::find(const Resources& targets) const Resources total; foreach (const Resource& target, targets) { Option<Resources> found = find(target); if (found.isNone()) { return None(); total += found.get(); return total; Try<Resources> Resources::apply(const Offer::Operation& operation) const Resources result = *this; switch (operation.type()) { case Offer::Operation::LAUNCH: break; case Offer::Operation::RESERVE: { Option<Error> error = validate(operation.reserve().resources()); if (error.isSome()) { return Error("Invalid RESERVE Operation: " + error.get().message); foreach (const Resource& reserved, operation.reserve().resources()) { if (!Resources::isReserved(reserved)) { return Error("Invalid RESERVE Operation: Resource must be reserved"); } else if (!reserved.has_reservation()) { return Error("Invalid RESERVE Operation: Missing 'reservation'"); Resources unreserved = Resources(reserved).flatten(); if (!result.contains(unreserved)) { return Error("Invalid RESERVE Operation: " + stringify(result) + " does not contain " + stringify(unreserved)); result -= unreserved; result += reserved; break; case Offer::Operation::UNRESERVE: { Option<Error> error = validate(operation.unreserve().resources()); if (error.isSome()) { return Error("Invalid UNRESERVE Operation: " + error.get().message); foreach (const Resource& reserved, operation.unreserve().resources()) { if (!Resources::isReserved(reserved)) { return Error("Invalid UNRESERVE Operation: Resource is not reserved"); } else if (!reserved.has_reservation()) { return Error("Invalid UNRESERVE Operation: Missing 'reservation'"); if (!result.contains(reserved)) { return Error("Invalid UNRESERVE Operation: " + stringify(result) + " does not contain " + stringify(reserved)); Resources unreserved = Resources(reserved).flatten(); result -= reserved; result += unreserved; break; case Offer::Operation::CREATE: { Option<Error> error = validate(operation.create().volumes()); if (error.isSome()) { return Error("Invalid CREATE Operation: " + error.get().message); foreach (const Resource& volume, operation.create().volumes()) { if (!volume.has_disk()) { return Error("Invalid CREATE Operation: Missing 'disk'"); } else if (!volume.disk().has_persistence()) { return Error("Invalid CREATE Operation: Missing 'persistence'"); Resource stripped = volume; stripped.clear_disk(); if (!result.contains(stripped)) { return Error("Invalid CREATE Operation: Insufficient disk resources"); result -= stripped; result += volume; break; case Offer::Operation::DESTROY: { Option<Error> error = validate(operation.destroy().volumes()); if (error.isSome()) { return Error("Invalid DESTROY Operation: " + error.get().message); foreach (const Resource& volume, operation.destroy().volumes()) { if (!volume.has_disk()) { return Error("Invalid DESTROY Operation: Missing 'disk'"); } else if (!volume.disk().has_persistence()) { return Error("Invalid DESTROY Operation: Missing 'persistence'"); if (!result.contains(volume)) { return Error( "Invalid DESTROY Operation: Persistent volume does not exist"); Resource stripped = volume; stripped.clear_disk(); result -= volume; result += stripped; break; default: return Error("Unknown offer operation " + stringify(operation.type())); CHECK(result.cpus() == cpus() && result.mem() == mem() && result.disk() == disk() && result.ports() == ports()); return result; template <> Option<Value::Scalar> Resources::get(const string& name) 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 None(); template <> Option<Value::Set> Resources::get(const string& name) 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 None(); template <> Option<Value::Ranges> Resources::get(const string& name) 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 None(); Resources Resources::get(const string& name) const return filter([=](const Resource& resource) { return resource.name() == name; }); Resources Resources::scalars() const return filter([=](const Resource& resource) { return resource.type() == Value::SCALAR; }); set<string> Resources::names() const set<string> result; foreach (const Resource& resource, resources) { result.insert(resource.name()); return result; map<string, Value_Type> Resources::types() const map<string, Value_Type> result; foreach (const Resource& resource, resources) { result[resource.name()] = resource.type(); return result; Option<double> Resources::cpus() const Option<Value::Scalar> value = get<Value::Scalar>("cpus"); if (value.isSome()) { return value.get().value(); } else { return None(); Option<Bytes> Resources::mem() const Option<Value::Scalar> value = get<Value::Scalar>("mem"); if (value.isSome()) { return Megabytes(static_cast<uint64_t>(value.get().value())); } else { return None(); Option<Bytes> Resources::disk() const Option<Value::Scalar> value = get<Value::Scalar>("disk"); if (value.isSome()) { return Megabytes(static_cast<uint64_t>(value.get().value())); } else { return None(); Option<Value::Ranges> Resources::ports() const Option<Value::Ranges> value = get<Value::Ranges>("ports"); if (value.isSome()) { return value.get(); } else { return None(); Option<Value::Ranges> Resources::ephemeral_ports() const Option<Value::Ranges> value = get<Value::Ranges>("ephemeral_ports"); if (value.isSome()) { return value.get(); } else { return None(); bool Resources::_contains(const Resource& that) const foreach (const Resource& resource, resources) { if (internal::contains(resource, that)) { return true; return false; Resources::operator const google::protobuf::RepeatedPtrField<Resource>&() const return resources; bool Resources::operator==(const Resources& that) const return this->contains(that) && that.contains(*this); bool Resources::operator!=(const Resources& that) const return !(*this == that); Resources Resources::operator+(const Resource& that) const Resources result = *this; result += that; return result; Resources Resources::operator+(const Resources& that) const Resources result = *this; result += that; return result; Resources& Resources::operator+=(const Resource& that) if (validate(that).isNone() && !isEmpty(that)) { bool found = false; foreach (Resource& resource, resources) { if (internal::addable(resource, that)) { resource += that; found = true; break; if (!found) { resources.Add()->CopyFrom(that); return *this; 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 = *this; result -= that; return result; Resources Resources::operator-(const Resources& that) const Resources result = *this; result -= that; return result; Resources& Resources::operator-=(const Resource& that) if (validate(that).isNone() && !isEmpty(that)) { for (int i = 0; i < resources.size(); i++) { Resource* resource = resources.Mutable(i); if (internal::subtractable(*resource, that)) { *resource -= that; if (validate(*resource).isSome() || isEmpty(*resource)) { resources.DeleteSubrange(i, 1); break; return *this; Resources& Resources::operator-=(const Resources& that) foreach (const Resource& resource, that.resources) { *this -= resource; return *this; ostream& operator<<(ostream& stream, const Volume& volume) string volumeConfig = volume.container_path(); if (volume.has_host_path()) { volumeConfig = volume.host_path() + ":" + volumeConfig; if (volume.has_mode()) { switch (volume.mode()) { case Volume::RW: volumeConfig += ":rw"; break; case Volume::RO: volumeConfig += ":ro"; break; default: LOG(FATAL) << "Unknown Volume mode: " << volume.mode(); break; stream << volumeConfig; return stream; ostream& operator<<(ostream& stream, const Resource::DiskInfo& disk) if (disk.has_persistence()) { stream << disk.persistence().id(); if (disk.has_volume()) { stream << ":" << disk.volume(); return stream; ostream& operator<<(ostream& stream, const Resource& resource) stream << resource.name(); stream << "(" << resource.role(); if (resource.has_reservation()) { stream << ", " << resource.reservation().principal(); stream << ")"; if (resource.has_disk()) { stream << "[" << resource.disk() << "]"; if (resource.has_revocable()) { stream << "{REV}"; stream << ":"; 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 stream; ostream& operator<<(ostream& stream, const Resources& resources) Resources::const_iterator it = resources.begin(); while (it != resources.end()) { stream << *it; if (++it != resources.end()) { stream << "; "; return stream; src/v1/resources.cpp(1007) src/common/resources.cpp(995) if (value.isSome()) { return Megabytes(static_cast<uint64_t>(value.get().value())); } else { return None(); src/v1/resources.cpp(1029) src/common/resources.cpp(1017) if (value.isSome()) { return value.get(); } else { return None(); src/v1/resources.cpp(910) src/common/resources.cpp(887) found = true; if (found) { return total; return None(); template <> src/v1/resources.cpp(932) src/common/resources.cpp(909) found = true; if (found) { return total; return None(); src/v1/resources.cpp(197) src/common/resources.cpp(145) if (left.name() != right.name() || left.type() != right.type() || left.role() != right.role()) { return false; if (left.has_reservation() != right.has_reservation()) { return false; if (left.has_reservation() && left.reservation() != right.reservation()) { return false; if (left.has_disk() != right.has_disk()) { return false; if (left.has_disk() && left.disk() != right.disk()) { return false; src/v1/resources.cpp(224) src/common/resources.cpp(174) return false; if (left.has_revocable() != right.has_revocable()) { return false; return true; src/v1/resources.cpp(932) src/common/resources.cpp(887) found = true; if (found) { return total; return None(); src/v1/resources.cpp(146) src/common/resources.cpp(91) if (left.name() != right.name() || left.type() != right.type() || left.role() != right.role()) { return false; if (left.has_reservation() != right.has_reservation()) { return false; if (left.has_reservation() && left.reservation() != right.reservation()) { return false; if (left.has_disk() != right.has_disk()) { return false; if (left.has_disk() && left.disk() != right.disk()) { return false; src/v1/resources.cpp(197) src/common/resources.cpp(91) if (left.name() != right.name() || left.type() != right.type() || left.role() != right.role()) { return false; if (left.has_reservation() != right.has_reservation()) { return false; if (left.has_reservation() && left.reservation() != right.reservation()) { return false; if (left.has_disk() != right.has_disk()) { return false; if (left.has_disk() && left.disk() != right.disk()) { return false; src/v1/resources.cpp(996) src/common/resources.cpp(1006) if (value.isSome()) { return Megabytes(static_cast<uint64_t>(value.get().value())); } else { return None(); src/v1/resources.cpp(1018) src/common/resources.cpp(1028) if (value.isSome()) { return value.get(); } else { return None(); src/v1/resources.cpp(888) src/common/resources.cpp(909) found = true; if (found) { return total; return None(); template <> src/v1/resources.cpp(910) src/common/resources.cpp(931) found = true; if (found) { return total; return None(); src/v1/resources.cpp(146) src/common/resources.cpp(196) if (left.name() != right.name() || left.type() != right.type() || left.role() != right.role()) { return false; if (left.has_reservation() != right.has_reservation()) { return false; if (left.has_reservation() && left.reservation() != right.reservation()) { return false; if (left.has_disk() != right.has_disk()) { return false; if (left.has_disk() && left.disk() != right.disk()) { return false; src/v1/resources.cpp(175) src/common/resources.cpp(223) return false; if (left.has_revocable() != right.has_revocable()) { return false; return true; src/v1/resources.cpp(888) src/common/resources.cpp(931) found = true; if (found) { return total; return None(); src/v1/resources.cpp(92) src/common/resources.cpp(145) if (left.name() != right.name() || left.type() != right.type() || left.role() != right.role()) { return false; if (left.has_reservation() != right.has_reservation()) { return false; if (left.has_reservation() && left.reservation() != right.reservation()) { return false; if (left.has_disk() != right.has_disk()) { return false; if (left.has_disk() && left.disk() != right.disk()) { return false; src/v1/resources.cpp(92) src/common/resources.cpp(196) if (left.name() != right.name() || left.type() != right.type() || left.role() != right.role()) { return false; if (left.has_reservation() != right.has_reservation()) { return false; if (left.has_reservation() && left.reservation() != right.reservation()) { return false; if (left.has_disk() != right.has_disk()) { return false; if (left.has_disk() && left.disk() != right.disk()) { return false; src/v1/values.cpp(41) src/common/attributes.cpp(29) using std::ostream; using std::string; using std::vector; namespace mesos { src/v1/values.cpp(310) src/common/type_utils.cpp(272) found = true; break; if (!found) { return false; return true; src/v1/values.cpp(310) src/common/type_utils.cpp(242) found = true; break; if (!found) { return false; return true; src/v1/values.cpp(310) src/common/type_utils.cpp(208) found = true; break; if (!found) { return false; src/v1/values.cpp(310) src/common/type_utils.cpp(181) found = true; break; if (!found) { return false; src/v1/values.cpp(409) src/common/type_utils.cpp(272) found = true; break; if (!found) { return false; return true; src/v1/values.cpp(310) src/common/type_utils.cpp(163) found = true; break; if (!found) { return false; src/v1/values.cpp(434) src/common/type_utils.cpp(272) found = true; break; if (!found) { return false; return true; src/v1/values.cpp(409) src/common/type_utils.cpp(242) found = true; break; if (!found) { return false; return true; src/v1/values.cpp(434) src/common/type_utils.cpp(242) found = true; break; if (!found) { return false; return true; src/v1/values.cpp(409) src/common/type_utils.cpp(208) found = true; break; if (!found) { return false; src/v1/values.cpp(310) src/common/type_utils.cpp(106) found = true; break; if (!found) { return false; return true; src/v1/values.cpp(434) src/common/type_utils.cpp(208) found = true; break; if (!found) { return false; src/v1/values.cpp(409) src/common/type_utils.cpp(181) found = true; break; if (!found) { return false; src/v1/values.cpp(409) src/common/type_utils.cpp(163) found = true; break; if (!found) { return false; src/v1/values.cpp(434) src/common/type_utils.cpp(181) found = true; break; if (!found) { return false; src/v1/values.cpp(310) src/common/type_utils.cpp(41) found = true; break; if (!found) { return false; src/v1/values.cpp(434) src/common/type_utils.cpp(163) found = true; break; if (!found) { return false; src/v1/values.cpp(409) src/common/type_utils.cpp(106) found = true; break; if (!found) { return false; return true; src/v1/values.cpp(434) src/common/type_utils.cpp(106) found = true; break; if (!found) { return false; return true; src/v1/values.cpp(409) src/common/type_utils.cpp(41) found = true; break; if (!found) { return false; src/v1/values.cpp(434) src/common/type_utils.cpp(41) found = true; break; if (!found) { return false; src/v1/values.cpp(18) src/common/values.cpp(18) #include <stdint.h> #include <algorithm> #include <initializer_list> #include <ostream> #include <string> #include <tuple> #include <utility> #include <vector> #include <glog/logging.h> #include <boost/lexical_cast.hpp> src/v1/values.cpp(35) src/common/values.cpp(35) #include <stout/error.hpp> #include <stout/foreach.hpp> #include <stout/strings.hpp> using std::max; using std::min; using std::ostream; using std::string; using std::vector; namespace mesos { src/v1/values.cpp(48) src/common/values.cpp(47) ostream& operator<<(ostream& stream, const Value::Scalar& scalar) return stream << scalar.value(); bool operator==(const Value::Scalar& left, const Value::Scalar& right) return left.value() == right.value(); bool operator<=(const Value::Scalar& left, const Value::Scalar& right) return left.value() <= right.value(); Value::Scalar operator+(const Value::Scalar& left, const Value::Scalar& right) Value::Scalar result; result.set_value(left.value() + right.value()); return result; Value::Scalar operator-(const Value::Scalar& left, const Value::Scalar& right) Value::Scalar result; result.set_value(left.value() - right.value()); return result; Value::Scalar& operator+=(Value::Scalar& left, const Value::Scalar& right) left.set_value(left.value() + right.value()); return left; Value::Scalar& operator-=(Value::Scalar& left, const Value::Scalar& right) left.set_value(left.value() - right.value()); return left; namespace internal { struct Range uint64_t start; uint64_t end; void coalesce(Value::Ranges* result, vector<Range> ranges) if (ranges.empty()) { result->clear_range(); return; std::sort( ranges.begin(), ranges.end(), [](const Range& left, const Range& right) { return std::tie(left.start, left.end) < std::tie(right.start, right.end); }); CHECK(!ranges.empty()); int count = 1; Range current = ranges.front(); foreach (const Range& range, ranges) { if (range.start == current.start && range.end == current.end) { continue; if (range.start == current.start && range.end > current.end) { current.end = range.end; } else if (range.start > current.start) { if (range.start <= current.end + 1) { current.end = max(current.end, range.end); } else { ranges[count - 1] = current; ++count; current = range; ranges[count - 1] = current; CHECK(count <= static_cast<int>(ranges.size())); if (count < result->range_size()) { result->mutable_range()->DeleteSubrange( count, result->range_size() - count); result->mutable_range()->Reserve(count); for (int i = 0; i < count; ++i) { if (i >= result->range_size()) { result->add_range(); CHECK(i < result->range_size()); result->mutable_range(i)->set_begin(ranges[i].start); result->mutable_range(i)->set_end(ranges[i].end); CHECK_EQ(result->range_size(), count); void coalesce( Value::Ranges* result, std::initializer_list<Value::Ranges> addedRanges) size_t rangesSum = result->range_size(); foreach (const Value::Ranges& range, addedRanges) { rangesSum += range.range_size(); vector<internal::Range> ranges; ranges.reserve(rangesSum); auto fill = [&ranges](const Value::Ranges& inputs) { foreach (const Value::Range& range, inputs.range()) { ranges.push_back({range.begin(), range.end()}); fill(*result); foreach (const Value::Ranges& range, addedRanges) { fill(range); internal::coalesce(result, std::move(ranges)); void coalesce(Value::Ranges* result) coalesce(result, {Value::Ranges()}); void coalesce(Value::Ranges* result, const Value::Range& addedRange) Value::Ranges ranges; Value::Range* range = ranges.add_range(); range->CopyFrom(addedRange); coalesce(result, {ranges}); static void remove(Value::Ranges* _ranges, const Value::Range& removal) vector<internal::Range> ranges; ranges.reserve(_ranges->range_size()); foreach (const Value::Range& range, _ranges->range()) { if (range.begin() >= removal.begin() && range.end() <= removal.end()) { continue; if (range.begin() < removal.begin() && range.end() > removal.end()) { ranges.emplace_back(internal::Range{range.begin(), removal.begin() - 1}); ranges.emplace_back(internal::Range{removal.end() + 1, range.end()}); if (range.end() < removal.begin() || range.begin() > removal.end()) { ranges.emplace_back(internal::Range{range.begin(), range.end()}); } else { if (range.end() > removal.end()) { ranges.emplace_back(internal::Range{removal.end() + 1, range.end()}); } else { CHECK(range.begin() < removal.begin()); ranges.emplace_back( internal::Range{range.begin(), removal.begin() - 1}); internal::coalesce(_ranges, std::move(ranges)); ostream& operator<<(ostream& stream, const Value::Ranges& ranges) stream << "["; for (int i = 0; i < ranges.range_size(); i++) { stream << ranges.range(i).begin() << "-" << ranges.range(i).end(); if (i + 1 < ranges.range_size()) { stream << ", "; stream << "]"; return stream; bool operator==(const Value::Ranges& _left, const Value::Ranges& _right) Value::Ranges left; coalesce(&left, {_left}); Value::Ranges right; coalesce(&right, {_right}); if (left.range_size() == right.range_size()) { for (int i = 0; i < left.range_size(); i++) { bool found = false; for (int j = 0; j < right.range_size(); j++) { if (left.range(i).begin() == right.range(j).begin() && left.range(i).end() == right.range(j).end()) { found = true; break; if (!found) { return false; return true; return false; bool operator<=(const Value::Ranges& _left, const Value::Ranges& _right) Value::Ranges left; coalesce(&left, {_left}); Value::Ranges right; coalesce(&right, {_right}); for (int i = 0; i < left.range_size(); i++) { bool matched = false; for (int j = 0; j < right.range_size(); j++) { if (left.range(i).begin() >= right.range(j).begin() && left.range(i).end() <= right.range(j).end()) { matched = true; break; if (!matched) { return false; return true; Value::Ranges operator+(const Value::Ranges& left, const Value::Ranges& right) Value::Ranges result; coalesce(&result, {left, right}); return result; Value::Ranges operator-(const Value::Ranges& left, const Value::Ranges& right) Value::Ranges result; coalesce(&result, {left}); return result -= right; Value::Ranges& operator+=(Value::Ranges& left, const Value::Ranges& right) coalesce(&left, {right}); return left; Value::Ranges& operator-=(Value::Ranges& left, const Value::Ranges& right) coalesce(&left); for (int i = 0; i < right.range_size(); ++i) { remove(&left, right.range(i)); return left; ostream& operator<<(ostream& stream, const Value::Set& set) stream << "{"; for (int i = 0; i < set.item_size(); i++) { stream << set.item(i); if (i + 1 < set.item_size()) { stream << ", "; stream << "}"; return stream; bool operator==(const Value::Set& left, const Value::Set& right) if (left.item_size() == right.item_size()) { for (int i = 0; i < left.item_size(); i++) { bool found = false; for (int j = 0; j < right.item_size(); j++) { if (left.item(i) == right.item(i)) { found = true; break; if (!found) { return false; return true; return false; bool operator<=(const Value::Set& left, const Value::Set& right) if (left.item_size() <= right.item_size()) { for (int i = 0; i < left.item_size(); i++) { bool found = false; for (int j = 0; j < right.item_size(); j++) { if (left.item(i) == right.item(j)) { found = true; break; if (!found) { return false; return true; return false; Value::Set operator+(const Value::Set& left, const Value::Set& right) Value::Set result; for (int i = 0; i < left.item_size(); i++) { result.add_item(left.item(i)); for (int i = 0; i < right.item_size(); i++) { bool found = false; for (int j = 0; j < result.item_size(); j++) { if (right.item(i) == result.item(j)) { found = true; break; if (!found) { result.add_item(right.item(i)); return result; Value::Set operator-(const Value::Set& left, const Value::Set& right) Value::Set result; for (int i = 0; i < left.item_size(); i++) { bool found = false; for (int j = 0; j < right.item_size(); j++) { if (left.item(i) == right.item(j)) { found = true; break; if (!found) { result.add_item(left.item(i)); return result; Value::Set& operator+=(Value::Set& left, const Value::Set& right) for (int i = 0; i < right.item_size(); i++) { bool found = false; for (int j = 0; j < left.item_size(); j++) { if (right.item(i) == left.item(j)) { found = true; break; if (!found) { left.add_item(right.item(i)); return left; Value::Set& operator-=(Value::Set& left, const Value::Set& right) for (int i = 0; i < right.item_size(); i++) { for (int j = 0; j < left.item_size(); j++) { if (right.item(i) == left.item(j)) { left.mutable_item()->DeleteSubrange(j, 1); break; return left; ostream& operator<<(ostream& stream, const Value::Text& value) return stream << value.value(); bool operator==(const Value::Text& left, const Value::Text& right) return left.value() == right.value(); namespace internal { namespace values { Try<Value> parse(const string& text) Value value; string temp; foreach (const char c, text) { if (c != ' ') { temp += c; if (temp.length() == 0) { return Error("Expecting non-empty string"); if (!strings::checkBracketsMatching(temp, '{', '}') || !strings::checkBracketsMatching(temp, '[', ']') || !strings::checkBracketsMatching(temp, '(', ')')) { return Error("Mismatched brackets"); size_t index = temp.find('['); if (index == 0) { value.set_type(Value::RANGES); Value::Ranges* ranges = value.mutable_ranges(); const vector<string>& tokens = strings::tokenize(temp, "[]-,\n"); if (tokens.size() % 2 != 0) { return Error("Expecting one or more \"ranges\""); } else { for (size_t i = 0; i < tokens.size(); i += 2) { Value::Range* range = ranges->add_range(); int j = i; try { range->set_begin(boost::lexical_cast<uint64_t>((tokens[j++]))); range->set_end(boost::lexical_cast<uint64_t>(tokens[j++])); } catch (const boost::bad_lexical_cast&) { return Error( "Expecting non-negative integers in '" + tokens[j - 1] + "'"); coalesce(ranges); return value; } else if (index == string::npos) { size_t index = temp.find('{'); if (index == 0) { value.set_type(Value::SET); Value::Set* set = value.mutable_set(); const vector<string>& tokens = strings::tokenize(temp, "{},\n"); for (size_t i = 0; i < tokens.size(); i++) { set->add_item(tokens[i]); return value; } else if (index == string::npos) { try { value.set_type(Value::SCALAR); Value::Scalar* scalar = value.mutable_scalar(); scalar->set_value(boost::lexical_cast<double>(temp)); return value; } catch (const boost::bad_lexical_cast&) { value.set_type(Value::TEXT); Value::Text* text = value.mutable_text(); text->set_value(temp); return value; } else { return Error("Unexpected '{' found"); return Error("Unexpected '[' found"); src/v1/values.cpp(434) src/common/values.cpp(409) found = true; break; if (!found) { return false; return true; return false; src/v1/values.cpp(329) src/common/values.cpp(297) Value::Ranges left; coalesce(&left, {_left}); Value::Ranges right; coalesce(&right, {_right}); src/v1/values.cpp(483) src/common/values.cpp(429) for (int i = 0; i < left.item_size(); i++) { bool found = false; for (int j = 0; j < right.item_size(); j++) { if (left.item(i) == right.item(j)) { found = true; break; if (!found) { src/v1/values.cpp(409) src/common/values.cpp(310) found = true; break; if (!found) { return false; return true; return false; src/v1/values.cpp(434) src/common/values.cpp(310) found = true; break; if (!found) { return false; return true; return false; src/v1/values.cpp(409) src/common/values.cpp(434) found = true; break; if (!found) { return false; return true; return false; src/v1/values.cpp(297) src/common/values.cpp(329) Value::Ranges left; coalesce(&left, {_left}); Value::Ranges right; coalesce(&right, {_right}); src/v1/values.cpp(429) src/common/values.cpp(483) for (int i = 0; i < left.item_size(); i++) { bool found = false; for (int j = 0; j < right.item_size(); j++) { if (left.item(i) == right.item(j)) { found = true; break; if (!found) { src/v1/values.cpp(310) src/common/values.cpp(409) found = true; break; if (!found) { return false; return true; return false; src/v1/values.cpp(310) src/common/values.cpp(434) found = true; break; if (!found) { return false; return true; return false; src/common/attributes.cpp(29) src/common/values.cpp(41) using std::ostream; using std::string; using std::vector; namespace mesos { src/common/http.cpp(37) src/common/resources.cpp(37) using std::set; using std::string; using std::vector; namespace mesos { src/common/type_utils.cpp(272) src/common/values.cpp(310) found = true; break; if (!found) { return false; return true; src/common/type_utils.cpp(242) src/common/values.cpp(310) found = true; break; if (!found) { return false; return true; src/common/type_utils.cpp(208) src/common/values.cpp(310) found = true; break; if (!found) { return false; src/common/type_utils.cpp(181) src/common/values.cpp(310) found = true; break; if (!found) { return false; src/common/type_utils.cpp(272) src/common/values.cpp(409) found = true; break; if (!found) { return false; return true; src/common/type_utils.cpp(163) src/common/values.cpp(310) found = true; break; if (!found) { return false; src/common/type_utils.cpp(272) src/common/values.cpp(434) found = true; break; if (!found) { return false; return true; src/common/type_utils.cpp(242) src/common/values.cpp(409) found = true; break; if (!found) { return false; return true; src/common/type_utils.cpp(242) src/common/values.cpp(434) found = true; break; if (!found) { return false; return true; src/common/type_utils.cpp(208) src/common/values.cpp(409) found = true; break; if (!found) { return false; src/common/type_utils.cpp(106) src/common/values.cpp(310) found = true; break; if (!found) { return false; return true; src/common/type_utils.cpp(208) src/common/values.cpp(434) found = true; break; if (!found) { return false; src/common/type_utils.cpp(181) src/common/values.cpp(409) found = true; break; if (!found) { return false; src/common/type_utils.cpp(163) src/common/values.cpp(409) found = true; break; if (!found) { return false; src/common/type_utils.cpp(181) src/common/values.cpp(434) found = true; break; if (!found) { return false; src/common/type_utils.cpp(41) src/common/values.cpp(310) found = true; break; if (!found) { return false; src/common/type_utils.cpp(163) src/common/values.cpp(434) found = true; break; if (!found) { return false; src/common/type_utils.cpp(106) src/common/values.cpp(409) found = true; break; if (!found) { return false; return true; src/common/type_utils.cpp(106) src/common/values.cpp(434) found = true; break; if (!found) { return false; return true; src/common/type_utils.cpp(41) src/common/values.cpp(409) found = true; break; if (!found) { return false; src/common/type_utils.cpp(41) src/common/values.cpp(434) found = true; break; if (!found) { return false; Configuration: Number of files: 13 Minimal block size: 4 Minimal characters in line: 3 Ignore preprocessor directives: 0 Ignore same filenames: 0 Results: Lines of code: 2910 Duplicate lines of code: 1980 Total 174 duplicate block(s) found. Time: 0.043474 seconds {code} > Merge duplicated code of Http V1 > -------------------------------- > > Key: MESOS-3404 > URL: https://issues.apache.org/jira/browse/MESOS-3404 > Project: Mesos > Issue Type: Bug > Components: HTTP API > Reporter: Klaus Ma > > After HTTP v1, there is a directory {{src/v1}} including all HTTP v1 related > code; but there some duplicated logic/code. The target of this ticket is to > draft a design to merge them. Refer to the following diff as an example: > {code} > klaus@klaus-ThinkPad-T420:~/Workspace/mesos-3063$ diff src/v1/values.cpp > src/common/values.cpp > 28,29c28,29 > < #include <mesos/v1/resources.hpp> > < #include <mesos/v1/values.hpp> > --- > > #include <mesos/resources.hpp> > > #include <mesos/values.hpp> > 42d41 > < namespace v1 { > 587d585 > < } // namespace v1 { > {code} -- This message was sent by Atlassian JIRA (v6.3.4#6332)