2012-07-18 18:59:03 +00:00
|
|
|
#pragma once
|
2023-04-01 03:18:41 +00:00
|
|
|
///@file
|
2006-11-30 20:13:59 +00:00
|
|
|
|
2024-03-04 03:24:23 +00:00
|
|
|
#include "common-protocol.hh"
|
2020-10-08 15:36:51 +00:00
|
|
|
|
2006-12-05 01:31:45 +00:00
|
|
|
namespace nix {
|
|
|
|
|
|
|
|
|
2007-09-18 09:11:20 +00:00
|
|
|
#define WORKER_MAGIC_1 0x6e697863
|
|
|
|
#define WORKER_MAGIC_2 0x6478696f
|
|
|
|
|
2024-05-25 02:45:05 +00:00
|
|
|
// This must remain 1.35 (Nix 2.18) forever in Lix, since the protocol has
|
|
|
|
// diverged in CppNix such that we cannot assign newer versions ourselves, the
|
|
|
|
// protocol is bad in design and implementation and Lix intends to replace it
|
|
|
|
// entirely.
|
2022-12-26 20:21:08 +00:00
|
|
|
#define PROTOCOL_VERSION (1 << 8 | 35)
|
2024-05-25 02:45:05 +00:00
|
|
|
// Nix 2.3 is protocol 1.21 (see RemoteStore::initConnection for client,
|
|
|
|
// processConnection for server).
|
|
|
|
#define MIN_SUPPORTED_MINOR_WORKER_PROTO_VERSION 21
|
|
|
|
#define MIN_SUPPORTED_WORKER_PROTO_VERSION (1 << 8 | MIN_SUPPORTED_MINOR_WORKER_PROTO_VERSION)
|
|
|
|
|
2007-09-18 09:11:20 +00:00
|
|
|
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
|
2007-11-16 16:15:26 +00:00
|
|
|
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
|
2006-11-30 20:13:59 +00:00
|
|
|
|
|
|
|
|
2024-06-18 05:13:24 +00:00
|
|
|
#define REMOVE_AFTER_DROPPING_PROTO_MINOR(protoMinor) \
|
|
|
|
static_assert(MIN_SUPPORTED_MINOR_WORKER_PROTO_VERSION <= (protoMinor))
|
|
|
|
|
|
|
|
|
2006-12-03 02:08:13 +00:00
|
|
|
#define STDERR_NEXT 0x6f6c6d67
|
2007-02-21 17:34:02 +00:00
|
|
|
#define STDERR_READ 0x64617461 // data needed from source
|
|
|
|
#define STDERR_WRITE 0x64617416 // data for sink
|
2006-12-03 02:08:13 +00:00
|
|
|
#define STDERR_LAST 0x616c7473
|
|
|
|
#define STDERR_ERROR 0x63787470
|
2017-08-28 16:49:42 +00:00
|
|
|
#define STDERR_START_ACTIVITY 0x53545254
|
|
|
|
#define STDERR_STOP_ACTIVITY 0x53544f50
|
|
|
|
#define STDERR_RESULT 0x52534c54
|
2006-12-03 02:08:13 +00:00
|
|
|
|
|
|
|
|
2018-09-24 11:53:44 +00:00
|
|
|
class Store;
|
2019-10-30 19:38:02 +00:00
|
|
|
struct Source;
|
2018-09-24 11:53:44 +00:00
|
|
|
|
2023-05-26 15:07:25 +00:00
|
|
|
// items being serialised
|
2022-03-08 22:03:03 +00:00
|
|
|
struct DerivedPath;
|
|
|
|
struct BuildResult;
|
|
|
|
struct KeyedBuildResult;
|
2024-03-04 03:59:31 +00:00
|
|
|
struct ValidPathInfo;
|
|
|
|
struct UnkeyedValidPathInfo;
|
2022-03-08 22:03:03 +00:00
|
|
|
enum TrustedFlag : bool;
|
|
|
|
|
|
|
|
|
2023-03-27 01:12:25 +00:00
|
|
|
/**
|
2023-05-26 15:07:25 +00:00
|
|
|
* The "worker protocol", used by unix:// and ssh-ng:// stores.
|
2023-03-27 01:12:25 +00:00
|
|
|
*
|
2023-05-26 15:07:25 +00:00
|
|
|
* This `struct` is basically just a `namespace`; We use a type rather
|
|
|
|
* than a namespace just so we can use it as a template argument.
|
2023-03-27 01:12:25 +00:00
|
|
|
*/
|
2023-05-26 15:07:25 +00:00
|
|
|
struct WorkerProto
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Enumeration of all the request types for the protocol.
|
|
|
|
*/
|
|
|
|
enum struct Op : uint64_t;
|
|
|
|
|
2023-10-20 13:34:26 +00:00
|
|
|
/**
|
|
|
|
* Version type for the protocol.
|
|
|
|
*
|
|
|
|
* @todo Convert to struct with separate major vs minor fields.
|
|
|
|
*/
|
|
|
|
using Version = unsigned int;
|
|
|
|
|
2023-04-17 17:40:46 +00:00
|
|
|
/**
|
|
|
|
* A unidirectional read connection, to be used by the read half of the
|
|
|
|
* canonical serializers below.
|
|
|
|
*/
|
|
|
|
struct ReadConn {
|
|
|
|
Source & from;
|
2023-10-20 13:34:26 +00:00
|
|
|
Version version;
|
2024-05-25 02:45:05 +00:00
|
|
|
|
|
|
|
ReadConn(Source & from, Version version) : from(from), version(version) {
|
|
|
|
assert(version >= MIN_SUPPORTED_WORKER_PROTO_VERSION);
|
|
|
|
}
|
2023-04-17 17:40:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A unidirectional write connection, to be used by the write half of the
|
|
|
|
* canonical serializers below.
|
|
|
|
*/
|
|
|
|
struct WriteConn {
|
2023-10-20 13:34:26 +00:00
|
|
|
Version version;
|
2024-05-25 02:45:05 +00:00
|
|
|
|
2024-07-08 00:18:03 +00:00
|
|
|
explicit WriteConn(Version version) : version(version) {
|
2024-05-25 02:45:05 +00:00
|
|
|
assert(version >= MIN_SUPPORTED_WORKER_PROTO_VERSION);
|
|
|
|
}
|
2023-04-17 17:40:46 +00:00
|
|
|
};
|
|
|
|
|
2023-05-26 15:07:25 +00:00
|
|
|
/**
|
|
|
|
* Data type for canonical pairs of serialisers for the worker protocol.
|
|
|
|
*
|
|
|
|
* See https://en.cppreference.com/w/cpp/language/adl for the broader
|
|
|
|
* concept of what is going on here.
|
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
struct Serialise;
|
|
|
|
// This is the definition of `Serialise` we *want* to put here, but
|
|
|
|
// do not do so.
|
|
|
|
//
|
|
|
|
// The problem is that if we do so, C++ will think we have
|
|
|
|
// seralisers for *all* types. We don't, of course, but that won't
|
|
|
|
// cause an error until link time. That makes for long debug cycles
|
|
|
|
// when there is a missing serialiser.
|
|
|
|
//
|
|
|
|
// By not defining it globally, and instead letting individual
|
|
|
|
// serialisers specialise the type, we get back the compile-time
|
|
|
|
// errors we would like. When no serialiser exists, C++ sees an
|
|
|
|
// abstract "incomplete" type with no definition, and any attempt to
|
|
|
|
// use `to` or `from` static methods is a compile-time error because
|
|
|
|
// they don't exist on an incomplete type.
|
|
|
|
//
|
|
|
|
// This makes for a quicker debug cycle, as desired.
|
|
|
|
#if 0
|
|
|
|
{
|
2023-04-17 17:40:46 +00:00
|
|
|
static T read(const Store & store, ReadConn conn);
|
2024-05-18 00:35:34 +00:00
|
|
|
static WireFormatGenerator write(const Store & store, WriteConn conn, const T & t);
|
2023-05-26 15:07:25 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wrapper function around `WorkerProto::Serialise<T>::write` that allows us to
|
|
|
|
* infer the type instead of having to write it down explicitly.
|
|
|
|
*/
|
|
|
|
template<typename T>
|
2024-05-18 00:35:34 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
static WireFormatGenerator write(const Store & store, WriteConn conn, const T & t)
|
2023-05-26 15:07:25 +00:00
|
|
|
{
|
2024-05-18 00:35:34 +00:00
|
|
|
return WorkerProto::Serialise<T>::write(store, conn, t);
|
2023-05-26 15:07:25 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
enum struct WorkerProto::Op : uint64_t
|
|
|
|
{
|
|
|
|
IsValidPath = 1,
|
2024-06-18 05:13:24 +00:00
|
|
|
HasSubstitutes = 3, // obsolete since 2012, stubbed to error
|
|
|
|
QueryPathHash = 4, // obsolete since 2016, stubbed to error
|
|
|
|
QueryReferences = 5, // obsolete since 2016, stubbed to error
|
2023-05-26 15:07:25 +00:00
|
|
|
QueryReferrers = 6,
|
|
|
|
AddToStore = 7,
|
2024-06-18 05:13:24 +00:00
|
|
|
AddTextToStore = 8, // obsolete since protocol 1.25, CppNix 2.4. Use WorkerProto::Op::AddToStore
|
2023-05-26 15:07:25 +00:00
|
|
|
BuildPaths = 9,
|
|
|
|
EnsurePath = 10,
|
|
|
|
AddTempRoot = 11,
|
|
|
|
AddIndirectRoot = 12,
|
2024-06-18 05:13:24 +00:00
|
|
|
SyncWithGC = 13, // obsolete since CppNix 2.5.0
|
2023-05-26 15:07:25 +00:00
|
|
|
FindRoots = 14,
|
2024-06-18 05:13:24 +00:00
|
|
|
ExportPath = 16, // obsolete since 2017, stubbed to error
|
|
|
|
QueryDeriver = 18, // obsolete since 2016, stubbed to error
|
2023-05-26 15:07:25 +00:00
|
|
|
SetOptions = 19,
|
|
|
|
CollectGarbage = 20,
|
|
|
|
QuerySubstitutablePathInfo = 21,
|
2024-06-18 05:13:24 +00:00
|
|
|
QueryDerivationOutputs = 22, // obsolete since protocol 1.21, CppNix 2.4
|
2023-05-26 15:07:25 +00:00
|
|
|
QueryAllValidPaths = 23,
|
2024-06-18 05:13:24 +00:00
|
|
|
QueryFailedPaths = 24, // obsolete, removed
|
|
|
|
ClearFailedPaths = 25, // obsolete, removed
|
2023-05-26 15:07:25 +00:00
|
|
|
QueryPathInfo = 26,
|
2024-06-18 05:13:24 +00:00
|
|
|
ImportPaths = 27, // obsolete since 2016
|
|
|
|
QueryDerivationOutputNames = 28, // obsolete since CppNix 2.4
|
2023-05-26 15:07:25 +00:00
|
|
|
QueryPathFromHashPart = 29,
|
|
|
|
QuerySubstitutablePathInfos = 30,
|
|
|
|
QueryValidPaths = 31,
|
|
|
|
QuerySubstitutablePaths = 32,
|
|
|
|
QueryValidDerivers = 33,
|
|
|
|
OptimiseStore = 34,
|
|
|
|
VerifyStore = 35,
|
|
|
|
BuildDerivation = 36,
|
|
|
|
AddSignatures = 37,
|
|
|
|
NarFromPath = 38,
|
|
|
|
AddToStoreNar = 39,
|
|
|
|
QueryMissing = 40,
|
|
|
|
QueryDerivationOutputMap = 41,
|
|
|
|
RegisterDrvOutput = 42,
|
|
|
|
QueryRealisation = 43,
|
|
|
|
AddMultipleToStore = 44,
|
|
|
|
AddBuildLog = 45,
|
|
|
|
BuildPathsWithResults = 46,
|
2023-05-18 02:04:59 +00:00
|
|
|
};
|
2020-09-30 00:39:06 +00:00
|
|
|
|
2023-05-18 02:04:59 +00:00
|
|
|
/**
|
2023-05-26 15:07:25 +00:00
|
|
|
* Convenience for sending operation codes.
|
|
|
|
*
|
|
|
|
* @todo Switch to using `WorkerProto::Serialise` instead probably. But
|
|
|
|
* this was not done at this time so there would be less churn.
|
2023-05-18 02:04:59 +00:00
|
|
|
*/
|
2023-05-26 15:07:25 +00:00
|
|
|
inline Sink & operator << (Sink & sink, WorkerProto::Op op)
|
|
|
|
{
|
|
|
|
return sink << (uint64_t) op;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience for debugging.
|
|
|
|
*
|
|
|
|
* @todo Perhaps render known opcodes more nicely.
|
|
|
|
*/
|
|
|
|
inline std::ostream & operator << (std::ostream & s, WorkerProto::Op op)
|
2023-05-18 02:04:59 +00:00
|
|
|
{
|
2023-05-26 15:07:25 +00:00
|
|
|
return s << (uint64_t) op;
|
2023-05-18 02:04:59 +00:00
|
|
|
}
|
2020-09-30 00:39:06 +00:00
|
|
|
|
2023-05-18 02:04:59 +00:00
|
|
|
/**
|
2023-05-26 15:07:25 +00:00
|
|
|
* Declare a canonical serialiser pair for the worker protocol.
|
2023-05-18 02:04:59 +00:00
|
|
|
*
|
2023-05-26 15:07:25 +00:00
|
|
|
* We specialise the struct merely to indicate that we are implementing
|
2023-05-18 02:04:59 +00:00
|
|
|
* the function for the given type.
|
|
|
|
*
|
|
|
|
* Some sort of `template<...>` must be used with the caller for this to
|
|
|
|
* be legal specialization syntax. See below for what that looks like in
|
|
|
|
* practice.
|
|
|
|
*/
|
2024-03-04 03:24:23 +00:00
|
|
|
#define DECLARE_WORKER_SERIALISER(T) \
|
|
|
|
struct WorkerProto::Serialise< T > \
|
|
|
|
{ \
|
2023-04-17 17:40:46 +00:00
|
|
|
static T read(const Store & store, WorkerProto::ReadConn conn); \
|
2024-05-18 00:35:34 +00:00
|
|
|
[[nodiscard]] static WireFormatGenerator write(const Store & store, WorkerProto::WriteConn conn, const T & t); \
|
2023-05-18 02:04:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
2024-03-04 03:24:23 +00:00
|
|
|
DECLARE_WORKER_SERIALISER(DerivedPath);
|
2023-05-18 02:04:59 +00:00
|
|
|
template<>
|
2024-03-04 03:24:23 +00:00
|
|
|
DECLARE_WORKER_SERIALISER(BuildResult);
|
2023-05-18 02:04:59 +00:00
|
|
|
template<>
|
2024-03-04 03:24:23 +00:00
|
|
|
DECLARE_WORKER_SERIALISER(KeyedBuildResult);
|
2023-05-18 02:04:59 +00:00
|
|
|
template<>
|
2024-03-04 03:59:31 +00:00
|
|
|
DECLARE_WORKER_SERIALISER(ValidPathInfo);
|
|
|
|
template<>
|
|
|
|
DECLARE_WORKER_SERIALISER(UnkeyedValidPathInfo);
|
|
|
|
template<>
|
2024-03-04 03:24:23 +00:00
|
|
|
DECLARE_WORKER_SERIALISER(std::optional<TrustedFlag>);
|
2020-09-30 00:39:06 +00:00
|
|
|
|
2023-05-18 02:04:59 +00:00
|
|
|
template<typename T>
|
2024-03-04 03:24:23 +00:00
|
|
|
DECLARE_WORKER_SERIALISER(std::vector<T>);
|
2023-05-18 02:04:59 +00:00
|
|
|
template<typename T>
|
2024-03-04 03:24:23 +00:00
|
|
|
DECLARE_WORKER_SERIALISER(std::set<T>);
|
2024-03-04 02:46:48 +00:00
|
|
|
template<typename... Ts>
|
2024-03-04 03:24:23 +00:00
|
|
|
DECLARE_WORKER_SERIALISER(std::tuple<Ts...>);
|
2020-08-06 22:04:13 +00:00
|
|
|
|
2024-03-04 03:24:23 +00:00
|
|
|
#define COMMA_ ,
|
2023-05-18 02:04:59 +00:00
|
|
|
template<typename K, typename V>
|
2024-03-04 03:24:23 +00:00
|
|
|
DECLARE_WORKER_SERIALISER(std::map<K COMMA_ V>);
|
|
|
|
#undef COMMA_
|
2020-10-07 12:48:35 +00:00
|
|
|
|
2020-09-30 00:39:06 +00:00
|
|
|
}
|