Skip to content

Commit

Permalink
nixd: use lspserver for RPC client/server
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc committed Mar 15, 2024
1 parent a4c76a6 commit 62918a3
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 126 deletions.
12 changes: 1 addition & 11 deletions nixd/nix-node-eval/meson.build
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
nixd_nix_node_eval_deps = [ libnixdrpc, nixt, libnixdutil ]
nixd_nix_node_eval_deps = [ libnixdrpc, nixt, libnixdutil, nixd_lsp_server ]

nixd_nix_node_eval_lib = library(
'nix-node-eval',
Expand All @@ -19,13 +19,3 @@ nixd_nix_node_eval = executable('nix-node-eval',
install_dir: get_option('libexecdir'),
dependencies: nixd_nix_node_eval_lib_dep
)

test(
'unit/nixd/nix-node-eval',
executable(
'unit-nixd-nix-node-eval',
'test/EvalProvider.cpp',
dependencies: [ nixd_nix_node_eval_lib_dep, gtest_main],
include_directories: include_directories('src')
)
)
47 changes: 14 additions & 33 deletions nixd/nix-node-eval/src/EvalProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <nixt/Deserialize.h>
#include <nixt/HackCache.h>

#include <lspserver/LSPServer.h>

#include <bc/Read.h>
#include <bc/Write.h>

Expand All @@ -22,40 +24,17 @@

namespace nixd {

using bc::readBytecode;
using rpc::readBytecode;

namespace bipc = boost::interprocess;

using namespace rpc;

EvalProvider::EvalProvider(int InboundFD, int OutboundFD)
: rpc::Transport(InboundFD, OutboundFD),
EvalProvider::EvalProvider(std::unique_ptr<lspserver::InboundPort> In,
std::unique_ptr<lspserver::OutboundPort> Out)
: lspserver::LSPServer(std::move(In), std::move(Out)),
State(std::unique_ptr<nix::EvalState>(
new nix::EvalState{{}, nix::openStore("dummy://")})) {}

void EvalProvider::handleInbound(const std::vector<char> &Buf) {
std::ostringstream OS;
rpc::RPCKind Kind;
std::string_view Data(Buf.data(), Buf.size());
readBytecode(Data, Kind);
switch (Kind) {
case rpc::RPCKind::RegisterBC: {
rpc::RegisterBCParams Params;
readBytecode(Data, Params);
onRegisterBC(Params);
break;
}
case rpc::RPCKind::UnregisterBC:
case rpc::RPCKind::Log:
case rpc::RPCKind::ExprValue: {
rpc::ExprValueParams Params;
readBytecode(Data, Params);
rpc::ExprValueResponse Response = onExprValue(Params);
sendPacket<ExprValueResponse>(Response);
break;
}
}
new nix::EvalState{{}, nix::openStore("dummy://")})) {
Registry.addMethod("exprValue", this, &EvalProvider::onExprValue);
Registry.addNotification("registerBC", this, &EvalProvider::onRegisterBC);
}

void EvalProvider::onRegisterBC(const rpc::RegisterBCParams &Params) {
Expand Down Expand Up @@ -84,17 +63,19 @@ void EvalProvider::onRegisterBC(const rpc::RegisterBCParams &Params) {
Cache[CachePath] = AST;
}

ExprValueResponse EvalProvider::onExprValue(const ExprValueParams &Params) {
void EvalProvider::onExprValue(const ExprValueParams &Params,
lspserver::Callback<ExprValueResponse> Reply) {
if (VMap.contains(Params.ExprID)) {
nix::Value V = VMap[Params.ExprID];

return {
Reply(ExprValueResponse{
ExprValueResponse::OK,
static_cast<uintptr_t>(V.integer),
ExprValueResponse::Int,
};
});
return;
}
return {ExprValueResponse::NotEvaluated, 0};
Reply(ExprValueResponse{ExprValueResponse::NotEvaluated, 0});
}

} // namespace nixd
14 changes: 9 additions & 5 deletions nixd/nix-node-eval/src/EvalProvider.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include "nixd/rpc/Protocol.h"
#include "nixd/rpc/Transport.h"

#include <lspserver/Function.h>
#include <lspserver/LSPServer.h>

#include <nixt/HookExpr.h>
#include <nixt/PtrPool.h>
Expand All @@ -10,21 +12,23 @@

namespace nixd {

class EvalProvider : public rpc::Transport {
class EvalProvider : public lspserver::LSPServer {

nixt::PtrPool<nix::Expr> Pool;
nixt::ValueMap VMap;
nixt::EnvMap EMap;
std::unique_ptr<nix::EvalState> State;

void handleInbound(const std::vector<char> &Buf) override;
llvm::unique_function<void(int)> Exit;

public:
EvalProvider(int InboundFD, int OutboundFD);
EvalProvider(std::unique_ptr<lspserver::InboundPort> In,
std::unique_ptr<lspserver::OutboundPort> Out);

void onRegisterBC(const rpc::RegisterBCParams &Params);

rpc::ExprValueResponse onExprValue(const rpc::ExprValueParams &Params);
void onExprValue(const rpc::ExprValueParams &Params,
lspserver::Callback<rpc::ExprValueResponse>);
};

} // namespace nixd
11 changes: 9 additions & 2 deletions nixd/nix-node-eval/src/Main.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@

#include "EvalProvider.h"

#include <lspserver/Connection.h>

#include <nixt/InitEval.h>

#include <unistd.h>

int main() {
nixt::initEval();
nixd::EvalProvider Provider(STDIN_FILENO, STDOUT_FILENO);
return Provider.run();
auto In = std::make_unique<lspserver::InboundPort>(
STDIN_FILENO, lspserver::JSONStreamStyle::Standard);

auto Out = std::make_unique<lspserver::OutboundPort>(false);
nixd::EvalProvider Provider(std::move(In), std::move(Out));

Provider.run();
}
44 changes: 0 additions & 44 deletions nixd/nix-node-eval/test/EvalProvider.cpp

This file was deleted.

2 changes: 1 addition & 1 deletion nixd/tools/nixd/src/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace nixd {

class Controller : public lspserver::LSPServer {
std::unique_ptr<EvalClient> Eval;
std::unique_ptr<OwnedEvalClient> Eval;
lspserver::DraftStore Store;

llvm::unique_function<void(const lspserver::PublishDiagnosticsParams &)>
Expand Down
22 changes: 10 additions & 12 deletions nixd/tools/nixd/src/EvalClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,21 @@

#include "EvalClient.h"

#include "nixd/rpc/Protocol.h"
#include "nixd/util/ForkPiped.h"

#include <bc/Read.h>
#include <bc/Write.h>

#include <llvm/Support/raw_ostream.h>

#include <unistd.h>

namespace nixd {

using namespace rpc;
using namespace nixd::util;

template <class T> using M = Message<T>;

std::unique_ptr<EvalClient> EvalClient::create(int &Fail) {
std::unique_ptr<OwnedEvalClient> OwnedEvalClient::create(int &Fail) {
int In;
int Out;
int Err;
Expand All @@ -35,16 +34,15 @@ std::unique_ptr<EvalClient> EvalClient::create(int &Fail) {
Fail = 0;
// Parent process.
auto Proc = std::make_unique<PipedProc>(Child, In, Out, Err);
return std::make_unique<EvalClient>(Out, In, std::move(Proc));
}
auto InP = std::make_unique<lspserver::InboundPort>(
Out, lspserver::JSONStreamStyle::Standard);

void EvalClient::registerBC(const RegisterBCParams &Params) {
sendPacket<M<RegisterBCParams>>({RPCKind::RegisterBC, Params});
}
auto ProcFdStream = std::make_unique<llvm::raw_fd_ostream>(In, false);

ExprValueResponse EvalClient::exprValue(const ExprValueParams &Params) {
sendPacket<M<ExprValueParams>>({RPCKind::ExprValue, Params});
return recvPacket<ExprValueResponse>();
auto OutP = std::make_unique<lspserver::OutboundPort>(*ProcFdStream, false);
return std::make_unique<OwnedEvalClient>(std::move(InP), std::move(OutP),
std::move(Proc),
std::move(ProcFdStream));
}

} // namespace nixd
57 changes: 42 additions & 15 deletions nixd/tools/nixd/src/EvalClient.h
Original file line number Diff line number Diff line change
@@ -1,35 +1,62 @@
#pragma once

#include "nixd/rpc/Protocol.h"
#include "nixd/rpc/Transport.h"

#include "nixd/util/PipedProc.h"

#include <lspserver/LSPServer.h>

#include <memory>
#include <thread>

namespace nixd {

class EvalClient : public rpc::Transport {
// Owned process of the evaluator
class EvalClient : public lspserver::LSPServer {
public:
llvm::unique_function<void(const rpc::RegisterBCParams &)> RegisterBC;
llvm::unique_function<void(const rpc::ExprValueParams &,
lspserver::Callback<rpc::ExprValueResponse>)>
ExprValue;

EvalClient(std::unique_ptr<lspserver::InboundPort> In,
std::unique_ptr<lspserver::OutboundPort> Out)
: lspserver::LSPServer(std::move(In), std::move(Out)) {
RegisterBC = mkOutNotifiction<rpc::RegisterBCParams>("registerBC");
ExprValue =
mkOutMethod<rpc::ExprValueParams, rpc::ExprValueResponse>("exprValue");
}

virtual ~EvalClient() = default;
};

class OwnedEvalClient : public EvalClient {
std::unique_ptr<util::PipedProc> Proc;
void handleInbound(const std::vector<char> &Buf) override{};
std::unique_ptr<llvm::raw_fd_ostream> Stream;

std::thread Input;

public:
EvalClient(int InboundFD, int OutboundFD,
std::unique_ptr<util::PipedProc> Proc)
: rpc::Transport(InboundFD, OutboundFD), Proc(std::move(Proc)) {}
OwnedEvalClient(std::unique_ptr<lspserver::InboundPort> In,
std::unique_ptr<lspserver::OutboundPort> Out,
std::unique_ptr<util::PipedProc> Proc,
std::unique_ptr<llvm::raw_fd_ostream> Stream)
: EvalClient(std::move(In), std::move(Out)), Proc(std::move(Proc)),
Stream(std::move(Stream)) {

virtual ~EvalClient() = default;
Input = std::thread([this]() { run(); });
}

util::PipedProc &proc() { return *Proc; }

~OwnedEvalClient() {
closeInbound();
Input.join();
}

/// Lanch nix-node-eval, with properly handled file descriptors.
/// System-wide errno will be written into "Fail" variable and thus cannot be
/// discarded.
static std::unique_ptr<EvalClient> create(int &Fail);

void registerBC(const rpc::RegisterBCParams &Params);

rpc::ExprValueResponse exprValue(const rpc::ExprValueParams &Params);

util::PipedProc *proc() { return Proc.get(); }
static std::unique_ptr<OwnedEvalClient> create(int &Fail);
};

} // namespace nixd
4 changes: 2 additions & 2 deletions nixd/tools/nixd/src/LifeTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ void Controller::
"textDocument/publishDiagnostics");

int Fail;
Eval = EvalClient::create(Fail);
Eval = OwnedEvalClient::create(Fail);
if (Fail != 0) {
lspserver::elog("failed to create nix-node-eval worker: {0}",
strerror(-Fail));
} else {
lspserver::log("launched nix-node-eval instance: {0}", Eval->proc()->PID);
lspserver::log("launched nix-node-eval instance: {0}", Eval->proc().PID);
}
}

Expand Down
3 changes: 2 additions & 1 deletion nixd/tools/nixd/src/Support.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "Controller.h"

#include "nixd/rpc/Protocol.h"
#include "nixd/util/OwnedRegion.h"

#include "nixf/Basic/Diagnostic.h"
Expand Down Expand Up @@ -68,7 +69,7 @@ void Controller::actOnDocumentAdd(PathRef File,
util::OwnedRegion{std::move(Shm), std::move(Region)});

if (Eval) {
Eval->registerBC({ShmName, ".", ".", Buf.size()});
Eval->RegisterBC(rpc::RegisterBCParams{ShmName, ".", ".", Buf.size()});
}
}

Expand Down

0 comments on commit 62918a3

Please sign in to comment.