feat(3p/nix): Implement FindRoots, CollectGarbage
Implement the RPC client and server handlers for the FindRoots and CollectGarbage RPC calls Change-Id: Ifa5d582c6a33bd1e7661ac2fc860505ef404dad0 Reviewed-on: https://cl.tvl.fyi/c/depot/+/1656 Tested-by: BuildkiteCI Reviewed-by: kanepyork <rikingcoding@gmail.com>
This commit is contained in:
parent
f9df9b4733
commit
ea488b5705
5 changed files with 117 additions and 3 deletions
29
third_party/nix/src/libstore/rpc-store.cc
vendored
29
third_party/nix/src/libstore/rpc-store.cc
vendored
|
@ -418,11 +418,36 @@ void RpcStore::syncWithGC() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Roots RpcStore::findRoots(bool censor) {
|
Roots RpcStore::findRoots(bool censor) {
|
||||||
throw Unsupported(absl::StrCat("Not implemented ", __func__));
|
ClientContext ctx;
|
||||||
|
proto::FindRootsResponse response;
|
||||||
|
SuccessOrThrow(stub_->FindRoots(&ctx, kEmpty, &response));
|
||||||
|
Roots result;
|
||||||
|
|
||||||
|
for (const auto& [target, links] : response.roots()) {
|
||||||
|
auto link_paths = FillFrom<std::unordered_set<std::string>>(links.paths());
|
||||||
|
result.insert({target, link_paths});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RpcStore::collectGarbage(const GCOptions& options, GCResults& results) {
|
void RpcStore::collectGarbage(const GCOptions& options, GCResults& results) {
|
||||||
throw Unsupported(absl::StrCat("Not implemented ", __func__));
|
ClientContext ctx;
|
||||||
|
proto::CollectGarbageRequest request;
|
||||||
|
request.set_action(options.ActionToProto());
|
||||||
|
for (const auto& path : options.pathsToDelete) {
|
||||||
|
request.add_paths_to_delete(path);
|
||||||
|
}
|
||||||
|
request.set_ignore_liveness(options.ignoreLiveness);
|
||||||
|
request.set_max_freed(options.maxFreed);
|
||||||
|
|
||||||
|
proto::CollectGarbageResponse response;
|
||||||
|
SuccessOrThrow(stub_->CollectGarbage(&ctx, request, &response));
|
||||||
|
|
||||||
|
for (const auto& path : response.deleted_paths()) {
|
||||||
|
results.paths.insert(path);
|
||||||
|
}
|
||||||
|
results.bytesFreed = response.bytes_freed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RpcStore::optimiseStore() {
|
void RpcStore::optimiseStore() {
|
||||||
|
|
29
third_party/nix/src/libstore/store-api.cc
vendored
29
third_party/nix/src/libstore/store-api.cc
vendored
|
@ -77,6 +77,35 @@ nix::proto::BuildStatus BuildResult::status_to_proto() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<GCOptions::GCAction> GCActionFromProto(
|
||||||
|
nix::proto::GCAction gc_action) {
|
||||||
|
switch (gc_action) {
|
||||||
|
case nix::proto::GCAction::ReturnLive:
|
||||||
|
return GCOptions::GCAction::gcReturnLive;
|
||||||
|
case nix::proto::GCAction::ReturnDead:
|
||||||
|
return GCOptions::GCAction::gcReturnDead;
|
||||||
|
case nix::proto::GCAction::DeleteDead:
|
||||||
|
return GCOptions::GCAction::gcDeleteDead;
|
||||||
|
case nix::proto::GCAction::DeleteSpecific:
|
||||||
|
return GCOptions::GCAction::gcDeleteSpecific;
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const proto::GCAction GCOptions::ActionToProto() const {
|
||||||
|
switch (action) {
|
||||||
|
case GCOptions::GCAction::gcReturnLive:
|
||||||
|
return nix::proto::GCAction::ReturnLive;
|
||||||
|
case GCOptions::GCAction::gcReturnDead:
|
||||||
|
return nix::proto::GCAction::ReturnDead;
|
||||||
|
case GCOptions::GCAction::gcDeleteDead:
|
||||||
|
return nix::proto::GCAction::DeleteDead;
|
||||||
|
case GCOptions::GCAction::gcDeleteSpecific:
|
||||||
|
return nix::proto::GCAction::DeleteSpecific;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Store::isInStore(const Path& path) const {
|
bool Store::isInStore(const Path& path) const {
|
||||||
return isInDir(path, storeDir);
|
return isInDir(path, storeDir);
|
||||||
}
|
}
|
||||||
|
|
5
third_party/nix/src/libstore/store-api.hh
vendored
5
third_party/nix/src/libstore/store-api.hh
vendored
|
@ -80,8 +80,13 @@ struct GCOptions {
|
||||||
|
|
||||||
/* Stop after at least `maxFreed' bytes have been freed. */
|
/* Stop after at least `maxFreed' bytes have been freed. */
|
||||||
unsigned long long maxFreed{std::numeric_limits<unsigned long long>::max()};
|
unsigned long long maxFreed{std::numeric_limits<unsigned long long>::max()};
|
||||||
|
|
||||||
|
[[nodiscard]] const proto::GCAction ActionToProto() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::optional<GCOptions::GCAction> GCActionFromProto(
|
||||||
|
nix::proto::GCAction gc_action);
|
||||||
|
|
||||||
struct GCResults {
|
struct GCResults {
|
||||||
/* Depending on the action, the GC roots, or the paths that would
|
/* Depending on the action, the GC roots, or the paths that would
|
||||||
be or have been deleted. */
|
be or have been deleted. */
|
||||||
|
|
|
@ -252,6 +252,61 @@ class WorkerServiceImpl final : public WorkerService::Service {
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status FindRoots(grpc::ServerContext*, const google::protobuf::Empty*,
|
||||||
|
nix::proto::FindRootsResponse* response) override {
|
||||||
|
return HandleExceptions(
|
||||||
|
[&]() -> Status {
|
||||||
|
auto roots = store_->findRoots(false);
|
||||||
|
for (const auto& [target, links] : roots) {
|
||||||
|
StorePaths link_paths;
|
||||||
|
for (const auto& link : links) {
|
||||||
|
link_paths.add_paths(link);
|
||||||
|
}
|
||||||
|
response->mutable_roots()->insert({target, link_paths});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status::OK;
|
||||||
|
},
|
||||||
|
__FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status CollectGarbage(grpc::ServerContext*,
|
||||||
|
const proto::CollectGarbageRequest* request,
|
||||||
|
proto::CollectGarbageResponse* response) override {
|
||||||
|
return HandleExceptions(
|
||||||
|
[&]() -> Status {
|
||||||
|
GCOptions options;
|
||||||
|
auto action = GCActionFromProto(request->action());
|
||||||
|
if (!action.has_value()) {
|
||||||
|
return Status(grpc::StatusCode::INVALID_ARGUMENT,
|
||||||
|
"Invalid GC action");
|
||||||
|
}
|
||||||
|
|
||||||
|
options.action = action.value();
|
||||||
|
for (const auto& path : request->paths_to_delete()) {
|
||||||
|
options.pathsToDelete.insert(path);
|
||||||
|
}
|
||||||
|
options.ignoreLiveness = request->ignore_liveness();
|
||||||
|
options.maxFreed = request->max_freed();
|
||||||
|
|
||||||
|
if (options.ignoreLiveness) {
|
||||||
|
return Status(grpc::StatusCode::INVALID_ARGUMENT,
|
||||||
|
"you are not allowed to ignore liveness");
|
||||||
|
}
|
||||||
|
|
||||||
|
GCResults results;
|
||||||
|
store_->collectGarbage(options, results);
|
||||||
|
|
||||||
|
for (const auto& path : results.paths) {
|
||||||
|
response->add_deleted_paths(path);
|
||||||
|
}
|
||||||
|
response->set_bytes_freed(results.bytesFreed);
|
||||||
|
|
||||||
|
return Status::OK;
|
||||||
|
},
|
||||||
|
__FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
Status QuerySubstitutablePathInfos(
|
Status QuerySubstitutablePathInfos(
|
||||||
grpc::ServerContext*, const StorePaths* request,
|
grpc::ServerContext*, const StorePaths* request,
|
||||||
nix::proto::SubstitutablePathInfos* response) override {
|
nix::proto::SubstitutablePathInfos* response) override {
|
||||||
|
|
2
third_party/nix/src/proto/worker.proto
vendored
2
third_party/nix/src/proto/worker.proto
vendored
|
@ -203,7 +203,7 @@ message BuildPathsRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
message FindRootsResponse {
|
message FindRootsResponse {
|
||||||
map<string, string> roots = 1;
|
map<string, StorePaths> roots = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SetOptionsRequest {
|
message SetOptionsRequest {
|
||||||
|
|
Loading…
Reference in a new issue