mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 23:38:50 +03:00
dynamically initialize mononoke backing stores
Summary: Move Mononoke backing store initialization process to every request so we can adjust the configuration value without restarting the process. Reviewed By: strager Differential Revision: D14583357 fbshipit-source-id: 49ce2736229ce3062d34337757ebda6bb6eae16a
This commit is contained in:
parent
bb59fbd4cc
commit
bbb0bc276e
@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "HgBackingStore.h"
|
#include "HgBackingStore.h"
|
||||||
|
|
||||||
|
#include <folly/Synchronized.h>
|
||||||
#include <folly/ThreadLocal.h>
|
#include <folly/ThreadLocal.h>
|
||||||
#include <folly/Try.h>
|
#include <folly/Try.h>
|
||||||
#include <folly/executors/CPUThreadPoolExecutor.h>
|
#include <folly/executors/CPUThreadPoolExecutor.h>
|
||||||
@ -28,6 +29,8 @@
|
|||||||
#include "eden/fs/store/hg/HgImportPyError.h"
|
#include "eden/fs/store/hg/HgImportPyError.h"
|
||||||
#include "eden/fs/store/hg/HgImporter.h"
|
#include "eden/fs/store/hg/HgImporter.h"
|
||||||
#include "eden/fs/store/hg/HgProxyHash.h"
|
#include "eden/fs/store/hg/HgProxyHash.h"
|
||||||
|
#include "eden/fs/store/mononoke/MononokeHttpBackingStore.h"
|
||||||
|
#include "eden/fs/utils/LazyInitialize.h"
|
||||||
#include "eden/fs/utils/SSLContext.h"
|
#include "eden/fs/utils/SSLContext.h"
|
||||||
#include "eden/fs/utils/UnboundedQueueExecutor.h"
|
#include "eden/fs/utils/UnboundedQueueExecutor.h"
|
||||||
|
|
||||||
@ -258,8 +261,7 @@ HgBackingStore::HgBackingStore(
|
|||||||
HgImporter importer(repository, localStore);
|
HgImporter importer(repository, localStore);
|
||||||
const auto& options = importer.getOptions();
|
const auto& options = importer.getOptions();
|
||||||
initializeTreeManifestImport(options, repository);
|
initializeTreeManifestImport(options, repository);
|
||||||
|
repoName_ = options.repoName;
|
||||||
initializeMononoke(options);
|
|
||||||
#endif // EDEN_HAVE_HG_TREEMANIFEST
|
#endif // EDEN_HAVE_HG_TREEMANIFEST
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,8 +374,8 @@ void HgBackingStore::initializeTreeManifestImport(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef EDEN_WIN_NOMONONOKE
|
#ifndef EDEN_WIN_NOMONONOKE
|
||||||
void HgBackingStore::initializeHttpMononokeBackingStore(
|
std::unique_ptr<MononokeHttpBackingStore>
|
||||||
const ImporterOptions& options) {
|
HgBackingStore::initializeHttpMononokeBackingStore() {
|
||||||
auto edenConfig = config_->getEdenConfig();
|
auto edenConfig = config_->getEdenConfig();
|
||||||
std::shared_ptr<folly::SSLContext> sslContext;
|
std::shared_ptr<folly::SSLContext> sslContext;
|
||||||
|
|
||||||
@ -384,122 +386,106 @@ void HgBackingStore::initializeHttpMononokeBackingStore(
|
|||||||
XLOG(WARN) << "mononoke is disabled because of build failure when "
|
XLOG(WARN) << "mononoke is disabled because of build failure when "
|
||||||
"creating SSLContext: "
|
"creating SSLContext: "
|
||||||
<< ex.what();
|
<< ex.what();
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto executor = folly::getIOExecutor();
|
auto executor = folly::getIOExecutor();
|
||||||
auto hostName = edenConfig->getMononokeHostName();
|
auto hostName = edenConfig->getMononokeHostName();
|
||||||
if (hostName) {
|
if (hostName) {
|
||||||
auto port = edenConfig->getMononokePort();
|
auto port = edenConfig->getMononokePort();
|
||||||
mononoke_ = std::make_unique<MononokeHttpBackingStore>(
|
XLOG(DBG2) << "Initializing HTTP Mononoke backing store for repository "
|
||||||
|
<< repoName_ << ", using host " << *hostName << ":" << port;
|
||||||
|
return std::make_unique<MononokeHttpBackingStore>(
|
||||||
*hostName,
|
*hostName,
|
||||||
folly::SocketAddress(hostName->c_str(), port, /*allowNameLookup=*/true),
|
folly::SocketAddress(hostName->c_str(), port, /*allowNameLookup=*/true),
|
||||||
options.repoName,
|
repoName_,
|
||||||
std::chrono::milliseconds(FLAGS_mononoke_timeout),
|
std::chrono::milliseconds(FLAGS_mononoke_timeout),
|
||||||
executor.get(),
|
executor.get(),
|
||||||
sslContext);
|
sslContext);
|
||||||
|
|
||||||
XLOG(DBG2) << "HTTP Mononoke enabled for repository " << options.repoName
|
|
||||||
<< ", using host " << *hostName << ":" << port;
|
|
||||||
} else {
|
} else {
|
||||||
const auto& tierName = edenConfig->getMononokeTierName();
|
const auto& tierName = edenConfig->getMononokeTierName();
|
||||||
mononoke_ = std::make_unique<MononokeHttpBackingStore>(
|
XLOG(DBG2) << "Initializing HTTP Mononoke backing store for repository "
|
||||||
|
<< repoName_ << ", using tier " << tierName;
|
||||||
|
|
||||||
|
return std::make_unique<MononokeHttpBackingStore>(
|
||||||
tierName,
|
tierName,
|
||||||
options.repoName,
|
repoName_,
|
||||||
std::chrono::milliseconds(FLAGS_mononoke_timeout),
|
std::chrono::milliseconds(FLAGS_mononoke_timeout),
|
||||||
executor.get(),
|
executor.get(),
|
||||||
sslContext);
|
sslContext);
|
||||||
|
|
||||||
XLOG(DBG2) << "HTTP Mononoke enabled for repository " << options.repoName
|
|
||||||
<< ", using tier " << tierName;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HgBackingStore::initializeThriftMononokeBackingStore(
|
std::unique_ptr<MononokeThriftBackingStore>
|
||||||
const ImporterOptions& options) {
|
HgBackingStore::initializeThriftMononokeBackingStore() {
|
||||||
auto edenConfig = config_->getEdenConfig();
|
auto edenConfig = config_->getEdenConfig();
|
||||||
auto tierName = edenConfig->getMononokeTierName();
|
auto tierName = edenConfig->getMononokeTierName();
|
||||||
auto executor = folly::getIOExecutor();
|
auto executor = folly::getIOExecutor();
|
||||||
mononoke_ = std::make_unique<MononokeThriftBackingStore>(
|
|
||||||
tierName, options.repoName, executor);
|
|
||||||
|
|
||||||
XLOG(DBG2) << "Thrift Mononoke enabled for repository " << options.repoName
|
XLOG(DBG2) << "Initializing thrift Mononoke backing store for repository "
|
||||||
<< ", using tier " << tierName;
|
<< repoName_ << ", using tier " << tierName;
|
||||||
|
return std::make_unique<MononokeThriftBackingStore>(
|
||||||
|
tierName, repoName_, executor);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(EDEN_HAVE_CURL) && EDEN_HAVE_HG_TREEMANIFEST
|
#if defined(EDEN_HAVE_CURL) && EDEN_HAVE_HG_TREEMANIFEST
|
||||||
void HgBackingStore::initializeCurlMononokeBackingStore(
|
std::unique_ptr<MononokeCurlBackingStore>
|
||||||
const ImporterOptions& options) {
|
HgBackingStore::initializeCurlMononokeBackingStore() {
|
||||||
auto edenConfig = config_->getEdenConfig();
|
auto edenConfig = config_->getEdenConfig();
|
||||||
auto host = edenConfig->getMononokeHostName();
|
auto hostname = edenConfig->getMononokeHostName();
|
||||||
auto clientCertificate = edenConfig->getClientCertificate();
|
auto clientCertificate = edenConfig->getClientCertificate();
|
||||||
|
|
||||||
if (host == std::nullopt) {
|
if (!hostname) {
|
||||||
XLOG(WARN) << "Mononoke is disabled because no Mononoke host is provided";
|
XLOG(WARN) << "Mononoke is disabled because no Mononoke host is provided";
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientCertificate == std::nullopt) {
|
if (!clientCertificate) {
|
||||||
XLOG(WARN)
|
XLOG(WARN)
|
||||||
<< "Mononoke is disabled because no client certificate is provided";
|
<< "Mononoke is disabled because no client certificate is provided";
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mononoke_ = std::make_unique<MononokeCurlBackingStore>(
|
XLOG(DBG2) << "Initializing cURL Mononoke backing store for repository "
|
||||||
host.value(),
|
<< repoName_ << ", using host " << *hostname;
|
||||||
AbsolutePath(folly::to<std::string>(clientCertificate.value())),
|
|
||||||
options.repoName,
|
return std::make_unique<MononokeCurlBackingStore>(
|
||||||
|
*hostname,
|
||||||
|
AbsolutePath(folly::to<std::string>(*clientCertificate)),
|
||||||
|
repoName_,
|
||||||
std::chrono::milliseconds(FLAGS_mononoke_timeout),
|
std::chrono::milliseconds(FLAGS_mononoke_timeout),
|
||||||
folly::getCPUExecutor());
|
folly::getCPUExecutor());
|
||||||
|
|
||||||
XLOG(DBG2) << "cURL Mononoke enabled for repository " << options.repoName
|
|
||||||
<< ", using host " << *host;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void HgBackingStore::initializeMononoke(const ImporterOptions& options) {
|
std::unique_ptr<BackingStore> HgBackingStore::initializeMononoke() {
|
||||||
if (!config_) {
|
|
||||||
XLOG(DBG2)
|
|
||||||
<< "mononoke is disabled because no config instance was provided to HgBackingStore";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto edenConfig = config_->getEdenConfig();
|
|
||||||
#if EDEN_HAVE_HG_TREEMANIFEST
|
#if EDEN_HAVE_HG_TREEMANIFEST
|
||||||
if (options.repoName.empty()) {
|
const auto& connectionType =
|
||||||
XLOG(DBG2) << "mononoke is disabled because it is not supported.";
|
config_->getEdenConfig()->getMononokeConnectionType();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto useMononoke = edenConfig->getUseMononoke();
|
|
||||||
if (!useMononoke) {
|
|
||||||
XLOG(DBG2) << "mononoke is disabled by config.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& connectionType = edenConfig->getMononokeConnectionType();
|
|
||||||
|
|
||||||
#ifndef EDEN_WIN_NOMONONOKE
|
#ifndef EDEN_WIN_NOMONONOKE
|
||||||
if (connectionType == "http") {
|
if (connectionType == "http") {
|
||||||
initializeHttpMononokeBackingStore(options);
|
return initializeHttpMononokeBackingStore();
|
||||||
} else if (connectionType == "thrift") {
|
} else if (connectionType == "thrift") {
|
||||||
initializeThriftMononokeBackingStore(options);
|
return initializeThriftMononokeBackingStore();
|
||||||
} else if (connectionType == "curl") {
|
} else if (connectionType == "curl") {
|
||||||
#ifdef EDEN_HAVE_CURL
|
#ifdef EDEN_HAVE_CURL
|
||||||
initializeCurlMononokeBackingStore(options);
|
return initializeCurlMononokeBackingStore();
|
||||||
#else
|
#else // EDEN_HAVE_CURL
|
||||||
XLOG(WARN)
|
XLOG(WARN)
|
||||||
<< "User specified Mononoke connection type as cURL, but eden is built without cURL";
|
<< "User specified Mononoke connection type as cURL, but eden is built "
|
||||||
#endif
|
"without cURL";
|
||||||
|
#endif // EDEN_HAVE_CURL
|
||||||
} else {
|
} else {
|
||||||
XLOG(WARN) << "got unexpected value for `mononoke:connection-type`: "
|
XLOG(WARN) << "got unexpected value for `mononoke:connection-type`: "
|
||||||
<< connectionType;
|
<< connectionType;
|
||||||
}
|
}
|
||||||
#elif defined(EDEN_HAVE_CURL)
|
#elif defined(EDEN_HAVE_CURL) // EDEN_WIN_NOMONONOKE
|
||||||
initializeCurlMononokeBackingStore(options);
|
return initializeCurlMononokeBackingStore();
|
||||||
#endif
|
#endif // EDEN_WIN_NOMONONOKE
|
||||||
#endif // EDEN_HAVE_HG_TREEMANIFEST
|
#endif // EDEN_HAVE_HG_TREEMANIFEST
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<unique_ptr<Tree>> HgBackingStore::getTree(const Hash& id) {
|
Future<unique_ptr<Tree>> HgBackingStore::getTree(const Hash& id) {
|
||||||
@ -544,7 +530,8 @@ Future<unique_ptr<Tree>> HgBackingStore::importTreeImpl(
|
|||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useMononoke()) {
|
auto mononoke = getMononoke();
|
||||||
|
if (mononoke) {
|
||||||
// ask Mononoke API Server first because it has more metadata available
|
// ask Mononoke API Server first because it has more metadata available
|
||||||
// than we'd get from a local treepack. Getting that data from mononoke
|
// than we'd get from a local treepack. Getting that data from mononoke
|
||||||
// can save us from materializing so many file contents later to compute
|
// can save us from materializing so many file contents later to compute
|
||||||
@ -552,7 +539,7 @@ Future<unique_ptr<Tree>> HgBackingStore::importTreeImpl(
|
|||||||
XLOG(DBG4) << "importing tree \"" << manifestNode << "\" from mononoke";
|
XLOG(DBG4) << "importing tree \"" << manifestNode << "\" from mononoke";
|
||||||
|
|
||||||
RelativePath ownedPath(path);
|
RelativePath ownedPath(path);
|
||||||
return mononoke_->getTree(manifestNode)
|
return mononoke->getTree(manifestNode)
|
||||||
.via(serverThreadPool_)
|
.via(serverThreadPool_)
|
||||||
.thenTry([edenTreeID, ownedPath, writeBatch](
|
.thenTry([edenTreeID, ownedPath, writeBatch](
|
||||||
auto mononokeTreeTry) mutable {
|
auto mononokeTreeTry) mutable {
|
||||||
@ -625,18 +612,17 @@ HgBackingStore::fetchTreeFromHgCacheOrImporter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HgBackingStore::useMononoke() const {
|
std::shared_ptr<BackingStore> HgBackingStore::getMononoke() {
|
||||||
// Currently, useMononoke needs to be true at construction time in order
|
// config_ might be uninitialized (e.g. testing).
|
||||||
// to configure the mononoke client safely. If that wasn't the case then
|
if (!config_ || repoName_.empty()) {
|
||||||
// we'll treat it as disabled even if the user has subsequently configured
|
return nullptr;
|
||||||
// it correctly.
|
|
||||||
if (!mononoke_) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
DCHECK(config_) << "mononoke_ cannot be set without config_";
|
|
||||||
|
|
||||||
// Check to see if the user has disabled mononoke since starting the server.
|
// Check to see if the user has disabled mononoke since starting the server.
|
||||||
return config_->getEdenConfig()->getUseMononoke();
|
auto useMononoke = config_->getEdenConfig()->getUseMononoke();
|
||||||
|
|
||||||
|
return lazyInitialize<BackingStore>(
|
||||||
|
useMononoke, mononoke_, [this]() { return initializeMononoke(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
folly::Future<std::unique_ptr<Tree>> HgBackingStore::fetchTreeFromImporter(
|
folly::Future<std::unique_ptr<Tree>> HgBackingStore::fetchTreeFromImporter(
|
||||||
@ -827,11 +813,12 @@ Future<unique_ptr<Blob>> HgBackingStore::getBlob(const Hash& id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useMononoke()) {
|
auto mononoke = getMononoke();
|
||||||
|
if (mononoke) {
|
||||||
XLOG(DBG5) << "requesting file contents of '" << hgInfo.path() << "', "
|
XLOG(DBG5) << "requesting file contents of '" << hgInfo.path() << "', "
|
||||||
<< hgInfo.revHash().toString() << " from mononoke";
|
<< hgInfo.revHash().toString() << " from mononoke";
|
||||||
auto revHashCopy = hgInfo.revHash();
|
auto revHashCopy = hgInfo.revHash();
|
||||||
return mononoke_->getBlob(revHashCopy)
|
return mononoke->getBlob(revHashCopy)
|
||||||
.thenError([this,
|
.thenError([this,
|
||||||
id,
|
id,
|
||||||
path = hgInfo.path().copy(),
|
path = hgInfo.path().copy(),
|
||||||
|
@ -36,6 +36,9 @@ namespace eden {
|
|||||||
class Importer;
|
class Importer;
|
||||||
class ImporterOptions;
|
class ImporterOptions;
|
||||||
class LocalStore;
|
class LocalStore;
|
||||||
|
class MononokeHttpBackingStore;
|
||||||
|
class MononokeThriftBackingStore;
|
||||||
|
class MononokeCurlBackingStore;
|
||||||
class UnboundedQueueExecutor;
|
class UnboundedQueueExecutor;
|
||||||
class ReloadableConfig;
|
class ReloadableConfig;
|
||||||
|
|
||||||
@ -97,37 +100,49 @@ class HgBackingStore : public BackingStore {
|
|||||||
AbsolutePathPiece repoPath);
|
AbsolutePathPiece repoPath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the mononoke_ needed for Mononoke API Server support.
|
* Create a Mononoke backing store based on config_.
|
||||||
*
|
*
|
||||||
* This leaves mononoke_ null if mononoke does not support the repository.
|
* Return nullptr if something is wrong (e.g. missing configs).
|
||||||
*/
|
*/
|
||||||
void initializeMononoke(const ImporterOptions& options);
|
std::unique_ptr<BackingStore> initializeMononoke();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an instace of Mononoke backing store as specified in config_. This will
|
||||||
|
* call `initializeMononoke` if no active Mononoke instance is stored.
|
||||||
|
*
|
||||||
|
* Return nullptr if Mononoke is disabled.
|
||||||
|
*/
|
||||||
|
std::shared_ptr<BackingStore> getMononoke();
|
||||||
|
|
||||||
#ifndef EDEN_WIN_NOMONONOKE
|
#ifndef EDEN_WIN_NOMONONOKE
|
||||||
/**
|
/**
|
||||||
* Initialize the mononoke_ with MononokeHttpBackingStore, which uses
|
* Create an instance of MononokeHttpBackingStore with values from config_
|
||||||
* HTTP to talk with Mononoke API Server.
|
* (Proxygen based Mononoke client)
|
||||||
*
|
*
|
||||||
* This leaves mononoke_ null if SSLContext cannot be constructed.
|
* Return null if SSLContext cannot be constructed.
|
||||||
*/
|
*/
|
||||||
void initializeHttpMononokeBackingStore(const ImporterOptions& options);
|
std::unique_ptr<MononokeHttpBackingStore>
|
||||||
|
initializeHttpMononokeBackingStore();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the mononoke_ with MononokeThriftBackingStore, which uses
|
* Create an instance of MononokeThriftBackingStore with values from config_
|
||||||
* thrift protocol to talk with Mononoke API Server.
|
* (Thrift based Mononoke client)
|
||||||
|
*
|
||||||
|
* Return nullptr if required config is missing.
|
||||||
*/
|
*/
|
||||||
void initializeThriftMononokeBackingStore(const ImporterOptions& options);
|
std::unique_ptr<MononokeThriftBackingStore>
|
||||||
|
initializeThriftMononokeBackingStore();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Returns true if we should use mononoke for a fetch */
|
|
||||||
bool useMononoke() const;
|
|
||||||
|
|
||||||
#if defined(EDEN_HAVE_CURL) && EDEN_HAVE_HG_TREEMANIFEST
|
#if defined(EDEN_HAVE_CURL) && EDEN_HAVE_HG_TREEMANIFEST
|
||||||
/**
|
/**
|
||||||
* Initialize the mononoke_ with MononokeCurlBackingStore, that is available
|
* Create an instance of MononokeCurlBackingStore with values from config_
|
||||||
* on macOS
|
* (Curl based Mononoke client)
|
||||||
|
*
|
||||||
|
* Return nullptr if required config is missing.
|
||||||
*/
|
*/
|
||||||
void initializeCurlMononokeBackingStore(const ImporterOptions& options);
|
std::unique_ptr<MononokeCurlBackingStore>
|
||||||
|
initializeCurlMononokeBackingStore();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
folly::Future<std::unique_ptr<Tree>> getTreeForCommitImpl(Hash commitID);
|
folly::Future<std::unique_ptr<Tree>> getTreeForCommitImpl(Hash commitID);
|
||||||
@ -182,7 +197,8 @@ class HgBackingStore : public BackingStore {
|
|||||||
std::unique_ptr<folly::Synchronized<UnionDatapackStore>> unionStore_;
|
std::unique_ptr<folly::Synchronized<UnionDatapackStore>> unionStore_;
|
||||||
bool useDatapackGetBlob_{false};
|
bool useDatapackGetBlob_{false};
|
||||||
|
|
||||||
std::unique_ptr<BackingStore> mononoke_;
|
std::string repoName_;
|
||||||
|
folly::Synchronized<std::shared_ptr<BackingStore>> mononoke_;
|
||||||
#ifndef EDEN_WIN_NO_RUST_DATAPACK
|
#ifndef EDEN_WIN_NO_RUST_DATAPACK
|
||||||
std::optional<folly::Synchronized<DataPackUnion>> dataPackStore_;
|
std::optional<folly::Synchronized<DataPackUnion>> dataPackStore_;
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user