///
/// Copyright 2015-2018 Oliver Giles
///
/// This file is part of Laminar
///
/// Laminar is free software: you can redistribute it and/or modify
/// it under the terms of the GNU General Public License as published by
/// the Free Software Foundation, either version 3 of the License, or
/// (at your option) any later version.
///
/// Laminar is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU General Public License for more details.
///
/// You should have received a copy of the GNU General Public License
/// along with Laminar. If not, see
///
#ifndef LAMINAR_RUN_H_
#define LAMINAR_RUN_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
// Definition needed for musl
typedef unsigned int uint;
enum class RunState {
UNKNOWN,
QUEUED,
RUNNING,
ABORTED,
FAILED,
SUCCESS
};
std::string to_string(const RunState& rs);
class Context;
typedef std::unordered_map ParamMap;
// Represents an execution of a job.
class Run {
public:
Run(std::string name, uint num, ParamMap params, kj::Path&& rootPath);
~Run();
// copying this class would be asking for trouble...
Run(const Run&) = delete;
Run& operator=(const Run&) = delete;
kj::Promise start(RunState lastResult, std::shared_ptr ctx, const kj::Directory &fsHome, std::function(kj::Maybe&)> getPromise);
// aborts this run
bool abort();
std::string reason() const;
kj::Promise whenStarted() { return startedFork.addBranch(); }
kj::Promise whenFinished() { return finishedFork.addBranch(); }
std::shared_ptr context;
RunState result;
std::string name;
std::string parentName;
int parentBuild = 0;
uint build = 0;
std::string log;
kj::Maybe pid;
int output_fd;
std::unordered_map params;
int timeout = 0;
time_t queuedAt;
time_t startedAt;
private:
// adds a script to the queue of scripts to be executed by this run
void addScript(kj::Path scriptPath, kj::Path scriptWorkingDir, bool runOnAbort = false);
// adds an environment file that will be sourced before this run
void addEnv(kj::Path path);
struct Script {
kj::Path path;
kj::Path cwd;
bool runOnAbort;
};
kj::Path rootPath;
std::string reasonMsg;
kj::PromiseFulfillerPair started;
kj::ForkedPromise startedFork;
kj::PromiseFulfillerPair finished;
kj::ForkedPromise finishedFork;
};
// All this below is a somewhat overengineered method of keeping track of
// currently executing builds (Run objects). This would probably scale
// very well, but it's completely gratuitous since we are not likely to
// be executing thousands of builds at the same time
#include
#include
#include
#include
#include
#include
#include
namespace bmi = boost::multi_index;
struct _run_same {
typedef const Run* result_type;
const Run* operator()(const std::shared_ptr& run) const {
return run.get();
}
};
// A single Run can be fetched by...
struct _run_index : bmi::indexed_by<
bmi::hashed_unique,
// a combination of their job name and build number
bmi::member,
bmi::member
>>,
// or a pointer to a Run object.
bmi::hashed_unique<_run_same>,
// A group of Runs can be fetched by the time they started
bmi::ordered_non_unique>,
// or by their job name
bmi::ordered_non_unique>
>
{};
struct RunSet: public boost::multi_index_container<
std::shared_ptr,
_run_index
> {
typename bmi::nth_index::type& byNameNumber() { return get<0>(); }
typename bmi::nth_index::type const& byNameNumber() const { return get<0>(); }
typename bmi::nth_index::type& byRunPtr() { return get<1>(); }
typename bmi::nth_index::type const& byRunPtr() const { return get<1>(); }
typename bmi::nth_index::type& byStartedAt() { return get<2>(); }
typename bmi::nth_index::type const& byStartedAt() const { return get<2>(); }
typename bmi::nth_index::type& byJobName() { return get<3>(); }
typename bmi::nth_index::type const& byJobName() const { return get<3>(); }
};
#endif // LAMINAR_RUN_H_