diff options
43 files changed, 266 insertions, 85 deletions
diff --git a/client/go/cmd/logfmt/cmd.go b/client/go/script-utils/logfmt/cmd.go index 84322c7ff08..84322c7ff08 100644 --- a/client/go/cmd/logfmt/cmd.go +++ b/client/go/script-utils/logfmt/cmd.go diff --git a/client/go/cmd/logfmt/formatflags.go b/client/go/script-utils/logfmt/formatflags.go index 097746d696f..097746d696f 100644 --- a/client/go/cmd/logfmt/formatflags.go +++ b/client/go/script-utils/logfmt/formatflags.go diff --git a/client/go/cmd/logfmt/formatflags_test.go b/client/go/script-utils/logfmt/formatflags_test.go index 53c47d24208..53c47d24208 100644 --- a/client/go/cmd/logfmt/formatflags_test.go +++ b/client/go/script-utils/logfmt/formatflags_test.go diff --git a/client/go/cmd/logfmt/handleline.go b/client/go/script-utils/logfmt/handleline.go index 813ca82acb4..813ca82acb4 100644 --- a/client/go/cmd/logfmt/handleline.go +++ b/client/go/script-utils/logfmt/handleline.go diff --git a/client/go/cmd/logfmt/internal.go b/client/go/script-utils/logfmt/internal.go index 992c537f939..992c537f939 100644 --- a/client/go/cmd/logfmt/internal.go +++ b/client/go/script-utils/logfmt/internal.go diff --git a/client/go/cmd/logfmt/internal_names.txt b/client/go/script-utils/logfmt/internal_names.txt index cc554546fcc..cc554546fcc 100644 --- a/client/go/cmd/logfmt/internal_names.txt +++ b/client/go/script-utils/logfmt/internal_names.txt diff --git a/client/go/cmd/logfmt/internal_notnames.txt b/client/go/script-utils/logfmt/internal_notnames.txt index 49543758ac3..49543758ac3 100644 --- a/client/go/cmd/logfmt/internal_notnames.txt +++ b/client/go/script-utils/logfmt/internal_notnames.txt diff --git a/client/go/cmd/logfmt/internal_test.go b/client/go/script-utils/logfmt/internal_test.go index 9b6b0f8404c..9b6b0f8404c 100644 --- a/client/go/cmd/logfmt/internal_test.go +++ b/client/go/script-utils/logfmt/internal_test.go diff --git a/client/go/cmd/logfmt/levelflags.go b/client/go/script-utils/logfmt/levelflags.go index 4e6c1284753..4e6c1284753 100644 --- a/client/go/cmd/logfmt/levelflags.go +++ b/client/go/script-utils/logfmt/levelflags.go diff --git a/client/go/cmd/logfmt/levelflags_test.go b/client/go/script-utils/logfmt/levelflags_test.go index 186ea2d96b0..186ea2d96b0 100644 --- a/client/go/cmd/logfmt/levelflags_test.go +++ b/client/go/script-utils/logfmt/levelflags_test.go diff --git a/client/go/cmd/logfmt/options.go b/client/go/script-utils/logfmt/options.go index 864868d4ce5..864868d4ce5 100644 --- a/client/go/cmd/logfmt/options.go +++ b/client/go/script-utils/logfmt/options.go diff --git a/client/go/cmd/logfmt/plusminusflag.go b/client/go/script-utils/logfmt/plusminusflag.go index 1768cf0e7be..1768cf0e7be 100644 --- a/client/go/cmd/logfmt/plusminusflag.go +++ b/client/go/script-utils/logfmt/plusminusflag.go diff --git a/client/go/cmd/logfmt/regexflag.go b/client/go/script-utils/logfmt/regexflag.go index 8f7d2a91373..8f7d2a91373 100644 --- a/client/go/cmd/logfmt/regexflag.go +++ b/client/go/script-utils/logfmt/regexflag.go diff --git a/client/go/cmd/logfmt/regexflag_test.go b/client/go/script-utils/logfmt/regexflag_test.go index 489439863a2..489439863a2 100644 --- a/client/go/cmd/logfmt/regexflag_test.go +++ b/client/go/script-utils/logfmt/regexflag_test.go diff --git a/client/go/cmd/logfmt/runlogfmt.go b/client/go/script-utils/logfmt/runlogfmt.go index 5b9a3ac0870..5b9a3ac0870 100644 --- a/client/go/cmd/logfmt/runlogfmt.go +++ b/client/go/script-utils/logfmt/runlogfmt.go diff --git a/client/go/cmd/logfmt/showflags.go b/client/go/script-utils/logfmt/showflags.go index b69860e0312..b69860e0312 100644 --- a/client/go/cmd/logfmt/showflags.go +++ b/client/go/script-utils/logfmt/showflags.go diff --git a/client/go/cmd/logfmt/showflags_test.go b/client/go/script-utils/logfmt/showflags_test.go index d1b66118afd..d1b66118afd 100644 --- a/client/go/cmd/logfmt/showflags_test.go +++ b/client/go/script-utils/logfmt/showflags_test.go diff --git a/client/go/cmd/logfmt/tail.go b/client/go/script-utils/logfmt/tail.go index 75e7cbb0693..75e7cbb0693 100644 --- a/client/go/cmd/logfmt/tail.go +++ b/client/go/script-utils/logfmt/tail.go diff --git a/client/go/cmd/logfmt/tail_not_unix.go b/client/go/script-utils/logfmt/tail_not_unix.go index 7030572575d..7030572575d 100644 --- a/client/go/cmd/logfmt/tail_not_unix.go +++ b/client/go/script-utils/logfmt/tail_not_unix.go diff --git a/client/go/cmd/logfmt/tail_unix.go b/client/go/script-utils/logfmt/tail_unix.go index 7703844da48..7703844da48 100644 --- a/client/go/cmd/logfmt/tail_unix.go +++ b/client/go/script-utils/logfmt/tail_unix.go diff --git a/client/go/script-utils/main.go b/client/go/script-utils/main.go index 79125292632..b0b7edd6f6c 100644 --- a/client/go/script-utils/main.go +++ b/client/go/script-utils/main.go @@ -10,9 +10,9 @@ import ( "github.com/vespa-engine/vespa/client/go/cmd/clusterstate" "github.com/vespa-engine/vespa/client/go/cmd/deploy" - "github.com/vespa-engine/vespa/client/go/cmd/logfmt" "github.com/vespa-engine/vespa/client/go/jvm" "github.com/vespa-engine/vespa/client/go/script-utils/configserver" + "github.com/vespa-engine/vespa/client/go/script-utils/logfmt" "github.com/vespa-engine/vespa/client/go/script-utils/services" "github.com/vespa-engine/vespa/client/go/script-utils/standalone" "github.com/vespa-engine/vespa/client/go/script-utils/startcbinary" diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/ResponseMetricAggregator.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/ResponseMetricAggregator.java index 5569919c39a..48823599608 100644 --- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/ResponseMetricAggregator.java +++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/ResponseMetricAggregator.java @@ -113,6 +113,7 @@ class ResponseMetricAggregator extends AbstractLifeCycle implements HttpChannel. static Dimensions of(Request req, Collection<String> monitoringHandlerPaths, Collection<String> searchHandlerPaths) { String requestType = requestType(req, monitoringHandlerPaths, searchHandlerPaths); + // note: some request members may not be populated for invalid requests, e.g. invalid request-line. return new Dimensions(protocol(req), scheme(req), method(req), requestType, statusCode(req)); } @@ -127,42 +128,31 @@ class ResponseMetricAggregator extends AbstractLifeCycle implements HttpChannel. } private static String protocol(Request req) { - switch (req.getProtocol()) { - case "HTTP/1": - case "HTTP/1.0": - case "HTTP/1.1": - return "http1"; - case "HTTP/2": - case "HTTP/2.0": - return "http2"; - default: - return "other"; - } + var protocol = req.getProtocol(); + if (protocol == null) return "none"; + return switch (protocol) { + case "HTTP/1", "HTTP/1.0", "HTTP/1.1" -> "http1"; + case "HTTP/2", "HTTP/2.0" -> "http2"; + default -> "other"; + }; } private static String scheme(Request req) { - switch (req.getScheme()) { - case "http": - case "https": - return req.getScheme(); - default: - return "other"; - } + var scheme = req.getScheme(); + if (scheme == null) return "none"; + return switch (scheme) { + case "http", "https" -> scheme; + default -> "other"; + }; } private static String method(Request req) { - switch (req.getMethod()) { - case "GET": - case "PATCH": - case "POST": - case "PUT": - case "DELETE": - case "OPTIONS": - case "HEAD": - return req.getMethod(); - default: - return "other"; - } + var method = req.getMethod(); + if (method == null) return "none"; + return switch (method) { + case "GET", "PATCH", "POST", "PUT", "DELETE", "OPTIONS", "HEAD" -> method; + default -> "other"; + }; } private static String requestType(Request req, Collection<String> monitoringHandlerPaths, @@ -171,13 +161,16 @@ class ResponseMetricAggregator extends AbstractLifeCycle implements HttpChannel. if (requestType != null) return requestType.name().toLowerCase(); // Deduce from path and method: String path = req.getRequestURI(); + if (path == null) return "none"; for (String monitoringHandlerPath : monitoringHandlerPaths) { if (path.startsWith(monitoringHandlerPath)) return "monitoring"; } for (String searchHandlerPath : searchHandlerPaths) { if (path.startsWith(searchHandlerPath)) return "read"; } - if ("GET".equals(req.getMethod())) return "read"; + var method = req.getMethod(); + if (method == null) return "none"; + else if ("GET".equals(method)) return "read"; else return "write"; } diff --git a/searchcore/src/vespa/searchcore/proton/server/CMakeLists.txt b/searchcore/src/vespa/searchcore/proton/server/CMakeLists.txt index c1f7b24b05c..34e2ee283f1 100644 --- a/searchcore/src/vespa/searchcore/proton/server/CMakeLists.txt +++ b/searchcore/src/vespa/searchcore/proton/server/CMakeLists.txt @@ -19,6 +19,7 @@ vespa_add_library(searchcore_server STATIC document_db_explorer.cpp document_db_flush_config.cpp document_db_maintenance_config.cpp + document_db_reconfig.cpp document_meta_store_read_guards.cpp document_scan_iterator.cpp document_subdb_collection_explorer.cpp @@ -26,6 +27,7 @@ vespa_add_library(searchcore_server STATIC document_subdb_explorer.cpp document_subdb_initializer.cpp document_subdb_initializer_result.cpp + document_subdb_reconfig.cpp documentbucketmover.cpp documentdb.cpp documentdb_metrics_updater.cpp diff --git a/searchcore/src/vespa/searchcore/proton/server/document_db_reconfig.cpp b/searchcore/src/vespa/searchcore/proton/server/document_db_reconfig.cpp new file mode 100644 index 00000000000..bd7b14483ad --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/server/document_db_reconfig.cpp @@ -0,0 +1,16 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "document_db_reconfig.h" +#include "document_subdb_reconfig.h" + +namespace proton { + +DocumentDBReconfig::DocumentDBReconfig(std::unique_ptr<const DocumentSubDBReconfig> ready_reconfig_in, + std::unique_ptr<const DocumentSubDBReconfig> not_ready_reconfig_in) + : _ready_reconfig(std::move(ready_reconfig_in)), + _not_ready_reconfig(std::move(not_ready_reconfig_in)) +{ +} + +} + diff --git a/searchcore/src/vespa/searchcore/proton/server/document_db_reconfig.h b/searchcore/src/vespa/searchcore/proton/server/document_db_reconfig.h new file mode 100644 index 00000000000..c1f768511c8 --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/server/document_db_reconfig.h @@ -0,0 +1,35 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include <memory> + +namespace proton { + +class DocumentSubDBReconfig; + +/** + * Class representing the result of the prepare step of a DocumentDB reconfig. + * + * The reconfig is performed in two steps: + * Prepare: + * Based on the config that is changed, new components are instantiated in each subdb. + * This can be costly and is handled by helper threads from the shared executor pool. + * + * Apply: + * The new components are swapped with the old ones in the DocumentDB master write thread. + */ +class DocumentDBReconfig { +private: + std::unique_ptr<const DocumentSubDBReconfig> _ready_reconfig; + std::unique_ptr<const DocumentSubDBReconfig> _not_ready_reconfig; + +public: + DocumentDBReconfig(std::unique_ptr<const DocumentSubDBReconfig> ready_reconfig_in, + std::unique_ptr<const DocumentSubDBReconfig> not_ready_reconfig_in); + + const DocumentSubDBReconfig& ready_reconfig() const { return *_ready_reconfig; } + const DocumentSubDBReconfig& not_ready_reconfig() const { return *_not_ready_reconfig; } +}; + +} + diff --git a/searchcore/src/vespa/searchcore/proton/server/document_subdb_reconfig.cpp b/searchcore/src/vespa/searchcore/proton/server/document_subdb_reconfig.cpp new file mode 100644 index 00000000000..3692fa07c06 --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/server/document_subdb_reconfig.cpp @@ -0,0 +1,14 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "document_subdb_reconfig.h" + +namespace proton { + +DocumentSubDBReconfig::DocumentSubDBReconfig(std::shared_ptr<Matchers> matchers_in) + : _old_matchers(matchers_in), + _new_matchers(matchers_in) +{ +} + +} + diff --git a/searchcore/src/vespa/searchcore/proton/server/document_subdb_reconfig.h b/searchcore/src/vespa/searchcore/proton/server/document_subdb_reconfig.h new file mode 100644 index 00000000000..ed9faeee6fc --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/server/document_subdb_reconfig.h @@ -0,0 +1,31 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include <memory> + +namespace proton { + +class Matchers; + +/** + * Class representing the result of the prepare step of a IDocumentSubDB reconfig. + */ +class DocumentSubDBReconfig { +private: + std::shared_ptr<Matchers> _old_matchers; + std::shared_ptr<Matchers> _new_matchers; + +public: + DocumentSubDBReconfig(std::shared_ptr<Matchers> matchers_in); + + void set_matchers(std::shared_ptr<Matchers> value) { + _new_matchers = std::move(value); + } + bool has_matchers_changed() const noexcept { + return _old_matchers != _new_matchers; + } + std::shared_ptr<Matchers> matchers() const { return _new_matchers; } +}; + +} + diff --git a/searchlib/src/vespa/searchlib/queryeval/profiled_iterator.h b/searchlib/src/vespa/searchlib/queryeval/profiled_iterator.h index f20ad1752d3..e1e16e164dc 100644 --- a/searchlib/src/vespa/searchlib/queryeval/profiled_iterator.h +++ b/searchlib/src/vespa/searchlib/queryeval/profiled_iterator.h @@ -48,6 +48,7 @@ public: void or_hits_into(BitVector &result, uint32_t begin_id) override; void and_hits_into(BitVector &result, uint32_t begin_id) override; void visitMembers(vespalib::ObjectVisitor &visitor) const override; + UP andWith(UP filter, uint32_t estimate) override { return _search->andWith(std::move(filter), estimate); } Trinary is_strict() const override { return _search->is_strict(); } Trinary matches_any() const override { return _search->matches_any(); } const PostingInfo *getPostingInfo() const override { return _search->getPostingInfo(); } diff --git a/vespalib/src/vespa/vespalib/coro/async_crypto_socket.cpp b/vespalib/src/vespa/vespalib/coro/async_crypto_socket.cpp index 4f862b48690..81b53102b4e 100644 --- a/vespalib/src/vespa/vespalib/coro/async_crypto_socket.cpp +++ b/vespalib/src/vespa/vespalib/coro/async_crypto_socket.cpp @@ -24,7 +24,9 @@ struct RawSocket : AsyncCryptoSocket { AsyncIo::SP async; SocketHandle handle; RawSocket(AsyncIo &async_in, SocketHandle handle_in) - : async(async_in.shared_from_this()), handle(std::move(handle_in)) {} + : async(async_in.shared_from_this()), handle(std::move(handle_in)) {} + RawSocket(RawSocket &&) noexcept; + ~RawSocket() override; Lazy<ssize_t> read(char *buf, size_t len) override { return async->read(handle, buf, len); } @@ -33,12 +35,16 @@ struct RawSocket : AsyncCryptoSocket { } }; +RawSocket::~RawSocket() = default; + struct SnoopedRawSocket : AsyncCryptoSocket { AsyncIo::SP async; SocketHandle handle; SmartBuffer data; SnoopedRawSocket(AsyncIo &async_in, SocketHandle handle_in) - : async(async_in.shared_from_this()), handle(std::move(handle_in)), data(0) {} + : async(async_in.shared_from_this()), handle(std::move(handle_in)), data(0) {} + SnoopedRawSocket(SnoopedRawSocket &&) noexcept; + ~SnoopedRawSocket() override; void inject_data(const char *buf, size_t len) { if (len > 0) { auto dst = data.reserve(len); @@ -68,6 +74,8 @@ struct SnoopedRawSocket : AsyncCryptoSocket { } }; +SnoopedRawSocket::~SnoopedRawSocket() = default; + struct TlsSocket : AsyncCryptoSocket { AsyncIo::SP async; SocketHandle handle; @@ -78,6 +86,8 @@ struct TlsSocket : AsyncCryptoSocket { TlsSocket(AsyncIo &async_in, SocketHandle handle_in, std::unique_ptr<CryptoCodec> codec_in) : async(async_in.shared_from_this()), handle(std::move(handle_in)), codec(std::move(codec_in)), app_input(0), enc_input(0), enc_output(0) {} + TlsSocket(TlsSocket &&) noexcept; + ~TlsSocket() override; void inject_enc_input(const char *buf, size_t len) { if (len > 0) { auto dst = enc_input.reserve(len); @@ -175,6 +185,8 @@ struct TlsSocket : AsyncCryptoSocket { } }; +TlsSocket::~TlsSocket() = default; + Lazy<AsyncCryptoSocket::UP> try_handshake(std::unique_ptr<TlsSocket> tls_socket) { bool hs_ok = co_await tls_socket->handshake(); if (hs_ok) { diff --git a/vespalib/src/vespa/vespalib/hwaccelrated/CMakeLists.txt b/vespalib/src/vespa/vespalib/hwaccelrated/CMakeLists.txt index d5a3ab429a9..84cd60887b7 100644 --- a/vespalib/src/vespa/vespalib/hwaccelrated/CMakeLists.txt +++ b/vespalib/src/vespa/vespalib/hwaccelrated/CMakeLists.txt @@ -13,5 +13,5 @@ vespa_add_library(vespalib_vespalib_hwaccelrated OBJECT ${ACCEL_FILES} DEPENDS ) -set_source_files_properties(avx2.cpp PROPERTIES COMPILE_FLAGS -march=haswell) -set_source_files_properties(avx512.cpp PROPERTIES COMPILE_FLAGS -march=skylake-avx512) +set_source_files_properties(avx2.cpp PROPERTIES COMPILE_FLAGS "-O3 -march=haswell") +set_source_files_properties(avx512.cpp PROPERTIES COMPILE_FLAGS "-O3 -march=skylake-avx512") diff --git a/vespalib/src/vespa/vespalib/net/http/json_handler_repo.cpp b/vespalib/src/vespa/vespalib/net/http/json_handler_repo.cpp index 07b9306b5dc..3f92cffb4af 100644 --- a/vespalib/src/vespa/vespalib/net/http/json_handler_repo.cpp +++ b/vespalib/src/vespa/vespalib/net/http/json_handler_repo.cpp @@ -46,17 +46,21 @@ JsonHandlerRepo::State::unbind(size_t my_seq) { //----------------------------------------------------------------------------- +JsonHandlerRepo::JsonHandlerRepo() + : _state(std::make_shared<State>()) +{} +JsonHandlerRepo::~JsonHandlerRepo() = default; JsonHandlerRepo::Token::UP JsonHandlerRepo::bind(vespalib::stringref path_prefix, const JsonGetHandler &get_handler) { - return Token::UP(new Unbinder(_state, _state->bind(path_prefix, get_handler))); + return std::make_unique<Unbinder>(_state, _state->bind(path_prefix, get_handler)); } JsonHandlerRepo::Token::UP JsonHandlerRepo::add_root_resource(vespalib::stringref path) { - return Token::UP(new Unbinder(_state, _state->add_root_resource(path))); + return std::make_unique<Unbinder>(_state, _state->add_root_resource(path)); } std::vector<vespalib::string> diff --git a/vespalib/src/vespa/vespalib/net/http/json_handler_repo.h b/vespalib/src/vespa/vespalib/net/http/json_handler_repo.h index 4ca3e061c71..46ef3bd762a 100644 --- a/vespalib/src/vespa/vespalib/net/http/json_handler_repo.h +++ b/vespalib/src/vespa/vespalib/net/http/json_handler_repo.h @@ -25,7 +25,7 @@ class JsonHandlerRepo : public JsonGetHandler public: struct Token { using UP = std::unique_ptr<Token>; - virtual ~Token() {} + virtual ~Token() = default; }; private: @@ -78,14 +78,13 @@ private: std::shared_ptr<State> _state; public: - JsonHandlerRepo() : _state(std::make_shared<State>()) {} - Token::UP bind(vespalib::stringref path_prefix, - const JsonGetHandler &get_handler); + JsonHandlerRepo(); + ~JsonHandlerRepo(); + Token::UP bind(vespalib::stringref path_prefix, const JsonGetHandler &get_handler); Token::UP add_root_resource(vespalib::stringref path); - std::vector<vespalib::string> get_root_resources() const; - vespalib::string get(const vespalib::string &host, - const vespalib::string &path, - const std::map<vespalib::string,vespalib::string> ¶ms) const override; + [[nodiscard]] std::vector<vespalib::string> get_root_resources() const; + [[nodiscard]] vespalib::string get(const vespalib::string &host, const vespalib::string &path, + const std::map<vespalib::string,vespalib::string> ¶ms) const override; }; } // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/testkit/test_master.cpp b/vespalib/src/vespa/vespalib/testkit/test_master.cpp index 434d08d6c7a..bacb1051cf3 100644 --- a/vespalib/src/vespa/vespalib/testkit/test_master.cpp +++ b/vespalib/src/vespa/vespalib/testkit/test_master.cpp @@ -31,16 +31,22 @@ TestMaster TestMaster::master; //----------------------------------------------------------------------------- -__thread TestMaster::ThreadState *TestMaster::_threadState = 0; +__thread TestMaster::ThreadState *TestMaster::_threadState = nullptr; //----------------------------------------------------------------------------- - +TestMaster::TraceItem::TraceItem(const std::string &file_in, uint32_t line_in, const std::string &msg_in) + : file(file_in), line(line_in), msg(msg_in) +{} +TestMaster::TraceItem::TraceItem(TraceItem &&) noexcept = default; +TestMaster::TraceItem & TestMaster::TraceItem::operator=(TraceItem &&) noexcept = default; +TestMaster::TraceItem::TraceItem(const TraceItem &) = default; +TestMaster::TraceItem & TestMaster::TraceItem::operator=(const TraceItem &) = default; TestMaster::TraceItem::~TraceItem() = default; TestMaster::ThreadState & TestMaster::threadState(const lock_guard &) { - if (_threadState == 0) { + if (_threadState == nullptr) { std::ostringstream threadName; threadName << "thread-" << _threadStorage.size(); _threadStorage.push_back(std::make_unique<ThreadState>(threadName.str())); @@ -52,7 +58,7 @@ TestMaster::threadState(const lock_guard &) TestMaster::ThreadState & TestMaster::threadState() { - if (_threadState != 0) { + if (_threadState != nullptr) { return *_threadState; } { @@ -87,7 +93,7 @@ TestMaster::printDiff(const lock_guard &guard, const std::string &lhs, const std::string &rhs) { ThreadState &thread = threadState(guard); - if (_state.lhsFile == NULL || _state.rhsFile == NULL) { + if (_state.lhsFile == nullptr || _state.rhsFile == nullptr) { fprintf(stderr, "lhs: %s\n" "rhs: %s\n", @@ -123,13 +129,13 @@ TestMaster::handleFailure(const lock_guard &guard, bool fatal) void TestMaster::closeDebugFiles(const lock_guard &) { - if (_state.lhsFile != NULL) { + if (_state.lhsFile != nullptr) { fclose(_state.lhsFile); - _state.lhsFile = NULL; + _state.lhsFile = nullptr; } - if (_state.rhsFile != NULL) { + if (_state.rhsFile != nullptr) { fclose(_state.rhsFile); - _state.rhsFile = NULL; + _state.rhsFile = nullptr; } } @@ -137,8 +143,8 @@ void TestMaster::importThreads(const lock_guard &) { size_t importCnt = 0; - for (size_t i = 0; i < _threadStorage.size(); ++i) { - ThreadState &thread = *_threadStorage[i]; + for (const auto & i : _threadStorage) { + ThreadState &thread = *i; _state.passCnt += thread.passCnt; importCnt += thread.passCnt; thread.passCnt = 0; @@ -245,7 +251,7 @@ void TestMaster::awaitThreadBarrier(const char *file, uint32_t line) { ThreadState &thread = threadState(); - if (thread.barrier == 0) { + if (thread.barrier == nullptr) { return; } if (!thread.barrier->await()) { @@ -275,7 +281,7 @@ TestMaster::Progress TestMaster::getProgress() { lock_guard guard(_lock); - return Progress(_state.passCnt, _state.failCnt); + return {_state.passCnt, _state.failCnt}; } void @@ -286,7 +292,7 @@ TestMaster::openDebugFiles(const std::string &lhsFile, closeDebugFiles(guard); _state.lhsFile = fopen(lhsFile.c_str(), "w"); _state.rhsFile = fopen(rhsFile.c_str(), "w"); - if (_state.lhsFile == NULL || _state.rhsFile == NULL) { + if (_state.lhsFile == nullptr || _state.rhsFile == nullptr) { closeDebugFiles(guard); fprintf(stderr, "%s: Warn: could not open debug files (%s, %s)\n", _name.c_str(), lhsFile.c_str(), rhsFile.c_str()); @@ -299,7 +305,7 @@ TestMaster::openDebugFiles(const std::string &lhsFile, void TestMaster::pushState(const char *file, uint32_t line, const char *msg) { - threadState().traceStack.push_back(TraceItem(skip_path(file), line, msg)); + threadState().traceStack.emplace_back(skip_path(file), line, msg); } void diff --git a/vespalib/src/vespa/vespalib/testkit/test_master.h b/vespalib/src/vespa/vespalib/testkit/test_master.h index 01ea94c074d..b841197f2f9 100644 --- a/vespalib/src/vespa/vespalib/testkit/test_master.h +++ b/vespalib/src/vespa/vespalib/testkit/test_master.h @@ -36,9 +36,11 @@ public: std::string file; uint32_t line; std::string msg; - TraceItem(const std::string &file_in, uint32_t line_in, - const std::string &msg_in) - : file(file_in), line(line_in), msg(msg_in) {} + TraceItem(const std::string &file_in, uint32_t line_in, const std::string &msg_in); + TraceItem(TraceItem &&) noexcept; + TraceItem & operator=(TraceItem &&) noexcept; + TraceItem(const TraceItem &); + TraceItem & operator=(const TraceItem &); ~TraceItem(); }; diff --git a/vespalib/src/vespa/vespalib/trace/tracenode.cpp b/vespalib/src/vespa/vespalib/trace/tracenode.cpp index 881b9cc3300..f05953e62df 100644 --- a/vespalib/src/vespa/vespalib/trace/tracenode.cpp +++ b/vespalib/src/vespa/vespalib/trace/tracenode.cpp @@ -67,6 +67,7 @@ TraceNode::TraceNode(const TraceNode &rhs) } TraceNode::TraceNode(TraceNode &&) noexcept = default; +TraceNode & TraceNode::operator =(TraceNode &&) noexcept = default; TraceNode & TraceNode::operator =(const TraceNode &) = default; TraceNode::~TraceNode() = default; diff --git a/vespalib/src/vespa/vespalib/trace/tracenode.h b/vespalib/src/vespa/vespalib/trace/tracenode.h index 4062dc78d3f..c38c5236e35 100644 --- a/vespalib/src/vespa/vespalib/trace/tracenode.h +++ b/vespalib/src/vespa/vespalib/trace/tracenode.h @@ -51,7 +51,7 @@ public: TraceNode & operator =(const TraceNode &); TraceNode(TraceNode &&) noexcept; - TraceNode & operator =(TraceNode &&) noexcept = default; + TraceNode & operator =(TraceNode &&) noexcept; ~TraceNode(); /** diff --git a/vespalib/src/vespa/vespalib/util/jsonstream.cpp b/vespalib/src/vespa/vespalib/util/jsonstream.cpp index 135611e975f..e8814ee95f6 100644 --- a/vespalib/src/vespa/vespalib/util/jsonstream.cpp +++ b/vespalib/src/vespa/vespalib/util/jsonstream.cpp @@ -8,6 +8,19 @@ namespace vespalib { +JsonStream::StateEntry::StateEntry() noexcept + : state(State::ROOT), object_key(""), array_index(size_t(0)) +{} +JsonStream::StateEntry::StateEntry(State s) noexcept + : state(s), object_key(""), array_index(size_t(0)) +{} +JsonStream::StateEntry::StateEntry(State s, stringref key) noexcept + : state(s), object_key(key), array_index(size_t(0)) +{} +JsonStream::StateEntry::StateEntry(const StateEntry &) noexcept = default; +JsonStream::StateEntry & JsonStream::StateEntry::operator =(const StateEntry &) noexcept = default; +JsonStream::StateEntry::~StateEntry() = default; + const char* JsonStream::getStateName(const State& s) { switch (s) { diff --git a/vespalib/src/vespa/vespalib/util/jsonstream.h b/vespalib/src/vespa/vespalib/util/jsonstream.h index e41c4238b09..b85ad7f5486 100644 --- a/vespalib/src/vespa/vespalib/util/jsonstream.h +++ b/vespalib/src/vespa/vespalib/util/jsonstream.h @@ -44,12 +44,12 @@ class JsonStream : public JsonStreamTypes { string object_key; size_t array_index; - StateEntry() noexcept - : state(State::ROOT), object_key(""), array_index(size_t(0)) {} - StateEntry(State s) - : state(s), object_key(""), array_index(size_t(0)) {} - StateEntry(State s, stringref key) - : state(s), object_key(key), array_index(size_t(0)) {} + StateEntry() noexcept; + StateEntry(State s) noexcept; + StateEntry(State s, stringref key) noexcept; + StateEntry(const StateEntry &) noexcept; + StateEntry & operator =(const StateEntry &) noexcept; + ~StateEntry(); }; std::vector<StateEntry> _state; diff --git a/vespamalloc/src/tests/test1/new_test.cpp b/vespamalloc/src/tests/test1/new_test.cpp index dfa67f2aa7c..9ea4418aad5 100644 --- a/vespamalloc/src/tests/test1/new_test.cpp +++ b/vespamalloc/src/tests/test1/new_test.cpp @@ -1,6 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include <vespa/vespalib/testkit/testapp.h> #include <vespa/vespalib/util/size_literals.h> +#include <vespa/vespalib/util/optimized.h> #include <vespa/log/log.h> #include <malloc.h> #include <dlfcn.h> @@ -250,4 +251,43 @@ TEST("test realloc large buffers") { EXPECT_EQUAL(1, mallopt(M_MMAP_THRESHOLD, 1_Gi)); } +void verify_alignment(void * ptr, size_t align, size_t min_sz) { + EXPECT_NOT_EQUAL(ptr, nullptr); + EXPECT_EQUAL(0u, size_t(ptr) & (align-1)); + assert(0ul == (size_t(ptr) & (align-1))); + EXPECT_GREATER_EQUAL(malloc_usable_size(ptr), min_sz); + free(ptr); +} + +TEST("test memalign") { + verify_alignment(memalign(0, 0), 1, 1); + verify_alignment(memalign(0, 1), 1, 1); + verify_alignment(memalign(1, 0), 1, 1); + + for (size_t align : {3,7,19}) { + // According to man pages these should fail, but it seems it rounds up and does best effort + verify_alignment(memalign(align, 73), 1ul << vespalib::Optimized::msbIdx(align), 73); + } + for (size_t align : {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}) { + verify_alignment(memalign(align, 1), align, 1); + } +} + +TEST("test aligned_alloc") { + verify_alignment(aligned_alloc(0, 0), 1, 1); + verify_alignment(aligned_alloc(0, 1), 1, 1); + verify_alignment(aligned_alloc(1, 0), 1, 1); + for (size_t align : {3,7,19}) { + // According to man pages these should fail, but it seems it rounds up and does best effort + verify_alignment(aligned_alloc(align, align*7), 1ul << vespalib::Optimized::msbIdx(align), align*7); + } + for (size_t align : {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}) { + verify_alignment(aligned_alloc(align, align*7), align, align*7); + } + for (size_t sz : {31,33,63}) { + // According to man pages these should fail, but it seems it rounds up and does best effort + verify_alignment(aligned_alloc(32, sz), 32, sz); + } +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespamalloc/src/vespamalloc/malloc/malloc.h b/vespamalloc/src/vespamalloc/malloc/malloc.h index 0ecdb8c58e1..5867852db31 100644 --- a/vespamalloc/src/vespamalloc/malloc/malloc.h +++ b/vespamalloc/src/vespamalloc/malloc/malloc.h @@ -73,7 +73,7 @@ public: size_t getMinSizeForAlignment(size_t align, size_t sz) const { return MemBlockPtrT::getMinSizeForAlignment(align, sz); } size_t sizeClass(const void *ptr) const { return _segment.sizeClass(ptr); } size_t usable_size(void *ptr) const { - return MemBlockPtrT::usable_size(ptr, _segment.getMaxSize<MemBlockPtrT>(ptr)); + return MemBlockPtrT::usable_size(ptr, _segment); } void * calloc(size_t nelm, size_t esz) { diff --git a/vespamalloc/src/vespamalloc/malloc/memblock.h b/vespamalloc/src/vespamalloc/malloc/memblock.h index f7b5923ecff..ee090de6f3d 100644 --- a/vespamalloc/src/vespamalloc/malloc/memblock.h +++ b/vespamalloc/src/vespamalloc/malloc/memblock.h @@ -18,7 +18,7 @@ public: SizeClassSpan = (MaxSizeClassMultiAllocC-MinSizeClassC) }; MemBlockT() : _ptr(nullptr) { } - MemBlockT(void * p) : _ptr(p) { } + explicit MemBlockT(void * p) : _ptr(p) { } MemBlockT(void * p, size_t /*sz*/) : _ptr(p) { } MemBlockT(void * p, size_t, bool) : _ptr(p) { } template<typename T> @@ -34,8 +34,9 @@ public: void setThreadId(uint32_t ) { } void free() { } size_t size() const { return 0; } - static size_t usable_size(void *, size_t classSize) { - return classSize; + template<typename T> + static size_t usable_size(void * ptr, const T & segment) { + return segment.template getMaxSize<MemBlockT>(ptr); } bool allocated() const { return false; } uint32_t threadId() const { return 0; } diff --git a/vespamalloc/src/vespamalloc/malloc/memblockboundscheck.h b/vespamalloc/src/vespamalloc/malloc/memblockboundscheck.h index 9d46dbce378..67b98701d8e 100644 --- a/vespamalloc/src/vespamalloc/malloc/memblockboundscheck.h +++ b/vespamalloc/src/vespamalloc/malloc/memblockboundscheck.h @@ -103,8 +103,11 @@ public: && ((p[3] == ALLOC_MAGIC) || (p[3] == FREE_MAGIC)) && *(reinterpret_cast<const unsigned *> ((const char*)_ptr + size() + alignment() + StackTraceLen*sizeof(void *))) == TAIL_MAGIC; } - static size_t usable_size(void *ptr, size_t ) { - return MemBlockBoundsCheckBaseT(ptr).size(); + template<typename T> + static size_t usable_size(void *ptr, const T & segment) { + MemBlockBoundsCheckBaseT mem(ptr); + mem.readjustAlignment(segment); + return mem.size(); } bool validAlloc1() const { unsigned *p((unsigned*)_ptr); diff --git a/vespamalloc/src/vespamalloc/malloc/overload.h b/vespamalloc/src/vespamalloc/malloc/overload.h index 6650f107ca9..e209d1b6df5 100644 --- a/vespamalloc/src/vespamalloc/malloc/overload.h +++ b/vespamalloc/src/vespamalloc/malloc/overload.h @@ -1,8 +1,9 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once +#include "common.h" #include <dlfcn.h> -#include <errno.h> +#include <cerrno> #include <new> #include <cstdlib> #include <malloc.h> @@ -174,15 +175,22 @@ void * reallocarray(void * ptr, size_t nemb, size_t elemSize) __THROW } void* memalign(size_t align, size_t sz) __THROW __attribute__((visibility ("default"))); -void* memalign(size_t align, size_t sz) __THROW +void* memalign(size_t align_in, size_t sz) __THROW { - void *ptr(nullptr); + size_t align = (align_in == 0) ? 1 : 1ul << vespamalloc::msbIdx(align_in*2 - 1); size_t align_1(align - 1); - if ((align & (align_1)) == 0) { - ptr = vespamalloc::_GmemP->malloc(vespamalloc::_GmemP->getMinSizeForAlignment(align, sz)); - ptr = (void *) ((size_t(ptr) + align_1) & ~align_1); - } - return ptr; + void * ptr = vespamalloc::_GmemP->malloc(vespamalloc::_GmemP->getMinSizeForAlignment(align, sz)); + return (void *) ((size_t(ptr) + align_1) & ~align_1); +} + +void *aligned_alloc (size_t align, size_t sz) __THROW __attribute__((visibility ("default"))); +void *aligned_alloc (size_t align_in, size_t sz_in) __THROW +{ + size_t align = (align_in == 0) ? 1 : 1ul << vespamalloc::msbIdx(align_in*2 - 1); + size_t align_1(align - 1); + size_t sz = ((sz_in - 1) + align) & ~align_1; + void * ptr = vespamalloc::_GmemP->malloc(vespamalloc::_GmemP->getMinSizeForAlignment(align, sz)); + return (void *) ((size_t(ptr) + align_1) & ~align_1); } int posix_memalign(void** ptr, size_t align, size_t sz) __THROW __nonnull((1)) __attribute__((visibility ("default"))); |