2015-07-07 08:17:21 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
#include <chrono>
|
|
|
|
|
#include <condition_variable>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <queue>
|
|
|
|
|
|
|
|
|
|
#include "db.hh"
|
|
|
|
|
#include "counter.hh"
|
2016-03-09 13:30:13 +00:00
|
|
|
|
#include "token-server.hh"
|
|
|
|
|
|
|
|
|
|
#include "derivations.hh"
|
2015-07-07 08:17:21 +00:00
|
|
|
|
#include "pathlocks.hh"
|
|
|
|
|
#include "pool.hh"
|
|
|
|
|
#include "store-api.hh"
|
2016-03-09 13:30:13 +00:00
|
|
|
|
#include "sync.hh"
|
2016-02-19 23:04:08 +00:00
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
typedef unsigned int BuildID;
|
|
|
|
|
|
|
|
|
|
typedef std::chrono::time_point<std::chrono::system_clock> system_time;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
bsSuccess = 0,
|
|
|
|
|
bsFailed = 1,
|
2016-03-09 14:15:12 +00:00
|
|
|
|
bsDepFailed = 2, // builds only
|
2015-07-07 08:17:21 +00:00
|
|
|
|
bsAborted = 3,
|
2016-10-31 13:58:29 +00:00
|
|
|
|
bsCancelled = 4,
|
2016-03-09 14:15:12 +00:00
|
|
|
|
bsFailedWithOutput = 6, // builds only
|
2015-07-07 08:17:21 +00:00
|
|
|
|
bsTimedOut = 7,
|
2016-03-09 14:15:12 +00:00
|
|
|
|
bsCachedFailure = 8, // steps only
|
2015-07-07 08:17:21 +00:00
|
|
|
|
bsUnsupported = 9,
|
2015-10-06 15:35:08 +00:00
|
|
|
|
bsLogLimitExceeded = 10,
|
2016-03-09 15:59:38 +00:00
|
|
|
|
bsNarSizeLimitExceeded = 11,
|
2016-03-09 14:15:12 +00:00
|
|
|
|
bsBusy = 100, // not stored
|
2015-07-07 08:17:21 +00:00
|
|
|
|
} BuildStatus;
|
|
|
|
|
|
|
|
|
|
|
2016-03-09 15:59:38 +00:00
|
|
|
|
struct RemoteResult
|
2015-07-07 08:25:33 +00:00
|
|
|
|
{
|
2016-03-09 15:59:38 +00:00
|
|
|
|
BuildStatus stepStatus = bsAborted;
|
|
|
|
|
bool canRetry = false; // for bsAborted
|
|
|
|
|
bool isCached = false; // for bsSucceed
|
|
|
|
|
bool canCache = false; // for bsFailed
|
|
|
|
|
std::string errorMsg; // for bsAborted
|
|
|
|
|
|
2015-07-07 08:25:33 +00:00
|
|
|
|
time_t startTime = 0, stopTime = 0;
|
2016-02-17 09:28:42 +00:00
|
|
|
|
unsigned int overhead = 0;
|
2015-07-07 08:25:33 +00:00
|
|
|
|
nix::Path logFile;
|
2016-02-26 14:21:44 +00:00
|
|
|
|
std::shared_ptr<nix::FSAccessor> accessor;
|
2015-07-20 23:45:00 +00:00
|
|
|
|
|
2016-03-09 15:59:38 +00:00
|
|
|
|
BuildStatus buildStatus()
|
2015-07-20 23:45:00 +00:00
|
|
|
|
{
|
2016-03-09 15:59:38 +00:00
|
|
|
|
return stepStatus == bsCachedFailure ? bsFailed : stepStatus;
|
2015-07-20 23:45:00 +00:00
|
|
|
|
}
|
2015-07-07 08:25:33 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
struct Step;
|
2015-07-20 23:45:00 +00:00
|
|
|
|
struct BuildOutput;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
|
2015-08-10 23:30:24 +00:00
|
|
|
|
class Jobset
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
typedef std::shared_ptr<Jobset> ptr;
|
|
|
|
|
typedef std::weak_ptr<Jobset> wptr;
|
|
|
|
|
|
|
|
|
|
static const time_t schedulingWindow = 24 * 60 * 60;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
std::atomic<time_t> seconds{0};
|
2015-08-12 11:17:56 +00:00
|
|
|
|
std::atomic<unsigned int> shares{1};
|
2015-08-10 23:30:24 +00:00
|
|
|
|
|
|
|
|
|
/* The start time and duration of the most recent build steps. */
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<std::map<time_t, time_t>> steps;
|
2015-08-10 23:30:24 +00:00
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
double shareUsed()
|
|
|
|
|
{
|
|
|
|
|
return (double) seconds / shares;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-12 11:17:56 +00:00
|
|
|
|
void setShares(int shares_)
|
|
|
|
|
{
|
|
|
|
|
assert(shares_ > 0);
|
|
|
|
|
shares = shares_;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-10 23:30:24 +00:00
|
|
|
|
time_t getSeconds() { return seconds; }
|
|
|
|
|
|
|
|
|
|
void addStep(time_t startTime, time_t duration);
|
|
|
|
|
|
|
|
|
|
void pruneSteps();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
struct Build
|
|
|
|
|
{
|
|
|
|
|
typedef std::shared_ptr<Build> ptr;
|
|
|
|
|
typedef std::weak_ptr<Build> wptr;
|
|
|
|
|
|
|
|
|
|
BuildID id;
|
2015-07-07 08:29:43 +00:00
|
|
|
|
nix::Path drvPath;
|
|
|
|
|
std::map<std::string, nix::Path> outputs;
|
2015-07-30 22:57:30 +00:00
|
|
|
|
std::string projectName, jobsetName, jobName;
|
|
|
|
|
time_t timestamp;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
unsigned int maxSilentTime, buildTimeout;
|
2015-08-12 10:05:43 +00:00
|
|
|
|
int localPriority, globalPriority;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
std::shared_ptr<Step> toplevel;
|
|
|
|
|
|
2015-08-10 23:30:24 +00:00
|
|
|
|
Jobset::ptr jobset;
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
std::atomic_bool finishedInDB{false};
|
2015-07-30 22:57:30 +00:00
|
|
|
|
|
|
|
|
|
std::string fullJobName()
|
|
|
|
|
{
|
|
|
|
|
return projectName + ":" + jobsetName + ":" + jobName;
|
|
|
|
|
}
|
2015-08-10 14:18:06 +00:00
|
|
|
|
|
|
|
|
|
void propagatePriorities();
|
2015-07-07 08:17:21 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Step
|
|
|
|
|
{
|
|
|
|
|
typedef std::shared_ptr<Step> ptr;
|
|
|
|
|
typedef std::weak_ptr<Step> wptr;
|
|
|
|
|
|
2015-07-07 08:29:43 +00:00
|
|
|
|
nix::Path drvPath;
|
|
|
|
|
nix::Derivation drv;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
std::set<std::string> requiredSystemFeatures;
|
|
|
|
|
bool preferLocalBuild;
|
2015-08-17 12:37:57 +00:00
|
|
|
|
std::string systemType; // concatenation of drv.platform and requiredSystemFeatures
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
struct State
|
|
|
|
|
{
|
|
|
|
|
/* Whether the step has finished initialisation. */
|
|
|
|
|
bool created = false;
|
|
|
|
|
|
|
|
|
|
/* The build steps on which this step depends. */
|
|
|
|
|
std::set<Step::ptr> deps;
|
|
|
|
|
|
|
|
|
|
/* The build steps that depend on this step. */
|
|
|
|
|
std::vector<Step::wptr> rdeps;
|
|
|
|
|
|
|
|
|
|
/* Builds that have this step as the top-level derivation. */
|
|
|
|
|
std::vector<Build::wptr> builds;
|
|
|
|
|
|
2015-08-10 23:30:24 +00:00
|
|
|
|
/* Jobsets to which this step belongs. Used for determining
|
|
|
|
|
scheduling priority. */
|
|
|
|
|
std::set<Jobset::ptr> jobsets;
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
/* Number of times we've tried this step. */
|
|
|
|
|
unsigned int tries = 0;
|
|
|
|
|
|
|
|
|
|
/* Point in time after which the step can be retried. */
|
|
|
|
|
system_time after;
|
2015-08-10 12:50:22 +00:00
|
|
|
|
|
2015-08-10 14:18:06 +00:00
|
|
|
|
/* The highest global priority of any build depending on this
|
|
|
|
|
step. */
|
|
|
|
|
int highestGlobalPriority{0};
|
|
|
|
|
|
2015-08-12 10:05:43 +00:00
|
|
|
|
/* The highest local priority of any build depending on this
|
|
|
|
|
step. */
|
|
|
|
|
int highestLocalPriority{0};
|
|
|
|
|
|
2015-08-10 14:18:06 +00:00
|
|
|
|
/* The lowest ID of any build depending on this step. */
|
2015-08-10 12:50:22 +00:00
|
|
|
|
BuildID lowestBuildID{std::numeric_limits<BuildID>::max()};
|
2015-08-17 13:45:44 +00:00
|
|
|
|
|
|
|
|
|
/* The time at which this step became runnable. */
|
|
|
|
|
system_time runnableSince;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::atomic_bool finished{false}; // debugging
|
|
|
|
|
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<State> state;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
~Step()
|
|
|
|
|
{
|
|
|
|
|
//printMsg(lvlError, format("destroying step %1%") % drvPath);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2015-07-21 13:14:17 +00:00
|
|
|
|
void getDependents(Step::ptr step, std::set<Build::ptr> & builds, std::set<Step::ptr> & steps);
|
|
|
|
|
|
2015-08-10 12:50:22 +00:00
|
|
|
|
/* Call ‘visitor’ for a step and all its dependencies. */
|
|
|
|
|
void visitDependencies(std::function<void(Step::ptr)> visitor, Step::ptr step);
|
|
|
|
|
|
2015-07-21 13:14:17 +00:00
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
struct Machine
|
|
|
|
|
{
|
|
|
|
|
typedef std::shared_ptr<Machine> ptr;
|
|
|
|
|
|
2015-09-02 11:31:47 +00:00
|
|
|
|
bool enabled{true};
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
std::string sshName, sshKey;
|
|
|
|
|
std::set<std::string> systemTypes, supportedFeatures, mandatoryFeatures;
|
|
|
|
|
unsigned int maxJobs = 1;
|
|
|
|
|
float speedFactor = 1.0;
|
2015-08-26 11:43:02 +00:00
|
|
|
|
std::string sshPublicHostKey;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
struct State {
|
|
|
|
|
typedef std::shared_ptr<State> ptr;
|
|
|
|
|
counter currentJobs{0};
|
|
|
|
|
counter nrStepsDone{0};
|
|
|
|
|
counter totalStepTime{0}; // total time for steps, including closure copying
|
|
|
|
|
counter totalStepBuildTime{0}; // total build time for steps
|
2015-08-17 11:50:41 +00:00
|
|
|
|
std::atomic<time_t> idleSince{0};
|
2015-07-07 12:04:36 +00:00
|
|
|
|
|
2015-07-21 13:53:27 +00:00
|
|
|
|
struct ConnectInfo
|
|
|
|
|
{
|
|
|
|
|
system_time lastFailure, disabledUntil;
|
|
|
|
|
unsigned int consecutiveFailures;
|
|
|
|
|
};
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<ConnectInfo> connectInfo;
|
2015-07-21 13:53:27 +00:00
|
|
|
|
|
2015-07-07 12:04:36 +00:00
|
|
|
|
/* Mutex to prevent multiple threads from sending data to the
|
|
|
|
|
same machine (which would be inefficient). */
|
|
|
|
|
std::mutex sendLock;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
State::ptr state;
|
|
|
|
|
|
|
|
|
|
bool supportsStep(Step::ptr step)
|
|
|
|
|
{
|
|
|
|
|
if (systemTypes.find(step->drv.platform) == systemTypes.end()) return false;
|
|
|
|
|
for (auto & f : mandatoryFeatures)
|
|
|
|
|
if (step->requiredSystemFeatures.find(f) == step->requiredSystemFeatures.end()
|
|
|
|
|
&& !(step->preferLocalBuild && f == "local"))
|
|
|
|
|
return false;
|
|
|
|
|
for (auto & f : step->requiredSystemFeatures)
|
|
|
|
|
if (supportedFeatures.find(f) == supportedFeatures.end()) return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class State
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
|
2015-07-21 13:14:17 +00:00
|
|
|
|
// FIXME: Make configurable.
|
|
|
|
|
const unsigned int maxTries = 5;
|
|
|
|
|
const unsigned int retryInterval = 60; // seconds
|
|
|
|
|
const float retryBackoff = 3.0;
|
|
|
|
|
const unsigned int maxParallelCopyClosure = 4;
|
|
|
|
|
|
2015-07-07 08:29:43 +00:00
|
|
|
|
nix::Path hydraData, logDir;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
2016-02-22 16:23:06 +00:00
|
|
|
|
std::map<std::string, std::string> hydraConfig;
|
|
|
|
|
|
2016-10-07 18:23:05 +00:00
|
|
|
|
bool useSubstitutes = false;
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
/* The queued builds. */
|
|
|
|
|
typedef std::map<BuildID, Build::ptr> Builds;
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<Builds> builds;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
2015-08-10 23:30:24 +00:00
|
|
|
|
/* The jobsets. */
|
|
|
|
|
typedef std::map<std::pair<std::string, std::string>, Jobset::ptr> Jobsets;
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<Jobsets> jobsets;
|
2015-08-10 23:30:24 +00:00
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
/* All active or pending build steps (i.e. dependencies of the
|
|
|
|
|
queued builds). Note that these are weak pointers. Steps are
|
|
|
|
|
kept alive by being reachable from Builds or by being in
|
|
|
|
|
progress. */
|
2015-07-07 08:29:43 +00:00
|
|
|
|
typedef std::map<nix::Path, Step::wptr> Steps;
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<Steps> steps;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
/* Build steps that have no unbuilt dependencies. */
|
|
|
|
|
typedef std::list<Step::wptr> Runnable;
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<Runnable> runnable;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
/* CV for waking up the dispatcher. */
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<bool> dispatcherWakeup;
|
|
|
|
|
std::condition_variable dispatcherWakeupCV;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
/* PostgreSQL connection pool. */
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Pool<Connection> dbPool;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
/* The build machines. */
|
2015-07-07 08:29:43 +00:00
|
|
|
|
typedef std::map<std::string, Machine::ptr> Machines;
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<Machines> machines; // FIXME: use atomic_shared_ptr
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
/* Various stats. */
|
|
|
|
|
time_t startedAt;
|
|
|
|
|
counter nrBuildsRead{0};
|
2016-03-08 12:09:14 +00:00
|
|
|
|
counter buildReadTimeMs{0};
|
2015-07-07 08:17:21 +00:00
|
|
|
|
counter nrBuildsDone{0};
|
2016-03-02 13:18:39 +00:00
|
|
|
|
counter nrStepsStarted{0};
|
2015-07-07 08:17:21 +00:00
|
|
|
|
counter nrStepsDone{0};
|
|
|
|
|
counter nrStepsBuilding{0};
|
|
|
|
|
counter nrStepsCopyingTo{0};
|
|
|
|
|
counter nrStepsCopyingFrom{0};
|
2015-07-10 17:10:14 +00:00
|
|
|
|
counter nrStepsWaiting{0};
|
2015-07-07 08:17:21 +00:00
|
|
|
|
counter nrRetries{0};
|
|
|
|
|
counter maxNrRetries{0};
|
|
|
|
|
counter totalStepTime{0}; // total time for steps, including closure copying
|
|
|
|
|
counter totalStepBuildTime{0}; // total build time for steps
|
|
|
|
|
counter nrQueueWakeups{0};
|
|
|
|
|
counter nrDispatcherWakeups{0};
|
2016-03-02 13:18:39 +00:00
|
|
|
|
counter dispatchTimeMs{0};
|
2015-07-07 08:17:21 +00:00
|
|
|
|
counter bytesSent{0};
|
|
|
|
|
counter bytesReceived{0};
|
2016-02-29 14:10:30 +00:00
|
|
|
|
counter nrActiveDbUpdates{0};
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
/* Log compressor work queue. */
|
2016-05-27 12:32:48 +00:00
|
|
|
|
struct CompressionItem
|
|
|
|
|
{
|
|
|
|
|
BuildID id;
|
|
|
|
|
unsigned int stepNr;
|
|
|
|
|
nix::Path logPath;
|
|
|
|
|
};
|
|
|
|
|
nix::Sync<std::queue<CompressionItem>> logCompressorQueue;
|
2016-02-24 13:04:31 +00:00
|
|
|
|
std::condition_variable logCompressorWakeup;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
/* Notification sender work queue. FIXME: if hydra-queue-runner is
|
|
|
|
|
killed before it has finished sending notifications about a
|
|
|
|
|
build, then the notifications may be lost. It would be better
|
|
|
|
|
to mark builds with pending notification in the database. */
|
2016-03-12 02:48:31 +00:00
|
|
|
|
struct NotificationItem
|
|
|
|
|
{
|
|
|
|
|
enum class Type : char {
|
2016-05-27 12:32:48 +00:00
|
|
|
|
BuildStarted,
|
|
|
|
|
BuildFinished,
|
|
|
|
|
StepFinished,
|
2016-03-12 02:48:31 +00:00
|
|
|
|
};
|
|
|
|
|
Type type;
|
|
|
|
|
BuildID id;
|
|
|
|
|
std::vector<BuildID> dependentIds;
|
2016-05-27 12:32:48 +00:00
|
|
|
|
unsigned int stepNr;
|
|
|
|
|
nix::Path logPath;
|
2016-03-12 02:48:31 +00:00
|
|
|
|
};
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<std::queue<NotificationItem>> notificationSenderQueue;
|
|
|
|
|
std::condition_variable notificationSenderWakeup;
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
2016-05-27 12:32:48 +00:00
|
|
|
|
void enqueueNotificationItem(const NotificationItem && item)
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
auto notificationSenderQueue_(notificationSenderQueue.lock());
|
|
|
|
|
notificationSenderQueue_->emplace(item);
|
|
|
|
|
}
|
|
|
|
|
notificationSenderWakeup.notify_one();
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
/* Specific build to do for --build-one (testing only). */
|
|
|
|
|
BuildID buildOne;
|
|
|
|
|
|
2015-08-17 11:50:41 +00:00
|
|
|
|
/* Statistics per machine type for the Hydra auto-scaler. */
|
|
|
|
|
struct MachineType
|
|
|
|
|
{
|
|
|
|
|
unsigned int runnable{0}, running{0};
|
2015-08-17 13:45:44 +00:00
|
|
|
|
system_time lastActive;
|
|
|
|
|
std::chrono::seconds waitTime; // time runnable steps have been waiting
|
2015-08-17 11:50:41 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-02-24 13:04:31 +00:00
|
|
|
|
nix::Sync<std::map<std::string, MachineType>> machineTypes;
|
2015-08-17 11:50:41 +00:00
|
|
|
|
|
|
|
|
|
struct MachineReservation
|
|
|
|
|
{
|
|
|
|
|
typedef std::shared_ptr<MachineReservation> ptr;
|
|
|
|
|
State & state;
|
|
|
|
|
Step::ptr step;
|
|
|
|
|
Machine::ptr machine;
|
|
|
|
|
MachineReservation(State & state, Step::ptr step, Machine::ptr machine);
|
|
|
|
|
~MachineReservation();
|
|
|
|
|
};
|
|
|
|
|
|
2016-11-02 11:41:00 +00:00
|
|
|
|
struct ActiveStep
|
|
|
|
|
{
|
|
|
|
|
Step::ptr step;
|
2016-11-07 18:34:35 +00:00
|
|
|
|
|
|
|
|
|
struct State
|
|
|
|
|
{
|
|
|
|
|
pid_t pid = -1;
|
|
|
|
|
bool cancelled = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
nix::Sync<State> state_;
|
2016-11-02 11:41:00 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
nix::Sync<std::set<std::shared_ptr<ActiveStep>>> activeSteps_;
|
2016-10-31 13:58:29 +00:00
|
|
|
|
|
2015-08-17 13:45:44 +00:00
|
|
|
|
std::atomic<time_t> lastDispatcherCheck{0};
|
|
|
|
|
|
2016-10-07 18:23:05 +00:00
|
|
|
|
std::shared_ptr<nix::Store> localStore;
|
2016-02-18 16:31:19 +00:00
|
|
|
|
std::shared_ptr<nix::Store> _destStore;
|
|
|
|
|
|
2016-03-09 13:30:13 +00:00
|
|
|
|
/* Token server to prevent threads from allocating too many big
|
|
|
|
|
strings concurrently while importing NARs from the build
|
|
|
|
|
machines. When a thread imports a NAR of size N, it will first
|
|
|
|
|
acquire N memory tokens, causing it to block until that many
|
|
|
|
|
tokens are available. */
|
|
|
|
|
nix::TokenServer memoryTokens;
|
|
|
|
|
|
2016-03-09 15:59:38 +00:00
|
|
|
|
size_t maxOutputSize = 2ULL << 30;
|
|
|
|
|
|
2016-03-09 16:11:34 +00:00
|
|
|
|
time_t lastStatusLogged = 0;
|
2016-03-09 16:31:57 +00:00
|
|
|
|
const int statusLogInterval = 300;
|
2016-03-09 16:11:34 +00:00
|
|
|
|
|
2016-04-13 14:18:35 +00:00
|
|
|
|
/* Steps that were busy while we encounted a PostgreSQL
|
|
|
|
|
error. These need to be cleared at a later time to prevent them
|
|
|
|
|
from showing up as busy until the queue runner is restarted. */
|
|
|
|
|
nix::Sync<std::set<std::pair<BuildID, int>>> orphanedSteps;
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
public:
|
|
|
|
|
State();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
2016-02-29 14:10:30 +00:00
|
|
|
|
MaintainCount startDbUpdate();
|
|
|
|
|
|
2016-02-15 20:10:29 +00:00
|
|
|
|
/* Return a store object to store build results. */
|
|
|
|
|
nix::ref<nix::Store> getDestStore();
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
void clearBusy(Connection & conn, time_t stopTime);
|
|
|
|
|
|
2015-08-25 12:11:50 +00:00
|
|
|
|
void parseMachines(const std::string & contents);
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
/* Thread to reload /etc/nix/machines periodically. */
|
|
|
|
|
void monitorMachinesFile();
|
|
|
|
|
|
2016-10-31 13:58:29 +00:00
|
|
|
|
unsigned int allocBuildStep(pqxx::work & txn, BuildID buildId);
|
2015-10-05 12:57:44 +00:00
|
|
|
|
|
2016-10-31 13:58:29 +00:00
|
|
|
|
unsigned int createBuildStep(pqxx::work & txn, time_t startTime, BuildID buildId, Step::ptr step,
|
2016-03-09 14:15:12 +00:00
|
|
|
|
const std::string & machine, BuildStatus status, const std::string & errorMsg = "",
|
2015-07-07 08:17:21 +00:00
|
|
|
|
BuildID propagatedFrom = 0);
|
|
|
|
|
|
2016-02-17 09:28:42 +00:00
|
|
|
|
void finishBuildStep(pqxx::work & txn, time_t startTime, time_t stopTime,
|
2016-05-27 12:32:48 +00:00
|
|
|
|
unsigned int overhead, BuildID buildId, unsigned int stepNr,
|
2016-03-09 14:15:12 +00:00
|
|
|
|
const std::string & machine, BuildStatus status, const std::string & errorMsg = "",
|
2015-07-07 08:17:21 +00:00
|
|
|
|
BuildID propagatedFrom = 0);
|
|
|
|
|
|
2015-10-05 12:57:44 +00:00
|
|
|
|
int createSubstitutionStep(pqxx::work & txn, time_t startTime, time_t stopTime,
|
|
|
|
|
Build::ptr build, const nix::Path & drvPath, const std::string & outputName, const nix::Path & storePath);
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
void updateBuild(pqxx::work & txn, Build::ptr build, BuildStatus status);
|
|
|
|
|
|
|
|
|
|
void queueMonitor();
|
|
|
|
|
|
|
|
|
|
void queueMonitorLoop();
|
|
|
|
|
|
2015-08-10 14:18:06 +00:00
|
|
|
|
/* Check the queue for new builds. */
|
2016-10-07 18:23:05 +00:00
|
|
|
|
bool getQueuedBuilds(Connection & conn,
|
2016-02-15 20:10:29 +00:00
|
|
|
|
nix::ref<nix::Store> destStore, unsigned int & lastBuildId);
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
2015-08-10 14:18:06 +00:00
|
|
|
|
/* Handle cancellation, deletion and priority bumps. */
|
|
|
|
|
void processQueueChange(Connection & conn);
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
2016-04-13 13:38:06 +00:00
|
|
|
|
BuildOutput getBuildOutputCached(Connection & conn, nix::ref<nix::Store> destStore,
|
|
|
|
|
const nix::Derivation & drv);
|
|
|
|
|
|
2016-02-11 14:59:47 +00:00
|
|
|
|
Step::ptr createStep(nix::ref<nix::Store> store,
|
2015-10-05 12:57:44 +00:00
|
|
|
|
Connection & conn, Build::ptr build, const nix::Path & drvPath,
|
2015-07-07 08:29:43 +00:00
|
|
|
|
Build::ptr referringBuild, Step::ptr referringStep, std::set<nix::Path> & finishedDrvs,
|
2015-07-07 08:17:21 +00:00
|
|
|
|
std::set<Step::ptr> & newSteps, std::set<Step::ptr> & newRunnable);
|
|
|
|
|
|
2015-08-10 23:30:24 +00:00
|
|
|
|
Jobset::ptr createJobset(pqxx::work & txn,
|
|
|
|
|
const std::string & projectName, const std::string & jobsetName);
|
|
|
|
|
|
2015-08-12 11:17:56 +00:00
|
|
|
|
void processJobsetSharesChange(Connection & conn);
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
void makeRunnable(Step::ptr step);
|
|
|
|
|
|
|
|
|
|
/* The thread that selects and starts runnable builds. */
|
|
|
|
|
void dispatcher();
|
|
|
|
|
|
2015-08-10 09:26:30 +00:00
|
|
|
|
system_time doDispatch();
|
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
void wakeDispatcher();
|
|
|
|
|
|
2015-08-17 11:50:41 +00:00
|
|
|
|
void builder(MachineReservation::ptr reservation);
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
/* Perform the given build step. Return true if the step is to be
|
|
|
|
|
retried. */
|
2016-03-08 12:09:39 +00:00
|
|
|
|
enum StepResult { sDone, sRetry, sMaybeCancelled };
|
|
|
|
|
StepResult doBuildStep(nix::ref<nix::Store> destStore,
|
2016-11-07 18:34:35 +00:00
|
|
|
|
MachineReservation::ptr reservation,
|
|
|
|
|
std::shared_ptr<ActiveStep> activeStep);
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
2016-02-15 20:10:29 +00:00
|
|
|
|
void buildRemote(nix::ref<nix::Store> destStore,
|
2015-07-07 08:25:33 +00:00
|
|
|
|
Machine::ptr machine, Step::ptr step,
|
|
|
|
|
unsigned int maxSilentTime, unsigned int buildTimeout,
|
2016-11-07 18:34:35 +00:00
|
|
|
|
RemoteResult & result, std::shared_ptr<ActiveStep> activeStep);
|
2015-07-07 08:25:33 +00:00
|
|
|
|
|
2015-07-07 08:17:21 +00:00
|
|
|
|
void markSucceededBuild(pqxx::work & txn, Build::ptr build,
|
2015-07-20 23:45:00 +00:00
|
|
|
|
const BuildOutput & res, bool isCachedBuild, time_t startTime, time_t stopTime);
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
bool checkCachedFailure(Step::ptr step, Connection & conn);
|
|
|
|
|
|
|
|
|
|
/* Thread that asynchronously bzips logs of finished steps. */
|
|
|
|
|
void logCompressor();
|
|
|
|
|
|
|
|
|
|
/* Thread that asynchronously invokes hydra-notify to send build
|
|
|
|
|
notifications. */
|
|
|
|
|
void notificationSender();
|
|
|
|
|
|
|
|
|
|
/* Acquire the global queue runner lock, or null if somebody else
|
|
|
|
|
has it. */
|
2015-07-07 08:29:43 +00:00
|
|
|
|
std::shared_ptr<nix::PathLocks> acquireGlobalLock();
|
2015-07-07 08:17:21 +00:00
|
|
|
|
|
|
|
|
|
void dumpStatus(Connection & conn, bool log);
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
void showStatus();
|
|
|
|
|
|
|
|
|
|
void unlock();
|
|
|
|
|
|
|
|
|
|
void run(BuildID buildOne = 0);
|
|
|
|
|
};
|