mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
fc48ab8614
Summary: EdenConfig had a bunch of hard-coded logic around stat()ing files and parsing TOML. Besides code clarity, this had several problems: * Using an EdenConfig in a unit test would touch the actual filesystem. * We didn't support reading configs from other sources. For example, we've talked about reading EdenConfig from .hgrc. * ReloadableConfig knew too much about EdenConfig's internal working. * Changing configs in tests involves calling setValue(), which is an unsafe API in the limit. This diff introduces a new abstraction called ConfigSource, with one implementation, TomlFileConfigSource. ConfigSource can indicate that it's time for a reload, and can apply its values to a non-const EdenConfig instance. Reviewed By: kmancini Differential Revision: D41830417 fbshipit-source-id: a0ff90c4a1adb870e4b34da5d16238a6e7b75be2
76 lines
2.0 KiB
C++
76 lines
2.0 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and 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::eden {
|
|
|
|
ReloadableConfig::ReloadableConfig(std::shared_ptr<const EdenConfig> config)
|
|
: state_{ConfigState{std::move(config)}} {}
|
|
|
|
ReloadableConfig::ReloadableConfig(
|
|
std::shared_ptr<const EdenConfig> config,
|
|
ConfigReloadBehavior reloadBehavior)
|
|
: state_{ConfigState{std::move(config)}}, reloadBehavior_{reloadBehavior} {}
|
|
|
|
ReloadableConfig::~ReloadableConfig() = default;
|
|
|
|
std::shared_ptr<const EdenConfig> ReloadableConfig::getEdenConfig(
|
|
ConfigReloadBehavior reload) {
|
|
auto now = std::chrono::steady_clock::now();
|
|
|
|
if (reloadBehavior_.has_value()) {
|
|
reload = reloadBehavior_.value();
|
|
}
|
|
|
|
bool shouldReload;
|
|
switch (reload) {
|
|
case ConfigReloadBehavior::NoReload:
|
|
shouldReload = false;
|
|
break;
|
|
case ConfigReloadBehavior::ForceReload:
|
|
shouldReload = true;
|
|
break;
|
|
case ConfigReloadBehavior::AutoReload: {
|
|
auto lastCheck = 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, std::memory_order_release);
|
|
|
|
auto& config = state->config;
|
|
if (auto newConfig = config->maybeReload()) {
|
|
state->config = std::move(newConfig);
|
|
}
|
|
return state->config;
|
|
}
|
|
|
|
} // namespace facebook::eden
|