/// /// 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_