blob: e5f2a4ae17fa6d2bac0829c99f3a86240f3df06f [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 __COMMON_RESOURCE_QUANTITIES_HPP__
#define __COMMON_RESOURCE_QUANTITIES_HPP__
#include <string>
#include <utility>
#include <vector>
#include <mesos/mesos.hpp>
#include <mesos/resources.hpp>
#include <stout/try.hpp>
namespace mesos {
namespace internal {
// An efficient collection of resource quantities. All values are guaranteed
// to be positive and finite.
//
// E.g. [("cpus", 4.5), ("gpus", 0.1), ("ports", 1000)]
//
// Absent resource entries imply there is no (zero) such resources.
//
// TODO(mzhu): Add `class ResourceLimits` where absence means infinite amount
// of such resources.
//
// Notes on handling negativity and arithmetic operations: values are guaranteed
// to be positive. This is achieved by construction validation and no public
// mutation interfaces. During construction, `Value::Scalar` arguments must be
// non-negative and finite, and entries with zero quantities will be dropped
// silently. Invalid arguments will result in an error where `Try`
// is returned. For arithmetic operations, non-positive values are silently
// dropped--this is consist with `class Resources`.
//
// Note for posterity, the status quo prior to this class
// was to use stripped-down `Resources` objects for storing
// quantities, however this approach:
//
// (1) did not support quantities of non-scalar resources;
// (2) was error prone, the caller must ensure that no
// `Resource` metatdata (e.g. `DiskInfo`) is present;
// (3) had poor performance, given the `Resources` storage
// model and arithmetic implementation have to operate
// on broader invariants.
class ResourceQuantities
{
public:
// Parse an input string of semicolon separated "name:number" pairs.
// Duplicate names are allowed in the input and will be merged into one entry.
// Entries with zero values will be silently dropped.
//
// Example: "cpus:10;mem:1024;ports:3"
// "cpus:10; mem:1024; ports:3"
// NOTE: we will trim the whitespace around the pair and in the number.
// However, whitespace in "c p us:10" are preserved and will be parsed to
// {"c p us", 10}. This is consistent with `Resources::fromSimpleString()`.
//
// Numbers must be non-negative and finite, otherwise an `Error`
// will be returned.
static Try<ResourceQuantities> fromString(const std::string& text);
// Take scalar `Resources` and combine them into `ResourceQuantities`.
// Only the resource name and its scalar value are used and the rest of the
// meta-data is ignored. It is caller's responsibility to ensure all
// `Resource` entries are of scalar type. Otherwise a `CHECK` error will
// be triggered.
static ResourceQuantities fromScalarResources(const Resources& resources);
// Take `Resources` and combine them into `ResourceQuantities`. This function
// assumes that the provided resources have already been validated; for
// example, it assumes that ranges do not overlap and that sets do not contain
// duplicate items.
static ResourceQuantities fromResources(const Resources& resources);
ResourceQuantities();
ResourceQuantities(const ResourceQuantities& that) = default;
ResourceQuantities(ResourceQuantities&& that) = default;
ResourceQuantities& operator=(const ResourceQuantities& that) = default;
ResourceQuantities& operator=(ResourceQuantities&& that) = default;
typedef std::vector<std::pair<std::string, Value::Scalar>>::const_iterator
iterator;
typedef std::vector<std::pair<std::string, Value::Scalar>>::const_iterator
const_iterator;
// NOTE: Non-`const` `iterator`, `begin()` and `end()` are __intentionally__
// defined with `const` semantics in order to prevent mutation during
// iteration. Mutation is allowed with the `[]` operator.
const_iterator begin();
const_iterator end();
const_iterator begin() const { return quantities.begin(); }
const_iterator end() const { return quantities.end(); }
size_t size() const { return quantities.size(); };
// Returns the quantity scalar value if a quantity with the given name.
// If the given name is absent, return zero.
Value::Scalar get(const std::string& name) const;
bool operator==(const ResourceQuantities& quantities) const;
bool operator!=(const ResourceQuantities& quantities) const;
ResourceQuantities& operator+=(const ResourceQuantities& quantities);
ResourceQuantities& operator-=(const ResourceQuantities& quantities);
private:
void add(const std::string& name, const Value::Scalar& scalar);
void add(const std::string& name, double value);
// List of name quantity pairs sorted by name.
// Arithmetic and comparison operations benefit from this sorting.
std::vector<std::pair<std::string, Value::Scalar>> quantities;
};
} // namespace internal {
} // namespace mesos {
#endif // __COMMON_RESOURCE_QUANTITIES_HPP__