Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package galera-4 for openSUSE:Factory checked in at 2023-05-05 15:57:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/galera-4 (Old) and /work/SRC/openSUSE:Factory/.galera-4.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "galera-4" Fri May 5 15:57:06 2023 rev:9 rq:1084718 version:26.4.14 Changes: -------- --- /work/SRC/openSUSE:Factory/galera-4/galera-4.changes 2022-12-16 17:50:54.375771483 +0100 +++ /work/SRC/openSUSE:Factory/.galera-4.new.1533/galera-4.changes 2023-05-05 15:57:10.424046844 +0200 @@ -1,0 +2,20 @@ +Thu May 4 13:43:00 UTC 2023 - Marcus Rueckert <[email protected]> + +- Update to 26.4.14: + - memory leak in the gcs gcomm backend fixed (tp_ object deleted + in GCommConn destructor) + - protonet.backend option deprecated since it only supports one + option, asio, and the option will be removed in future release. + Related, protonet.version is also deprecated + - deprecation message for socket.ssl_compression as SSL + compression cannot be enabled and the option will be removed in + future releases + - library could parse incorrect parameters as long as it had a + "good" prefix, i.e. evs.*, so fix prevents setting of invalid + option values + - parsing of ISO8601 durations previously accepted invalid + values, now fixed + - in addition to ISO8601 format, parsing durations now supports + real number representation + +------------------------------------------------------------------- Old: ---- galera-4-26.4.13.tar.gz galera-4-26.4.13.tar.gz.asc New: ---- galera-4-26.4.14.tar.gz galera-4-26.4.14.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ galera-4.spec ++++++ --- /var/tmp/diff_new_pack.t9GWkH/_old 2023-05-05 15:57:11.996055850 +0200 +++ /var/tmp/diff_new_pack.t9GWkH/_new 2023-05-05 15:57:12.000055873 +0200 @@ -1,7 +1,7 @@ # # spec file for package galera-4 # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -25,7 +25,7 @@ %define _fillupdir %{_localstatedir}/adm/fillup-templates %endif Name: galera-4 -Version: 26.4.13 +Version: 26.4.14 Release: 0 Summary: Galera: a synchronous multi-master wsrep provider (replication engine) License: GPL-2.0-only ++++++ galera-4-26.4.13.tar.gz -> galera-4-26.4.14.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/GALERA_GIT_REVISION new/galera-4-26.4.14/GALERA_GIT_REVISION --- old/galera-4-26.4.13/GALERA_GIT_REVISION 2022-11-03 11:54:19.000000000 +0100 +++ new/galera-4-26.4.14/GALERA_GIT_REVISION 2023-02-24 09:38:50.000000000 +0100 @@ -1 +1 @@ -0f7af311 \ No newline at end of file +456ad404 \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/GALERA_REVISION new/galera-4-26.4.14/GALERA_REVISION --- old/galera-4-26.4.13/GALERA_REVISION 2022-11-03 11:54:19.000000000 +0100 +++ new/galera-4-26.4.14/GALERA_REVISION 2023-02-24 09:38:50.000000000 +0100 @@ -1 +1 @@ -0f7af311 \ No newline at end of file +456ad404 \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/GALERA_VERSION new/galera-4-26.4.14/GALERA_VERSION --- old/galera-4-26.4.13/GALERA_VERSION 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/GALERA_VERSION 2023-02-24 09:38:48.000000000 +0100 @@ -1,4 +1,4 @@ GALERA_VERSION_WSREP_API=26 GALERA_VERSION_MAJOR=4 -GALERA_VERSION_MINOR=13 +GALERA_VERSION_MINOR=14 GALERA_VERSION_EXTRA= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/SConstruct new/galera-4-26.4.14/SConstruct --- old/galera-4-26.4.13/SConstruct 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/SConstruct 2023-02-24 09:38:48.000000000 +0100 @@ -163,7 +163,7 @@ install = ARGUMENTS.get('install', None) version_script = int(ARGUMENTS.get('version_script', 1)) -GALERA_VER = ARGUMENTS.get('version', '4.13') +GALERA_VER = ARGUMENTS.get('version', '4.14') GALERA_REV = ARGUMENTS.get('revno', 'XXXX') # Attempt to read from file if not given diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/debian/changelog new/galera-4-26.4.14/debian/changelog --- old/galera-4-26.4.13/debian/changelog 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/debian/changelog 2023-02-24 09:38:48.000000000 +0100 @@ -1,5 +1,5 @@ -galera-4 (26.4.13) UNRELEASED; urgency=medium +galera-4 (26.4.14) UNRELEASED; urgency=medium * Galera 4 release - -- Codership Oy <[email protected]> Mon, 04 Jul 2022 14:56:52 +0300 + -- Codership Oy <[email protected]> Thu, 26 Jan 2023 09:31:00 +0200 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galera/src/CMakeLists.txt new/galera-4-26.4.14/galera/src/CMakeLists.txt --- old/galera-4-26.4.13/galera/src/CMakeLists.txt 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galera/src/CMakeLists.txt 2023-02-24 09:38:48.000000000 +0100 @@ -26,7 +26,6 @@ replicator_smm.cpp replicator_str.cpp replicator_smm_stats.cpp - event_service.cpp ) target_include_directories(galera diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galera/src/SConscript new/galera-4-26.4.14/galera/src/SConscript --- old/galera-4-26.4.13/galera/src/SConscript 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galera/src/SConscript 2023-02-24 09:38:48.000000000 +0100 @@ -33,7 +33,6 @@ 'ist.cpp', 'gcs_dummy.cpp', 'saved_state.cpp', - 'event_service.cpp', 'galera_view.cpp' ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galera/src/event_service.cpp new/galera-4-26.4.14/galera/src/event_service.cpp --- old/galera-4-26.4.13/galera/src/event_service.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galera/src/event_service.cpp 1970-01-01 01:00:00.000000000 +0100 @@ -1,48 +0,0 @@ -// -// Copyright (C) 2021 Codership Oy <[email protected]> -// - -#include "event_service.hpp" - -#include <cassert> - -// -// Event service hooks. -// - -namespace galera -{ - std::mutex EventService::mutex; - size_t EventService::usage(0); - - EventService* EventService::instance = nullptr; - - int EventService::init_v1(const wsrep_event_service_v1_t* es) - { - std::lock_guard<std::mutex> lock(EventService::mutex); - ++EventService::usage; - - if (EventService::instance) - { - assert(0); - return 0; - } - - EventService::instance = new EventService(es->context, es->event_cb); - return 0; - } - - void EventService::deinit_v1() - { - std::lock_guard<std::mutex> lock(EventService::mutex); - assert(EventService::usage > 0); - --EventService::usage; - - if (EventService::usage == 0) - { - delete EventService::instance; - EventService::instance = 0; - } - } - -} /* galera*/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galera/src/event_service.hpp new/galera-4-26.4.14/galera/src/event_service.hpp --- old/galera-4-26.4.13/galera/src/event_service.hpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galera/src/event_service.hpp 1970-01-01 01:00:00.000000000 +0100 @@ -1,54 +0,0 @@ -// -// Copyright (C) 2021 Codership Oy <[email protected]> -// - -/** - * Event service class - */ - -#ifndef GALERA_EVENT_SERVICE_HPP -#define GALERA_EVENT_SERVICE_HPP - -#include "wsrep_event_service.h" - -#include <string> -#include <mutex> - -namespace galera -{ - class EventService - { - public: - static int init_v1(const wsrep_event_service_v1_t*); - static void deinit_v1(); - - static void callback(const std::string& name, const std::string& value) - { - std::lock_guard<std::mutex> lock(EventService::mutex); - - if (instance && instance->cb_) - { - instance->cb_(instance->ctx_, name.c_str(), value.c_str()); - } - } - - private: - wsrep_event_context_t* const ctx_; - wsrep_event_cb_t const cb_; - - static std::mutex mutex; - static size_t usage; - static EventService* instance; - - EventService(wsrep_event_context_t* ctx, wsrep_event_cb_t cb) - : ctx_(ctx), cb_(cb) - {} - virtual ~EventService() {} - - EventService(const EventService&); - EventService& operator =(EventService); - }; - -} /* galera */ - -#endif /* GALERA_EVENT_SERVICE_HPP */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galera/src/progress_callback.hpp new/galera-4-26.4.14/galera/src/progress_callback.hpp --- old/galera-4-26.4.13/galera/src/progress_callback.hpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galera/src/progress_callback.hpp 2023-02-24 09:38:48.000000000 +0100 @@ -6,7 +6,7 @@ #define GALERA_PROGRESS_CALLBACK_HPP #include "gu_progress.hpp" // gu::Progress::Callback -#include "event_service.hpp" +#include "gu_event_service.hpp" #include "wsrep_api.h" #include <string> @@ -34,7 +34,7 @@ << ", \"done\": " << done << ", \"undefined\": -1 }"; - EventService::callback(event_name, os.str()); + gu::EventService::callback(event_name, os.str()); } private: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galera/src/replicator_smm_params.cpp new/galera-4-26.4.14/galera/src/replicator_smm_params.cpp --- old/galera-4-26.4.13/galera/src/replicator_smm_params.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galera/src/replicator_smm_params.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -60,6 +60,7 @@ conf.add(i->first, i->second); } + conf.set_flags(Param::causal_read_timeout, gu::Config::Flag::type_duration); conf.set_flags(Param::max_write_set_size, gu::Config::Flag::type_integer); conf.set_flags(Param::base_dir, gu::Config::Flag::read_only); conf.set_flags(Param::base_port, gu::Config::Flag::read_only | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galera/src/wsrep_provider.cpp new/galera-4-26.4.14/galera/src/wsrep_provider.cpp --- old/galera-4-26.4.13/galera/src/wsrep_provider.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galera/src/wsrep_provider.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -14,7 +14,7 @@ #endif #include "wsrep_params.hpp" -#include "event_service.hpp" +#include "gu_event_service.hpp" #include "wsrep_config_service.h" #include <cassert> @@ -1656,12 +1656,12 @@ extern "C" int wsrep_init_event_service_v1(wsrep_event_service_v1_t *event_service) { - return galera::EventService::init_v1(event_service); + return gu::EventService::init_v1(event_service); } extern "C" void wsrep_deinit_event_service_v1() { - galera::EventService::deinit_v1(); + gu::EventService::deinit_v1(); } static int map_parameter_flags(int flags) @@ -1677,6 +1677,8 @@ ret |= WSREP_PARAM_TYPE_INTEGER; if (flags & gu::Config::Flag::type_double) ret |= WSREP_PARAM_TYPE_DOUBLE; + if (flags & gu::Config::Flag::type_duration) + ret |= WSREP_PARAM_TYPE_DOUBLE; return ret; } @@ -1702,6 +1704,21 @@ case gu::Config::Flag::type_double: ret = gu_str2dbl(param.value().c_str(), &wsrep_param.value.as_double); break; + case gu::Config::Flag::type_duration: + { + try + { + // durations are mapped to doubles + wsrep_param.value.as_double + = to_double(gu::datetime::Period(param.value())); + } + catch (...) + { + assert(0); + return 1; + } + break; + } default: assert((param.flags() & gu::Config::Flag::type_mask) == 0); wsrep_param.value.as_string = param.value().c_str(); @@ -1749,10 +1766,14 @@ int wsrep_init_config_service_v1(wsrep_config_service_v1_t *config_service) { config_service->get_parameters = get_parameters; + // Deprecation checks will be done by application which uses + // the service. + gu::Config::disable_deprecation_check(); return WSREP_OK; } extern "C" void wsrep_deinit_config_service_v1() { + gu::Config::enable_deprecation_check(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galera/tests/progress_check.cpp new/galera-4-26.4.14/galera/tests/progress_check.cpp --- old/galera-4-26.4.13/galera/tests/progress_check.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galera/tests/progress_check.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -41,7 +41,7 @@ wsrep_event_context_t event_context; wsrep_event_service_v1_t evs = { event_cb, &event_context }; - galera::EventService::init_v1(&evs); + gu::EventService::init_v1(&evs); { galera::ProgressCallback<int> pcb(WSREP_MEMBER_JOINED, @@ -59,7 +59,7 @@ /* Dtor calls event callback for the third time */ } - galera::EventService::deinit_v1(); + gu::EventService::deinit_v1(); } END_TEST diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/CMakeLists.txt new/galera-4-26.4.14/galerautils/src/CMakeLists.txt --- old/galera-4-26.4.13/galerautils/src/CMakeLists.txt 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/CMakeLists.txt 2023-02-24 09:38:48.000000000 +0100 @@ -72,6 +72,7 @@ gu_vlq.cpp gu_datetime.cpp gu_gtid.cpp + gu_event_service.cpp gu_exception.cpp gu_hexdump.cpp gu_serialize.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/SConscript new/galera-4-26.4.14/galerautils/src/SConscript --- old/galera-4-26.4.13/galerautils/src/SConscript 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/SConscript 2023-02-24 09:38:48.000000000 +0100 @@ -67,6 +67,7 @@ libgalerautilsxx_sources = [ 'gu_vlq.cpp', 'gu_datetime.cpp', + 'gu_event_service.cpp', 'gu_exception.cpp', 'gu_serialize.cpp', 'gu_logger.cpp', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/gu_asio.cpp new/galera-4-26.4.14/galerautils/src/gu_asio.cpp --- old/galera-4-26.4.13/galerautils/src/gu_asio.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/gu_asio.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -525,7 +525,8 @@ gu::Config::Flag::type_bool); conf.add(gu::conf::ssl_compression, gu::Config::Flag::read_only | - gu::Config::Flag::type_bool); + gu::Config::Flag::type_bool | + gu::Config::Flag::deprecated); conf.add(gu::conf::ssl_key, gu::Config::Flag::read_only); conf.add(gu::conf::ssl_cert, @@ -595,6 +596,12 @@ log_info << "disabling SSL compression"; sk_SSL_COMP_zero(SSL_COMP_get_compression_methods()); } + else + { + log_warn << "SSL compression is not effective. The option " + << conf::ssl_compression << " is deprecated and " + << "will be removed in future releases."; + } conf.set(conf::ssl_compression, compression); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/gu_config.cpp new/galera-4-26.4.14/galerautils/src/gu_config.cpp --- old/galera-4-26.4.13/galerautils/src/gu_config.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/gu_config.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -102,6 +102,9 @@ gu::Config::Config() : params_() {} +std::function<void(const std::string&, const gu::Config::Parameter&)> + gu::Config::deprecation_check_func_ = check_deprecated; + void gu::Config::set_longlong (const std::string& key, long long val) { @@ -156,6 +159,26 @@ } } +void gu::Config::enable_deprecation_check() +{ + deprecation_check_func_ = check_deprecated; +} + +void gu::Config::disable_deprecation_check() +{ + deprecation_check_func_ = nullptr; +} + +void gu::Config::check_deprecated(const std::string& key, + const Parameter& param) +{ + if (param.is_deprecated()) + { + log_warn << "Parameter '" << key + << "' is deprecated and will be removed in future versions"; + } +} + char gu::Config::overflow_char(long long ret) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/gu_config.hpp new/galera-4-26.4.14/galerautils/src/gu_config.hpp --- old/galera-4-26.4.13/galerautils/src/gu_config.hpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/gu_config.hpp 2023-02-24 09:38:48.000000000 +0100 @@ -18,6 +18,7 @@ #include <map> #include <climits> +#include <functional> namespace gu { @@ -95,6 +96,10 @@ if (i != params_.end()) { + if (deprecation_check_func_) + { + deprecation_check_func_(i->first, i->second); + } i->second.set(value); } else @@ -215,9 +220,10 @@ static const int type_bool = (1 << 3); static const int type_integer = (1 << 4); static const int type_double = (1 << 5); + static const int type_duration = (1 << 6); - static const int type_mask = - Flag::type_bool | Flag::type_integer | Flag::type_double; + static const int type_mask = Flag::type_bool | Flag::type_integer + | Flag::type_double | Flag::type_duration; static std::string to_string(int f) { @@ -234,6 +240,8 @@ s << "integer | "; if (f & Flag::type_double) s << "double | "; + if (f & Flag::type_duration) + s << "duration | "; std::string ret(s.str()); if (ret.length() > 3) ret.erase(ret.length() - 3); @@ -264,6 +272,11 @@ return flags_ & Flag::hidden; } + bool is_deprecated() const + { + return flags_ & Flag::deprecated; + } + void set(const std::string& value) { value_ = value; @@ -288,8 +301,10 @@ const_iterator begin() const { return params_.begin(); } const_iterator end() const { return params_.end(); } -private: + static void enable_deprecation_check(); + static void disable_deprecation_check(); +private: static void key_check (const std::string& key); @@ -297,6 +312,8 @@ check_conversion (const char* ptr, const char* endptr, const char* type, bool range_error = false); + static void check_deprecated(const std::string& str, const Parameter& param); + static char overflow_char(long long ret); @@ -309,8 +326,10 @@ void set_longlong (const std::string& key, long long value); param_map_t params_; -}; + static std::function<void(const std::string&, const Parameter&)> + deprecation_check_func_; +}; extern "C" const char* gu_str2dbl (const char* str, double* dbl); extern "C" const char* gu_str2bool (const char* str, bool* bl); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/gu_datetime.cpp new/galera-4-26.4.14/galerautils/src/gu_datetime.cpp --- old/galera-4-26.4.13/galerautils/src/gu_datetime.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/gu_datetime.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -7,10 +7,197 @@ #include "gu_datetime.hpp" #include "gu_logger.hpp" #include "gu_utils.hpp" +#include "gu_throw.hpp" +#include "gu_regex.hpp" -extern "C" +#include <functional> + +namespace { -#include "gu_time.h" + /* + * Parser for real numbers without loss of precision. Returns long long. + */ + + /* Regular expression for reals. Allowed formats: + * 1 + * 1.1 + * .1 + */ + const char* real_regex_str = "^([0-9]*)?\\.?([0-9]*)?$"; + enum RealParts + { + integer = 1, + decimal = 2 + }; + constexpr size_t num_real_parts = 3; + gu::RegEx real_regex(real_regex_str); + + /* Helper to compute powers of 10 without floating point arithmetic. + * The exponents must be integer in range [0, 9). */ + long long pow_10(int exponent) + { + if (exponent < 0 || exponent >= 9) + { + throw gu::NotFound(); + } + long long result = 1; + while (exponent != 0) + { + result *= 10; + --exponent; + } + return result; + } + + /* Real number representation with integer and decimal parts + separated. Decimal part is represented in nanounits. */ + struct Real + { + long long integer{0}; // Integer part + long long decimal{0}; // Decimal part in nanounits + }; + + /* Parse real number frrom string. */ + Real real_from_string(const std::string& str) try + { + Real ret; + std::vector<gu::RegEx::Match> parts( + real_regex.match(str, num_real_parts)); + if (parts.size() != 3) + { + throw gu::NotFound(); + } + if (parts[RealParts::integer].is_set()) + { + const auto& str = parts[RealParts::integer].str(); + if (str.size()) + { + ret.integer = std::stoll(str); + } + } + if (parts[RealParts::decimal].is_set()) + { + const auto& str = parts[RealParts::decimal].str(); + if (str.size()) + { + const auto n_decis = str.size(); + if (n_decis > 9) + { + throw gu::NotFound(); + } + const int exponent = 9 - n_decis; + const long long multiplier = pow_10(exponent); + ret.decimal = std::stoll(str) * multiplier; + } + } + return ret; + } + catch (...) + { + throw gu::NotFound(); + } + + /* Parse seconds from string, return long long. */ + long long seconds_from_string(const std::string& str) + { + auto real = real_from_string(str); + const auto max = std::numeric_limits<long long>::max(); + if (max/gu::datetime::Sec < real.integer) + { + /* Multiplication would overflow */ + throw gu::NotFound(); + } + if (real.integer * gu::datetime::Sec > max - real.decimal) + { + /* Addition would overflow */ + throw gu::NotFound(); + } + return real.integer * gu::datetime::Sec + real.decimal; + } + + /* Parse seconds from string with multiplier. It is assumed that the + * str argument contains integer. */ + template <long long Mult> + long long seconds_from_string_mult(const std::string& str) try + { + const auto val = std::stoll(str); + const auto max = std::numeric_limits<long long>::max(); + if (max/Mult < val) + { + /* Multiplication would overflow */ + throw gu::NotFound(); + } + return (val * Mult); + } + catch(...) + { + throw gu::NotFound(); + } + + const char* const period_regex = + "^(P)(([0-9]+)Y)?(([0-9]+)M)?(([0-9]+)D)?" +/* 1 23 45 67 */ + "((T)?(([0-9]+)H)?(([0-9]+)M)?(([0-9]+(\\.?[0-9]*))?S)?)?$"; +/* 89 11 13 15 */ + + gu::RegEx regex(period_regex); + + enum + { + GU_P = 1, + GU_YEAR = 3, + GU_MONTH = 5, + GU_DAY = 7, + GU_HOUR = 10, + GU_MIN = 12, + GU_SEC = 15, + GU_NUM_PARTS = 17 + }; + + struct regex_group + { + int index; + std::function<long long(const std::string& str)> parse; + }; + + const struct regex_group regex_groups[] + { + { GU_YEAR, seconds_from_string_mult<gu::datetime::Year> }, + { GU_MONTH, seconds_from_string_mult<gu::datetime::Month> }, + { GU_DAY, seconds_from_string_mult<gu::datetime::Day> }, + { GU_HOUR, seconds_from_string_mult<gu::datetime::Hour> }, + { GU_MIN, seconds_from_string_mult<gu::datetime::Min> }, + { GU_SEC, seconds_from_string }, + }; + + long long iso8601_duration_to_nsecs(const std::string& str) + { + long long nsecs = 0; + std::vector<gu::RegEx::Match> parts; + try + { + parts = regex.match(str, GU_NUM_PARTS); + } + catch (...) { + throw gu::NotFound(); + } + + for (auto g : regex_groups) + { + if (parts[g.index].is_set()) + { + const long long val(g.parse(parts[g.index].str())); + const long long max(std::numeric_limits<long long>::max()); + if (nsecs > max - val) + { + // addition would overflow + throw gu::NotFound(); + } + nsecs += val; + } + } + return nsecs; + } } long long gu::datetime::SimClock::counter_(0); @@ -49,79 +236,15 @@ gu_throw_fatal << "not implemented"; } -const char* const gu::datetime::Period::period_regex = - "^(P)(([0-9]+)Y)?(([0-9]+)M)?(([0-9]+)D)?" -/* 1 23 45 67 */ - "((T)?(([0-9]+)H)?(([0-9]+)M)?(([0-9]+)(\\.([0-9]+))?S)?)?"; -/* 89 11 13 15 16 */ - -enum -{ - GU_P = 1, - GU_YEAR = 3, - GU_MONTH = 5, - GU_DAY = 7, - GU_HOUR = 10, - GU_MIN = 12, - GU_SEC = 15, - GU_SEC_D = 16, - GU_NUM_PARTS = 17 -}; - -gu::RegEx const gu::datetime::Period::regex(period_regex); void gu::datetime::Period::parse(const std::string& str) { - std::vector<RegEx::Match> parts = regex.match(str, GU_NUM_PARTS); - - if (parts[GU_P].is_set() == false) - { - if (str == "") - { - return; - } - else - { - gu_throw_error (EINVAL) << "Period " << str << " not valid"; - } - } - - if (parts[GU_YEAR].is_set()) - { - nsecs += from_string<long long>(parts[GU_YEAR].str())*Year; - } - - if (parts[GU_MONTH].is_set()) - { - nsecs += from_string<long long>(parts[GU_MONTH].str())*Month; - } - - if (parts[GU_DAY].is_set()) - { - nsecs += from_string<long long>(parts[GU_DAY].str())*Day; - } - - if (parts[GU_HOUR].is_set()) - { - nsecs += from_string<long long>(parts[GU_HOUR].str())*Hour; - } - - if (parts[GU_MIN].is_set()) - { - nsecs += from_string<long long>(parts[GU_MIN].str())*Min; - } - - if (parts[GU_SEC].is_set()) + try { - long long s(from_string<long long>(parts[GU_SEC].str())); - nsecs += s*Sec; + nsecs = ::iso8601_duration_to_nsecs(str); } - - if (parts[GU_SEC_D].is_set()) + catch (...) { - double d(from_string<double>(parts[GU_SEC_D].str())); - nsecs += static_cast<long long>(d*Sec); + nsecs = seconds_from_string(str); } } - - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/gu_datetime.hpp new/galera-4-26.4.14/galerautils/src/gu_datetime.hpp --- old/galera-4-26.4.13/galerautils/src/gu_datetime.hpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/gu_datetime.hpp 2023-02-24 09:38:48.000000000 +0100 @@ -11,10 +11,9 @@ #include "gu_exception.hpp" -#include "gu_regex.hpp" #include "gu_time.h" -#include <iostream> +#include <sstream> #include <string> #include <limits> @@ -41,16 +40,24 @@ { public: /*! - * @brief Constructor + * @brief Construct gu::datetime::Period from string * - * Duration format is PnYnMnDTnHnMnS where Y is year, M is month, - * D is day, T is the time designator separating date and time - * parts, H denotes hours, M (after T) is minutes and S seconds. + * This constructor accepts a string that contains a duration + * represented in ISO8601 format. Alternatively, it accepts a + * string that represents a double duration in number of seconds. + * + * The ISO8601 duration format is PnYnMnDTnHnMnS where Y is year, + * M is month, D is day, T is the time designator separating date + * and time parts, H denotes hours, M (after T) is minutes and S + * seconds. * * All other n:s are expected to be integers except the one * before S which can be decimal to represent fractions of second. * - * @param str Time period represented in ISO8601 duration format. + * @param str Time period represented in ISO8601 duration format, + * or number of seconds represented as double. + * + * @throws NotFound */ Period(const std::string& str = "") : nsecs() @@ -97,9 +104,6 @@ friend class Date; friend std::istream& operator>>(std::istream&, Period&); - static const char* const period_regex; /*! regexp string */ - static RegEx const regex; /*! period string parser */ - /*! * @brief Parse period string. */ @@ -237,6 +241,11 @@ return os.str(); } + inline double to_double(const Period& p) + { + return static_cast<double>(p.get_nsecs()) / Sec; + } + inline std::istream& operator>>(std::istream& is, Period& p) { std::string str; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/gu_event_service.cpp new/galera-4-26.4.14/galerautils/src/gu_event_service.cpp --- old/galera-4-26.4.13/galerautils/src/gu_event_service.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/gu_event_service.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -0,0 +1,48 @@ +// +// Copyright (C) 2021 Codership Oy <[email protected]> +// + +#include "gu_event_service.hpp" + +#include <cassert> + +// +// Event service hooks. +// + +namespace gu +{ + std::mutex EventService::mutex; + size_t EventService::usage(0); + + EventService* EventService::instance = nullptr; + + int EventService::init_v1(const wsrep_event_service_v1_t* es) + { + std::lock_guard<std::mutex> lock(EventService::mutex); + ++EventService::usage; + + if (EventService::instance) + { + assert(0); + return 0; + } + + EventService::instance = new EventService(es->context, es->event_cb); + return 0; + } + + void EventService::deinit_v1() + { + std::lock_guard<std::mutex> lock(EventService::mutex); + assert(EventService::usage > 0); + --EventService::usage; + + if (EventService::usage == 0) + { + delete EventService::instance; + EventService::instance = 0; + } + } + +} /* galera*/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/gu_event_service.hpp new/galera-4-26.4.14/galerautils/src/gu_event_service.hpp --- old/galera-4-26.4.13/galerautils/src/gu_event_service.hpp 1970-01-01 01:00:00.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/gu_event_service.hpp 2023-02-24 09:38:48.000000000 +0100 @@ -0,0 +1,54 @@ +// +// Copyright (C) 2021 Codership Oy <[email protected]> +// + +/** + * Event service class + */ + +#ifndef GALERA_EVENT_SERVICE_HPP +#define GALERA_EVENT_SERVICE_HPP + +#include "wsrep_event_service.h" + +#include <string> +#include <mutex> + +namespace gu +{ + class EventService + { + public: + static int init_v1(const wsrep_event_service_v1_t*); + static void deinit_v1(); + + static void callback(const std::string& name, const std::string& value) + { + std::lock_guard<std::mutex> lock(EventService::mutex); + + if (instance && instance->cb_) + { + instance->cb_(instance->ctx_, name.c_str(), value.c_str()); + } + } + + private: + wsrep_event_context_t* const ctx_; + wsrep_event_cb_t const cb_; + + static std::mutex mutex; + static size_t usage; + static EventService* instance; + + EventService(wsrep_event_context_t* ctx, wsrep_event_cb_t cb) + : ctx_(ctx), cb_(cb) + {} + ~EventService() {} + + EventService(const EventService&); + EventService& operator =(EventService); + }; + +} /* galera */ + +#endif /* GALERA_EVENT_SERVICE_HPP */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/src/gu_utils.hpp new/galera-4-26.4.14/galerautils/src/gu_utils.hpp --- old/galera-4-26.4.13/galerautils/src/gu_utils.hpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/src/gu_utils.hpp 2023-02-24 09:38:48.000000000 +0100 @@ -66,7 +66,11 @@ try { - if ((iss >> f >> ret).fail()) throw NotFound(); + iss >> f >> ret; + if (iss.fail() || not iss.eof()) + { + throw NotFound(); + } } catch (gu::Exception& e) { @@ -93,7 +97,11 @@ std::istringstream iss(s); void* ret; - if ((iss >> std::hex >> ret).fail()) throw NotFound(); + iss >> std::hex >> ret; + if (iss.fail() || not iss.eof()) + { + throw NotFound(); + } return ret; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/tests/CMakeLists.txt new/galera-4-26.4.14/galerautils/tests/CMakeLists.txt --- old/galera-4-26.4.13/galerautils/tests/CMakeLists.txt 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/tests/CMakeLists.txt 2023-02-24 09:38:48.000000000 +0100 @@ -58,6 +58,7 @@ gu_mem_pool_test.cpp gu_alloc_test.cpp gu_rset_test.cpp + gu_utils_test++.cpp gu_string_utils_test.cpp gu_uri_test.cpp gu_config_test.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/tests/SConscript new/galera-4-26.4.14/galerautils/tests/SConscript --- old/galera-4-26.4.13/galerautils/tests/SConscript 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/tests/SConscript 2023-02-24 09:38:48.000000000 +0100 @@ -74,6 +74,7 @@ gu_asio_test.cpp gu_deqmap_test.cpp gu_progress_test.cpp + gu_utils_test++.cpp gu_tests++.cpp ''')) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/tests/gu_datetime_test.cpp new/galera-4-26.4.14/galerautils/tests/gu_datetime_test.cpp --- old/galera-4-26.4.13/galerautils/tests/gu_datetime_test.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/tests/gu_datetime_test.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -5,10 +5,9 @@ #include "gu_datetime.hpp" #include "gu_logger.hpp" #include "gu_utils.hpp" - #include "gu_datetime_test.hpp" - +#include <cmath> // std::fabs using namespace gu; using namespace gu::datetime; @@ -53,22 +52,78 @@ ck_assert(Period("P5Y66DT").get_nsecs() == 5*Year + 66*Day); ck_assert(Period("P37M44DT").get_nsecs() == 37*Month + 44*Day); - // Hour-min-sec ck_assert(Period("PT3H").get_nsecs() == 3*Hour); ck_assert(Period("PT5M").get_nsecs() == 5*Min); ck_assert(Period("P37S").get_nsecs() == 37*Sec); - // ck_assert(Period("PT3.578777S").get_nsecs() == 3*Sec + 578*MSec + 777*USec); + // Decimal seconds ck_assert(Period("PT0.5S").get_nsecs() == 500*MSec); + ck_assert(Period("PT3.578777S").get_nsecs() == 3*Sec + 578*MSec + 777*USec); + ck_assert(Period("PT5H7M3.578777S").get_nsecs() + == 5*Hour + 7*Min + 3*Sec + 578*MSec + 777*USec); + + // Full + ck_assert(Period("P10Y5M4DT3H24M1.1S").get_nsecs() + == 10*Year + 5*Month + 4*Day + 3*Hour + 24*Min + 1.1*Sec); +} +END_TEST +static void assert_invalid_period(const std::string& period) +{ + bool exception = false; + try + { + Period p(period); + } + catch (gu::NotFound& exp) + { + exception = true; + } + ck_assert(exception); +} - // ck_assert(Period("PT5H7M3.578777S").get_nsecs() == 5*Hour + 7*Min + 3*Sec + 578*MSec + 777*USec); - - // @todo these should fail - ck_assert(Period("PT.S").get_nsecs() == 0); - ck_assert(Period("PT.D").get_nsecs() == 0); +START_TEST(test_period_invalid) +{ + assert_invalid_period("a"); + assert_invalid_period("anyvalue"); + assert_invalid_period("Panyvalue"); + assert_invalid_period("PT.S"); + assert_invalid_period("PT.D"); + assert_invalid_period("PT1D"); + assert_invalid_period("P1D1Y"); + assert_invalid_period("P9223372036854775807Y"); // Overflow +} +END_TEST +static void assert_double_eq_tol(double left, double right, double tol) +{ + ck_assert(std::fabs(left - right) < tol); +} + +START_TEST(test_period_from_double) +{ + ck_assert(Period("0").get_nsecs() == 0); + ck_assert(Period(".1").get_nsecs() == 100*MSec); + ck_assert(Period("0.0").get_nsecs() == 0); + ck_assert(Period("0.5").get_nsecs() == 500*MSec); + // Use microsecond precision for comparison to make + // it work on x86 + assert_double_eq_tol(to_double(Period("0.5")), 0.5, 0.000001); + assert_double_eq_tol(to_double(Period(".111111111")), 0.111111111, + 0.000001);; +} +END_TEST + +START_TEST(test_period_overflow) +{ + long long max_secs = std::numeric_limits<long long>::max() / gu::datetime::Sec; + + std::string max_duration("PT" + std::to_string(max_secs) + "S"); + ck_assert(Period(max_duration).get_nsecs()); // no overflow + + std::string overflow_duration("PT" + std::to_string(max_secs + 1.0) + "S"); + assert_invalid_period(overflow_duration); } END_TEST @@ -112,6 +167,18 @@ tcase_add_test(tc, test_period); suite_add_tcase(s, tc); + tc = tcase_create("test_period_invalid"); + tcase_add_test(tc, test_period_invalid); + suite_add_tcase(s, tc); + + tc = tcase_create("test_period_from_double"); + tcase_add_test(tc, test_period_from_double); + suite_add_tcase(s, tc); + + tc = tcase_create("test_period_overflow"); + tcase_add_test(tc, test_period_overflow); + suite_add_tcase(s, tc); + tc = tcase_create("test_date"); tcase_add_test(tc, test_date); suite_add_tcase(s, tc); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/tests/gu_tests++.hpp new/galera-4-26.4.14/galerautils/tests/gu_tests++.hpp --- old/galera-4-26.4.13/galerautils/tests/gu_tests++.hpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/tests/gu_tests++.hpp 2023-02-24 09:38:48.000000000 +0100 @@ -29,6 +29,7 @@ #include "gu_thread_test.hpp" #include "gu_asio_test.hpp" #include "gu_deqmap_test.hpp" +#include "gu_utils_test++.hpp" typedef Suite *(*suite_creator_t)(void); @@ -53,6 +54,7 @@ gu_thread_suite, gu_asio_suite, gu_deqmap_suite, + gu_utils_cpp_suite, 0 }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/tests/gu_utils_test++.cpp new/galera-4-26.4.14/galerautils/tests/gu_utils_test++.cpp --- old/galera-4-26.4.13/galerautils/tests/gu_utils_test++.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/tests/gu_utils_test++.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009-2020 Codership Oy <[email protected]> + */ + +#include "gu_utils.hpp" +#include "gu_utils_test++.hpp" + +static void assert_invalid_int(const std::string& test_str, + std::ios_base& (*f)(std::ios_base&) = std::dec) +{ + bool exception(false); + try + { + gu::from_string<int>(test_str); + } + catch (gu::NotFound) + { + exception = true; + } + ck_assert(exception); +} + +START_TEST(test_from_string_invalid_int) +{ + // used to parse '1' + assert_invalid_int("1dummy"); + assert_invalid_int("1 dummy"); + assert_invalid_int("0x1whatever", std::hex); + + // used to parse 'd' + assert_invalid_int("dummy", std::hex); +} +END_TEST + + +static void assert_invalid_bool(const std::string& test_str) +{ + bool exception(false); + try + { + gu::from_string<bool>(test_str); + } + catch (gu::NotFound) + { + exception = true; + } + ck_assert(exception); +} + +START_TEST(test_from_string_invalid_bool) +{ + assert_invalid_bool("true 1"); +} +END_TEST + + +Suite* gu_utils_cpp_suite() +{ + Suite* s = suite_create("gu::utils"); + TCase* tc; + + tc = tcase_create("test_from_string_invalid_int"); + tcase_add_test(tc, test_from_string_invalid_int); + suite_add_tcase(s, tc); + + tc = tcase_create("test_from_string_invalid_bool"); + tcase_add_test(tc, test_from_string_invalid_bool); + suite_add_tcase(s, tc); + + return s; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/galerautils/tests/gu_utils_test++.hpp new/galera-4-26.4.14/galerautils/tests/gu_utils_test++.hpp --- old/galera-4-26.4.13/galerautils/tests/gu_utils_test++.hpp 1970-01-01 01:00:00.000000000 +0100 +++ new/galera-4-26.4.14/galerautils/tests/gu_utils_test++.hpp 2023-02-24 09:38:48.000000000 +0100 @@ -0,0 +1,10 @@ +// Copyright (C) 2022 Codership Oy <[email protected]> + +#ifndef __gu_utils_test_hpp__ +#define __gu_utils_test_hpp__ + +#include <check.h> + +Suite* gu_utils_cpp_suite(); + +#endif /* __gu_utils_test_hpp__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/gcomm/src/defaults.cpp new/galera-4-26.4.14/gcomm/src/defaults.cpp --- old/galera-4-26.4.13/gcomm/src/defaults.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/gcomm/src/defaults.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -9,12 +9,7 @@ namespace gcomm { -#ifdef HAVE_ASIO_HPP std::string const Defaults::ProtonetBackend = "asio"; -#else -#error "Only asio protonet backend is currently supported" -#endif /* HAVE_ASIO_HPP */ - std::string const Defaults::ProtonetVersion = "0"; std::string const Defaults::SocketChecksum = "2"; std::string const Defaults::SocketRecvBufSize = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/gcomm/src/defaults.hpp new/galera-4-26.4.14/gcomm/src/defaults.hpp --- old/galera-4-26.4.13/gcomm/src/defaults.hpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/gcomm/src/defaults.hpp 2023-02-24 09:38:48.000000000 +0100 @@ -61,8 +61,10 @@ static const int BasePort = gu::Config::Flag::read_only | gu::Config::Flag::type_integer; - static const int ProtonetBackend = gu::Config::Flag::read_only; - static const int ProtonetVersion = gu::Config::Flag::read_only; + static const int ProtonetBackend + = gu::Config::Flag::read_only | gu::Config::Flag::deprecated; + static const int ProtonetVersion + = gu::Config::Flag::read_only | gu::Config::Flag::deprecated; // Hidden because not documented / does not seem to be used? static const int TcpNonBlocking = gu::Config::Flag::hidden; @@ -81,8 +83,10 @@ gu::Config::Flag::type_integer; static const int GMCastMCastTTL = gu::Config::Flag::read_only | gu::Config::Flag::type_integer; - static const int GMCastTimeWait = gu::Config::Flag::read_only; - static const int GMCastPeerTimeout = gu::Config::Flag::read_only; + static const int GMCastTimeWait = gu::Config::Flag::read_only | + gu::Config::Flag::type_duration; + static const int GMCastPeerTimeout = gu::Config::Flag::read_only | + gu::Config::Flag::type_duration;; // Hidden because undocumented static const int GMCastMaxInitialReconnectAttempts = gu::Config::Flag::hidden | gu::Config::Flag::type_integer; @@ -94,23 +98,24 @@ gu::Config::Flag::type_integer; static const int EvsVersion = gu::Config::Flag::read_only; - static const int EvsViewForgetTimeout = gu::Config::Flag::read_only; - static const int EvsSuspectTimeout = 0; - static const int EvsInactiveTimeout = 0; - static const int EvsInactiveCheckPeriod = 0; - static const int EvsInstallTimeout = 0; - static const int EvsKeepalivePeriod = 0; - static const int EvsJoinRetransPeriod = 0; - static const int EvsStatsReportPeriod = 0; + static const int EvsViewForgetTimeout = gu::Config::Flag::read_only | + gu::Config::Flag::type_duration; + static const int EvsSuspectTimeout = gu::Config::Flag::type_duration; + static const int EvsInactiveTimeout = gu::Config::Flag::type_duration; + static const int EvsInactiveCheckPeriod = gu::Config::Flag::type_duration; + static const int EvsInstallTimeout = gu::Config::Flag::type_duration; + static const int EvsKeepalivePeriod = gu::Config::Flag::type_duration; + static const int EvsJoinRetransPeriod = gu::Config::Flag::type_duration; + static const int EvsStatsReportPeriod = gu::Config::Flag::type_duration; static const int EvsDebugLogMask = 0; static const int EvsInfoLogMask = 0; static const int EvsSendWindow = gu::Config::Flag::type_integer; static const int EvsUserSendWindow = gu::Config::Flag::type_integer; static const int EvsUseAggregate = gu::Config::Flag::type_bool; - static const int EvsCausalKeepalivePeriod = 0; + static const int EvsCausalKeepalivePeriod = gu::Config::Flag::type_duration; static const int EvsMaxInstallTimeouts = gu::Config::Flag::type_integer; - static const int EvsDelayMargin = 0; - static const int EvsDelayedKeepPeriod = 0; + static const int EvsDelayMargin = gu::Config::Flag::type_duration; + static const int EvsDelayedKeepPeriod = gu::Config::Flag::type_duration; static const int EvsEvict = 0; static const int EvsAutoEvict = gu::Config::Flag::read_only | gu::Config::Flag::type_bool; @@ -119,13 +124,16 @@ static const int PcIgnoreSb = gu::Config::Flag::type_bool; static const int PcIgnoreQuorum = gu::Config::Flag::type_bool; static const int PcChecksum = gu::Config::Flag::type_bool; - static const int PcAnnounceTimeout = gu::Config::Flag::read_only; - static const int PcLinger = gu::Config::Flag::read_only; + static const int PcAnnounceTimeout = gu::Config::Flag::read_only | + gu::Config::Flag::type_duration; + static const int PcLinger = gu::Config::Flag::read_only | + gu::Config::Flag::type_duration; static const int PcNpvo = gu::Config::Flag::type_bool; static const int PcBootstrap = gu::Config::Flag::type_bool; static const int PcWaitPrim = gu::Config::Flag::read_only | gu::Config::Flag::type_bool; - static const int PcWaitPrimTimeout = gu::Config::Flag::read_only; + static const int PcWaitPrimTimeout = gu::Config::Flag::read_only | + gu::Config::Flag::type_duration; static const int PcWeight = gu::Config::Flag::type_integer; static const int PcRecovery = gu::Config::Flag::read_only | gu::Config::Flag::type_bool; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/gcomm/src/evs_proto.cpp new/galera-4-26.4.14/gcomm/src/evs_proto.cpp --- old/galera-4-26.4.13/gcomm/src/evs_proto.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/gcomm/src/evs_proto.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -19,6 +19,7 @@ #include <numeric> #include <iterator> #include <set> +#include <iostream> // std::cerr using namespace std::rel_ops; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/gcomm/src/gmcast_proto.cpp new/galera-4-26.4.14/gcomm/src/gmcast_proto.cpp --- old/galera-4-26.4.13/gcomm/src/gmcast_proto.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/gcomm/src/gmcast_proto.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -6,6 +6,17 @@ #include "gmcast.hpp" #include "gu_uri.hpp" +#include "gu_event_service.hpp" + +static void emit_evicted_event() +{ + std::ostringstream os; + os << "{\"status\": \"evicted\", " + << "\"message\": " + << "\"This node was evicted permanently from cluster, " + << "restart is required\"}"; + gu::EventService::callback("event", os.str()); +} static const std::string gmcast_proto_err_evicted("evicted"); static const std::string gmcast_proto_err_invalid_group("invalid group"); @@ -280,6 +291,7 @@ // otherwise node use the uuid in view state file. // which is probably still in other nodes evict list. gmcast_.remove_viewstate_file(); + emit_evicted_event(); gu_throw_fatal << "this node has been evicted out of the cluster, " << "gcomm backend restart is required"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/gcomm/src/pc_proto.cpp new/galera-4-26.4.14/gcomm/src/pc_proto.cpp --- old/galera-4-26.4.13/gcomm/src/pc_proto.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/gcomm/src/pc_proto.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -12,6 +12,7 @@ #include "gu_macros.h" #include <algorithm> #include <set> +#include <iostream> // std::cerr #include <boost/bind.hpp> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/gcomm/test/check_trace.cpp new/galera-4-26.4.14/gcomm/test/check_trace.cpp --- old/galera-4-26.4.13/gcomm/test/check_trace.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/gcomm/test/check_trace.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -11,6 +11,7 @@ #include "check_trace.hpp" #include "gcomm/conf.hpp" #include "gu_asio.hpp" // gu::ssl_register_params() +#include <iostream> // std::cerr using namespace std; using namespace gu; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/gcomm/test/ssl_test.cpp new/galera-4-26.4.14/gcomm/test/ssl_test.cpp --- old/galera-4-26.4.13/gcomm/test/ssl_test.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/gcomm/test/ssl_test.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -6,6 +6,7 @@ #include <map> #include <stdexcept> +#include <iostream> // std::cerr static gu::Config conf; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/gcs/src/unit_tests/gcs_core_test.cpp new/galera-4-26.4.14/gcs/src/unit_tests/gcs_core_test.cpp --- old/galera-4-26.4.13/gcs/src/unit_tests/gcs_core_test.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/gcs/src/unit_tests/gcs_core_test.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -550,14 +550,18 @@ // do a single send step, compare with the expected result static inline bool -CORE_SEND_STEP (gcs_core_t* core, long timeout, long ret) +CORE_SEND_STEP (gcs_core_t* core, long timeout, long ret, int line) { long err = gcs_core_send_step (core, timeout); ck_assert_msg(err >= 0, "gcs_core_send_step(): %ld (%s)", err, strerror (-err)); if (ret >= 0) { - ck_assert_msg(err == ret, "gcs_core_send_step(): expected %ld, got %ld", - ret, err); + if (err != ret) { + fprintf(stderr, "gcs_core_send_step(%ld, %ld) at line %d:" + " expected %ld, got %ld", timeout, ret, line, ret, err); + assert(0); // to catch a core if possible + ck_abort(); + } } return false; @@ -625,11 +629,11 @@ ck_assert(!CORE_RECV_START (&act_r)); ck_assert(!CORE_SEND_START (&act_s)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 1st frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 1st frag usleep (10000); // resolve race between sending and setting transitional gcs_dummy_set_transitional (Backend); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 2nd frag - ck_assert(!CORE_SEND_STEP (Core, tout, 0)); // no frags left + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 2nd frag + ck_assert(!CORE_SEND_STEP (Core, tout, 0, __LINE__)); // no frags left ck_assert(NULL == act_r.out); // should not have received anything ck_assert(!gcs_dummy_set_component (Backend, prim)); // return to PRIM state ck_assert(!CORE_SEND_END (&act_s, act_size)); @@ -643,8 +647,8 @@ */ ck_assert(!DUMMY_INJECT_COMPONENT (Backend, non_prim)); ck_assert(!CORE_SEND_START (&act_s)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 1st frag - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 2nd frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 1st frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 2nd frag ck_assert(!CORE_SEND_END (&act_s, act_size)); ck_assert(!gcs_dummy_set_component(Backend, non_prim)); ck_assert(!CORE_RECV_ACT (&act_r, NULL, UNKNOWN_SIZE, GCS_ACT_CCHANGE)); @@ -662,8 +666,8 @@ * fragment send fails. */ ck_assert(!CORE_SEND_START (&act_s)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 1st frag - ck_assert(!CORE_SEND_STEP (Core, tout, 0)); // bail out after 1st frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 1st frag + ck_assert(!CORE_SEND_STEP (Core, tout, 0, __LINE__)); // bail out after 1st frag ck_assert(!CORE_SEND_END (&act_s, -ENOTCONN)); /* @@ -676,7 +680,7 @@ ck_assert(!gcs_dummy_set_component(Backend, non_prim)); ck_assert(!DUMMY_INJECT_COMPONENT (Backend, non_prim)); ck_assert(!CORE_SEND_START (&act_s)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 1st frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 1st frag ck_assert(!CORE_SEND_END (&act_s, -ENOTCONN)); ck_assert(!CORE_RECV_ACT (&act_r, NULL, UNKNOWN_SIZE, GCS_ACT_CCHANGE)); ck_assert(!core_test_check_conf(act_r.out, act_r.size, false, 0, 1)); @@ -690,9 +694,9 @@ */ ck_assert(!DUMMY_INSTALL_COMPONENT (Backend, prim)); ck_assert(!CORE_SEND_START (&act_s)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 1st frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 1st frag ck_assert(!DUMMY_INJECT_COMPONENT (Backend, non_prim)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 2nd frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 2nd frag ck_assert(!CORE_SEND_END (&act_s, act_size)); ck_assert(!CORE_RECV_ACT (&act_r, NULL, UNKNOWN_SIZE, GCS_ACT_CCHANGE)); ck_assert(!core_test_check_conf(act_r.out, act_r.size, false, 0, 1)); @@ -710,11 +714,11 @@ */ ck_assert(!DUMMY_INSTALL_COMPONENT (Backend, prim)); ck_assert(!CORE_SEND_START (&act_s)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 1st frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 1st frag usleep (100000); // make sure 1st fragment gets in before new component ck_assert(!DUMMY_INSTALL_COMPONENT (Backend, non_prim)); ck_assert(!DUMMY_INSTALL_COMPONENT (Backend, prim)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 2nd frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 2nd frag ck_assert(!CORE_SEND_END (&act_s, act_size)); ck_assert(!CORE_RECV_ACT (&act_r, act_buf, act_size, GCS_ACT_WRITESET)); ck_assert_msg(-ERESTART == act_r.seqno, @@ -739,26 +743,26 @@ // subcase 1 ck_assert(!DUMMY_INSTALL_COMPONENT (Backend, prim)); ck_assert(!CORE_SEND_START (&act_s)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 1st frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 1st frag ck_assert(!DUMMY_INJECT_COMPONENT (Backend, non_prim)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 2nd frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 2nd frag usleep (500000); // fail_if_seq ck_assert(!gcs_dummy_set_component(Backend, non_prim)); ck_assert(!CORE_RECV_ACT (&act_r, NULL, UNKNOWN_SIZE, GCS_ACT_CCHANGE)); ck_assert(!core_test_check_conf(act_r.out, act_r.size, false, 0, 1)); Cache->free(act_r.out); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 3rd frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 3rd frag ck_assert(!CORE_SEND_END (&act_s, -ENOTCONN)); // subcase 2 ck_assert(!DUMMY_INSTALL_COMPONENT (Backend, prim)); ck_assert(!CORE_SEND_START (&act_s)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 1st frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 1st frag ck_assert(!DUMMY_INJECT_COMPONENT (Backend, non_prim)); - ck_assert(!CORE_SEND_STEP (Core, tout, 1)); // 2nd frag + ck_assert(!CORE_SEND_STEP (Core, tout, 1, __LINE__)); // 2nd frag usleep (1000000); ck_assert(!gcs_dummy_set_component(Backend, non_prim)); - ck_assert(!CORE_SEND_STEP (Core, 4*tout, 1)); // 3rd frag + ck_assert(!CORE_SEND_STEP (Core, 4*tout, 1, __LINE__)); // 3rd frag ck_assert(!CORE_RECV_ACT (&act_r, NULL, UNKNOWN_SIZE, GCS_ACT_CCHANGE)); ck_assert(!core_test_check_conf(act_r.out, act_r.size, false, 0, 1)); Cache->free(act_r.out); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/gcs/src/unit_tests/gcs_memb_test.cpp new/galera-4-26.4.14/gcs/src/unit_tests/gcs_memb_test.cpp --- old/galera-4-26.4.13/gcs/src/unit_tests/gcs_memb_test.cpp 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/gcs/src/unit_tests/gcs_memb_test.cpp 2023-02-24 09:38:48.000000000 +0100 @@ -116,7 +116,9 @@ Suite *suite = suite_create("GCS membership changes"); TCase *tcase = tcase_create("gcs_memb"); - suite_add_tcase (suite, tcase); - tcase_add_test (tcase, gcs_memb_test_465); + suite_add_tcase (suite, tcase); + tcase_add_test (tcase, gcs_memb_test_465); + tcase_set_timeout(tcase, 30); + return suite; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/scripts/packages/codership-galera.spec new/galera-4-26.4.14/scripts/packages/codership-galera.spec --- old/galera-4-26.4.13/scripts/packages/codership-galera.spec 2022-11-03 11:54:20.000000000 +0100 +++ new/galera-4-26.4.14/scripts/packages/codership-galera.spec 2023-02-24 09:38:51.000000000 +0100 @@ -21,7 +21,7 @@ %define name galera-4 %define wsrep_api 26 -%{!?version: %define version 26.4.13} +%{!?version: %define version 26.4.14} %{!?release: %define release 1} %define copyright Copyright 2007-2020 Codership Oy. All rights reserved. Use is subject to license terms under GPLv2 license. %define libs %{_libdir}/%{name} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/galera-4-26.4.13/tests/scripts/action.sh new/galera-4-26.4.14/tests/scripts/action.sh --- old/galera-4-26.4.13/tests/scripts/action.sh 2022-11-03 11:54:17.000000000 +0100 +++ new/galera-4-26.4.14/tests/scripts/action.sh 2023-02-24 09:38:48.000000000 +0100 @@ -1,11 +1,23 @@ # Helper to get status variable value +mysql_command() +{ + local node=$1 + if [ "${NODE_LOCATION[$node]}" = "local" ] + then + echo "${NODE_TEST_DIR[$node]}/mysql/bin/mysql" + else + echo "mysql" + fi +} + cluster_status() { local node=$1 case "$DBMS" in "MYSQL") - local res=$(mysql -u$DBMS_ROOT_USER -p$DBMS_ROOT_PSWD \ + local command=$(mysql_command $node) + local res=$($command -u$DBMS_ROOT_USER -p$DBMS_ROOT_PSWD \ -h${NODE_INCOMING_HOST[$node]} -P${NODE_INCOMING_PORT[$node]} \ --skip-column-names -ss \ -e "SET wsrep_on=0; @@ -22,7 +34,9 @@ { local node=$1 local query=$2 - mysql -u$DBMS_ROOT_USER -p$DBMS_ROOT_PSWD \ + local command=$(mysql_command $node) + + $command -u$DBMS_ROOT_USER -p$DBMS_ROOT_PSWD \ -h${NODE_INCOMING_HOST[$node]} -P${NODE_INCOMING_PORT[$node]} \ --skip-column-names -ss -e "$query" }
