blob: 320983929cd7d14973c4b98d6ed5338de690ff5f [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.
#include <string>
#include <vector>
#include <mesos/values.hpp>
#include <stout/check.hpp>
#include <stout/error.hpp>
#include <stout/foreach.hpp>
#include <stout/numify.hpp>
#include "common/resource_quantities.hpp"
using std::pair;
using std::string;
using std::vector;
namespace mesos {
namespace internal {
// This function tries to be consistent with `Resources::fromSimpleString()`.
// We trim the whitespace around the pair and in the number but whitespace in
// "c p us:10" are preserved and will be parsed to {"c p us", 10}.
Try<ResourceQuantities> ResourceQuantities::fromString(const string& text)
{
ResourceQuantities result;
foreach (const string& token, strings::tokenize(text, ";")) {
vector<string> pair = strings::tokenize(token, ":");
if (pair.size() != 2) {
return Error("Failed to parse '" + token + "': missing or extra ':'");
}
Try<Value> value = values::parse(pair[1]);
if (value.isError()) {
return Error(
"Failed to parse '" + pair[1] + "' to quantity: " + value.error());
}
if (value->type() != Value::SCALAR) {
return Error(
"Failed to parse '" + pair[1] + "' to quantity:"
" only scalar values are allowed");
}
if (value->scalar().value() < 0) {
return Error(
"Failed to parse '" + pair[1] + "' to quantity:"
" negative values are not allowed");
}
result[strings::trim(pair[0])] += value->scalar();
}
return result;
}
ResourceQuantities::ResourceQuantities()
{
// Pre-reserve space for first-class resources.
// [cpus, disk, gpus, mem, ports]
quantities.reserve(5u);
}
ResourceQuantities::const_iterator ResourceQuantities::begin()
{
return static_cast<const std::vector<std::pair<std::string, Value::Scalar>>&>(
quantities)
.begin();
}
ResourceQuantities::const_iterator ResourceQuantities::end()
{
return static_cast<const std::vector<std::pair<std::string, Value::Scalar>>&>(
quantities)
.end();
}
Option<Value::Scalar> ResourceQuantities::get(const string& name) const
{
// Don't bother binary searching since
// we don't expect a large number of elements.
foreach (auto& quantity, quantities) {
if (quantity.first == name) {
return quantity.second;
} else if (quantity.first > name) {
// We can return early since we keep names in alphabetical order.
break;
}
}
return None();
}
Value::Scalar& ResourceQuantities::operator[](const string& name)
{
// Find the location to insert while maintaining
// alphabetical ordering. Don't bother binary searching
// since we don't expect a large number of quantities.
auto it = quantities.begin();
for (; it != quantities.end(); ++it) {
if (it->first == name) {
return it->second;
}
if (it->first > name) {
break;
}
}
it = quantities.insert(it, std::make_pair(name, Value::Scalar()));
return it->second;
}
} // namespace internal {
} // namespace mesos {