nix-store --serve: Use a versioned protocol

Signed-off-by: Shea Levy <shea@shealevy.com>
This commit is contained in:
Shea Levy 2014-02-10 07:43:13 -05:00
parent 38c3beac1a
commit c89d6b9b63
4 changed files with 102 additions and 34 deletions

View file

@ -4,6 +4,7 @@
#include "archive.hh" #include "archive.hh"
#include "affinity.hh" #include "affinity.hh"
#include "globals.hh" #include "globals.hh"
#include "serve-protocol.hh"
#include <iostream> #include <iostream>
#include <unistd.h> #include <unistd.h>
@ -54,7 +55,7 @@ static pair<FdSink, FdSource> connect(string conn) {
} }
static void substitute(pair<FdSink, FdSource> & pipes, Path storePath, Path destPath) { static void substitute(pair<FdSink, FdSource> & pipes, Path storePath, Path destPath) {
writeString("substitute", pipes.first); writeInt(cmdSubstitute, pipes.first);
writeString(storePath, pipes.first); writeString(storePath, pipes.first);
pipes.first.flush(); pipes.first.flush();
restorePath(destPath, pipes.second); restorePath(destPath, pipes.second);
@ -63,20 +64,24 @@ static void substitute(pair<FdSink, FdSource> & pipes, Path storePath, Path dest
static void query(pair<FdSink, FdSource> & pipes) { static void query(pair<FdSink, FdSource> & pipes) {
using std::cin; using std::cin;
writeString("query", pipes.first); writeInt(cmdQuery, pipes.first);
for (string line; getline(cin, line);) { for (string line; getline(cin, line);) {
Strings tokenized = tokenizeString<Strings>(line); Strings tokenized = tokenizeString<Strings>(line);
string cmd = tokenized.front(); string cmd = tokenized.front();
writeString(cmd, pipes.first);
tokenized.pop_front(); tokenized.pop_front();
if (cmd == "have") {
writeInt(qCmdHave, pipes.first);
foreach (Strings::iterator, i, tokenized) foreach (Strings::iterator, i, tokenized)
writeStrings(tokenized, pipes.first); writeStrings(tokenized, pipes.first);
pipes.first.flush(); pipes.first.flush();
if (cmd == "have") {
PathSet paths = readStrings<PathSet>(pipes.second); PathSet paths = readStrings<PathSet>(pipes.second);
foreach (PathSet::iterator, i, paths) foreach (PathSet::iterator, i, paths)
cout << *i << endl; cout << *i << endl;
} else if (cmd == "info") { } else if (cmd == "info") {
writeInt(qCmdInfo, pipes.first);
foreach (Strings::iterator, i, tokenized)
writeStrings(tokenized, pipes.first);
pipes.first.flush();
for (Path path = readString(pipes.second); !path.empty(); path = readString(pipes.second)) { for (Path path = readString(pipes.second); !path.empty(); path = readString(pipes.second)) {
cout << path << endl; cout << path << endl;
cout << readString(pipes.second) << endl; cout << readString(pipes.second) << endl;
@ -91,7 +96,6 @@ static void query(pair<FdSink, FdSource> & pipes) {
throw Error(format("Unknown substituter query `%1%'") % cmd); throw Error(format("Unknown substituter query `%1%'") % cmd);
cout << endl; cout << endl;
} }
writeString("", pipes.first);
} }
void run(Strings args) void run(Strings args)
@ -106,6 +110,16 @@ void run(Strings args)
pair<FdSink, FdSource> pipes = connect(settings.sshSubstituterHosts.front()); pair<FdSink, FdSource> pipes = connect(settings.sshSubstituterHosts.front());
/* Exchange the greeting */
writeInt(SERVE_MAGIC_1, pipes.first);
pipes.first.flush();
unsigned int magic = readInt(pipes.second);
if (magic != SERVE_MAGIC_2)
throw Error("protocol mismatch");
readInt(pipes.second); // Server version, unused for now
writeInt(SERVE_PROTOCOL_VERSION, pipes.first);
pipes.first.flush();
Strings::iterator i = args.begin(); Strings::iterator i = args.begin();
if (*i == "--query") if (*i == "--query")
query(pipes); query(pipes);

View file

@ -6,4 +6,6 @@ download-via-ssh_SOURCES := $(d)/download-via-ssh.cc
download-via-ssh_INSTALL_DIR := $(libexecdir)/nix/substituters download-via-ssh_INSTALL_DIR := $(libexecdir)/nix/substituters
download-via-ssh_CXXFLAGS = -Isrc/nix-store
download-via-ssh_LIBS = libmain libstore libutil libformat download-via-ssh_LIBS = libmain libstore libutil libformat

View file

@ -6,6 +6,7 @@
#include "xmlgraph.hh" #include "xmlgraph.hh"
#include "local-store.hh" #include "local-store.hh"
#include "util.hh" #include "util.hh"
#include "serve-protocol.hh"
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
@ -843,13 +844,34 @@ static void opServe(Strings opFlags, Strings opArgs)
FdSource in(STDIN_FILENO); FdSource in(STDIN_FILENO);
FdSink out(STDOUT_FILENO); FdSink out(STDOUT_FILENO);
string cmd = readString(in); /* Exchange the greeting. */
if (cmd == "query") { unsigned int magic = readInt(in);
for (cmd = readString(in); !cmd.empty(); cmd = readString(in)) { if (magic != SERVE_MAGIC_1) throw Error("protocol mismatch");
writeInt(SERVE_MAGIC_2, out);
writeInt(SERVE_PROTOCOL_VERSION, out);
out.flush();
readInt(in); // Client version, unused for now
ServeCommand cmd = (ServeCommand) readInt(in);
switch (cmd) {
case cmdQuery:
while (true) {
QueryCommand qCmd;
try {
qCmd = (QueryCommand) readInt(in);
} catch (EndOfFile & e) {
break;
}
switch (qCmd) {
case qCmdHave:
{
PathSet paths = readStrings<PathSet>(in); PathSet paths = readStrings<PathSet>(in);
if (cmd == "have") {
writeStrings(store->queryValidPaths(paths), out); writeStrings(store->queryValidPaths(paths), out);
} else if (cmd == "info") { }
break;
case qCmdInfo:
{
PathSet paths = readStrings<PathSet>(in);
// !!! Maybe we want a queryPathInfos? // !!! Maybe we want a queryPathInfos?
foreach (PathSet::iterator, i, paths) { foreach (PathSet::iterator, i, paths) {
if (!store->isValidPath(*i)) if (!store->isValidPath(*i))
@ -863,14 +885,20 @@ static void opServe(Strings opFlags, Strings opArgs)
writeLongLong(info.narSize, out); writeLongLong(info.narSize, out);
} }
writeString("", out); writeString("", out);
} else }
break;
default:
throw Error(format("Unknown serve query `%1%'") % cmd); throw Error(format("Unknown serve query `%1%'") % cmd);
}
out.flush(); out.flush();
} }
} else if (cmd == "substitute") break;
case cmdSubstitute:
dumpPath(readString(in), out); dumpPath(readString(in), out);
else break;
default:
throw Error(format("Unknown serve command `%1%'") % cmd); throw Error(format("Unknown serve command `%1%'") % cmd);
}
} }

View file

@ -0,0 +1,24 @@
#pragma once
namespace nix {
#define SERVE_MAGIC_1 0x390c9deb
#define SERVE_MAGIC_2 0x5452eecb
#define SERVE_PROTOCOL_VERSION 0x101
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
typedef enum {
cmdQuery = 0,
cmdSubstitute = 1,
} ServeCommand;
typedef enum {
qCmdHave = 0,
qCmdInfo = 1,
} QueryCommand;
}