blob: 11eb426104577bbbbb7977c2307df3e4917085cd [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 <stout/try.hpp>
namespace mesos {
namespace internal {
// An efficient collection of resource quantities.
//
// E.g. [("cpus", 4.5), ("gpus", 0), ("ports", 1000)]
//
// We provide map-like semantics: [] operator for inserting/retrieving values,
// keys are unique, and iteration is sorted.
//
// Notes on handling negativity and arithmetic operations: during construction,
// `Value::Scalar` arguments must be non-negative and finite. Invalid arguments
// will result in an error where `Try` is returned. Once constructed, users can
// use `[]` operator to mutate values directly. No member methods are provided
// for arithmetic operations. Users should be mindful of producing negatives
// when mutating the `Value::Scalar` directly.
//
// An alternative design for this class was to provide addition and
// subtraction functions as opposed to a map interface. However, this
// leads to some un-obvious semantics around presence of zero values
// (will zero entries be automatically removed?) and handling of negatives
// (will negatives trigger a crash? will they be converted to zero? Note
// that Value::Scalar should be non-negative but there is currently no
// enforcement of this by Value::Scalar arithmetic operations; we probably
// want all Value::Scalar operations to go through the same negative
// handling). To avoid the confusion, we provided a map like interface
// which produces clear semantics: insertion works like maps, and the
// user is responsible for performing arithmetic operations on the values
// (using the already provided Value::Scalar arithmetic overloads).
//
// 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.
//
// 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);
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
// exists (even if the quantity is zero), otherwise return `None()`.
Option<Value::Scalar> get(const std::string& name) const;
// Like std::map, returns a reference to the quantity with the given name.
// If no quantity exists with the given name, a new entry will be created.
Value::Scalar& operator[](const std::string& name);
private:
// 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__