blob: fe02a1f6b8293439ebbf0b5058d9e72ee4631ee8 [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_STATE_PROTOBUF_HPP__
#define __MESOS_STATE_PROTOBUF_HPP__
#include <string>
#include <mesos/state/state.hpp>
#include <mesos/state/storage.hpp>
#include <process/future.hpp>
#include <stout/lambda.hpp>
#include <stout/option.hpp>
#include <stout/protobuf.hpp>
#include <stout/some.hpp>
#include <stout/try.hpp>
#include <stout/uuid.hpp>
namespace mesos {
namespace state {
namespace protobuf {
class State; // Forward declaration.
template <typename T>
class Variable
{
public:
T get() const
{
return t;
}
Variable mutate(const T& t) const
{
Variable variable(*this);
variable.t = t;
return variable;
}
private:
friend class State; // Creates and manages variables.
Variable(const mesos::state::Variable& _variable, const T& _t)
: variable(_variable), t(_t)
{}
mesos::state::Variable variable; // Not const to keep Variable assignable.
T t;
};
class State : public mesos::state::State
{
public:
explicit State(mesos::state::Storage* storage)
: mesos::state::State(storage) {}
~State() override {}
// Returns a variable from the state, creating a new one if one
// previously did not exist (or an error if one occurs).
template <typename T>
process::Future<Variable<T>> fetch(const std::string& name);
// Returns the variable specified if it was successfully stored in
// the state, otherwise returns none if the version of the variable
// was no longer valid, or an error if one occurs.
template <typename T>
process::Future<Option<Variable<T>>> store(const Variable<T>& variable);
// Expunges the variable from the state.
template <typename T>
process::Future<bool> expunge(const Variable<T>& variable);
private:
// Helpers to handle future results from fetch and swap. We make
// these static members of State for friend access to Variable's
// constructor.
template <typename T>
static process::Future<Variable<T>> _fetch(
const mesos::state::Variable& variable);
template <typename T>
static process::Future<Option<Variable<T>>> _store(
const T& t,
const Option<mesos::state::Variable>& variable);
};
template <typename T>
process::Future<Variable<T>> State::fetch(const std::string& name)
{
return mesos::state::State::fetch(name)
.then(lambda::bind(&State::template _fetch<T>, lambda::_1));
}
template <typename T>
process::Future<Variable<T>> State::_fetch(
const mesos::state::Variable& variable)
{
Try<T> t = ::protobuf::deserialize<T>(variable.value());
if (t.isError()) {
return process::Failure(t.error());
}
return Variable<T>(variable, t.get());
}
template <typename T>
process::Future<Option<Variable<T>>> State::store(
const Variable<T>& variable)
{
Try<std::string> value = ::protobuf::serialize(variable.t);
if (value.isError()) {
return process::Failure(value.error());
}
return mesos::state::State::store(variable.variable.mutate(value.get()))
.then(lambda::bind(&State::template _store<T>, variable.t, lambda::_1));
}
template <typename T>
process::Future<Option<Variable<T>>> State::_store(
const T& t,
const Option<mesos::state::Variable>& variable)
{
if (variable.isSome()) {
return Some(Variable<T>(variable.get(), t));
}
return None();
}
template <typename T>
process::Future<bool> State::expunge(const Variable<T>& variable)
{
return mesos::state::State::expunge(variable.variable);
}
} // namespace protobuf {
} // namespace state {
} // namespace mesos {
#endif // __MESOS_STATE_PROTOBUF_HPP__