Merge pull request #10749 from NixOS/serve-protocol-stuff-for-hydra

Query path infos (plural) and handshake version minimum for hydra
This commit is contained in:
John Ericson 2024-05-20 18:10:47 -04:00 committed by GitHub
commit a57abbd143
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 50 additions and 18 deletions

View file

@ -105,24 +105,26 @@ void LegacySSHStore::queryPathInfoUncached(const StorePath & path,
debug("querying remote host '%s' for info on '%s'", host, printStorePath(path)); debug("querying remote host '%s' for info on '%s'", host, printStorePath(path));
conn->to << ServeProto::Command::QueryPathInfos << PathSet{printStorePath(path)}; auto infos = conn->queryPathInfos(*this, {path});
conn->to.flush();
auto p = readString(conn->from); switch (infos.size()) {
if (p.empty()) return callback(nullptr); case 0:
auto path2 = parseStorePath(p); return callback(nullptr);
assert(path == path2); case 1: {
auto info = std::make_shared<ValidPathInfo>( auto & [path2, info] = *infos.begin();
path,
ServeProto::Serialise<UnkeyedValidPathInfo>::read(*this, *conn));
if (info->narHash == Hash::dummy) if (info.narHash == Hash::dummy)
throw Error("NAR hash is now mandatory"); throw Error("NAR hash is now mandatory");
auto s = readString(conn->from); assert(path == path2);
assert(s == ""); return callback(std::make_shared<ValidPathInfo>(
std::move(path),
callback(std::move(info)); std::move(info)
));
}
default:
throw Error("More path infos returned than queried");
}
} catch (...) { callback.rethrow(); } } catch (...) { callback.rethrow(); }
} }

View file

@ -19,7 +19,7 @@ ServeProto::Version ServeProto::BasicClientConnection::handshake(
auto remoteVersion = readInt(from); auto remoteVersion = readInt(from);
if (GET_PROTOCOL_MAJOR(remoteVersion) != 0x200) if (GET_PROTOCOL_MAJOR(remoteVersion) != 0x200)
throw Error("unsupported 'nix-store --serve' protocol version on '%s'", host); throw Error("unsupported 'nix-store --serve' protocol version on '%s'", host);
return remoteVersion; return std::min(remoteVersion, localVersion);
} }
ServeProto::Version ServeProto::BasicServerConnection::handshake( ServeProto::Version ServeProto::BasicServerConnection::handshake(
@ -31,7 +31,8 @@ ServeProto::Version ServeProto::BasicServerConnection::handshake(
if (magic != SERVE_MAGIC_1) throw Error("protocol mismatch"); if (magic != SERVE_MAGIC_1) throw Error("protocol mismatch");
to << SERVE_MAGIC_2 << localVersion; to << SERVE_MAGIC_2 << localVersion;
to.flush(); to.flush();
return readInt(from); auto remoteVersion = readInt(from);
return std::min(remoteVersion, localVersion);
} }
@ -51,6 +52,30 @@ StorePathSet ServeProto::BasicClientConnection::queryValidPaths(
} }
std::map<StorePath, UnkeyedValidPathInfo> ServeProto::BasicClientConnection::queryPathInfos(
const Store & store,
const StorePathSet & paths)
{
std::map<StorePath, UnkeyedValidPathInfo> infos;
to << ServeProto::Command::QueryPathInfos;
ServeProto::write(store, *this, paths);
to.flush();
while (true) {
auto storePathS = readString(from);
if (storePathS == "") break;
auto storePath = store.parseStorePath(storePathS);
assert(paths.count(storePath) == 1);
auto info = ServeProto::Serialise<UnkeyedValidPathInfo>::read(store, *this);
infos.insert_or_assign(std::move(storePath), std::move(info));
}
return infos;
}
void ServeProto::BasicClientConnection::putBuildDerivationRequest( void ServeProto::BasicClientConnection::putBuildDerivationRequest(
const Store & store, const Store & store,
const StorePath & drvPath, const BasicDerivation & drv, const StorePath & drvPath, const BasicDerivation & drv,

View file

@ -122,6 +122,10 @@ struct ServeProto::BasicClientConnection
bool lock, const StorePathSet & paths, bool lock, const StorePathSet & paths,
SubstituteFlag maybeSubstitute); SubstituteFlag maybeSubstitute);
std::map<StorePath, UnkeyedValidPathInfo> queryPathInfos(
const Store & store,
const StorePathSet & paths);
/** /**
* Just the request half, because Hydra may do other things between * Just the request half, because Hydra may do other things between
* issuing the request and reading the `BuildResult` response. * issuing the request and reading the `BuildResult` response.

View file

@ -505,7 +505,8 @@ TEST_F(ServeProtoTest, handshake_client_corrupted_throws)
} else { } else {
auto ver = ServeProto::BasicClientConnection::handshake( auto ver = ServeProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion, "blah"); nullSink, in, defaultVersion, "blah");
EXPECT_NE(ver, defaultVersion); // `std::min` of this and the other version saves us
EXPECT_EQ(ver, defaultVersion);
} }
} }
}); });