From 19748396db4b41ac1e8dab476d180aff47e8260a Mon Sep 17 00:00:00 2001 From: Dave Rigby Date: Wed, 21 Aug 2019 14:55:29 +0100 Subject: [PATCH] Settings: Avoid static initialization fiasco When building on macOS with clang 8 and ThreadSanitizer enabled, memcached_testapp crashes when destructing the Settings object: libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument With the following backtrace from where the system_error exception is thrown: * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x00007fff7b6411f6 libc++abi.dylib` __cxa_throw frame #1: 0x00007fff7b6147af libc++.1.dylib` std::__1::__throw_system_error(int, char const*) + 77 frame #2: 0x00007fff7b606c93 libc++.1.dylib` std::__1::mutex::lock() + 29 frame #3: 0x00000001009c27ff memcached_testapp` folly::SharedMutexImpl<...>::annotateLazyCreate() [inlined] std::__1::unique_lock::unique_lock(__m=) + 191 at __mutex_base:131 frame #4: 0x00000001009c27f7 memcached_testapp` folly::SharedMutexImpl<...>::annotateLazyCreate() [inlined] std::__1::unique_lock::unique_lock(__m=) at __mutex_base:131 * frame #5: 0x00000001009c27f7 memcached_testapp` folly::SharedMutexImpl<...>::annotateLazyCreate() + 140 at SharedMutex.cpp:33 frame #6: 0x00000001009c276b memcached_testapp` folly::SharedMutexImpl<...>::annotateLazyCreate(this=0x0000000100c7ddc8) + 43 at SharedMutex.h:705 frame #7: 0x00000001009c191a memcached_testapp` folly::SharedMutexImpl<...>::~SharedMutexImpl() [inlined] folly::SharedMutexImpl<...>::annotateDestroy(this=) + 8 at SharedMutex.h:718 frame #8: 0x00000001009c1912 memcached_testapp` folly::SharedMutexImpl<...>::~SharedMutexImpl() + 24 at SharedMutex.h:324 frame #9: 0x00000001009c18fa memcached_testapp` folly::SharedMutexImpl<...>::~SharedMutexImpl(this=0x0000000100c7ddc8) + 26 at SharedMutex.h:300 frame #10: 0x000000010076b837 memcached_testapp` folly::Synchronized<...>::~Synchronized(this=0x0000000100c7ddb0) + 55 at Synchronized.h:484 frame #11: 0x000000010075d1d9 memcached_testapp` folly::Synchronized<...>::~Synchronized(this=0x0000000100c7ddb0) + 41 at Synchronized.h:484 frame #12: 0x000000010075e8fc memcached_testapp` Settings::~Settings(this=0x0000000100c7db10) + 76 at settings.h:51 frame #13: 0x000000010075c8b9 memcached_testapp` Settings::~Settings(this=0x0000000100c7db10) + 41 at settings.h:51 frame #14: 0x0000000102b7d5c1 libclang_rt.tsan_osx_dynamic.dylib` cxa_at_exit_wrapper(void*) + 33 frame #15: 0x00007fff7d72beed libsystem_c.dylib` __cxa_finalize_ranges + 351 frame #16: 0x00007fff7d72c1fe libsystem_c.dylib` exit + 55 frame #17: 0x00007fff7d67f01c libdyld.dylib` start + 8 The problem is at frame 5, where as part of the destruction of SharedMutex (as used by a member variable of Settings) we are attempting to acquire a mutex which has already been destructed (as it is itself a function-local static) - i.e. we have encountered the static initialization order fiasco :( Address this by changing `settings` to no longer be a plain static (global) variable, and instead be created on first use via a new Settings::instance() static method. Change-Id: I40bd44ed0ae32eb55271ce739fdf990d9869c32f Reviewed-on: http://review.couchbase.org/113640 Tested-by: Build Bot Reviewed-by: Jim Walker --- daemon/cmdline.cc | 10 +- daemon/config_parse.cc | 4 +- daemon/connection.cc | 29 +-- daemon/connections.cc | 2 +- daemon/cookie.cc | 6 +- daemon/datatype.cc | 6 +- daemon/mcaudit.cc | 6 +- daemon/mcbp.cc | 2 +- daemon/mcbp_executors.cc | 30 +-- daemon/memcached.cc | 189 ++++++++++-------- .../protocol/mcbp/audit_configure_context.cc | 4 +- daemon/protocol/mcbp/hello_packet_executor.cc | 4 +- .../mcbp/rbac_reload_command_context.cc | 6 +- daemon/protocol/mcbp/stats_context.cc | 8 +- daemon/runtime.cc | 2 +- daemon/server_socket.cc | 4 +- daemon/settings.cc | 9 +- daemon/settings.h | 6 +- daemon/ssl_context_openssl.cc | 12 +- daemon/start_sasl_auth_task.cc | 13 +- daemon/subdocument.cc | 4 +- daemon/thread.cc | 2 +- daemon/topkeys.cc | 6 +- engines/ep/src/dcp/active_stream.cc | 4 + tests/mcbp/mcbp_test.cc | 2 +- tests/topkeys/topkeys_benchmark.cc | 8 +- tests/topkeys/topkeys_test.cc | 2 +- 27 files changed, 208 insertions(+), 172 deletions(-) diff --git a/daemon/cmdline.cc b/daemon/cmdline.cc index cd57bdce36..ed420bbbb2 100644 --- a/daemon/cmdline.cc +++ b/daemon/cmdline.cc @@ -79,19 +79,19 @@ void parse_arguments(int argc, char** argv) { std::exit(EXIT_FAILURE); } - load_config_file(config_file.c_str(), settings); + load_config_file(config_file.c_str(), Settings::instance()); if (verbosity > 0) { - settings.setVerbose(verbosity); + Settings::instance().setVerbose(verbosity); } if (threads > 0) { - settings.setNumWorkerThreads(threads); + Settings::instance().setNumWorkerThreads(threads); } if (requests > 0) { - settings.setRequestsPerEventNotification(requests, - EventPriority::Default); + Settings::instance().setRequestsPerEventNotification( + requests, EventPriority::Default); } } diff --git a/daemon/config_parse.cc b/daemon/config_parse.cc index 2585ab740b..1f7027b349 100644 --- a/daemon/config_parse.cc +++ b/daemon/config_parse.cc @@ -43,7 +43,7 @@ boost::optional validate_proposed_config_changes( try { auto json = nlohmann::json::parse(new_cfg); Settings new_settings(json); - settings.updateSettings(new_settings, false); + Settings::instance().updateSettings(new_settings, false); return {}; } catch (const std::exception& exception) { errors.push_back(exception.what()); @@ -58,7 +58,7 @@ void reload_config_file() { try { auto content = cb::io::loadFile(get_config_file()); Settings new_settings(nlohmann::json::parse(content)); - settings.updateSettings(new_settings, true); + Settings::instance().updateSettings(new_settings, true); } catch (const std::exception& exception) { LOG_WARNING( "Validation failed while reloading config file '{}'. Error: {}", diff --git a/daemon/connection.cc b/daemon/connection.cc index bd3fad8e53..13961fb8f2 100644 --- a/daemon/connection.cc +++ b/daemon/connection.cc @@ -357,7 +357,7 @@ cb::rbac::PrivilegeAccess Connection::checkPrivilege( const std::string privilege_string = cb::rbac::to_string(privilege); const std::string context = privilegeContext.to_string(); - if (settings.isPrivilegeDebug()) { + if (Settings::instance().isPrivilegeDebug()) { audit_privilege_debug(*this, command, all_buckets[bucketIndex].name, @@ -743,7 +743,8 @@ int Connection::sslPreConnection() { disconnect = true; break; case cb::x509::Status::NotPresent: - if (settings.getClientCertMode() == cb::x509::Mode::Mandatory) { + if (Settings::instance().getClientCertMode() == + cb::x509::Mode::Mandatory) { disconnect = true; } else if (is_default_bucket_enabled()) { associate_bucket(*this, "default"); @@ -1122,7 +1123,7 @@ int Connection::sslRead(char* dest, size_t nbytes) { int Connection::sslWrite(const char* src, size_t nbytes) { int ret = 0; - int chunksize = settings.getBioDrainBufferSize(); + int chunksize = Settings::instance().getBioDrainBufferSize(); while (ret < int(nbytes)) { int n; @@ -1249,7 +1250,7 @@ void Connection::ensureIovSpace() { bool Connection::enableSSL(const std::string& cert, const std::string& pkey) { if (ssl.enable(cert, pkey)) { - if (settings.getVerbose() > 1) { + if (Settings::instance().getVerbose() > 1) { ssl.dumpCipherList(getId()); } @@ -1267,7 +1268,7 @@ Connection::Connection(FrontEndThread& thr) peername("unknown"), sockname("unknown"), stateMachine(*this), - max_reqs_per_event(settings.getRequestsPerEventNotification( + max_reqs_per_event(Settings::instance().getRequestsPerEventNotification( EventPriority::Default)) { updateDescription(); cookies.emplace_back(std::unique_ptr{new Cookie(*this)}); @@ -1286,7 +1287,7 @@ Connection::Connection(SOCKET sfd, peername(cb::net::getpeername(socketDescriptor)), sockname(cb::net::getsockname(socketDescriptor)), stateMachine(*this), - max_reqs_per_event(settings.getRequestsPerEventNotification( + max_reqs_per_event(Settings::instance().getRequestsPerEventNotification( EventPriority::Default)) { setTcpNoDelay(true); updateDescription(); @@ -1330,7 +1331,7 @@ void Connection::setState(StateMachine::State next_state) { } void Connection::runStateMachinery() { - if (settings.getVerbose() > 1) { + if (Settings::instance().getVerbose() > 1) { do { LOG_DEBUG("{} - Running task: {}", getId(), @@ -1557,15 +1558,18 @@ void Connection::setPriority(Connection::Priority priority) { switch (priority) { case Priority::High: max_reqs_per_event = - settings.getRequestsPerEventNotification(EventPriority::High); + Settings::instance().getRequestsPerEventNotification( + EventPriority::High); return; case Priority::Medium: max_reqs_per_event = - settings.getRequestsPerEventNotification(EventPriority::Medium); + Settings::instance().getRequestsPerEventNotification( + EventPriority::Medium); return; case Priority::Low: max_reqs_per_event = - settings.getRequestsPerEventNotification(EventPriority::Low); + Settings::instance().getRequestsPerEventNotification( + EventPriority::Low); return; } throw std::invalid_argument("Unkown priority: " + @@ -1575,9 +1579,10 @@ void Connection::setPriority(Connection::Priority priority) { bool Connection::selectedBucketIsXattrEnabled() const { auto* bucketEngine = getBucketEngine(); if (bucketEngine) { - return settings.isXattrEnabled() && bucketEngine->isXattrEnabled(); + return Settings::instance().isXattrEnabled() && + bucketEngine->isXattrEnabled(); } - return settings.isXattrEnabled(); + return Settings::instance().isXattrEnabled(); } ENGINE_ERROR_CODE Connection::add_packet_to_send_pipe( diff --git a/daemon/connections.cc b/daemon/connections.cc index 664c665461..a6b06fe698 100644 --- a/daemon/connections.cc +++ b/daemon/connections.cc @@ -180,7 +180,7 @@ Connection* conn_new(SOCKET sfd, bucket.name); } - if (settings.getVerbose() > 1) { + if (Settings::instance().getVerbose() > 1) { LOG_DEBUG("<{} new client connection", sfd); } diff --git a/daemon/cookie.cc b/daemon/cookie.cc index f8a5eb9eff..7fab3d6dc7 100644 --- a/daemon/cookie.cc +++ b/daemon/cookie.cc @@ -251,7 +251,7 @@ void Cookie::sendDynamicBuffer() { void Cookie::sendNotMyVBucket() { auto pair = connection.getBucket().clusterConfiguration.getConfiguration(); if (pair.first == -1 || (pair.first == connection.getClustermapRevno() && - settings.isDedupeNmvbMaps())) { + Settings::instance().isDedupeNmvbMaps())) { // We don't have a vbucket map, or we've already sent it to the // client mcbp_add_header(*this, @@ -414,7 +414,7 @@ std::string Cookie::getPrintableRequestKey() const { } void Cookie::logCommand() const { - if (settings.getVerbose() == 0) { + if (Settings::instance().getVerbose() == 0) { // Info is not enabled.. we don't want to try to format // output return; @@ -437,7 +437,7 @@ void Cookie::logResponse(const char* reason) const { } void Cookie::logResponse(ENGINE_ERROR_CODE code) const { - if (settings.getVerbose() == 0) { + if (Settings::instance().getVerbose() == 0) { // Info is not enabled.. we don't want to try to format // output return; diff --git a/daemon/datatype.cc b/daemon/datatype.cc index 1e19a09775..f7bb3c3cd1 100644 --- a/daemon/datatype.cc +++ b/daemon/datatype.cc @@ -21,11 +21,11 @@ bool Datatype::isSupported(cb::mcbp::Feature feature) { switch (feature) { case cb::mcbp::Feature::XATTR: - return settings.isXattrEnabled(); + return Settings::instance().isXattrEnabled(); case cb::mcbp::Feature::JSON: - return settings.isDatatypeJsonEnabled(); + return Settings::instance().isDatatypeJsonEnabled(); case cb::mcbp::Feature::SNAPPY: - return settings.isDatatypeSnappyEnabled(); + return Settings::instance().isDatatypeSnappyEnabled(); case cb::mcbp::Feature::TLS: case cb::mcbp::Feature::TCPNODELAY: case cb::mcbp::Feature::MUTATION_SEQNO: diff --git a/daemon/mcaudit.cc b/daemon/mcaudit.cc index 498b6014b9..2e7e774021 100644 --- a/daemon/mcaudit.cc +++ b/daemon/mcaudit.cc @@ -335,8 +335,8 @@ static void event_state_listener(uint32_t id, bool enabled) { void initialize_audit() { /* Start the audit daemon */ - auditHandle = cb::audit::create_audit_daemon(settings.getAuditFile(), - get_server_api()->cookie); + auditHandle = cb::audit::create_audit_daemon( + Settings::instance().getAuditFile(), get_server_api()->cookie); if (!auditHandle) { FATAL_ERROR(EXIT_FAILURE, "FATAL: Failed to start audit daemon"); } @@ -349,7 +349,7 @@ void shutdown_audit() { } ENGINE_ERROR_CODE reconfigure_audit(Cookie& cookie) { - if (auditHandle->configure_auditdaemon(settings.getAuditFile(), + if (auditHandle->configure_auditdaemon(Settings::instance().getAuditFile(), static_cast(&cookie))) { return ENGINE_EWOULDBLOCK; } diff --git a/daemon/mcbp.cc b/daemon/mcbp.cc index 05a1c916b6..3fcca88507 100644 --- a/daemon/mcbp.cc +++ b/daemon/mcbp.cc @@ -114,7 +114,7 @@ void mcbp_add_header(Cookie& cookie, header.getOpaque(), cookie.getCas()); - if (settings.getVerbose() > 1) { + if (Settings::instance().getVerbose() > 1) { auto* header = reinterpret_cast(wbuf.data()); try { LOG_TRACE("<{} Sending: {}", diff --git a/daemon/mcbp_executors.cc b/daemon/mcbp_executors.cc index 9898f6af93..503165ef92 100644 --- a/daemon/mcbp_executors.cc +++ b/daemon/mcbp_executors.cc @@ -216,7 +216,7 @@ static void verbosity_executor(Cookie& cookie) { if (level < 0 || level > MAX_VERBOSITY_LEVEL) { level = MAX_VERBOSITY_LEVEL; } - settings.setVerbose(level); + Settings::instance().setVerbose(level); cookie.sendResponse(cb::mcbp::Status::Success); } @@ -254,7 +254,7 @@ static void sasl_list_mech_executor(Cookie& cookie) { return; } - if (settings.isExternalAuthServiceEnabled()) { + if (Settings::instance().isExternalAuthServiceEnabled()) { // If the system is configured to use ns_server for authentication // we should only advertise PLAIN as the mechanism (as it can't use // SCRAM to connect to LDAP) @@ -267,16 +267,18 @@ static void sasl_list_mech_executor(Cookie& cookie) { return; } - if (connection.isSslEnabled() && settings.has.ssl_sasl_mechanisms) { - const auto& mechs = settings.getSslSaslMechanisms(); + if (connection.isSslEnabled() && + Settings::instance().has.ssl_sasl_mechanisms) { + const auto& mechs = Settings::instance().getSslSaslMechanisms(); cookie.sendResponse(cb::mcbp::Status::Success, {}, {}, mechs, cb::mcbp::Datatype::Raw, 0); - } else if (!connection.isSslEnabled() && settings.has.sasl_mechanisms) { - const auto& mechs = settings.getSaslMechanisms(); + } else if (!connection.isSslEnabled() && + Settings::instance().has.sasl_mechanisms) { + const auto& mechs = Settings::instance().getSaslMechanisms(); cookie.sendResponse(cb::mcbp::Status::Success, {}, {}, @@ -453,11 +455,11 @@ static void config_reload_executor(Cookie& cookie) { // We need to audit that the privilege debug mode changed and // in order to do that we need the "connection" object so we can't // do this by using the common "changed_listener"-interface. - const bool old_priv_debug = settings.isPrivilegeDebug(); + const bool old_priv_debug = Settings::instance().isPrivilegeDebug(); reload_config_file(); - if (settings.isPrivilegeDebug() != old_priv_debug) { + if (Settings::instance().isPrivilegeDebug() != old_priv_debug) { audit_set_privilege_debug_mode(cookie.getConnection(), - settings.isPrivilegeDebug()); + Settings::instance().isPrivilegeDebug()); } cookie.sendResponse(cb::mcbp::Status::Success); } @@ -487,7 +489,7 @@ static void get_errmap_executor(Cookie& cookie) { auto value = cookie.getRequest(Cookie::PacketContent::Full).getValue(); auto* req = reinterpret_cast( value.data()); - auto const& errormap = settings.getErrorMap(req->getVersion()); + auto const& errormap = Settings::instance().getErrorMap(req->getVersion()); if (errormap.empty()) { cookie.sendResponse(cb::mcbp::Status::KeyEnoent); } else { @@ -543,7 +545,7 @@ static void rbac_refresh_executor(Cookie& cookie) { } static void auth_provider_executor(Cookie& cookie) { - if (!settings.isExternalAuthServiceEnabled()) { + if (!Settings::instance().isExternalAuthServiceEnabled()) { cookie.setErrorContext( "Support for external authentication service is disabled"); cookie.sendResponse(cb::mcbp::Status::NotSupported); @@ -982,7 +984,7 @@ void try_read_mcbp_command(Cookie& cookie) { return; } - if (settings.getVerbose() > 1) { + if (Settings::instance().getVerbose() > 1) { try { LOG_TRACE(">{} Read command {}", c.getId(), @@ -997,13 +999,13 @@ void try_read_mcbp_command(Cookie& cookie) { // Protect ourself from someone trying to kill us by sending insanely // large packets. - if (header.getBodylen() > settings.getMaxPacketSize()) { + if (header.getBodylen() > Settings::instance().getMaxPacketSize()) { LOG_WARNING( "{}: The package size ({}) exceeds the limit ({}) for what " "the system accepts.. Disconnecting client", c.getId(), header.getBodylen(), - settings.getMaxPacketSize()); + Settings::instance().getMaxPacketSize()); c.setState(StateMachine::State::closing); return; } diff --git a/daemon/memcached.cc b/daemon/memcached.cc index 76bb1fc3c4..0313e5f4e9 100644 --- a/daemon/memcached.cc +++ b/daemon/memcached.cc @@ -265,11 +265,11 @@ void associate_initial_bucket(Connection& connection) { } static void populate_log_level() { - const auto val = settings.getLogLevel(); + const auto val = Settings::instance().getLogLevel(); // Log the verbosity value set by the user and not the log level as they // are inverted - LOG_INFO("Changing logging level to {}", settings.getVerbose()); + LOG_INFO("Changing logging level to {}", Settings::instance().getVerbose()); cb::logger::setLogLevels(val); } @@ -368,7 +368,8 @@ static void stats_init() { } struct thread_stats* get_thread_stats(Connection* c) { - cb_assert(c->getThread().index < (settings.getNumWorkerThreads() + 1)); + cb_assert(c->getThread().index < + (Settings::instance().getNumWorkerThreads() + 1)); auto& independent_stats = all_buckets[c->getBucketIndex()].stats; return &independent_stats.at(c->getThread().index); } @@ -417,26 +418,27 @@ static size_t get_number_of_worker_threads() { /// We might not support as many connections as requested if /// we don't have enough file descriptors available static void recalculate_max_connections() { - const auto maxconn = settings.getMaxConnections(); - const auto system = (3 * (settings.getNumWorkerThreads() + 2)) + 1024; + const auto maxconn = Settings::instance().getMaxConnections(); + const auto system = + (3 * (Settings::instance().getNumWorkerThreads() + 2)) + 1024; const uint64_t maxfiles = maxconn + system; if (max_file_handles < maxfiles) { const auto newmax = max_file_handles - system; - settings.setMaxConnections(newmax, false); + Settings::instance().setMaxConnections(newmax, false); LOG_WARNING( "max_connections is set higher than the available number of " "file descriptors available. Reduce max_connections to: {}", newmax); - if (newmax > settings.getSystemConnections()) { + if (newmax > Settings::instance().getSystemConnections()) { LOG_WARNING( "system_connections:{} > max_connections:{}. Reduce " "system_connections to {}", - settings.getSystemConnections(), + Settings::instance().getSystemConnections(), newmax, newmax / 2); - settings.setSystemConnections(newmax / 2); + Settings::instance().setSystemConnections(newmax / 2); } } } @@ -456,7 +458,7 @@ static void ssl_cipher_list_changed_listener(const std::string&, Settings &s) { static void verbosity_changed_listener(const std::string&, Settings &s) { auto logger = cb::logger::get(); if (logger) { - logger->set_level(settings.getLogLevel()); + logger->set_level(Settings::instance().getLogLevel()); } // MB-33637: Make the verbosity change in the calling thread. @@ -476,10 +478,10 @@ static void opcode_attributes_override_changed_listener(const std::string&, Settings& s) { try { cb::mcbp::sla::reconfigure( - settings.getRoot(), + Settings::instance().getRoot(), nlohmann::json::parse(s.getOpcodeAttributesOverride())); } catch (const std::exception&) { - cb::mcbp::sla::reconfigure(settings.getRoot()); + cb::mcbp::sla::reconfigure(Settings::instance().getRoot()); } LOG_INFO("SLA configuration changed to: {}", cb::mcbp::sla::to_json().dump()); @@ -523,21 +525,23 @@ static std::string configure_numa_policy() { static void settings_init() { // Set up the listener functions - settings.addChangeListener("breakpad", - breakpad_changed_listener); - settings.addChangeListener("max_connections", - [](const std::string&, Settings& s) -> void { - recalculate_max_connections(); - }); - settings.addChangeListener("ssl_minimum_protocol", - ssl_minimum_protocol_changed_listener); - settings.addChangeListener("ssl_cipher_list", - ssl_cipher_list_changed_listener); - settings.addChangeListener("verbosity", verbosity_changed_listener); - settings.addChangeListener("interfaces", interfaces_changed_listener); - settings.addChangeListener("scramsha_fallback_salt", - scramsha_fallback_salt_changed_listener); - settings.addChangeListener( + Settings::instance().addChangeListener("breakpad", + breakpad_changed_listener); + Settings::instance().addChangeListener( + "max_connections", [](const std::string&, Settings& s) -> void { + recalculate_max_connections(); + }); + Settings::instance().addChangeListener( + "ssl_minimum_protocol", ssl_minimum_protocol_changed_listener); + Settings::instance().addChangeListener("ssl_cipher_list", + ssl_cipher_list_changed_listener); + Settings::instance().addChangeListener("verbosity", + verbosity_changed_listener); + Settings::instance().addChangeListener("interfaces", + interfaces_changed_listener); + Settings::instance().addChangeListener( + "scramsha_fallback_salt", scramsha_fallback_salt_changed_listener); + Settings::instance().addChangeListener( "active_external_users_push_interval", [](const std::string&, Settings& s) -> void { if (externalAuthManager) { @@ -546,7 +550,7 @@ static void settings_init() { } }); - settings.addChangeListener( + Settings::instance().addChangeListener( "opentracing_config", [](const std::string&, Settings& s) -> void { auto config = s.getOpenTracingConfig(); if (config) { @@ -555,35 +559,39 @@ static void settings_init() { }); NetworkInterface default_interface; - settings.addInterface(default_interface); - - settings.setBioDrainBufferSize(8192); - - settings.setVerbose(0); - settings.setConnectionIdleTime(0); // Connection idle time disabled - settings.setNumWorkerThreads(get_number_of_worker_threads()); - settings.setDatatypeJsonEnabled(true); - settings.setDatatypeSnappyEnabled(true); - settings.setRequestsPerEventNotification(50, EventPriority::High); - settings.setRequestsPerEventNotification(5, EventPriority::Medium); - settings.setRequestsPerEventNotification(1, EventPriority::Low); - settings.setRequestsPerEventNotification(20, EventPriority::Default); + Settings::instance().addInterface(default_interface); + + Settings::instance().setBioDrainBufferSize(8192); + + Settings::instance().setVerbose(0); + Settings::instance().setConnectionIdleTime( + 0); // Connection idle time disabled + Settings::instance().setNumWorkerThreads(get_number_of_worker_threads()); + Settings::instance().setDatatypeJsonEnabled(true); + Settings::instance().setDatatypeSnappyEnabled(true); + Settings::instance().setRequestsPerEventNotification(50, + EventPriority::High); + Settings::instance().setRequestsPerEventNotification(5, + EventPriority::Medium); + Settings::instance().setRequestsPerEventNotification(1, EventPriority::Low); + Settings::instance().setRequestsPerEventNotification( + 20, EventPriority::Default); /* * The max object size is 20MB. Let's allow packets up to 30MB to * be handled "properly" by returing E2BIG, but packets bigger * than that will cause the server to disconnect the client */ - settings.setMaxPacketSize(30 * 1024 * 1024); + Settings::instance().setMaxPacketSize(30 * 1024 * 1024); - settings.setDedupeNmvbMaps(false); + Settings::instance().setDedupeNmvbMaps(false); char *tmp = getenv("MEMCACHED_TOP_KEYS"); - settings.setTopkeysSize(20); + Settings::instance().setTopkeysSize(20); if (tmp) { int count; if (safe_strtol(tmp, count)) { - settings.setTopkeysSize(count); + Settings::instance().setTopkeysSize(count); } } @@ -599,18 +607,18 @@ static void settings_init() { // in memcached.json and override these settings. const char *env = getenv("COUCHBASE_SSL_CIPHER_LIST"); if (env == nullptr) { - settings.setSslCipherList("HIGH"); + Settings::instance().setSslCipherList("HIGH"); } else { - settings.setSslCipherList(env); + Settings::instance().setSslCipherList(env); } } - settings.setSslMinimumProtocol("tlsv1"); + Settings::instance().setSslMinimumProtocol("tlsv1"); if (getenv("COUCHBASE_ENABLE_PRIVILEGE_DEBUG") != nullptr) { - settings.setPrivilegeDebug(true); + Settings::instance().setPrivilegeDebug(true); } - settings.setTopkeysEnabled(true); + Settings::instance().setTopkeysEnabled(true); } /** @@ -625,8 +633,8 @@ static void update_settings_from_config() { std::string root(DESTINATION_ROOT); - if (!settings.getRoot().empty()) { - root = settings.getRoot(); + if (!Settings::instance().getRoot().empty()) { + root = Settings::instance().getRoot(); #ifdef WIN32 std::string libdir = root + "/lib"; cb::io::sanitizePath(libdir); @@ -634,12 +642,12 @@ static void update_settings_from_config() #endif } - if (settings.getErrorMapsDir().empty()) { + if (Settings::instance().getErrorMapsDir().empty()) { // Set the error map dir. std::string error_maps_dir(root + "/etc/couchbase/kv/error_maps"); cb::io::sanitizePath(error_maps_dir); if (cb::io::isDirectory(error_maps_dir)) { - settings.setErrorMapsDir(error_maps_dir); + Settings::instance().setErrorMapsDir(error_maps_dir); } } @@ -649,8 +657,9 @@ static void update_settings_from_config() FATAL_ERROR(EXIT_FAILURE, e.what()); } - settings.addChangeListener("opcode_attributes_override", - opcode_attributes_override_changed_listener); + Settings::instance().addChangeListener( + "opcode_attributes_override", + opcode_attributes_override_changed_listener); } struct { @@ -755,7 +764,7 @@ bool is_bucket_dying(Connection& c) { } static void create_portnumber_file(bool terminate) { - auto filename = settings.getPortnumberFile(); + auto filename = Settings::instance().getPortnumberFile(); if (!filename.empty()) { nlohmann::json json; json["ports"] = nlohmann::json::array(); @@ -894,7 +903,7 @@ static void dispatch_event_handler(evutil_socket_t fd, short, void *) { check_listen_conn = false; bool changes = false; - auto interfaces = settings.getInterfaces(); + auto interfaces = Settings::instance().getInterfaces(); // Step one, enable all new ports bool success = true; @@ -1304,7 +1313,7 @@ static bool server_sockets() { bool success = true; LOG_INFO("Enable port(s)"); - for (auto& interface : settings.getInterfaces()) { + for (auto& interface : Settings::instance().getInterfaces()) { if (!server_socket(interface)) { success = false; } @@ -1470,13 +1479,13 @@ struct ServerLogApi : public ServerLogIface { void set_level(spdlog::level::level_enum severity) override { switch (severity) { case spdlog::level::level_enum::trace: - settings.setVerbose(2); + Settings::instance().setVerbose(2); break; case spdlog::level::level_enum::debug: - settings.setVerbose(1); + Settings::instance().setVerbose(1); break; default: - settings.setVerbose(0); + Settings::instance().setVerbose(0); break; } } @@ -1825,8 +1834,8 @@ void CreateBucketThread::create() { all_buckets[ii].type = type; strcpy(all_buckets[ii].name, name.c_str()); try { - all_buckets[ii].topkeys = - std::make_unique(settings.getTopkeysSize()); + all_buckets[ii].topkeys = std::make_unique( + Settings::instance().getTopkeysSize()); } catch (const std::bad_alloc &) { result = ENGINE_ENOMEM; LOG_WARNING("{} Create bucket [{}] failed - out of memory", @@ -2098,7 +2107,7 @@ void DestroyBucketThread::run() { } static void initialize_buckets() { - size_t numthread = settings.getNumWorkerThreads() + 1; + size_t numthread = Settings::instance().getNumWorkerThreads() + 1; for (auto &b : all_buckets) { b.stats.resize(numthread); } @@ -2314,15 +2323,16 @@ extern "C" int memcached_main(int argc, char **argv) { cb::rbac::initialize(); if (getenv("COUCHBASE_FORCE_ENABLE_XATTR") != nullptr) { - settings.setXattrEnabled(true); + Settings::instance().setXattrEnabled(true); } /* Initialize breakpad crash catcher with our just-parsed settings. */ - cb::breakpad::initialize(settings.getBreakpadSettings()); + cb::breakpad::initialize(Settings::instance().getBreakpadSettings()); /* Configure file logger, if specified as a settings object */ - if (settings.has.logger) { - auto ret = cb::logger::initialize(settings.getLoggerConfig()); + if (Settings::instance().has.logger) { + auto ret = + cb::logger::initialize(Settings::instance().getLoggerConfig()); if (ret) { FATAL_ERROR( EXIT_FAILURE, "Failed to initialize logger: {}", ret.get()); @@ -2336,27 +2346,27 @@ extern "C" int memcached_main(int argc, char **argv) { LOG_INFO("Using SLA configuration: {}", cb::mcbp::sla::to_json().dump()); - auto opentracingconfig = settings.getOpenTracingConfig(); + auto opentracingconfig = Settings::instance().getOpenTracingConfig(); if (opentracingconfig) { OpenTracing::updateConfig(*opentracingconfig); } - if (settings.isStdinListenerEnabled()) { + if (Settings::instance().isStdinListenerEnabled()) { LOG_INFO("Enable standard input listener"); start_stdin_listener(shutdown_server); } - if (settings.getPortnumberFile().empty()) { + if (Settings::instance().getPortnumberFile().empty()) { const auto* env = getenv("MEMCACHED_PORT_FILENAME"); if (env != nullptr) { - settings.setPortnumberFile(env); + Settings::instance().setPortnumberFile(env); } } - if (settings.getParentIdentifier() == -1) { + if (Settings::instance().getParentIdentifier() == -1) { const auto* env = getenv("MEMCACHED_PARENT_MONITOR"); if (env != nullptr) { - settings.setParentIdentifier(std::stoi(env)); + Settings::instance().setParentIdentifier(std::stoi(env)); } } @@ -2365,27 +2375,30 @@ extern "C" int memcached_main(int argc, char **argv) { LOG_INFO("NUMA: {}", numa_status); #endif - if (!settings.has.rbac_file) { + if (!Settings::instance().has.rbac_file) { FATAL_ERROR(EXIT_FAILURE, "RBAC file not specified"); } - if (!cb::io::isFile(settings.getRbacFile())) { + if (!cb::io::isFile(Settings::instance().getRbacFile())) { FATAL_ERROR(EXIT_FAILURE, "RBAC [{}] does not exist", - settings.getRbacFile()); + Settings::instance().getRbacFile()); } - LOG_INFO("Loading RBAC configuration from [{}]", settings.getRbacFile()); + LOG_INFO("Loading RBAC configuration from [{}]", + Settings::instance().getRbacFile()); try { - cb::rbac::loadPrivilegeDatabase(settings.getRbacFile()); + cb::rbac::loadPrivilegeDatabase(Settings::instance().getRbacFile()); } catch (const std::exception& exception) { // We can't run without a privilege database FATAL_ERROR(EXIT_FAILURE, exception.what()); } - LOG_INFO("Loading error maps from [{}]", settings.getErrorMapsDir()); + LOG_INFO("Loading error maps from [{}]", + Settings::instance().getErrorMapsDir()); try { - settings.loadErrorMaps(settings.getErrorMapsDir()); + Settings::instance().loadErrorMaps( + Settings::instance().getErrorMapsDir()); } catch (const std::exception& e) { FATAL_ERROR(EXIT_FAILURE, "Failed to load error maps: {}", e.what()); } @@ -2393,7 +2406,7 @@ extern "C" int memcached_main(int argc, char **argv) { LOG_INFO("Starting external authentication manager"); externalAuthManager = std::make_unique(); externalAuthManager->setPushActiveUsersInterval( - settings.getActiveExternalUsersPushInterval()); + Settings::instance().getActiveExternalUsersPushInterval()); externalAuthManager->start(); initialize_audit(); @@ -2454,10 +2467,12 @@ extern "C" int memcached_main(int argc, char **argv) { create_listen_sockets(); /* start up worker threads if MT mode */ - thread_init(settings.getNumWorkerThreads(), main_base, dispatch_event_handler); + thread_init(Settings::instance().getNumWorkerThreads(), + main_base, + dispatch_event_handler); - executorPool = - std::make_unique(settings.getNumWorkerThreads()); + executorPool = std::make_unique( + Settings::instance().getNumWorkerThreads()); initializeTracing(); TRACE_GLOBAL0("memcached", "Started"); @@ -2474,7 +2489,7 @@ extern "C" int memcached_main(int argc, char **argv) { // Optional parent monitor { - const int parent = settings.getParentIdentifier(); + const int parent = Settings::instance().getParentIdentifier(); if (parent != -1) { LOG_INFO("Starting parent monitor"); parent_monitor = std::make_unique(parent); diff --git a/daemon/protocol/mcbp/audit_configure_context.cc b/daemon/protocol/mcbp/audit_configure_context.cc index f81b4660ad..35ff915daf 100644 --- a/daemon/protocol/mcbp/audit_configure_context.cc +++ b/daemon/protocol/mcbp/audit_configure_context.cc @@ -29,7 +29,7 @@ ENGINE_ERROR_CODE AuditConfigureCommandContext::configuring() { // configure method. state = State::Done; - if (settings.getAuditFile().empty()) { + if (Settings::instance().getAuditFile().empty()) { return ENGINE_SUCCESS; } @@ -40,7 +40,7 @@ ENGINE_ERROR_CODE AuditConfigureCommandContext::configuring() { break; default: LOG_WARNING("configuration of audit daemon failed with config file: {}", - settings.getAuditFile()); + Settings::instance().getAuditFile()); } return ret; diff --git a/daemon/protocol/mcbp/hello_packet_executor.cc b/daemon/protocol/mcbp/hello_packet_executor.cc index 53e1dc0b50..b03683ca9d 100644 --- a/daemon/protocol/mcbp/hello_packet_executor.cc +++ b/daemon/protocol/mcbp/hello_packet_executor.cc @@ -289,7 +289,7 @@ void process_hello_packet_executor(Cookie& cookie) { break; case cb::mcbp::Feature::Collections: // Allow KV engine to chicken out - if (settings.isCollectionsEnabled()) { + if (Settings::instance().isCollectionsEnabled()) { auto& bucket = connection.getBucket(); // Abort if the engine cannot support collections if (bucket.supports(cb::engine::Feature::Collections)) { @@ -320,7 +320,7 @@ void process_hello_packet_executor(Cookie& cookie) { break; case cb::mcbp::Feature::Tracing: - if (settings.isTracingEnabled()) { + if (Settings::instance().isTracingEnabled()) { connection.setTracingEnabled(true); added = true; break; diff --git a/daemon/protocol/mcbp/rbac_reload_command_context.cc b/daemon/protocol/mcbp/rbac_reload_command_context.cc index f5c0619d8d..96f7b23fe5 100644 --- a/daemon/protocol/mcbp/rbac_reload_command_context.cc +++ b/daemon/protocol/mcbp/rbac_reload_command_context.cc @@ -40,9 +40,9 @@ class RbacConfigReloadTask : public Task { try { LOG_INFO("{}: Loading RBAC configuration from [{}] {}", connection.getId(), - settings.getRbacFile(), + Settings::instance().getRbacFile(), connection.getDescription()); - cb::rbac::loadPrivilegeDatabase(settings.getRbacFile()); + cb::rbac::loadPrivilegeDatabase(Settings::instance().getRbacFile()); LOG_INFO("{}: RBAC configuration updated {}", connection.getId(), connection.getDescription()); @@ -51,7 +51,7 @@ class RbacConfigReloadTask : public Task { "{}: RbacConfigReloadTask(): An error occured while " "loading RBAC configuration from [{}] {}: {}", connection.getId(), - settings.getRbacFile(), + Settings::instance().getRbacFile(), connection.getDescription(), error.what()); status = ENGINE_FAILED; diff --git a/daemon/protocol/mcbp/stats_context.cc b/daemon/protocol/mcbp/stats_context.cc index e7ac206417..ef028cb701 100644 --- a/daemon/protocol/mcbp/stats_context.cc +++ b/daemon/protocol/mcbp/stats_context.cc @@ -229,7 +229,10 @@ static ENGINE_ERROR_CODE server_stats(const AddStatFn& add_stat_callback, add_stat(cookie, add_stat_callback, "listen_disabled_num", get_listen_disabled_num()); add_stat(cookie, add_stat_callback, "rejected_conns", stats.rejected_conns); - add_stat(cookie, add_stat_callback, "threads", settings.getNumWorkerThreads()); + add_stat(cookie, + add_stat_callback, + "threads", + Settings::instance().getNumWorkerThreads()); add_stat(cookie, add_stat_callback, "conn_yields", thread_stats.conn_yields); add_stat(cookie, add_stat_callback, "rbufs_allocated", thread_stats.rbufs_allocated); @@ -400,7 +403,8 @@ static ENGINE_ERROR_CODE stat_reset_executor(const std::string& arg, static ENGINE_ERROR_CODE stat_sched_executor(const std::string& arg, Cookie& cookie) { if (arg.empty()) { - for (size_t ii = 0; ii < settings.getNumWorkerThreads(); ++ii) { + for (size_t ii = 0; ii < Settings::instance().getNumWorkerThreads(); + ++ii) { auto hist = scheduler_info[ii].to_string(); std::string key = std::to_string(ii); append_stats(key.data(), diff --git a/daemon/runtime.cc b/daemon/runtime.cc index fe096f0a04..607058e89c 100644 --- a/daemon/runtime.cc +++ b/daemon/runtime.cc @@ -68,7 +68,7 @@ void set_ssl_protocol_mask(const std::string& mask) { void set_ssl_ctx_protocol_mask(SSL_CTX* ctx) { auto mask = ssl_protocol_mask.load(std::memory_order_acquire); - if (settings.isSslCipherOrder()) { + if (Settings::instance().isSslCipherOrder()) { mask |= SSL_OP_CIPHER_SERVER_PREFERENCE; } SSL_CTX_set_options(ctx, mask); diff --git a/daemon/server_socket.cc b/daemon/server_socket.cc index 38230d85e4..42f9163b47 100644 --- a/daemon/server_socket.cc +++ b/daemon/server_socket.cc @@ -152,10 +152,10 @@ void ServerSocket::acceptNewClient() { if (interface->system) { ++stats.system_conns; current = stats.getSystemConnections(); - limit = settings.getSystemConnections(); + limit = Settings::instance().getSystemConnections(); } else { current = stats.getUserConnections(); - limit = settings.getMaxUserConnections(); + limit = Settings::instance().getMaxUserConnections(); } LOG_DEBUG("Accepting client {} of {}{}", diff --git a/daemon/settings.cc b/daemon/settings.cc index 263aa7a8f1..44b4e1c97c 100644 --- a/daemon/settings.cc +++ b/daemon/settings.cc @@ -36,10 +36,6 @@ #include #include -// the global entry of the settings object -Settings settings; - - /** * Initialize all members to "null" to preserve backwards * compatibility with the previous versions. @@ -69,6 +65,11 @@ Settings::Settings(const nlohmann::json& json) : Settings() { reconfigure(json); } +Settings& Settings::instance() { + static Settings settings; + return settings; +} + /** * Handle deprecated tags in the settings by simply ignoring them */ diff --git a/daemon/settings.h b/daemon/settings.h index 97f795e052..d9240c9d2d 100644 --- a/daemon/settings.h +++ b/daemon/settings.h @@ -47,6 +47,8 @@ enum class EventPriority { /** * Globally accessible settings as derived from the commandline / JSON config * file. + * + * Typically only the singleton instance (accessible via instance() is used. */ class Settings { public: @@ -62,6 +64,8 @@ class Settings { Settings(const Settings&) = delete; + /// Returns a reference to the singleton instance of Settings. + static Settings& instance(); /** * Allow the global settings instance to be changed by loading the @@ -1036,5 +1040,3 @@ class Settings { void notify_changed(const std::string& key); }; - -extern Settings settings; diff --git a/daemon/ssl_context_openssl.cc b/daemon/ssl_context_openssl.cc index cc5c45d8df..bf2d5c1c92 100644 --- a/daemon/ssl_context_openssl.cc +++ b/daemon/ssl_context_openssl.cc @@ -72,7 +72,7 @@ bool SslContext::enable(const std::string& cert, const std::string& pkey) { set_ssl_ctx_cipher_list(ctx); int ssl_flags = 0; - switch (settings.getClientCertMode()) { + switch (Settings::instance().getClientCertMode()) { case cb::x509::Mode::Mandatory: ssl_flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; // FALLTHROUGH @@ -97,16 +97,16 @@ bool SslContext::enable(const std::string& cert, const std::string& pkey) { client = NULL; try { - inputPipe.ensureCapacity(settings.getBioDrainBufferSize()); - outputPipe.ensureCapacity(settings.getBioDrainBufferSize()); + inputPipe.ensureCapacity(Settings::instance().getBioDrainBufferSize()); + outputPipe.ensureCapacity(Settings::instance().getBioDrainBufferSize()); } catch (std::bad_alloc) { return false; } BIO_new_bio_pair(&application, - settings.getBioDrainBufferSize(), + Settings::instance().getBioDrainBufferSize(), &network, - settings.getBioDrainBufferSize()); + Settings::instance().getBioDrainBufferSize()); client = SSL_new(ctx); SSL_set_bio(client, application, application); @@ -116,7 +116,7 @@ bool SslContext::enable(const std::string& cert, const std::string& pkey) { std::pair SslContext::getCertUserName() { cb::openssl::unique_x509_ptr cert(SSL_get_peer_certificate(client)); - return settings.lookupUser(cert.get()); + return Settings::instance().lookupUser(cert.get()); } void SslContext::disable() { diff --git a/daemon/start_sasl_auth_task.cc b/daemon/start_sasl_auth_task.cc index 7538434aa5..2f175a32f3 100644 --- a/daemon/start_sasl_auth_task.cc +++ b/daemon/start_sasl_auth_task.cc @@ -46,11 +46,13 @@ Task::Status StartSaslAuthTask::internal_auth() { try { if (connection.isSslEnabled()) { - response = server.start( - mechanism, settings.getSslSaslMechanisms(), challenge); + response = server.start(mechanism, + Settings::instance().getSslSaslMechanisms(), + challenge); } else { - response = server.start( - mechanism, settings.getSaslMechanisms(), challenge); + response = server.start(mechanism, + Settings::instance().getSaslMechanisms(), + challenge); } } catch (const cb::sasl::unknown_mechanism&) { response.first = cb::sasl::Error::NO_MECH; @@ -75,7 +77,8 @@ Task::Status StartSaslAuthTask::internal_auth() { } if (response.first == cb::sasl::Error::NO_USER && - settings.isExternalAuthServiceEnabled() && mechanism == "PLAIN") { + Settings::instance().isExternalAuthServiceEnabled() && + mechanism == "PLAIN") { // We can't hold this lock when we're trying to enqueue the // request internal = false; diff --git a/daemon/subdocument.cc b/daemon/subdocument.cc index 09e7a95ff3..c716b9d9f2 100644 --- a/daemon/subdocument.cc +++ b/daemon/subdocument.cc @@ -175,7 +175,7 @@ static void create_single_path_context(SubdocCmdContext& context, traits.subdocCommand, path.buf, path.len); } - if (settings.getVerbose() > 1) { + if (Settings::instance().getVerbose() > 1) { const auto keybuf = request.getKey(); const char* key = reinterpret_cast(keybuf.data()); const auto keylen = gsl::narrow(keybuf.size()); @@ -275,7 +275,7 @@ static void create_multi_path_context(SubdocCmdContext& context, offset += headerlen + path.len + spec_value.len; } - if (settings.getVerbose() > 1) { + if (Settings::instance().getVerbose() > 1) { const auto keybuf = request.getKey(); const char* key = reinterpret_cast(keybuf.data()); const auto keylen = gsl::narrow(keybuf.size()); diff --git a/daemon/thread.cc b/daemon/thread.cc index 784eb8501a..6bf2af9382 100644 --- a/daemon/thread.cc +++ b/daemon/thread.cc @@ -383,7 +383,7 @@ static size_t last_thread = 0; * from the main thread, or because of an incoming connection. */ void dispatch_conn_new(SOCKET sfd, SharedListeningPort& interface) { - size_t tid = (last_thread + 1) % settings.getNumWorkerThreads(); + size_t tid = (last_thread + 1) % Settings::instance().getNumWorkerThreads(); auto& thread = threads[tid]; last_thread = tid; diff --git a/daemon/topkeys.cc b/daemon/topkeys.cc index 018eb95bf4..52f5bb5a80 100644 --- a/daemon/topkeys.cc +++ b/daemon/topkeys.cc @@ -116,7 +116,7 @@ TopKeys::~TopKeys() { void TopKeys::updateKey(const void* key, size_t nkey, rel_time_t operation_time) { - if (settings.isTopkeysEnabled()) { + if (Settings::instance().isTopkeysEnabled()) { doUpdateKey(key, nkey, operation_time); } } @@ -124,7 +124,7 @@ void TopKeys::updateKey(const void* key, ENGINE_ERROR_CODE TopKeys::stats(const void* cookie, rel_time_t current_time, const AddStatFn& add_stat) { - if (settings.isTopkeysEnabled()) { + if (Settings::instance().isTopkeysEnabled()) { return doStats(cookie, current_time, add_stat); } @@ -133,7 +133,7 @@ ENGINE_ERROR_CODE TopKeys::stats(const void* cookie, ENGINE_ERROR_CODE TopKeys::json_stats(nlohmann::json& object, rel_time_t current_time) { - if (settings.isTopkeysEnabled()) { + if (Settings::instance().isTopkeysEnabled()) { return do_json_stats(object, current_time); } diff --git a/engines/ep/src/dcp/active_stream.cc b/engines/ep/src/dcp/active_stream.cc index 0c583d4dd6..41e6b5aee7 100644 --- a/engines/ep/src/dcp/active_stream.cc +++ b/engines/ep/src/dcp/active_stream.cc @@ -733,6 +733,10 @@ void ActiveStream::addTakeoverStats(const AddStatFn& add_stat, } size_t total = backfillRemaining.load(std::memory_order_relaxed); + if (backfillRemaining == 0) { + Expects(!isPending()); + } + if (isBackfilling()) { add_casted_stat("status", "backfilling", add_stat, cookie); } else { diff --git a/tests/mcbp/mcbp_test.cc b/tests/mcbp/mcbp_test.cc index e59cd327b0..980af9eae0 100644 --- a/tests/mcbp/mcbp_test.cc +++ b/tests/mcbp/mcbp_test.cc @@ -43,7 +43,7 @@ ValidatorTest::ValidatorTest(bool collectionsEnabled) } void ValidatorTest::SetUp() { - settings.setXattrEnabled(true); + Settings::instance().setXattrEnabled(true); connection.setCollectionsSupported(collectionsEnabled); memset(request.bytes, 0, sizeof(request)); request.message.header.request.setMagic(cb::mcbp::Magic::ClientRequest); diff --git a/tests/topkeys/topkeys_benchmark.cc b/tests/topkeys/topkeys_benchmark.cc index f9c40d4bbb..f72e5a010f 100644 --- a/tests/topkeys/topkeys_benchmark.cc +++ b/tests/topkeys/topkeys_benchmark.cc @@ -29,7 +29,7 @@ class TopkeysBench : public benchmark::Fixture { protected: TopkeysBench() { topkeys = std::make_unique(50); - settings.setTopkeysEnabled(true); + Settings::instance().setTopkeysEnabled(true); for (int ii = 0; ii < 10000; ii++) { keys.emplace_back("topkey_test_" + std::to_string(ii)); } @@ -44,7 +44,7 @@ class TopkeysBench : public benchmark::Fixture { */ BENCHMARK_DEFINE_F(TopkeysBench, TopkeysDisabled)(benchmark::State& state) { if (state.thread_index == 0) { - settings.setTopkeysEnabled(false); + Settings::instance().setTopkeysEnabled(false); } const auto* k = keys[0].data(); @@ -61,7 +61,7 @@ BENCHMARK_DEFINE_F(TopkeysBench, TopkeysDisabled)(benchmark::State& state) { */ BENCHMARK_DEFINE_F(TopkeysBench, UpdateSameKey)(benchmark::State& state) { if (state.thread_index == 0) { - settings.setTopkeysEnabled(true); + Settings::instance().setTopkeysEnabled(true); } const auto* k = keys[0].data(); @@ -78,7 +78,7 @@ BENCHMARK_DEFINE_F(TopkeysBench, UpdateSameKey)(benchmark::State& state) { */ BENCHMARK_DEFINE_F(TopkeysBench, UpdateRandomKey)(benchmark::State& state) { if (state.thread_index == 0) { - settings.setTopkeysEnabled(true); + Settings::instance().setTopkeysEnabled(true); } std::vector mine; diff --git a/tests/topkeys/topkeys_test.cc b/tests/topkeys/topkeys_test.cc index 3663c922e6..d4b124acca 100644 --- a/tests/topkeys/topkeys_test.cc +++ b/tests/topkeys/topkeys_test.cc @@ -23,7 +23,7 @@ class TopKeysTest : public ::testing::Test { protected: void SetUp() { - settings.setTopkeysEnabled(true); + Settings::instance().setTopkeysEnabled(true); topkeys.reset(new TopKeys(10)); }