blob: b3a4413ca8e55d2462cd2af4e105a2019b87a80a [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __MESOS_TYPE_UTILS_H__
#define __MESOS_TYPE_UTILS_H__
#include <iosfwd>
#include <string>
#include <vector>
#include <boost/functional/hash.hpp>
#include <google/protobuf/map.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/util/message_differencer.h>
#include <mesos/mesos.hpp>
#include <stout/option.hpp>
#include <stout/stringify.hpp>
#include <stout/strings.hpp>
#include <stout/uuid.hpp>
// This file includes definitions for operators on public protobuf
// classes (defined in mesos.proto, module.proto, etc.) that don't
// have these operators generated by the protobuf compiler. The
// corresponding definitions are in src/common/type_utils.cpp.
//
// Mesos modules need some of the protobuf classes defined in
// mesos.proto, module.proto, etc., and require some of these
// operators declared in type_utils.hpp. Exposing type_utils.hpp
// allows us to build modules without having a dependency on mesos
// source tree (src/*).
namespace mesos {
bool operator==(const CheckStatusInfo& left, const CheckStatusInfo& right);
bool operator==(const CommandInfo& left, const CommandInfo& right);
bool operator==(const CommandInfo::URI& left, const CommandInfo::URI& right);
bool operator==(const ContainerID& left, const ContainerID& right);
bool operator==(const ContainerInfo& left, const ContainerInfo& right);
bool operator==(const Credential& left, const Credential& right);
bool operator==(const CSIPluginInfo& left, const CSIPluginInfo& right);
bool operator==(
const CSIPluginContainerInfo& left,
const CSIPluginContainerInfo& right);
bool operator==(const DiscoveryInfo& left, const DiscoveryInfo& right);
bool operator==(const Environment& left, const Environment& right);
bool operator==(const ExecutorInfo& left, const ExecutorInfo& right);
bool operator==(const HealthCheck& left, const HealthCheck& right);
bool operator==(const KillPolicy& left, const KillPolicy& right);
bool operator==(const Label& left, const Label& right);
bool operator==(const Labels& left, const Labels& right);
bool operator==(const MasterInfo& left, const MasterInfo& right);
bool operator==(const Offer::Operation& left, const Offer::Operation& right);
bool operator==(const Operation& left, const Operation& right);
bool operator==(const OperationStatus& left, const OperationStatus& right);
bool operator==(
const ResourceProviderInfo& left,
const ResourceProviderInfo& right);
bool operator==(
const ResourceStatistics& left,
const ResourceStatistics& right);
bool operator==(const SlaveInfo& left, const SlaveInfo& right);
bool operator==(const Task& left, const Task& right);
bool operator==(const TaskGroupInfo& left, const TaskGroupInfo& right);
bool operator==(const TaskInfo& left, const TaskInfo& right);
bool operator==(const TaskStatus& left, const TaskStatus& right);
bool operator==(const URL& left, const URL& right);
bool operator==(const UUID& left, const UUID& right);
bool operator==(const Volume& left, const Volume& right);
bool operator==(
const Volume::Source::CSIVolume::VolumeCapability& left,
const Volume::Source::CSIVolume::VolumeCapability& right);
bool operator!=(const CheckStatusInfo& left, const CheckStatusInfo& right);
bool operator!=(const ExecutorInfo& left, const ExecutorInfo& right);
bool operator!=(const Labels& left, const Labels& right);
bool operator!=(const Offer::Operation& left, const Offer::Operation& right);
bool operator!=(const Operation& left, const Operation& right);
bool operator!=(const OperationStatus& left, const OperationStatus& right);
bool operator!=(const TaskStatus& left, const TaskStatus& right);
bool operator!=(
const Volume::Source::CSIVolume::VolumeCapability& left,
const Volume::Source::CSIVolume::VolumeCapability& right);
inline bool operator==(const ExecutorID& left, const ExecutorID& right)
{
return left.value() == right.value();
}
inline bool operator==(const FrameworkID& left, const FrameworkID& right)
{
return left.value() == right.value();
}
// This operator, which was comparing only `user` and `name` fields,
// has been deleted in favor of `typeutils::equivalent()` function (see below)
// with different semantics.
bool operator==(const FrameworkInfo& left, const FrameworkInfo& right) = delete;
namespace typeutils {
// Returns whether two `FrameworkInfo`s are equivalent for framework
// subscription purposes or not (i.e. whether subscribing a framework with the
// `left` should have the same effects as with the `right`).
bool equivalent(const FrameworkInfo& left, const FrameworkInfo& right);
// Performs the same comparison as `equivalent()` and returns a human-readable
// diff if the `FrameworkInfo`s are not equivalnt.
Option<std::string> diff(const FrameworkInfo& left, const FrameworkInfo& right);
} // namespace typeutils {
inline bool operator==(const OfferID& left, const OfferID& right)
{
return left.value() == right.value();
}
inline bool operator==(const OperationID& left, const OperationID& right)
{
return left.value() == right.value();
}
inline bool operator==(
const ResourceProviderID& left,
const ResourceProviderID& right)
{
return left.value() == right.value();
}
inline bool operator==(const SlaveID& left, const SlaveID& right)
{
return left.value() == right.value();
}
inline bool operator==(const TaskID& left, const TaskID& right)
{
return left.value() == right.value();
}
inline bool operator==(const TimeInfo& left, const TimeInfo& right)
{
return left.nanoseconds() == right.nanoseconds();
}
inline bool operator==(const DurationInfo& left, const DurationInfo& right)
{
return left.nanoseconds() == right.nanoseconds();
}
inline bool operator==(const ContainerID& left, const std::string& right)
{
return left.value() == right;
}
inline bool operator==(const ExecutorID& left, const std::string& right)
{
return left.value() == right;
}
inline bool operator==(const FrameworkID& left, const std::string& right)
{
return left.value() == right;
}
inline bool operator==(const OfferID& left, const std::string& right)
{
return left.value() == right;
}
inline bool operator==(const SlaveID& left, const std::string& right)
{
return left.value() == right;
}
inline bool operator==(const TaskID& left, const std::string& right)
{
return left.value() == right;
}
inline bool operator==(
const DomainInfo::FaultDomain::RegionInfo& left,
const DomainInfo::FaultDomain::RegionInfo& right)
{
return left.name() == right.name();
}
inline bool operator==(
const DomainInfo::FaultDomain::ZoneInfo& left,
const DomainInfo::FaultDomain::ZoneInfo& right)
{
return left.name() == right.name();
}
inline bool operator==(
const DomainInfo::FaultDomain& left,
const DomainInfo::FaultDomain& right)
{
return left.region() == right.region() && left.zone() == right.zone();
}
inline bool operator==(const DomainInfo& left, const DomainInfo& right)
{
return left.fault_domain() == right.fault_domain();
}
inline bool operator==(const DrainInfo& left, const DrainInfo& right)
{
return google::protobuf::util::MessageDifferencer::Equals(left, right);
}
inline bool operator==(const DrainConfig& left, const DrainConfig& right)
{
return google::protobuf::util::MessageDifferencer::Equals(left, right);
}
/**
* For machines to match, both the `hostname` and `ip` must be equivalent.
* Hostname is not case sensitive, so it is lowercased before comparison.
*/
inline bool operator==(const MachineID& left, const MachineID& right)
{
// NOTE: Both fields default to the empty string if they are not specified,
// so the string comparisons are safe.
return left.has_hostname() == right.has_hostname() &&
strings::lower(left.hostname()) == strings::lower(right.hostname()) &&
left.has_ip() == right.has_ip() &&
left.ip() == right.ip();
}
inline bool operator!=(const ContainerID& left, const ContainerID& right)
{
return !(left == right);
}
inline bool operator!=(
const CSIPluginContainerInfo& left,
const CSIPluginContainerInfo& right)
{
return !(left == right);
}
inline bool operator!=(const ExecutorID& left, const ExecutorID& right)
{
return left.value() != right.value();
}
inline bool operator!=(const FrameworkID& left, const FrameworkID& right)
{
return left.value() != right.value();
}
inline bool operator!=(const OperationID& left, const OperationID& right)
{
return left.value() != right.value();
}
inline bool operator!=(
const ResourceProviderID& left,
const ResourceProviderID& right)
{
return left.value() != right.value();
}
inline bool operator!=(const SlaveID& left, const SlaveID& right)
{
return left.value() != right.value();
}
inline bool operator!=(
const ResourceProviderInfo& left,
const ResourceProviderInfo& right)
{
return !(left == right);
}
inline bool operator!=(const TimeInfo& left, const TimeInfo& right)
{
return !(left == right);
}
inline bool operator!=(const UUID& left, const UUID& right)
{
return !(left == right);
}
inline bool operator!=(const DurationInfo& left, const DurationInfo& right)
{
return !(left == right);
}
inline bool operator!=(
const DomainInfo::FaultDomain::RegionInfo& left,
const DomainInfo::FaultDomain::RegionInfo& right)
{
return left.name() != right.name();
}
inline bool operator<(const ContainerID& left, const ContainerID& right)
{
return left.value() < right.value();
}
inline bool operator<(const DurationInfo& left, const DurationInfo& right)
{
return left.nanoseconds() < right.nanoseconds();
}
inline bool operator<(const ExecutorID& left, const ExecutorID& right)
{
return left.value() < right.value();
}
inline bool operator<(const FrameworkID& left, const FrameworkID& right)
{
return left.value() < right.value();
}
inline bool operator<(const OfferID& left, const OfferID& right)
{
return left.value() < right.value();
}
inline bool operator<(const SlaveID& left, const SlaveID& right)
{
return left.value() < right.value();
}
inline bool operator<(const TaskID& left, const TaskID& right)
{
return left.value() < right.value();
}
std::ostream& operator<<(
std::ostream& stream,
const CapabilityInfo& capabilityInfo);
std::ostream& operator<<(
std::ostream& stream,
const DeviceWhitelist& deviceWhitelist);
std::ostream& operator<<(
std::ostream& stream,
const CheckStatusInfo& checkStatusInfo);
std::ostream& operator<<(std::ostream& stream, const CommandInfo& commandInfo);
std::ostream& operator<<(std::ostream& stream, const ContainerID& containerId);
std::ostream& operator<<(
std::ostream& stream,
const ContainerInfo& containerInfo);
std::ostream& operator<<(std::ostream& stream, const DomainInfo& domainInfo);
std::ostream& operator<<(std::ostream& stream, const DrainConfig& drainConfig);
std::ostream& operator<<(std::ostream& stream, const DrainState& state);
std::ostream& operator<<(std::ostream& stream, const Environment& environment);
std::ostream& operator<<(std::ostream& stream, const ExecutorID& executorId);
std::ostream& operator<<(std::ostream& stream, const ExecutorInfo& executor);
std::ostream& operator<<(std::ostream& stream, const FrameworkID& frameworkId);
std::ostream& operator<<(std::ostream& stream, const MasterInfo& master);
std::ostream& operator<<(std::ostream& stream, const OfferID& offerId);
std::ostream& operator<<(std::ostream& stream, const OperationID& operationId);
std::ostream& operator<<(std::ostream& stream, const OperationState& state);
std::ostream& operator<<(std::ostream& stream, const Operation& operation);
std::ostream& operator<<(std::ostream& stream, const RateLimits& limits);
std::ostream& operator<<(
std::ostream& stream,
const ResourceProviderID& resourceProviderId);
std::ostream& operator<<(
std::ostream& stream,
const ResourceProviderInfo& resourceProviderInfo);
std::ostream& operator<<(std::ostream& stream, const RLimitInfo& rlimitInfo);
std::ostream& operator<<(std::ostream& stream, const SlaveID& slaveId);
std::ostream& operator<<(std::ostream& stream, const SlaveInfo& slave);
std::ostream& operator<<(std::ostream& stream, const TaskID& taskId);
std::ostream& operator<<(std::ostream& stream, const MachineID& machineId);
std::ostream& operator<<(std::ostream& stream, const TaskInfo& task);
std::ostream& operator<<(std::ostream& stream, const TaskState& state);
std::ostream& operator<<(
std::ostream& stream,
const UUID& uuid);
std::ostream& operator<<(std::ostream& stream, const CheckInfo::Type& type);
std::ostream& operator<<(
std::ostream& stream,
const CSIPluginContainerInfo::Service& service);
std::ostream& operator<<(
std::ostream& stream,
const FrameworkInfo::Capability& capability);
std::ostream& operator<<(std::ostream& stream, const Image::Type& imageType);
std::ostream& operator<<(std::ostream& stream, const Secret::Type& secretType);
std::ostream& operator<<(
std::ostream& stream,
const Offer::Operation::Type& operationType);
std::ostream& operator<<(
std::ostream& stream,
const Resource::DiskInfo::Source::Type& sourceType);
template <typename T>
inline std::ostream& operator<<(
std::ostream& stream,
const std::vector<T>& messages)
{
stream << "[ ";
for (auto it = messages.begin(); it != messages.end(); ++it) {
if (it != messages.begin()) {
stream << ", ";
}
stream << *it;
}
stream << " ]";
return stream;
}
} // namespace mesos {
/**
* Type utilities for the protobuf library that are not specific to particular
* protobuf classes. They are defined in the `google::protobuf` namespace for
* argument-dependent lookup.
*/
namespace google {
namespace protobuf {
template <typename Key, typename Value>
inline bool operator==(
const Map<Key, Value>& left, const Map<Key, Value>& right)
{
if (left.size() != right.size()) {
return false;
}
for (auto it = left.begin(); it != left.end(); ++it) {
auto found = right.find(it->first);
if (found == right.end() || found->second != it->second) {
return false;
}
}
return true;
}
template <typename Key, typename Value>
inline bool operator!=(
const Map<Key, Value>& left, const Map<Key, Value>& right)
{
return !(left == right);
}
template <typename Key, typename Value>
inline std::ostream& operator<<(
std::ostream& stream, const Map<Key, Value>& map)
{
stream << "{ ";
for (auto it = map.cbegin(); it != map.end(); ++it) {
if (it != map.cbegin()) {
stream << ", ";
}
stream << it->first << ": " << it->second;
}
stream << " }";
return stream;
}
template <typename T>
inline std::ostream& operator<<(
std::ostream& stream,
const RepeatedPtrField<T>& messages)
{
stream << "[ ";
for (auto it = messages.begin(); it != messages.end(); ++it) {
if (it != messages.begin()) {
stream << ", ";
}
stream << *it;
}
stream << " ]";
return stream;
}
} // namespace protobuf {
} // namespace google {
namespace std {
template <>
struct hash<mesos::CommandInfo::URI>
{
typedef size_t result_type;
typedef mesos::CommandInfo::URI argument_type;
result_type operator()(const argument_type& uri) const
{
size_t seed = 0;
if (uri.extract()) {
seed += 11;
}
if (uri.executable()) {
seed += 2003;
}
boost::hash_combine(seed, uri.value());
boost::hash_combine(seed, uri.output_file());
return seed;
}
};
template <>
struct hash<mesos::ContainerID>
{
typedef size_t result_type;
typedef mesos::ContainerID argument_type;
result_type operator()(const argument_type& containerId) const
{
size_t seed = 0;
boost::hash_combine(seed, containerId.value());
if (containerId.has_parent()) {
boost::hash_combine(
seed,
std::hash<mesos::ContainerID>()(containerId.parent()));
}
return seed;
}
};
template <>
struct hash<mesos::ExecutorID>
{
typedef size_t result_type;
typedef mesos::ExecutorID argument_type;
result_type operator()(const argument_type& executorId) const
{
size_t seed = 0;
boost::hash_combine(seed, executorId.value());
return seed;
}
};
template <>
struct hash<mesos::FrameworkID>
{
typedef size_t result_type;
typedef mesos::FrameworkID argument_type;
result_type operator()(const argument_type& frameworkId) const
{
size_t seed = 0;
boost::hash_combine(seed, frameworkId.value());
return seed;
}
};
template <>
struct hash<mesos::Image::Type>
{
typedef size_t result_type;
typedef mesos::Image::Type argument_type;
result_type operator()(const argument_type& imageType) const
{
// Use the underlying type of the enum as hash value.
return static_cast<size_t>(imageType);
}
};
template <>
struct hash<mesos::MachineID>
{
typedef size_t result_type;
typedef mesos::MachineID argument_type;
result_type operator()(const argument_type& machineId) const
{
size_t seed = 0;
boost::hash_combine(seed, strings::lower(machineId.hostname()));
boost::hash_combine(seed, machineId.ip());
return seed;
}
};
template <>
struct hash<mesos::OfferID>
{
typedef size_t result_type;
typedef mesos::OfferID argument_type;
result_type operator()(const argument_type& offerId) const
{
size_t seed = 0;
boost::hash_combine(seed, offerId.value());
return seed;
}
};
template <>
struct hash<mesos::OperationID>
{
typedef size_t result_type;
typedef mesos::OperationID argument_type;
result_type operator()(const argument_type& operationId) const
{
size_t seed = 0;
boost::hash_combine(seed, operationId.value());
return seed;
}
};
template <>
struct hash<mesos::ResourceProviderID>
{
typedef size_t result_type;
typedef mesos::ResourceProviderID argument_type;
result_type operator()(const argument_type& resourceProviderId) const
{
size_t seed = 0;
boost::hash_combine(seed, resourceProviderId.value());
return seed;
}
};
template <>
struct hash<mesos::SlaveID>
{
typedef size_t result_type;
typedef mesos::SlaveID argument_type;
result_type operator()(const argument_type& slaveId) const
{
size_t seed = 0;
boost::hash_combine(seed, slaveId.value());
return seed;
}
};
template <>
struct hash<mesos::TaskID>
{
typedef size_t result_type;
typedef mesos::TaskID argument_type;
result_type operator()(const argument_type& taskId) const
{
size_t seed = 0;
boost::hash_combine(seed, taskId.value());
return seed;
}
};
template <>
struct hash<mesos::TaskState>
{
typedef size_t result_type;
typedef mesos::TaskState argument_type;
result_type operator()(const argument_type& taskState) const
{
// Use the underlying type of the enum as hash value.
return static_cast<size_t>(taskState);
}
};
template <>
struct hash<mesos::TaskStatus_Source>
{
typedef size_t result_type;
typedef mesos::TaskStatus_Source argument_type;
result_type operator()(const argument_type& source) const
{
// Use the underlying type of the enum as hash value.
return static_cast<size_t>(source);
}
};
template <>
struct hash<mesos::TaskStatus_Reason>
{
typedef size_t result_type;
typedef mesos::TaskStatus_Reason argument_type;
result_type operator()(const argument_type& reason) const
{
// Use the underlying type of the enum as hash value.
return static_cast<size_t>(reason);
}
};
template <>
struct hash<mesos::UUID>
{
typedef size_t result_type;
typedef mesos::UUID argument_type;
result_type operator()(const argument_type& uuid) const
{
size_t seed = 0;
boost::hash_combine(seed, uuid.value());
return seed;
}
};
template <>
struct hash<std::pair<mesos::FrameworkID, mesos::ExecutorID>>
{
typedef size_t result_type;
typedef std::pair<
mesos::FrameworkID, mesos::ExecutorID> argument_type;
result_type operator()(const argument_type& pair) const
{
size_t seed = 0;
boost::hash_combine(seed, std::hash<mesos::FrameworkID>()(pair.first));
boost::hash_combine(seed, std::hash<mesos::ExecutorID>()(pair.second));
return seed;
}
};
template <>
struct hash<std::pair<mesos::FrameworkID, mesos::OperationID>>
{
typedef size_t result_type;
typedef std::pair<
mesos::FrameworkID, mesos::OperationID> argument_type;
result_type operator()(const argument_type& pair) const
{
size_t seed = 0;
boost::hash_combine(seed, std::hash<mesos::FrameworkID>()(pair.first));
boost::hash_combine(seed, std::hash<mesos::OperationID>()(pair.second));
return seed;
}
};
} // namespace std {
#endif // __MESOS_TYPE_UTILS_H__