From 89dc62c1745950748084a763ea325bc427045e07 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 14 Sep 2017 18:10:38 +0200 Subject: [PATCH] RemoteStore: Add option to drop old connections from the pool This is a hack to make hydra-queue-runner free its temproots periodically, thereby ensuring that garbage collection of the corresponding paths is not blocked until the queue runner is restarted. It would be better if temproots could be released earlier than at process exit. I started working on a RAII object returned by functions like addToStore() that releases temproots. However, this would be a pretty massive change so I gave up on it for now. --- src/libstore/remote-store.cc | 16 +++++++++++++++- src/libstore/remote-store.hh | 6 ++++++ src/libutil/pool.hh | 10 ++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 1af84cff5..b9076c047 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -45,7 +45,13 @@ RemoteStore::RemoteStore(const Params & params) , connections(make_ref>( std::max(1, (int) maxConnections), [this]() { return openConnectionWrapper(); }, - [](const ref & r) { return r->to.good() && r->from.good(); } + [this](const ref & r) { + return + r->to.good() + && r->from.good() + && std::chrono::duration_cast( + std::chrono::steady_clock::now() - r->startTime).count() < maxConnectionAge; + } )) { } @@ -106,6 +112,8 @@ ref UDSRemoteStore::openConnection() conn->from.fd = conn->fd.get(); conn->to.fd = conn->fd.get(); + conn->startTime = std::chrono::steady_clock::now(); + initConnection(*conn); return conn; @@ -619,6 +627,12 @@ void RemoteStore::connect() } +void RemoteStore::flushBadConnections() +{ + connections->flushBad(); +} + + RemoteStore::Connection::~Connection() { try { diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index e370e4797..30c6beae6 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -25,6 +25,9 @@ public: const Setting maxConnections{(Store*) this, 1, "max-connections", "maximum number of concurrent connections to the Nix daemon"}; + const Setting maxConnectionAge{(Store*) this, std::numeric_limits::max(), + "max-connection-age", "number of seconds to reuse a connection"}; + RemoteStore(const Params & params); /* Implementations of abstract store API methods. */ @@ -95,6 +98,8 @@ public: void connect() override; + void flushBadConnections(); + protected: struct Connection @@ -102,6 +107,7 @@ protected: FdSink to; FdSource from; unsigned int daemonVersion; + std::chrono::time_point startTime; virtual ~Connection(); diff --git a/src/libutil/pool.hh b/src/libutil/pool.hh index 703309002..0b142b059 100644 --- a/src/libutil/pool.hh +++ b/src/libutil/pool.hh @@ -168,6 +168,16 @@ public: { return state.lock()->max; } + + void flushBad() + { + auto state_(state.lock()); + std::vector> left; + for (auto & p : state_->idle) + if (validator(p)) + left.push_back(p); + std::swap(state_->idle, left); + } }; }