1
0
mirror of https://github.com/ohwgiles/laminar.git synced 2024-10-27 20:34:20 +00:00
ohwgiles_laminar/src/run.h

170 lines
5.2 KiB
C
Raw Normal View History

2015-09-13 20:25:26 +00:00
///
/// Copyright 2015-2018 Oliver Giles
2015-09-13 20:25:26 +00:00
///
/// 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.
///
2015-09-24 19:07:48 +00:00
/// Laminar is distributed in the hope that it will be useful,
2015-09-13 20:25:26 +00:00
/// 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 <http://www.gnu.org/licenses/>
///
2017-12-20 06:24:25 +00:00
#ifndef LAMINAR_RUN_H_
#define LAMINAR_RUN_H_
2015-09-13 20:25:26 +00:00
#include <string>
#include <queue>
#include <list>
2015-09-13 20:25:26 +00:00
#include <functional>
#include <ostream>
#include <unordered_map>
#include <memory>
#include <kj/async.h>
#include <kj/filesystem.h>
2015-09-13 20:25:26 +00:00
2019-07-04 09:28:33 +00:00
// Definition needed for musl
typedef unsigned int uint;
2015-09-13 20:25:26 +00:00
enum class RunState {
UNKNOWN,
PENDING,
RUNNING,
2015-09-13 20:25:26 +00:00
ABORTED,
FAILED,
SUCCESS
};
std::string to_string(const RunState& rs);
class Node;
typedef std::unordered_map<std::string, std::string> ParamMap;
// Represents an execution of a job.
2015-09-13 20:25:26 +00:00
class Run {
public:
Run(std::string name, ParamMap params, kj::Path&& rootPath);
2015-09-13 20:25:26 +00:00
~Run();
// copying this class would be asking for trouble...
Run(const Run&) = delete;
Run& operator=(const Run&) = delete;
// Call this to "start" the run with a specific number and node
bool configure(uint buildNum, std::shared_ptr<Node> node, const kj::Directory &fsHome);
2015-09-13 20:25:26 +00:00
// executes the next script (if any), returning true if there is nothing
// more to be done.
2015-09-13 20:25:26 +00:00
bool step();
// aborts this run
void abort(bool respectRunOnAbort);
2015-09-13 20:25:26 +00:00
// called when a process owned by this run has been reaped. The status
// may be used to set the run's job status
void reaped(int status);
std::string reason() const;
kj::Promise<void>&& whenStarted() { return kj::mv(started.promise); }
std::shared_ptr<Node> node;
2015-09-13 20:25:26 +00:00
RunState result;
2015-09-19 08:31:51 +00:00
RunState lastResult;
2015-09-13 20:25:26 +00:00
std::string name;
std::string parentName;
int parentBuild = 0;
2017-12-21 06:19:45 +00:00
uint build = 0;
2015-09-13 20:25:26 +00:00
std::string log;
kj::Maybe<pid_t> current_pid;
int output_fd;
2015-09-13 20:25:26 +00:00
std::unordered_map<std::string, std::string> params;
2019-02-15 16:24:36 +00:00
int timeout = 0;
2015-09-13 20:25:26 +00:00
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::queue<Script> scripts;
std::list<kj::Path> env;
std::string reasonMsg;
kj::PromiseFulfillerPair<void> started;
2015-09-13 20:25:26 +00:00
};
// 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 <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
namespace bmi = boost::multi_index;
2015-11-19 20:43:08 +00:00
struct _run_same {
2015-09-13 20:25:26 +00:00
typedef const Run* result_type;
const Run* operator()(const std::shared_ptr<Run>& run) const {
return run.get();
}
};
2015-11-19 20:43:08 +00:00
// A single Run can be fetched by...
struct _run_index : bmi::indexed_by<
2015-09-13 20:25:26 +00:00
bmi::hashed_unique<bmi::composite_key<
std::shared_ptr<Run>,
// a combination of their job name and build number
bmi::member<Run, std::string, &Run::name>,
2017-12-21 06:19:45 +00:00
bmi::member<Run, uint, &Run::build>
2015-09-13 20:25:26 +00:00
>>,
// or a pointer to a Run object.
2015-11-19 20:43:08 +00:00
bmi::hashed_unique<_run_same>,
2015-09-13 20:25:26 +00:00
// A group of Runs can be fetched by the time they started
bmi::ordered_non_unique<bmi::member<Run, time_t, &Run::startedAt>>,
// or by their job name
bmi::ordered_non_unique<bmi::member<Run, std::string, &Run::name>>
>
2015-11-19 20:43:08 +00:00
{};
struct RunSet: public boost::multi_index_container<
std::shared_ptr<Run>,
_run_index
2015-09-13 20:25:26 +00:00
> {
typename bmi::nth_index<RunSet, 0>::type& byNameNumber() { return get<0>(); }
typename bmi::nth_index<RunSet, 0>::type const& byNameNumber() const { return get<0>(); }
typename bmi::nth_index<RunSet, 1>::type& byRunPtr() { return get<1>(); }
typename bmi::nth_index<RunSet, 1>::type const& byRunPtr() const { return get<1>(); }
typename bmi::nth_index<RunSet, 2>::type& byStartedAt() { return get<2>(); }
typename bmi::nth_index<RunSet, 2>::type const& byStartedAt() const { return get<2>(); }
typename bmi::nth_index<RunSet, 3>::type& byJobName() { return get<3>(); }
typename bmi::nth_index<RunSet, 3>::type const& byJobName() const { return get<3>(); }
2015-09-13 20:25:26 +00:00
};
2017-12-20 06:24:25 +00:00
#endif // LAMINAR_RUN_H_