2022-03-09 00:21:41 +02:00
# include "serialise.hh"
# include "path-with-outputs.hh"
# include "store-api.hh"
# include "build-result.hh"
# include "worker-protocol.hh"
2022-03-08 23:53:26 +02:00
# include "worker-protocol-impl.hh"
2022-03-09 00:21:41 +02:00
# include "archive.hh"
2022-03-09 01:09:26 +02:00
# include "path-info.hh"
2022-03-09 00:21:41 +02:00
2023-12-13 23:37:17 +02:00
# include <chrono>
2022-03-09 00:21:41 +02:00
# include <nlohmann/json.hpp>
2023-05-18 05:04:59 +03:00
namespace nix {
2022-03-09 00:21:41 +02:00
2022-03-25 06:39:57 +02:00
/* protocol-specific definitions */
2022-03-09 00:21:41 +02:00
2022-03-18 17:35:45 +02:00
std : : optional < TrustedFlag > WorkerProto : : Serialise < std : : optional < TrustedFlag > > : : read ( const StoreDirConfig & store , WorkerProto : : ReadConn conn )
2022-03-09 00:21:41 +02:00
{
2023-04-17 20:40:46 +03:00
auto temp = readNum < uint8_t > ( conn . from ) ;
2022-03-09 00:21:41 +02:00
switch ( temp ) {
case 0 :
return std : : nullopt ;
case 1 :
return { Trusted } ;
case 2 :
return { NotTrusted } ;
default :
throw Error ( " Invalid trusted status from remote " ) ;
}
}
2022-03-18 17:35:45 +02:00
void WorkerProto : : Serialise < std : : optional < TrustedFlag > > : : write ( const StoreDirConfig & store , WorkerProto : : WriteConn conn , const std : : optional < TrustedFlag > & optTrusted )
2022-03-09 00:21:41 +02:00
{
if ( ! optTrusted )
2023-11-07 14:40:21 +02:00
conn . to < < uint8_t { 0 } ;
2022-03-09 00:21:41 +02:00
else {
switch ( * optTrusted ) {
case Trusted :
2023-11-07 14:40:21 +02:00
conn . to < < uint8_t { 1 } ;
2022-03-09 00:21:41 +02:00
break ;
case NotTrusted :
2023-11-07 14:40:21 +02:00
conn . to < < uint8_t { 2 } ;
2022-03-09 00:21:41 +02:00
break ;
default :
assert ( false ) ;
} ;
}
}
2023-12-13 23:37:17 +02:00
std : : optional < std : : chrono : : microseconds > WorkerProto : : Serialise < std : : optional < std : : chrono : : microseconds > > : : read ( const StoreDirConfig & store , WorkerProto : : ReadConn conn )
{
auto tag = readNum < uint8_t > ( conn . from ) ;
switch ( tag ) {
case 0 :
return std : : nullopt ;
case 1 :
return std : : optional < std : : chrono : : microseconds > { std : : chrono : : microseconds ( readNum < int64_t > ( conn . from ) ) } ;
default :
throw Error ( " Invalid optional tag from remote " ) ;
}
}
void WorkerProto : : Serialise < std : : optional < std : : chrono : : microseconds > > : : write ( const StoreDirConfig & store , WorkerProto : : WriteConn conn , const std : : optional < std : : chrono : : microseconds > & optDuration )
{
if ( ! optDuration . has_value ( ) ) {
conn . to < < uint8_t { 0 } ;
} else {
conn . to
< < uint8_t { 1 }
< < optDuration . value ( ) . count ( ) ;
}
}
2022-03-18 17:35:45 +02:00
DerivedPath WorkerProto : : Serialise < DerivedPath > : : read ( const StoreDirConfig & store , WorkerProto : : ReadConn conn )
2022-03-09 00:21:41 +02:00
{
2023-04-17 20:40:46 +03:00
auto s = readString ( conn . from ) ;
2023-05-26 21:48:11 +03:00
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 30 ) {
return DerivedPath : : parseLegacy ( store , s ) ;
} else {
return parsePathWithOutputs ( store , s ) . toDerivedPath ( ) ;
}
2022-03-09 00:21:41 +02:00
}
2022-03-18 17:35:45 +02:00
void WorkerProto : : Serialise < DerivedPath > : : write ( const StoreDirConfig & store , WorkerProto : : WriteConn conn , const DerivedPath & req )
2022-03-09 00:21:41 +02:00
{
2023-05-26 21:48:11 +03:00
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 30 ) {
conn . to < < req . to_string_legacy ( store ) ;
} else {
auto sOrDrvPath = StorePathWithOutputs : : tryFromDerivedPath ( req ) ;
std : : visit ( overloaded {
[ & ] ( const StorePathWithOutputs & s ) {
conn . to < < s . to_string ( store ) ;
} ,
[ & ] ( const StorePath & drvPath ) {
throw Error ( " trying to request '%s', but daemon protocol %d.%d is too old (< 1.29) to request a derivation file " ,
store . printStorePath ( drvPath ) ,
GET_PROTOCOL_MAJOR ( conn . version ) ,
GET_PROTOCOL_MINOR ( conn . version ) ) ;
} ,
[ & ] ( std : : monostate ) {
throw Error ( " wanted to build a derivation that is itself a build product, but protocols do not support that. Try upgrading the Nix on the other end of this connection " ) ;
} ,
} , sOrDrvPath ) ;
}
2022-03-09 00:21:41 +02:00
}
2022-03-18 17:35:45 +02:00
KeyedBuildResult WorkerProto : : Serialise < KeyedBuildResult > : : read ( const StoreDirConfig & store , WorkerProto : : ReadConn conn )
2022-03-09 00:21:41 +02:00
{
2023-04-17 20:40:46 +03:00
auto path = WorkerProto : : Serialise < DerivedPath > : : read ( store , conn ) ;
auto br = WorkerProto : : Serialise < BuildResult > : : read ( store , conn ) ;
2022-03-09 00:21:41 +02:00
return KeyedBuildResult {
std : : move ( br ) ,
/* .path = */ std : : move ( path ) ,
} ;
}
2022-03-18 17:35:45 +02:00
void WorkerProto : : Serialise < KeyedBuildResult > : : write ( const StoreDirConfig & store , WorkerProto : : WriteConn conn , const KeyedBuildResult & res )
2022-03-09 00:21:41 +02:00
{
2023-04-17 20:40:46 +03:00
WorkerProto : : write ( store , conn , res . path ) ;
WorkerProto : : write ( store , conn , static_cast < const BuildResult & > ( res ) ) ;
2022-03-09 00:21:41 +02:00
}
2022-03-18 17:35:45 +02:00
BuildResult WorkerProto : : Serialise < BuildResult > : : read ( const StoreDirConfig & store , WorkerProto : : ReadConn conn )
2022-03-09 00:21:41 +02:00
{
BuildResult res ;
2023-11-07 14:40:21 +02:00
res . status = static_cast < BuildResult : : Status > ( readInt ( conn . from ) ) ;
2021-02-28 20:42:46 +02:00
conn . from > > res . errorMsg ;
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 29 ) {
conn . from
> > res . timesBuilt
> > res . isNonDeterministic
> > res . startTime
> > res . stopTime ;
}
2023-12-13 23:37:17 +02:00
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 37 ) {
res . cpuUser = WorkerProto : : Serialise < std : : optional < std : : chrono : : microseconds > > : : read ( store , conn ) ;
res . cpuSystem = WorkerProto : : Serialise < std : : optional < std : : chrono : : microseconds > > : : read ( store , conn ) ;
}
2021-02-28 20:42:46 +02:00
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 28 ) {
auto builtOutputs = WorkerProto : : Serialise < DrvOutputs > : : read ( store , conn ) ;
for ( auto & & [ output , realisation ] : builtOutputs )
res . builtOutputs . insert_or_assign (
std : : move ( output . outputName ) ,
std : : move ( realisation ) ) ;
}
2022-03-09 00:21:41 +02:00
return res ;
}
2022-03-18 17:35:45 +02:00
void WorkerProto : : Serialise < BuildResult > : : write ( const StoreDirConfig & store , WorkerProto : : WriteConn conn , const BuildResult & res )
2022-03-09 00:21:41 +02:00
{
2023-04-17 20:40:46 +03:00
conn . to
2022-03-09 00:21:41 +02:00
< < res . status
2021-02-28 20:42:46 +02:00
< < res . errorMsg ;
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 29 ) {
conn . to
< < res . timesBuilt
< < res . isNonDeterministic
< < res . startTime
< < res . stopTime ;
}
2023-12-13 23:37:17 +02:00
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 37 ) {
WorkerProto : : write ( store , conn , res . cpuUser ) ;
WorkerProto : : write ( store , conn , res . cpuSystem ) ;
}
2021-02-28 20:42:46 +02:00
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 28 ) {
DrvOutputs builtOutputs ;
for ( auto & [ output , realisation ] : res . builtOutputs )
builtOutputs . insert_or_assign ( realisation . id , realisation ) ;
WorkerProto : : write ( store , conn , builtOutputs ) ;
}
2022-03-09 00:21:41 +02:00
}
2022-03-18 17:35:45 +02:00
ValidPathInfo WorkerProto : : Serialise < ValidPathInfo > : : read ( const StoreDirConfig & store , ReadConn conn )
2022-03-09 01:09:26 +02:00
{
auto path = WorkerProto : : Serialise < StorePath > : : read ( store , conn ) ;
2023-04-18 00:13:44 +03:00
return ValidPathInfo {
std : : move ( path ) ,
WorkerProto : : Serialise < UnkeyedValidPathInfo > : : read ( store , conn ) ,
} ;
2022-03-09 01:09:26 +02:00
}
2022-03-18 17:35:45 +02:00
void WorkerProto : : Serialise < ValidPathInfo > : : write ( const StoreDirConfig & store , WriteConn conn , const ValidPathInfo & pathInfo )
2023-04-18 00:13:44 +03:00
{
WorkerProto : : write ( store , conn , pathInfo . path ) ;
WorkerProto : : write ( store , conn , static_cast < const UnkeyedValidPathInfo & > ( pathInfo ) ) ;
}
2022-03-18 17:35:45 +02:00
UnkeyedValidPathInfo WorkerProto : : Serialise < UnkeyedValidPathInfo > : : read ( const StoreDirConfig & store , ReadConn conn )
2022-03-09 01:09:26 +02:00
{
auto deriver = readString ( conn . from ) ;
2023-11-28 15:20:27 +02:00
auto narHash = Hash : : parseAny ( readString ( conn . from ) , HashAlgorithm : : SHA256 ) ;
2023-04-18 00:13:44 +03:00
UnkeyedValidPathInfo info ( narHash ) ;
2022-03-09 01:09:26 +02:00
if ( deriver ! = " " ) info . deriver = store . parseStorePath ( deriver ) ;
info . references = WorkerProto : : Serialise < StorePathSet > : : read ( store , conn ) ;
conn . from > > info . registrationTime > > info . narSize ;
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 16 ) {
conn . from > > info . ultimate ;
info . sigs = readStrings < StringSet > ( conn . from ) ;
info . ca = ContentAddress : : parseOpt ( readString ( conn . from ) ) ;
}
return info ;
}
2022-03-18 17:35:45 +02:00
void WorkerProto : : Serialise < UnkeyedValidPathInfo > : : write ( const StoreDirConfig & store , WriteConn conn , const UnkeyedValidPathInfo & pathInfo )
2022-03-09 01:09:26 +02:00
{
conn . to
< < ( pathInfo . deriver ? store . printStorePath ( * pathInfo . deriver ) : " " )
< < pathInfo . narHash . to_string ( HashFormat : : Base16 , false ) ;
WorkerProto : : write ( store , conn , pathInfo . references ) ;
conn . to < < pathInfo . registrationTime < < pathInfo . narSize ;
if ( GET_PROTOCOL_MINOR ( conn . version ) > = 16 ) {
conn . to
< < pathInfo . ultimate
< < pathInfo . sigs
< < renderContentAddress ( pathInfo . ca ) ;
}
}
2022-03-09 00:21:41 +02:00
}