Skip to content

Commit 351261f

Browse files
kavehahmadi60meta-codesync[bot]
authored andcommitted
Rate-limit daemon mount health event emission
Summary: Track emitted daemon mount-health issues per checkout path and reason. Suppress repeats until a later health check for that checkout succeeds, then clear the remembered reasons so future disruptions are logged again. Reviewed By: muirdm Differential Revision: D108201867 fbshipit-source-id: b463fd11c49fbc0cbd51a4014e61458e96020566
1 parent 52964dc commit 351261f

2 files changed

Lines changed: 68 additions & 1 deletion

File tree

eden/fs/service/EdenServer.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,60 @@ using namespace facebook::eden;
182182

183183
constexpr auto kMountHealthCheckTimeout = std::chrono::seconds{5};
184184

185+
using EmittedMountHealthIssues =
186+
folly::Synchronized<std::unordered_map<std::string, std::set<std::string>>>;
187+
188+
bool shouldLogMountHealthIssue(
189+
const std::shared_ptr<EmittedMountHealthIssues>& emittedMountHealthIssues,
190+
const std::string& mountPath,
191+
const std::string& reason) {
192+
auto emittedIssues = emittedMountHealthIssues->wlock();
193+
auto& emittedReasons = (*emittedIssues)[mountPath];
194+
return emittedReasons.insert(reason).second;
195+
}
196+
197+
void clearMountHealthIssues(
198+
const std::shared_ptr<EmittedMountHealthIssues>& emittedMountHealthIssues,
199+
const std::string& mountPath) {
200+
auto emittedIssues = emittedMountHealthIssues->wlock();
201+
emittedIssues->erase(mountPath);
202+
}
203+
204+
void clearAllMountHealthIssues(
205+
const std::shared_ptr<EmittedMountHealthIssues>& emittedMountHealthIssues) {
206+
auto emittedIssues = emittedMountHealthIssues->wlock();
207+
emittedIssues->clear();
208+
}
209+
210+
void pruneMountHealthIssues(
211+
const std::shared_ptr<EmittedMountHealthIssues>& emittedMountHealthIssues,
212+
const std::unordered_set<std::string>& configuredMountPaths) {
213+
auto emittedIssues = emittedMountHealthIssues->wlock();
214+
for (auto it = emittedIssues->begin(); it != emittedIssues->end();) {
215+
if (configuredMountPaths.find(it->first) == configuredMountPaths.end()) {
216+
it = emittedIssues->erase(it);
217+
} else {
218+
++it;
219+
}
220+
}
221+
}
222+
185223
struct MountHealthIssueLogContext {
186224
MountHealthIssueLogContext(
187225
std::weak_ptr<EdenFsEventsLogger> edenFsEventsLogger,
226+
std::shared_ptr<EmittedMountHealthIssues> emittedMountHealthIssues,
188227
std::string mountPath,
189228
std::string repoSource)
190229
: edenFsEventsLogger_{std::move(edenFsEventsLogger)},
230+
emittedMountHealthIssues{std::move(emittedMountHealthIssues)},
191231
mountPath{std::move(mountPath)},
192232
repoSource{std::move(repoSource)} {}
193233

194234
void log(std::string reason, std::string error) const {
235+
if (!shouldLogMountHealthIssue(
236+
emittedMountHealthIssues, mountPath, reason)) {
237+
return;
238+
}
195239
auto edenFsEventsLogger = edenFsEventsLogger_.lock();
196240
if (!edenFsEventsLogger) {
197241
return;
@@ -210,6 +254,7 @@ struct MountHealthIssueLogContext {
210254
}
211255

212256
std::weak_ptr<EdenFsEventsLogger> edenFsEventsLogger_;
257+
std::shared_ptr<EmittedMountHealthIssues> emittedMountHealthIssues;
213258
std::string mountPath;
214259
std::string repoSource;
215260
};
@@ -659,6 +704,7 @@ EdenServer::EdenServer(
659704
config_{std::make_shared<ReloadableConfig>(edenConfig)},
660705
mountPoints_{std::make_shared<folly::Synchronized<MountMap>>(
661706
MountMap{kPathMapDefaultCaseSensitive})},
707+
emittedMountHealthIssues_{std::make_shared<EmittedMountHealthIssues>()},
662708
// Store a pointer to the EventBase that will be used to drive
663709
// the main thread. The runServer() code will end up driving this
664710
// EventBase.
@@ -3442,8 +3488,10 @@ void EdenServer::scheduleRunningMountHealthCheck(
34423488

34433489
auto started = make_shared<std::atomic_bool>(false);
34443490
auto completed = make_shared<std::atomic_bool>(false);
3491+
auto emittedMountHealthIssues = emittedMountHealthIssues_;
34453492
auto logContext = make_shared<const MountHealthIssueLogContext>(
34463493
serverState_->getEdenFsEventsLogger(),
3494+
emittedMountHealthIssues,
34473495
std::move(mountPathString),
34483496
std::move(repoSource));
34493497

@@ -3463,7 +3511,10 @@ void EdenServer::scheduleRunningMountHealthCheck(
34633511
return checkRunningEdenMountHealth(logContext->mountPath);
34643512
})
34653513
.thenTry(
3466-
[completed, logContext, runningMountHealthChecks](
3514+
[completed,
3515+
emittedMountHealthIssues,
3516+
logContext,
3517+
runningMountHealthChecks](
34673518
folly::Try<std::optional<EdenMountHealthCheckIssue>>&& result) {
34683519
const auto alreadyCompleted = completed->exchange(true);
34693520
{
@@ -3482,6 +3533,8 @@ void EdenServer::scheduleRunningMountHealthCheck(
34823533
}
34833534
const auto& issue = result.value();
34843535
if (!issue.has_value()) {
3536+
clearMountHealthIssues(
3537+
emittedMountHealthIssues, logContext->mountPath);
34853538
return;
34863539
}
34873540
logContext->log(
@@ -3504,12 +3557,20 @@ void EdenServer::accidentalUnmountRecovery() {
35043557
}
35053558

35063559
if (dirs.empty()) {
3560+
clearAllMountHealthIssues(emittedMountHealthIssues_);
35073561
XLOGF(
35083562
DBG5,
35093563
"No mount points currently configured, skipping accidental unmount recovery.");
35103564
return;
35113565
}
35123566

3567+
std::unordered_set<std::string> configuredMountPaths;
3568+
for (const auto& client : dirs.items()) {
3569+
configuredMountPaths.insert(
3570+
std::string{canonicalPath(client.first.stringPiece()).view()});
3571+
}
3572+
pruneMountHealthIssues(emittedMountHealthIssues_, configuredMountPaths);
3573+
35133574
const auto mountPoints = mountPoints_->rlock();
35143575
for (const auto& client : dirs.items()) {
35153576
auto mountPath = canonicalPath(client.first.stringPiece());
@@ -3518,6 +3579,8 @@ void EdenServer::accidentalUnmountRecovery() {
35183579
if (it != mountPoints->end()) {
35193580
scheduleRunningMountHealthCheck(mountPath, client.second.asString());
35203581
} else {
3582+
clearMountHealthIssues(
3583+
emittedMountHealthIssues_, std::string{mountPath.view()});
35213584
// This mount point is not currently mounted, but it was configured
35223585
// in config.json. This means that the client was unmounted.
35233586
// We should attempt to remount it, if it is unmounted accidentally.

eden/fs/service/EdenServer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <functional>
1313
#include <memory>
1414
#include <optional>
15+
#include <set>
1516
#include <string>
1617
#include <string_view>
1718
#include <unordered_map>
@@ -763,6 +764,9 @@ class EdenServer : private TakeoverHandler {
763764
std::shared_ptr<ReloadableConfig> config_;
764765

765766
std::shared_ptr<folly::Synchronized<MountMap>> mountPoints_;
767+
std::shared_ptr<folly::Synchronized<
768+
std::unordered_map<std::string, std::set<std::string>>>>
769+
emittedMountHealthIssues_;
766770

767771
#ifndef _WIN32
768772
/**

0 commit comments

Comments
 (0)