sapling/eden/fs/config/ReloadableConfig.cpp
Katie Mancini 8a1a529fcc use custom in memory tree cache
Summary:
Chad first noted that deserializing trees from the local store can be expensive.
From the thrift side EdenFS does not have a copy of trees in memory. This
means for glob files each of the trees that have not been materialized will be
read from the local store. Since reading an deserializing trees from the local
store can be expensive lets add an in memory cache so that some of these
reads can be satisfied from here instead.

Here we actually start to use the cache!

Reviewed By: chadaustin

Differential Revision: D27050310

fbshipit-source-id: e35db193fea0af7f387b6f44c49b5bcc2a902858
2021-04-27 17:38:40 -07:00

93 lines
2.8 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
#include "eden/fs/config/ReloadableConfig.h"
#include "eden/fs/config/EdenConfig.h"
#include "eden/fs/utils/Bug.h"
#include "eden/fs/utils/EnumValue.h"
#include <folly/logging/xlog.h>
namespace {
/// Throttle change checks to a maximum of one per
/// kEdenConfigMinimumPollDuration.
constexpr std::chrono::seconds kEdenConfigMinimumPollDuration{5};
} // namespace
namespace facebook {
namespace eden {
ReloadableConfig::ReloadableConfig(std::shared_ptr<const EdenConfig> config)
: state_{ConfigState{config}} {}
ReloadableConfig::ReloadableConfig(
std::shared_ptr<const EdenConfig> config,
ConfigReloadBehavior reloadBehavior)
: state_{ConfigState{config}}, reloadBehavior_{reloadBehavior} {}
ReloadableConfig::~ReloadableConfig() {}
std::shared_ptr<const EdenConfig> ReloadableConfig::getEdenConfig(
ConfigReloadBehavior reload) {
auto now = std::chrono::steady_clock::now();
// TODO: Update this monitoring code to use FileChangeMonitor.
bool shouldReload;
if (reloadBehavior_.has_value()) {
reload = reloadBehavior_.value();
}
switch (reload) {
case ConfigReloadBehavior::NoReload:
shouldReload = false;
break;
case ConfigReloadBehavior::ForceReload:
shouldReload = true;
break;
case ConfigReloadBehavior::AutoReload: {
auto lastCheck = std::chrono::steady_clock::time_point{
std::chrono::steady_clock::duration{
lastCheck_.load(std::memory_order_acquire)}};
shouldReload = now - lastCheck >= kEdenConfigMinimumPollDuration;
break;
}
default:
EDEN_BUG() << "Unexpected reload flag: " << enumValue(reload);
}
if (!shouldReload) {
return state_.rlock()->config;
}
auto state = state_.wlock();
// Throttle the updates when using ConfigReloadBehavior::AutoReload
lastCheck_.store(now.time_since_epoch().count(), std::memory_order_release);
auto& config = state->config;
auto userConfigChanged = config->hasUserConfigFileChanged();
auto systemConfigChanged = config->hasSystemConfigFileChanged();
if (userConfigChanged || systemConfigChanged) {
auto newConfig = std::make_shared<EdenConfig>(*config);
if (userConfigChanged) {
XLOG(DBG3) << "Reloading " << config->getUserConfigPath() << " because "
<< userConfigChanged.str();
newConfig->loadUserConfig();
}
if (systemConfigChanged) {
XLOG(DBG3) << "Reloading " << config->getSystemConfigPath() << " because "
<< systemConfigChanged.str();
newConfig->loadSystemConfig();
}
state->config = std::move(newConfig);
}
return state->config;
}
} // namespace eden
} // namespace facebook