diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2018-07-17 14:46:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-17 14:46:44 +0200 |
commit | 7ef120081865de0ab9455dba5c94941018d03a3d (patch) | |
tree | ff287528edb9864c9f6731f45f09272f23504d0b | |
parent | 3f59a7da59991ef74adfd5bc334d96095945c575 (diff) | |
parent | 391927c653aff07f8e5a285aef797bb5e8377fd4 (diff) |
Merge pull request #6402 from vespa-engine/balder/reduce-sleep
Balder/reduce sleep
5 files changed, 83 insertions, 145 deletions
diff --git a/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.cpp b/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.cpp index 95b3008985b..0d2c556b4d6 100644 --- a/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.cpp +++ b/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.cpp @@ -8,6 +8,7 @@ #include "tls_stats_factory.h" #include <vespa/searchcore/proton/common/eventlogger.h> #include <vespa/vespalib/util/jsonwriter.h> +#include <thread> #include <vespa/log/log.h> LOG_SETUP(".proton.flushengine.flushengine"); @@ -22,8 +23,7 @@ namespace proton { namespace { search::SerialNum -findOldestFlushedSerial(const IFlushTarget::List &lst, - const IFlushHandler &handler) +findOldestFlushedSerial(const IFlushTarget::List &lst, const IFlushHandler &handler) { search::SerialNum ret(handler.getCurrentSerialNumber()); for (const IFlushTarget::SP & target : lst) { @@ -33,42 +33,46 @@ findOldestFlushedSerial(const IFlushTarget::List &lst, return ret; } +void +logTarget(const char * text, const FlushContext & ctx) { + LOG(debug, "Target '%s' %s flush of transactions %" PRIu64 " through %" PRIu64 ".", + ctx.getName().c_str(), text, + ctx.getTarget()->getFlushedSerialNum() + 1, + ctx.getHandler()->getCurrentSerialNumber()); +} + } -FlushEngine::FlushMeta::FlushMeta(const vespalib::string & name, fastos::TimeStamp start, uint32_t id) : - _name(name), - _start(start), - _id(id) +FlushEngine::FlushMeta::FlushMeta(const vespalib::string & name, fastos::TimeStamp start, uint32_t id) + : _name(name), + _start(start), + _id(id) { } -FlushEngine::FlushMeta::~FlushMeta() { } +FlushEngine::FlushMeta::~FlushMeta() = default; -FlushEngine::FlushInfo::FlushInfo() : - FlushMeta("", fastos::ClockSystem::now(), 0), - _target() +FlushEngine::FlushInfo::FlushInfo() + : FlushMeta("", fastos::ClockSystem::now(), 0), + _target() { } -FlushEngine::FlushInfo::~FlushInfo() { } +FlushEngine::FlushInfo::~FlushInfo() = default; -FlushEngine::FlushInfo::FlushInfo(uint32_t taskId, - const IFlushTarget::SP &target, - const vespalib::string & destination) : - FlushMeta(destination, fastos::ClockSystem::now(), taskId), - _target(target) +FlushEngine::FlushInfo::FlushInfo(uint32_t taskId, const IFlushTarget::SP &target, const vespalib::string & destination) + : FlushMeta(destination, fastos::ClockSystem::now(), taskId), + _target(target) { } -FlushEngine::FlushEngine(std::shared_ptr<flushengine::ITlsStatsFactory> - tlsStatsFactory, - IFlushStrategy::SP strategy, uint32_t numThreads, - uint32_t idleIntervalMS) +FlushEngine::FlushEngine(std::shared_ptr<flushengine::ITlsStatsFactory> tlsStatsFactory, + IFlushStrategy::SP strategy, uint32_t numThreads, uint32_t idleIntervalMS) : _closed(false), _maxConcurrent(numThreads), _idleIntervalMS(idleIntervalMS), _taskId(0), _threadPool(128 * 1024), - _strategy(strategy), + _strategy(std::move(strategy)), _priorityStrategy(), _executor(numThreads, 128 * 1024), _lock(), @@ -78,11 +82,9 @@ FlushEngine::FlushEngine(std::shared_ptr<flushengine::ITlsStatsFactory> _setStrategyLock(), _strategyLock(), _strategyCond(), - _tlsStatsFactory(tlsStatsFactory), + _tlsStatsFactory(std::move(tlsStatsFactory)), _pendingPrune() -{ - // empty -} +{ } FlushEngine::~FlushEngine() { @@ -92,7 +94,7 @@ FlushEngine::~FlushEngine() FlushEngine & FlushEngine::start() { - if (_threadPool.NewThread(this) == NULL) { + if (_threadPool.NewThread(this) == nullptr) { throw vespalib::IllegalStateException("Failed to start engine thread."); } return *this; @@ -148,10 +150,8 @@ FlushEngine::wait(size_t minimumWaitTimeIfReady) } void -FlushEngine::Run(FastOS_ThreadInterface *thread, void *arg) +FlushEngine::Run(FastOS_ThreadInterface *, void *) { - (void)thread; - (void)arg; bool shouldIdle = false; vespalib::string prevFlushName; while (wait(shouldIdle ? _idleIntervalMS : 0)) { @@ -161,13 +161,14 @@ FlushEngine::Run(FastOS_ThreadInterface *thread, void *arg) } prevFlushName = flushNextTarget(prevFlushName); if ( ! prevFlushName.empty()) { - // Sleep at least 10 ms after a successful flush in order to avoid busy loop in case - // of strategy error or target error. - FastOS_Thread::Sleep(10); + // Sleep 1 ms after a successful flush in order to avoid busy loop in case + // of strategy or target error. + std::this_thread::sleep_for(1ms); } else { shouldIdle = true; } - LOG(debug, "Making another wait(idle=%s, timeMS=%d) last was '%s'", shouldIdle ? "true" : "false", shouldIdle ? _idleIntervalMS : 0, prevFlushName.c_str()); + LOG(debug, "Making another wait(idle=%s, timeMS=%d) last was '%s'", + shouldIdle ? "true" : "false", shouldIdle ? _idleIntervalMS : 0, prevFlushName.c_str()); } _executor.sync(); prune(); @@ -211,18 +212,16 @@ FlushEngine::getTargetList(bool includeFlushingTargets) const for (const auto & it : _handlers) { IFlushHandler & handler(*it.second); search::SerialNum serial(handler.getCurrentSerialNumber()); - LOG(spam, "Checking FlushHandler '%s' current serial = %ld", - handler.getName().c_str(), serial); + LOG(spam, "Checking FlushHandler '%s' current serial = %ld", handler.getName().c_str(), serial); IFlushTarget::List lst = handler.getFlushTargets(); for (const IFlushTarget::SP & target : lst) { - LOG(spam, "Checking target '%s' with flushedSerialNum = %ld", target->getName().c_str(), target->getFlushedSerialNum()); + LOG(spam, "Checking target '%s' with flushedSerialNum = %ld", + target->getName().c_str(), target->getFlushedSerialNum()); if (!isFlushing(guard, FlushContext::createName(handler, *target)) || includeFlushingTargets) { - ret.push_back(FlushContext::SP(new FlushContext(it.second, - IFlushTarget::SP(new CachedFlushTarget(target)), - serial))); + ret.push_back(std::make_shared<FlushContext>(it.second, std::make_shared<CachedFlushTarget>(target), serial)); } else { LOG(debug, "Target '%s' with flushedSerialNum = %ld already has a flush going. Local last serial = %ld.", - target->getName().c_str(), target->getFlushedSerialNum(), serial); + target->getName().c_str(), target->getFlushedSerialNum(), serial); } } } @@ -258,17 +257,12 @@ FlushEngine::initNextFlush(const FlushContext::List &lst) break; } } - if (ctx.get() != NULL) { - LOG(debug, "Target '%s' initiated flush of transactions %" PRIu64 " through %" PRIu64 ".", - ctx->getName().c_str(), - ctx->getTarget()->getFlushedSerialNum() + 1, - ctx->getHandler()->getCurrentSerialNumber()); + if (ctx) { + logTarget("initiated", *ctx); } return ctx; } - - void FlushEngine::flushAll(const FlushContext::List &lst) { @@ -276,19 +270,12 @@ FlushEngine::flushAll(const FlushContext::List &lst) for (const FlushContext::SP & ctx : lst) { if (wait(0)) { if (ctx->initFlush()) { - LOG(debug, "Target '%s' initiated flush of transactions %" PRIu64 " through %" PRIu64 ".", - ctx->getName().c_str(), - ctx->getTarget()->getFlushedSerialNum() + 1, - ctx->getHandler()->getCurrentSerialNumber()); - _executor.execute(Task::UP(new FlushTask(initFlush(*ctx), *this, ctx))); + logTarget("initiated", *ctx); + _executor.execute(std::make_unique<FlushTask>(initFlush(*ctx), *this, ctx)); } else { - LOG(debug, "Target '%s' failed to initiate flush of transactions %" PRIu64 " through %" PRIu64 ".", - ctx->getName().c_str(), - ctx->getTarget()->getFlushedSerialNum() + 1, - ctx->getHandler()->getCurrentSerialNumber()); + logTarget("failed to initiate", *ctx); } } - } } @@ -311,17 +298,17 @@ FlushEngine::flushNextTarget(const vespalib::string & name) return ""; } FlushContext::SP ctx = initNextFlush(lst.first); - if (ctx.get() == NULL) { + if ( ! ctx) { LOG(debug, "All targets refused to flush."); return ""; } if ( name == ctx->getName()) { LOG(info, "The same target %s out of %ld has been asked to flush again. " - "This might indicate flush logic flaw so I will wait 1s before doing it.", + "This might indicate flush logic flaw so I will wait 100 ms before doing it.", name.c_str(), lst.first.size()); - FastOS_Thread::Sleep(1000); + std::this_thread::sleep_for(100ms); } - _executor.execute(Task::UP(new FlushTask(initFlush(*ctx), *this, ctx))); + _executor.execute(std::make_unique<FlushTask>(initFlush(*ctx), *this, ctx)); return ctx->getName(); } @@ -330,12 +317,8 @@ FlushEngine::initFlush(const FlushContext &ctx) { if (LOG_WOULD_LOG(event)) { IFlushTarget::MemoryGain mgain(ctx.getTarget()->getApproxMemoryGain()); - EventLogger::flushStart(ctx.getName(), - mgain.getBefore(), - mgain.getAfter(), - mgain.gain(), - ctx.getTarget()->getFlushedSerialNum() + 1, - ctx.getHandler()->getCurrentSerialNumber()); + EventLogger::flushStart(ctx.getName(), mgain.getBefore(), mgain.getAfter(), mgain.gain(), + ctx.getTarget()->getFlushedSerialNum() + 1, ctx.getHandler()->getCurrentSerialNumber()); } return initFlush(ctx.getHandler(), ctx.getTarget()); } @@ -350,10 +333,7 @@ FlushEngine::flushDone(const FlushContext &ctx, uint32_t taskId) } if (LOG_WOULD_LOG(event)) { FlushStats stats = ctx.getTarget()->getLastFlushStats(); - EventLogger::flushComplete(ctx.getName(), - duration.ms(), - stats.getPath(), - stats.getPathElementsToLog()); + EventLogger::flushComplete(ctx.getName(), duration.ms(), stats.getPath(), stats.getPathElementsToLog()); } LOG(debug, "FlushEngine::flushDone(taskId='%d') took '%f' secs", taskId, duration.sec()); std::lock_guard<std::mutex> guard(_lock); @@ -366,8 +346,7 @@ FlushEngine::flushDone(const FlushContext &ctx, uint32_t taskId) } IFlushHandler::SP -FlushEngine::putFlushHandler(const DocTypeName &docTypeName, - const IFlushHandler::SP &flushHandler) +FlushEngine::putFlushHandler(const DocTypeName &docTypeName, const IFlushHandler::SP &flushHandler) { std::lock_guard<std::mutex> guard(_lock); IFlushHandler::SP result(_handlers.putHandler(docTypeName, flushHandler)); @@ -379,13 +358,6 @@ FlushEngine::putFlushHandler(const DocTypeName &docTypeName, } IFlushHandler::SP -FlushEngine::getFlushHandler(const DocTypeName &docTypeName) const -{ - std::lock_guard<std::mutex> guard(_lock); - return _handlers.getHandler(docTypeName); -} - -IFlushHandler::SP FlushEngine::removeFlushHandler(const DocTypeName &docTypeName) { std::lock_guard<std::mutex> guard(_lock); @@ -430,7 +402,7 @@ FlushEngine::setStrategy(IFlushStrategy::SP strategy) return; } assert(!_priorityStrategy); - _priorityStrategy = strategy; + _priorityStrategy = std::move(strategy); { std::lock_guard<std::mutex> guard(_lock); _cond.notify_all(); diff --git a/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.h b/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.h index 19175f9ce2a..c1be05ba067 100644 --- a/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.h +++ b/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.h @@ -15,7 +15,7 @@ namespace proton { namespace flushengine { class ITlsStatsFactory; } -class FlushEngine : public FastOS_Runnable +class FlushEngine final : public FastOS_Runnable { public: class FlushMeta { @@ -37,9 +37,7 @@ private: struct FlushInfo : public FlushMeta { FlushInfo(); - FlushInfo(uint32_t taskId, - const IFlushTarget::SP &target, - const vespalib::string &destination); + FlushInfo(uint32_t taskId, const IFlushTarget::SP &target, const vespalib::string &destination); ~FlushInfo(); IFlushTarget::SP _target; @@ -96,14 +94,13 @@ public: * @param numThreads The number of worker threads to use. * @param idleInterval The interval between when flushes are checked whne there are no one progressing. */ - FlushEngine(std::shared_ptr<flushengine::ITlsStatsFactory> - tlsStatsFactory, + FlushEngine(std::shared_ptr<flushengine::ITlsStatsFactory> tlsStatsFactory, IFlushStrategy::SP strategy, uint32_t numThreads, uint32_t idleIntervalMS); /** * Destructor. Waits for all pending tasks to complete. */ - ~FlushEngine(); + ~FlushEngine() override; /** * Observe and reset internal executor stats @@ -145,19 +142,8 @@ public: * @param flushHandler The handler to register. * @return The replaced handler, if any. */ - IFlushHandler::SP - putFlushHandler(const DocTypeName &docTypeName, - const IFlushHandler::SP &flushHandler); + IFlushHandler::SP putFlushHandler(const DocTypeName &docTypeName, const IFlushHandler::SP &flushHandler); - /** - * Returns the flush handler for the given document type. If no handler was - * registered, this method returns an empty shared pointer. - * - * @param docType The document type whose handler to return. - * @return The registered handler, if any. - */ - IFlushHandler::SP - getFlushHandler(const DocTypeName &docTypeName) const; /** * Removes and returns the flush handler for the given document type. If no @@ -166,10 +152,8 @@ public: * @param docType The document type whose handler to remove. * @return The removed handler, if any. */ - IFlushHandler::SP - removeFlushHandler(const DocTypeName &docTypeName); + IFlushHandler::SP removeFlushHandler(const DocTypeName &docTypeName); - // Implements FastOS_Runnable. void Run(FastOS_ThreadInterface *thread, void *arg) override; FlushMetaSet getCurrentlyFlushingSet() const; diff --git a/searchcore/src/vespa/searchcore/proton/flushengine/iflushhandler.h b/searchcore/src/vespa/searchcore/proton/flushengine/iflushhandler.h index 3a24330f8ec..914de9df30c 100644 --- a/searchcore/src/vespa/searchcore/proton/flushengine/iflushhandler.h +++ b/searchcore/src/vespa/searchcore/proton/flushengine/iflushhandler.h @@ -30,9 +30,7 @@ public: */ IFlushHandler(const vespalib::string &name) : _name(name) - { - // empty - } + { } /** * Virtual destructor required for inheritance. @@ -76,8 +74,7 @@ public: * This method is called to sync tls to stable media, up to and * including the given serial number. * - * @param syncTo The last serial number that has to be persisted to stable - * media. + * @param syncTo The last serial number that has to be persisted to stable media. */ virtual void syncTls(SerialNum syncTo) = 0; }; diff --git a/searchcore/src/vespa/searchcore/proton/server/prepare_restart_handler.cpp b/searchcore/src/vespa/searchcore/proton/server/prepare_restart_handler.cpp index aef49c51f7a..1c930ef1ddc 100644 --- a/searchcore/src/vespa/searchcore/proton/server/prepare_restart_handler.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/prepare_restart_handler.cpp @@ -50,8 +50,7 @@ PrepareRestartHandler::performPrepareRestart(const ProtonConfig &protonCfg, std: { _running = true; lock.unlock(); - auto strategy = std::make_shared<PrepareRestartFlushStrategy>(createPrepareRestartConfig(protonCfg)); - _flushEngine.setStrategy(strategy); + _flushEngine.setStrategy(std::make_shared<PrepareRestartFlushStrategy>(createPrepareRestartConfig(protonCfg))); lock.lock(); _running = false; _cond.notify_all(); diff --git a/searchcore/src/vespa/searchcore/proton/server/proton.cpp b/searchcore/src/vespa/searchcore/proton/server/proton.cpp index 32dc711d5cf..6ffb82a2ad3 100644 --- a/searchcore/src/vespa/searchcore/proton/server/proton.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/proton.cpp @@ -240,9 +240,8 @@ Proton::init(const BootstrapConfig::SP & configSnapshot) const HwInfo & hwInfo = configSnapshot->getHwInfo(); setFS4Compression(protonConfig); - _diskMemUsageSampler = std::make_unique<DiskMemUsageSampler> - (protonConfig.basedir, - diskMemUsageSamplerConfig(protonConfig, hwInfo)); + _diskMemUsageSampler = std::make_unique<DiskMemUsageSampler>(protonConfig.basedir, + diskMemUsageSamplerConfig(protonConfig, hwInfo)); _tls = std::make_unique<TLS>(_configUri.createWithNewId(protonConfig.tlsconfigid), _fileHeaderContext); _metricsEngine->addMetricsHook(_metricsHook); @@ -253,6 +252,7 @@ Proton::init(const BootstrapConfig::SP & configSnapshot) _distributionKey = protonConfig.distributionkey; _summaryEngine= std::make_unique<SummaryEngine>(protonConfig.numsummarythreads); _docsumBySlime = std::make_unique<DocsumBySlime>(*_summaryEngine); + IFlushStrategy::SP strategy; const ProtonConfig::Flush & flush(protonConfig.flush); switch (flush.strategy) { @@ -283,17 +283,15 @@ Proton::init(const BootstrapConfig::SP & configSnapshot) LOG(debug, "Start proton server with root at %s and cwd at %s", protonConfig.basedir.c_str(), getcwd(tmp, sizeof(tmp))); - _persistenceEngine.reset(new PersistenceEngine(*this, - _diskMemUsageSampler->writeFilter(), - protonConfig.visit.defaultserializedsize, - protonConfig.visit.ignoremaxbytes)); - + _persistenceEngine = std::make_unique<PersistenceEngine>(*this, _diskMemUsageSampler->writeFilter(), + protonConfig.visit.defaultserializedsize, + protonConfig.visit.ignoremaxbytes); vespalib::string fileConfigId; - _warmupExecutor.reset(new vespalib::ThreadStackExecutor(4, 128*1024)); + _warmupExecutor = std::make_unique<vespalib::ThreadStackExecutor>(4, 128*1024); const size_t summaryThreads = deriveCompactionCompressionThreads(protonConfig, hwInfo.cpu()); - _summaryExecutor.reset(new vespalib::BlockingThreadStackExecutor(summaryThreads, 128*1024, summaryThreads*16)); + _summaryExecutor = std::make_unique<vespalib::BlockingThreadStackExecutor>(summaryThreads, 128*1024, summaryThreads*16); InitializeThreads initializeThreads; if (protonConfig.initialize.threads > 0) { initializeThreads = std::make_shared<vespalib::ThreadStackExecutor>(protonConfig.initialize.threads, 128 * 1024); @@ -305,7 +303,7 @@ Proton::init(const BootstrapConfig::SP & configSnapshot) _prepareRestartHandler = std::make_unique<PrepareRestartHandler>(*_flushEngine); RPCHooks::Params rpcParams(*this, protonConfig.rpcport, _configUri.getConfigId()); rpcParams.slobrok_config = _configUri.createWithNewId(protonConfig.slobrokconfigid); - _rpcHooks.reset(new RPCHooks(rpcParams)); + _rpcHooks = std::make_unique<RPCHooks>(rpcParams); waitForInitDone(); @@ -528,23 +526,11 @@ Proton::addDocumentDB(const document::DocumentType &docType, // 1 thread per document type. initializeThreads = std::make_shared<vespalib::ThreadStackExecutor>(1, 128 * 1024); } - DocumentDB::SP ret(new DocumentDB(config.basedir + "/documents", - documentDBConfig, - config.tlsspec, - _queryLimiter, - _clock, - docTypeName, - bucketSpace, - config, - *this, - *_warmupExecutor, - *_summaryExecutor, - *_tls->getTransLogServer(), - *_metricsEngine, - _fileHeaderContext, - std::move(config_store), - initializeThreads, - bootstrapConfig->getHwInfo())); + auto ret = std::make_shared<DocumentDB>(config.basedir + "/documents", documentDBConfig, config.tlsspec, + _queryLimiter, _clock, docTypeName, bucketSpace, config, *this, + *_warmupExecutor, *_summaryExecutor, *_tls->getTransLogServer(), + *_metricsEngine, _fileHeaderContext, std::move(config_store), + initializeThreads, bootstrapConfig->getHwInfo()); try { ret->start(); } catch (vespalib::Exception &e) { @@ -571,10 +557,10 @@ Proton::addDocumentDB(const document::DocumentType &docType, // TODO: Fix race with new cluster state setting. _persistenceEngine->putHandler(bucketSpace, docTypeName, persistenceHandler); } - SearchHandlerProxy::SP searchHandler(new SearchHandlerProxy(ret)); + auto searchHandler = std::make_shared<SearchHandlerProxy>(ret); _summaryEngine->putSearchHandler(docTypeName, searchHandler); _matchEngine->putSearchHandler(docTypeName, searchHandler); - FlushHandlerProxy::SP flushHandler(new FlushHandlerProxy(ret)); + auto flushHandler = std::make_shared<FlushHandlerProxy>(ret); _flushEngine->putFlushHandler(docTypeName, flushHandler); _diskMemUsageSampler->notifier().addDiskMemUsageListener(ret->diskMemUsageListener()); return ret; @@ -624,7 +610,7 @@ Proton::MonitorReply::UP Proton::ping(MonitorRequest::UP request, MonitorClient & client) { (void) client; - MonitorReply::UP reply(new MonitorReply()); + auto reply = std::make_unique<MonitorReply>(); MonitorReply &ret = *reply; BootstrapConfig::SP configSnapshot = getActiveConfigSnapshot(); @@ -807,8 +793,8 @@ struct DocumentDBMapExplorer : vespalib::StateExplorer { std::shared_timed_mutex &mutex; DocumentDBMapExplorer(const DocumentDBMap &documentDBMap_in, std::shared_timed_mutex &mutex_in) : documentDBMap(documentDBMap_in), mutex(mutex_in) {} - virtual void get_state(const vespalib::slime::Inserter &, bool) const override {} - virtual std::vector<vespalib::string> get_children_names() const override { + void get_state(const vespalib::slime::Inserter &, bool) const override {} + std::vector<vespalib::string> get_children_names() const override { std::shared_lock<std::shared_timed_mutex> guard(mutex); std::vector<vespalib::string> names; for (const auto &item: documentDBMap) { @@ -816,14 +802,14 @@ struct DocumentDBMapExplorer : vespalib::StateExplorer { } return names; } - virtual std::unique_ptr<vespalib::StateExplorer> get_child(vespalib::stringref name) const override { + std::unique_ptr<vespalib::StateExplorer> get_child(vespalib::stringref name) const override { typedef std::unique_ptr<StateExplorer> Explorer_UP; std::shared_lock<std::shared_timed_mutex> guard(mutex); auto result = documentDBMap.find(DocTypeName(vespalib::string(name))); if (result == documentDBMap.end()) { return Explorer_UP(nullptr); } - return Explorer_UP(new DocumentDBExplorer(result->second)); + return std::make_unique<DocumentDBExplorer>(result->second); } }; |