diff --git a/DartConfiguration.tcl b/DartConfiguration.tcl
deleted file mode 100644
index b529d7b..0000000
--- a/DartConfiguration.tcl
+++ /dev/null
@@ -1,111 +0,0 @@
-# This file is configured by CMake automatically as DartConfiguration.tcl
-# If you choose not to use CMake, this file may be hand configured, by
-# filling in the required variables.
-
-
-# Configuration directories and files
-SourceDirectory: /var/lib/jenkins/workspace/build-galera-source/galera-source
-BuildDirectory: /var/lib/jenkins/workspace/build-galera-source/galera-source
-
-# Where to place the cost data store
-CostDataFile: 
-
-# Site is something like machine.domain, i.e. pragmatic.crd
-Site: master
-
-# Build name is osname-revision-compiler, i.e. Linux-2.4.2-2smp-c++
-BuildName: Linux-c++
-
-# Submission information
-IsCDash: 
-CDashVersion: 
-QueryCDashVersion: 
-DropSite: 
-DropLocation: 
-DropSiteUser: 
-DropSitePassword: 
-DropSiteMode: 
-DropMethod: http
-TriggerSite: 
-ScpCommand: /usr/bin/scp
-
-# Dashboard start time
-NightlyStartTime: 00:00:00 EDT
-
-# Commands for the build/test/submit cycle
-ConfigureCommand: "/usr/bin/cmake" "/var/lib/jenkins/workspace/build-galera-source/galera-source"
-MakeCommand: /usr/bin/cmake --build . --config "${CTEST_CONFIGURATION_TYPE}" -- -i
-DefaultCTestConfigurationType: Release
-
-# version control
-UpdateVersionOnly: 
-
-# CVS options
-# Default is "-d -P -A"
-CVSCommand: CVSCOMMAND-NOTFOUND
-CVSUpdateOptions: -d -A -P
-
-# Subversion options
-SVNCommand: /usr/bin/svn
-SVNOptions: 
-SVNUpdateOptions: 
-
-# Git options
-GITCommand: /usr/bin/git
-GITUpdateOptions: 
-GITUpdateCustom: 
-
-# Perforce options
-P4Command: P4COMMAND-NOTFOUND
-P4Client: 
-P4Options: 
-P4UpdateOptions: 
-P4UpdateCustom: 
-
-# Generic update command
-UpdateCommand: /usr/bin/git
-UpdateOptions: 
-UpdateType: git
-
-# Compiler info
-Compiler: /usr/bin/c++
-CompilerVersion: 5.4.0
-
-# Dynamic analysis (MemCheck)
-PurifyCommand: 
-ValgrindCommand: 
-ValgrindCommandOptions: 
-MemoryCheckType: 
-MemoryCheckSanitizerOptions: 
-MemoryCheckCommand: /usr/bin/valgrind
-MemoryCheckCommandOptions: 
-MemoryCheckSuppressionFile: 
-
-# Coverage
-CoverageCommand: /usr/bin/gcov
-CoverageExtraFlags: -l
-
-# Cluster commands
-SlurmBatchCommand: SLURM_SBATCH_COMMAND-NOTFOUND
-SlurmRunCommand: SLURM_SRUN_COMMAND-NOTFOUND
-
-# Testing options
-# TimeOut is the amount of time in seconds to wait for processes
-# to complete during testing.  After TimeOut seconds, the
-# process will be summarily terminated.
-# Currently set to 25 minutes
-TimeOut: 1500
-
-# During parallel testing CTest will not start a new test if doing
-# so would cause the system load to exceed this value.
-TestLoad: 
-
-UseLaunchers: 
-CurlOptions: 
-# warning, if you add new options here that have to do with submit,
-# you have to update cmCTestSubmitCommand.cxx
-
-# For CTest submissions that timeout, these options
-# specify behavior for retrying the submission
-CTestSubmitRetryDelay: 5
-CTestSubmitRetryCount: 3
diff --git a/GALERA_GIT_REVISION b/GALERA_GIT_REVISION
index 0af9857..cc21e0a 100644
--- a/GALERA_GIT_REVISION
+++ b/GALERA_GIT_REVISION
@@ -1 +1 @@
-d54ebf8
\ No newline at end of file
+cece3ba2
\ No newline at end of file
diff --git a/GALERA_REVISION b/GALERA_REVISION
deleted file mode 100644
index 0af9857..0000000
--- a/GALERA_REVISION
+++ /dev/null
@@ -1 +0,0 @@
-d54ebf8
\ No newline at end of file
diff --git a/GALERA_VERSION b/GALERA_VERSION
index 464563b..467dc9f 100644
--- a/GALERA_VERSION
+++ b/GALERA_VERSION
@@ -1,4 +1,4 @@
 GALERA_VERSION_WSREP_API=26
 GALERA_VERSION_MAJOR=4
-GALERA_VERSION_MINOR=8
+GALERA_VERSION_MINOR=9
 GALERA_VERSION_EXTRA=
diff --git a/SConstruct b/SConstruct
index 5e881d3..139da08 100644
--- a/SConstruct
+++ b/SConstruct
@@ -163,7 +163,7 @@ static_ssl = ARGUMENTS.get('static_ssl', None)
 install = ARGUMENTS.get('install', None)
 version_script = int(ARGUMENTS.get('version_script', 1))
 
-GALERA_VER = ARGUMENTS.get('version', '4.8')
+GALERA_VER = ARGUMENTS.get('version', '4.9')
 GALERA_REV = ARGUMENTS.get('revno', 'XXXX')
 
 # Attempt to read from file if not given
diff --git a/cmake/crc32c.cmake b/cmake/crc32c.cmake
index e53c55f..a9100f9 100644
--- a/cmake/crc32c.cmake
+++ b/cmake/crc32c.cmake
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2020 Codership Oy <info@codership.com>
+# Copyright (C) 2020-2021 Codership Oy <info@codership.com>
 #
 
 message(STATUS "Checking for hardware CRC support for ${CMAKE_SYSTEM_PROCESSOR}")
@@ -26,7 +26,38 @@ int main() { __get_cpuid(1, &eax, &ebx, &ecx, &edx); return 0; }
     set(GALERA_CRC32C_X86_64 ON)
   endif()
 elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL aarch64)
-  check_c_compiler_flag(-march=armv8-a+crc HAVE_CRC_FLAG)
+  set(CMAKE_REQUIRED_FLAGS -march=armv8-a+crc)
+  check_c_source_compiles(
+"
+// Here we assume that CPU feature detection and
+// CRC32 support in hardware is the same thing and
+// if the former is not available, the latter is
+// not available as well, so we test for both at
+// the same time
+
+#include <sys/auxv.h>
+#include <arm_acle.h>
+
+int main()
+{
+#if defined(__linux__)
+    (void)getauxval(AT_HWCAP);
+#elif defined(__FreeBSD__)
+    unsigned long info;
+    (void)elf_aux_info(AT_HWCAP, &info, sizeof(info));
+#else
+    #error Hardware feature detection for OS not supported
+#endif
+
+    (void)__crc32b(0, 0);
+    (void)__crc32h(0, 0);
+    (void)__crc32w(0, 0);
+    (void)__crc32d(0, 0);
+
+    return 0;
+}
+" HAVE_CRC_FLAG)
+  unset(CMAKE_REQUIRED_FLAGS)
   if (HAVE_CRC_FLAG)
     set(GALERA_CRC32C_COMPILER_FLAG "-march=armv8-a+crc")
     set(GALERA_CRC32C_ARM64 ON)
diff --git a/debian/changelog b/debian/changelog
index 4473f17..122f747 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,17 @@
+galera-4 (26.4.9-0+deb11u1) bullseye; urgency=medium
+
+  [ Otto Kekäläinen ]
+  * New upstream release 26.4.9. Includes multiple bug fixes, see
+    https://github.com/codership/documentation/blob/master/release-notes/release-notes-galera-26.4.9.txt
+  * Restore CK_TIMEOUT_MULTIPLIER in debian rules to avoid unnecassary
+    test failures due to slow builders
+
+  [ Andreas Beckmann ]
+  * Solve circular Conflicts with galera-3 by no longer providing a virtual
+    galera package (Closes: #990708)
+
+ -- Otto Kekäläinen <otto@debian.org>  Sun, 29 Aug 2021 20:05:11 -0700
+
 galera-4 (26.4.8-1) unstable; urgency=medium
 
   * New upstream release 26.4.8
diff --git a/debian/control b/debian/control
index 832c92e..475eeb3 100644
--- a/debian/control
+++ b/debian/control
@@ -20,9 +20,7 @@ Architecture: any
 Section: libs
 Depends: ${misc:Depends},
          ${shlibs:Depends}
-Conflicts: galera,
-           galera-3,
-           garbd-2,
+Conflicts: garbd-2,
            garbd-3,
            garbd2,
            garbd3,
@@ -34,13 +32,11 @@ Conflicts: galera,
            percona-xtradb-cluster-galera-4.x,
            percona-xtradb-cluster-garbd-2.x,
            percona-xtradb-cluster-garbd-3.x
-Provides: galera,
-          galera4,
+Provides: galera4,
           percona-xtradb-cluster-galera-26,
           wsrep
-Breaks: galera,
-        galera-3
-Replaces: galera
+Breaks: galera-3 (<< 26.4)
+Replaces: galera-3 (<< 26.4)
 Description: Replication framework for transactional applications
  Galera is a fast synchronous multimaster wsrep provider (replication engine)
  for transactional databases and similar applications. For more information
diff --git a/debian/rules b/debian/rules
index aa3981e..afc22f6 100755
--- a/debian/rules
+++ b/debian/rules
@@ -7,6 +7,10 @@ DPKG_EXPORT_BUILDFLAGS = 1
 # Include all defaults, including buildflags.mk
 include /usr/share/dpkg/default.mk
 
+# Set unit test timeout multiplier to make slow tests
+# pass on loaded builders.
+export CK_TIMEOUT_MULTIPLIER=5
+
 override_dh_auto_test:
 	dh_auto_test -O--no-parallel -- ARGS=--output-on-failure
 
diff --git a/galera/src/certification.cpp b/galera/src/certification.cpp
index 5bafa3d..b4f8ac9 100644
--- a/galera/src/certification.cpp
+++ b/galera/src/certification.cpp
@@ -187,10 +187,7 @@ check_against(const galera::KeyEntryNG*   const found,
             }
             /* fall through */
         case DEPENDENCY:
-            if (conflict)
-                depends_seqno = WSREP_SEQNO_UNDEFINED;
-            else
-                depends_seqno = std::max(ref_trx->global_seqno(), depends_seqno);
+            depends_seqno = std::max(ref_trx->global_seqno(), depends_seqno);
             /* fall through */
         case NOTHING:;
         }
@@ -206,6 +203,7 @@ certify_and_depend_v3to5(const galera::KeyEntryNG*   const found,
                          galera::TrxHandleSlave*     const trx,
                          bool                        const log_conflict)
 {
+    bool ret(false);
     wsrep_seqno_t depends_seqno(trx->depends_seqno());
     wsrep_key_type_t const key_type(key.wsrep_type(trx->version()));
 
@@ -237,14 +235,13 @@ certify_and_depend_v3to5(const galera::KeyEntryNG*   const found,
           check_against<WSREP_KEY_SHARED>
           (found, key, key_type, trx, log_conflict, depends_seqno))))
     {
-        return true;
-    }
-    else
-    {
-        if (depends_seqno > trx->depends_seqno())
-            trx->set_depends_seqno(depends_seqno);
-        return false;
+        ret = true;
     }
+
+    if (depends_seqno > trx->depends_seqno())
+        trx->set_depends_seqno(depends_seqno);
+
+    return ret;
 }
 
 /* returns true on collision, false otherwise */
@@ -378,6 +375,7 @@ galera::Certification::do_test_v3to5(TrxHandleSlave* trx, bool store_keys)
 
         if (certify_v3to5(cert_index_ng_, key, trx, store_keys, log_conflicts_))
         {
+            trx->set_depends_seqno(std::max(trx->depends_seqno(), last_pa_unsafe_));
             goto cert_fail;
         }
     }
@@ -495,8 +493,6 @@ galera::Certification::do_test(const TrxHandleSlavePtr& trx, bool store_keys)
                        << version_ << " not implemented";
     }
 
-    assert(TEST_FAILED == res || trx->depends_seqno() >= 0);
-
     if (store_keys == true && res == TEST_OK)
     {
         ++trx_count_;
@@ -1141,8 +1137,6 @@ galera::Certification::test(const TrxHandleSlavePtr& trx, bool store_keys)
         (trx->preordered() ?
          do_test_preordered(trx.get()) : do_test(trx, store_keys));
 
-    assert(TEST_FAILED == ret || trx->depends_seqno() >= 0);
-
     if (gu_unlikely(ret != TEST_OK)) { trx->mark_dummy(); }
 
     return ret;
diff --git a/galera/src/certification.hpp b/galera/src/certification.hpp
index 342b367..3f3d903 100644
--- a/galera/src/certification.hpp
+++ b/galera/src/certification.hpp
@@ -207,7 +207,7 @@ namespace galera
                     // NBO certification depends seqno is set to
                     // WSREP_SEQNO_UNDEFINED. Therefore purge should always
                     // be done for TOI write sets.
-                    if (trx->depends_seqno() >= 0 || trx->is_toi() == true)
+                    if (trx->is_dummy() == false || trx->is_toi() == true)
                     {
                         cert_.purge_for_trx(trx);
                     }
diff --git a/galera/src/key_set.cpp b/galera/src/key_set.cpp
index df4b77f..55f78b8 100644
--- a/galera/src/key_set.cpp
+++ b/galera/src/key_set.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2013-2018 Codership Oy <info@codership.com>
+// Copyright (C) 2013-2021 Codership Oy <info@codership.com>
 //
 
 #include "key_set.hpp"
@@ -151,28 +151,50 @@ KeySet::KeyPart::print_annotation(std::ostream& os, const gu::byte_t* buf)
 void
 KeySet::KeyPart::throw_buffer_too_short (size_t expected, size_t got)
 {
-    gu_throw_error (EINVAL) << "Buffer too short: expected "
-                            << expected << ", got " << got;
+#ifndef NDEBUG
+    log_fatal
+#else
+    gu_throw_error(EINVAL)
+#endif /* NDEBUG */
+        << "Buffer too short: expected " << expected << ", got " << got;
+    assert(0);
 }
 
 void
 KeySet::KeyPart::throw_bad_type_version (wsrep_key_type_t t, int v)
 {
-    gu_throw_error(EINVAL) << "Internal program error: wsrep key type: " << t
-                           << ", writeset version: " << v;
+#ifndef NDEBUG
+    log_fatal
+#else
+    gu_throw_error(EINVAL)
+#endif /* NDEBUG */
+        << "Internal program error: wsrep key type: " << t
+        << ", writeset version: " << v;
+    assert(0);
 }
 
 void
 KeySet::KeyPart::throw_bad_prefix (gu::byte_t p)
 {
-    gu_throw_error(EPROTO) << "Unsupported key prefix: " << int(p);
+#ifndef NDEBUG
+    log_fatal
+#else
+    gu_throw_error(EPROTO)
+#endif /* NDEBUG */
+        << "Unsupported key prefix: " << int(p);
+    assert(0);
 }
 
 void
 KeySet::KeyPart::throw_match_empty_key (Version my, Version other)
 {
-    gu_throw_error(EINVAL) << "Attempt to match against an empty key ("
-                           << my << ',' << other << ')';
+#ifndef NDEBUG
+    log_fatal
+#else
+    gu_throw_error(EINVAL)
+#endif /* NDEBUG */
+        << "Attempt to match against an empty key (" << my << ',' << other <<')';
+    assert(0);
 }
 
 void
diff --git a/galera/src/monitor.hpp b/galera/src/monitor.hpp
index 2310196..8f6e959 100644
--- a/galera/src/monitor.hpp
+++ b/galera/src/monitor.hpp
@@ -64,7 +64,8 @@ namespace galera
             entered_(0),
             oooe_(0),
             oool_(0),
-            win_size_(0)
+            win_size_(0),
+            waits_(0)
         { }
 
         ~Monitor()
@@ -158,6 +159,7 @@ namespace galera
                 while (may_enter(obj) == false &&
                        process_[idx].state_ == Process::S_WAITING)
                 {
+                    ++waits_;
                     lock.wait(process_[idx].cond_);
                 }
 
@@ -361,7 +363,8 @@ namespace galera
             }
         }
 
-        void get_stats(double* oooe, double* oool, double* win_size) const
+        void get_stats(double* oooe, double* oool, double* win_size,
+                       long long* waits) const
         {
             gu::Lock lock(mutex_);
 
@@ -375,12 +378,13 @@ namespace galera
             {
                 *oooe = .0; *oool = .0; *win_size = .0;
             }
+            *waits = waits_;
         }
 
         void flush_stats()
         {
             gu::Lock lock(mutex_);
-            oooe_ = 0; oool_ = 0; win_size_ = 0; entered_ = 0;
+            oooe_ = 0; oool_ = 0; win_size_ = 0; entered_ = 0; waits_ = 0;
         }
 
     private:
@@ -547,6 +551,9 @@ namespace galera
         long oooe_;     // out of order entered
         long oool_;     // out of order left
         long win_size_; // window between last_left_ and last_entered_
+        // Total number of waits in the monitor. Incremented before
+        // entering into waiting state.
+        long long waits_;
     };
 }
 
diff --git a/galera/src/replicator_smm.cpp b/galera/src/replicator_smm.cpp
index 2e395c7..1078fee 100644
--- a/galera/src/replicator_smm.cpp
+++ b/galera/src/replicator_smm.cpp
@@ -993,7 +993,7 @@ wsrep_status_t galera::ReplicatorSMM::certify(TrxHandleMaster&  trx,
             /* committing fragment fails certification or non-committing BF'ed */
             // If the ts was queued, the depends seqno cannot be trusted
             // as it may be modified concurrently.
-            assert(ts->queued() || ts->depends_seqno() < 0 ||
+            assert(ts->queued() || ts->is_dummy() ||
                    (ts->flags() & TrxHandle::F_COMMIT) == 0);
             assert(ts->state() == TrxHandle::S_CERTIFYING ||
                    ts->state() == TrxHandle::S_REPLICATING);
@@ -1066,18 +1066,10 @@ wsrep_status_t galera::ReplicatorSMM::replay_trx(TrxHandleMaster& trx,
     case TrxHandle::S_CERTIFYING:
     {
         assert(ts.state() == TrxHandle::S_CERTIFYING);
-        // safety measure to make sure that all preceding trxs finish before
-        // replaying
-        wsrep_seqno_t const ds(ts.depends_seqno());
-        ts.set_depends_seqno(ts.global_seqno() - 1);
 
         ApplyOrder ao(ts);
         assert(apply_monitor_.entered(ao) == false);
         gu_trace(apply_monitor_.enter(ao));
-
-        // restore dependency info
-        ts.set_depends_seqno(WSREP_SEQNO_UNDEFINED);
-        ts.set_depends_seqno(ds);
         TX_SET_STATE(ts, TrxHandle::S_APPLYING);
     }
     // fall through
@@ -1089,6 +1081,10 @@ wsrep_status_t galera::ReplicatorSMM::replay_trx(TrxHandleMaster& trx,
     case TrxHandle::S_COMMITTING:
         ++local_replays_;
 
+        // safety measure to make sure that all preceding trxs are
+        // ordered for commit before replaying
+        commit_monitor_.wait(ts.global_seqno() - 1);
+
         TX_SET_STATE(trx, TrxHandle::S_REPLAYING);
         try
         {
@@ -3274,7 +3270,7 @@ wsrep_status_t galera::ReplicatorSMM::handle_local_monitor_interrupted(
     }
     else
     {
-        assert(WSREP_SEQNO_UNDEFINED == ts->depends_seqno());
+        assert(ts->is_dummy());
         pending_cert_queue_.push(ts);
     }
 
@@ -3330,9 +3326,10 @@ wsrep_status_t galera::ReplicatorSMM::finish_cert(
         {
             retval = WSREP_OK;
         }
-        assert(ts->depends_seqno() >= 0);
+        assert(!ts->is_dummy());
         break;
     case Certification::TEST_FAILED:
+        assert(ts->is_dummy());
         if (ts->nbo_end()) assert(ts->ends_nbo() == WSREP_SEQNO_UNDEFINED);
         local_cert_failures_ += ts->local();
         if (trx != 0) TX_SET_STATE(*trx, TrxHandle::S_ABORTING);
@@ -3350,7 +3347,7 @@ wsrep_status_t galera::ReplicatorSMM::finish_cert(
 
     // we must do seqno assignment 'in order' for std::map reasons,
     // so keeping it inside the monitor. NBO end should never be skipped.
-    bool const skip(ts->depends_seqno() < 0 && !ts->nbo_end());
+    bool const skip(ts->is_dummy() && !ts->nbo_end());
     gcache_.seqno_assign (ts->action().first, ts->global_seqno(),
                           GCS_ACT_WRITESET, skip);
 
diff --git a/galera/src/replicator_smm_params.cpp b/galera/src/replicator_smm_params.cpp
index dd4be44..b29545e 100644
--- a/galera/src/replicator_smm_params.cpp
+++ b/galera/src/replicator_smm_params.cpp
@@ -197,7 +197,15 @@ galera::ReplicatorSMM::param_set (const std::string& key,
 {
     try
     {
+#ifdef GALERA_HAVE_SSL
+        // Param `socket.ssl_reload` is used as trigger. We should
+        // skip checking if value is changed.
+        if (key != gu::conf::ssl_reload) {
+#endif
         if (config_.get(key) == value) return;
+#ifdef GALERA_HAVE_SSL
+        }
+#endif
     }
     catch (gu::NotSet&) {}
 
diff --git a/galera/src/replicator_smm_stats.cpp b/galera/src/replicator_smm_stats.cpp
index 1451fdc..6b0ce16 100644
--- a/galera/src/replicator_smm_stats.cpp
+++ b/galera/src/replicator_smm_stats.cpp
@@ -100,6 +100,7 @@ typedef enum status_vars
     STATS_APPLY_OOOE,
     STATS_APPLY_OOOL,
     STATS_APPLY_WINDOW,
+    STATS_APPLY_WAITS,
     STATS_COMMIT_OOOE,
     STATS_COMMIT_OOOL,
     STATS_COMMIT_WINDOW,
@@ -150,6 +151,7 @@ static const struct wsrep_stats_var wsrep_stats[STATS_MAX + 1] =
     { "apply_oooe",               WSREP_VAR_DOUBLE, { 0 }  },
     { "apply_oool",               WSREP_VAR_DOUBLE, { 0 }  },
     { "apply_window",             WSREP_VAR_DOUBLE, { 0 }  },
+    { "apply_waits",              WSREP_VAR_INT64,  { 0 }  },
     { "commit_oooe",              WSREP_VAR_DOUBLE, { 0 }  },
     { "commit_oool",              WSREP_VAR_DOUBLE, { 0 }  },
     { "commit_window",            WSREP_VAR_DOUBLE, { 0 }  },
@@ -236,13 +238,14 @@ galera::ReplicatorSMM::stats_get() const
     double oooe;
     double oool;
     double win;
-    apply_monitor_.get_stats(&oooe, &oool, &win);
+    long long waits;
+    apply_monitor_.get_stats(&oooe, &oool, &win, &waits);
 
     sv[STATS_APPLY_OOOE          ].value._double = oooe;
     sv[STATS_APPLY_OOOL          ].value._double = oool;
     sv[STATS_APPLY_WINDOW        ].value._double = win;
-
-    commit_monitor_.get_stats(&oooe, &oool, &win);
+    sv[STATS_APPLY_WAITS         ].value._int64 = waits;
+    commit_monitor_.get_stats(&oooe, &oool, &win, &waits);
 
     sv[STATS_COMMIT_OOOE         ].value._double = oooe;
     sv[STATS_COMMIT_OOOL         ].value._double = oool;
diff --git a/galera/src/replicator_str.cpp b/galera/src/replicator_str.cpp
index 12acfa2..2f9fdf2 100644
--- a/galera/src/replicator_str.cpp
+++ b/galera/src/replicator_str.cpp
@@ -991,7 +991,7 @@ ReplicatorSMM::request_state_transfer (void* recv_ctx,
         else
         {
             log_fatal << "Application state is corrupt and cannot "
-                      << "be recorvered. Restart required.";
+                      << "be recovered. Restart required.";
             abort();
         }
     }
@@ -1117,7 +1117,15 @@ void ReplicatorSMM::process_IST_writeset(void* recv_ctx,
         assert(ts.is_dummy());
     }
 
-    gu_trace(apply_trx(recv_ctx, ts));
+    try
+    {
+        apply_trx(recv_ctx, ts);
+    }
+    catch (...)
+    {
+        st_.mark_corrupt();
+        throw;
+    }
     GU_DBUG_SYNC_WAIT("recv_IST_after_apply_trx");
 
     if (gu_unlikely
@@ -1204,7 +1212,8 @@ void ReplicatorSMM::recv_IST(void* recv_ctx)
 
         log_fatal << os.str();
 
-        mark_corrupt_and_close();
+        gu::Lock lock(closing_mutex_);
+        start_closing();
     }
 }
 
diff --git a/galera/src/trx_handle.hpp b/galera/src/trx_handle.hpp
index cb6c623..3bf131f 100644
--- a/galera/src/trx_handle.hpp
+++ b/galera/src/trx_handle.hpp
@@ -639,7 +639,6 @@ namespace galera
 
         void mark_dummy()
         {
-            set_depends_seqno(WSREP_SEQNO_UNDEFINED);
             set_flags(flags() | F_ROLLBACK);
         }
 
diff --git a/galera/tests/certification_check.cpp b/galera/tests/certification_check.cpp
index 9abbba5..82029d8 100644
--- a/galera/tests/certification_check.cpp
+++ b/galera/tests/certification_check.cpp
@@ -193,7 +193,7 @@ START_TEST(test_certification_trx_v3)
         // 6: collides with 5
         { { {1, } }, 1, 6,
           { {void_cast("1"), 1}, {void_cast("1"), 1}, {void_cast("1"), 1} }, 3, true,
-          6, 6, 4, -1, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
+          6, 6, 4, 5, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
           Certification::TEST_FAILED, {0}, 0},
         // 7: depends on 5
         { { {2, } }, 1, 7,
@@ -203,7 +203,7 @@ START_TEST(test_certification_trx_v3)
         // 8: collides with 5
         { { {1, } }, 1, 8,
           { {void_cast("1"), 1}, {void_cast("1"), 1}, {void_cast("1"), 1}}, 3, true,
-          8, 8, 4, -1, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
+          8, 8, 4, 5, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
           Certification::TEST_FAILED, {0}, 0},
         // 9 - 10: shared key shadows dependency to 5
         // 9: depends on 5
@@ -232,7 +232,7 @@ START_TEST(test_certification_trx_v3)
         // 14: conflicts with 13
         { { {1, } }, 1, 14,
           { {void_cast("1"), 1}, {void_cast("1"), 1}, {void_cast("1"), 1}}, 3, false,
-          14, 14, 12, -1, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
+          14, 14, 12, 13, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
           Certification::TEST_FAILED, {0}, 0}
     };
 
@@ -272,7 +272,7 @@ START_TEST(test_certification_trx_different_level_v3)
           Certification::TEST_OK, {0}, 0},
         { { {1, } }, 1, 1,
           { {void_cast("1"), 1}, {void_cast("1"), 1}, {void_cast("1"), 1} }, 3, false,
-          4, 4, 2, -1, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
+          4, 4, 2, 3, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
           Certification::TEST_FAILED, {0}, 0}
     };
 
@@ -320,7 +320,7 @@ START_TEST(test_certification_toi_v3)
         // Trx 4 from different source conflicts with 3
         { { {3, } }, 3, 3,
           { {void_cast("1"), 1}, {void_cast("1"), 1}, {void_cast("1"), 1}}, 3, false,
-          4, 4, 2, -1,
+          4, 4, 2, 3,
           TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
           Certification::TEST_FAILED, {0}, 0},
         // Non conflicting TOI 5 depends on 4
@@ -332,7 +332,7 @@ START_TEST(test_certification_toi_v3)
         // Trx 6 from different source conflicts with TOI 5
         { { {3, } }, 3, 3,
           { {void_cast("2"), 1}, {void_cast("1"), 1}, {void_cast("1"), 1}}, 3, false,
-          6, 6, 4, -1,
+          6, 6, 4, 5,
           TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
           Certification::TEST_FAILED, {0}, 0}
     };
@@ -366,12 +366,12 @@ START_TEST(test_certification_nbo)
           Certification::TEST_OK, {0}, 0},
         { { {1, } }, 2, 2,
           { {void_cast("1"), 1}, }, 1, false,
-          2, 2, 0, -1,
+          2, 2, 0, 1,
           TrxHandle::F_ISOLATION | TrxHandle::F_BEGIN | TrxHandle::F_COMMIT,
           Certification::TEST_FAILED, {0}, 0},
         { { {1, } }, 3, 3,
           { {void_cast("1"), 1}, }, 1, false,
-          3, 3, 0, -1,
+          3, 3, 0, 2,
           TrxHandle::F_ISOLATION | TrxHandle::F_BEGIN,
           Certification::TEST_FAILED, {0}, 0},
         // 4 - 5 no conflict, different key
@@ -446,7 +446,7 @@ START_TEST(test_certification_commit_fragment)
           Certification::TEST_OK, {0}, 0},
         { { {1, } }, 1, 1,
           { {void_cast("1"), 1}, {void_cast("1"), 1} }, 2, true,
-          4, 4, 2, -1, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT | TrxHandle::F_PA_UNSAFE,
+          4, 4, 2, 3, TrxHandle::F_BEGIN | TrxHandle::F_COMMIT | TrxHandle::F_PA_UNSAFE,
           Certification::TEST_FAILED, {0}, 0},
 
         // commit fragment vs TOI
diff --git a/galerautils/src/gu_asio.cpp b/galerautils/src/gu_asio.cpp
index e98f73f..91bba1d 100644
--- a/galerautils/src/gu_asio.cpp
+++ b/galerautils/src/gu_asio.cpp
@@ -557,6 +557,7 @@ void gu::ssl_init_options(gu::Config& conf)
     if (use_ssl == true)
     {
         // set defaults
+        conf.set(conf::ssl_reload, 1);
 
         // cipher list
         const std::string cipher_list(conf.get(conf::ssl_cipher, ""));
diff --git a/galerautils/src/gu_asio_stream_react.cpp b/galerautils/src/gu_asio_stream_react.cpp
index f3a5b55..d99427d 100644
--- a/galerautils/src/gu_asio_stream_react.cpp
+++ b/galerautils/src/gu_asio_stream_react.cpp
@@ -715,14 +715,19 @@ gu::AsioAcceptorReact::AsioAcceptorReact(AsioIoService& io_service,
     , engine_()
 { }
 
-void gu::AsioAcceptorReact::open(const gu::URI& uri)
+void gu::AsioAcceptorReact::open(const gu::URI& uri) try
 {
     auto resolve_result(resolve_tcp(io_service_.impl().native(), uri));
     acceptor_.open(resolve_result->endpoint().protocol());
     set_fd_options(acceptor_);
 }
+catch (const asio::system_error& e)
+{
+    gu_throw_error(e.code().value()) << "Failed to open acceptor: " << e.what();
+}
 
-void gu::AsioAcceptorReact::listen(const gu::URI& uri)
+
+void gu::AsioAcceptorReact::listen(const gu::URI& uri) try
 {
     auto resolve_result(resolve_tcp(io_service_.impl().native(), uri));
     if (not acceptor_.is_open())
@@ -736,8 +741,12 @@ void gu::AsioAcceptorReact::listen(const gu::URI& uri)
     acceptor_.listen();
     listening_ = true;
 }
+catch (const asio::system_error& e)
+{
+    gu_throw_error(e.code().value()) << "Failed to listen: " << e.what();
+}
 
-void gu::AsioAcceptorReact::close()
+void gu::AsioAcceptorReact::close() try
 {
     if (acceptor_.is_open())
     {
@@ -745,10 +754,16 @@ void gu::AsioAcceptorReact::close()
     }
     listening_ = false;
 }
+catch (const asio::system_error& e)
+{
+    gu_throw_error(e.code().value()) << "Failed to close acceptor: "
+                                     << e.what();
+}
+
 
 void gu::AsioAcceptorReact::async_accept(
     const std::shared_ptr<AsioAcceptorHandler>& handler,
-    const std::shared_ptr<AsioStreamEngine>& engine)
+    const std::shared_ptr<AsioStreamEngine>& engine) try
 {
     GU_ASIO_DEBUG(this << " AsioAcceptorReact::async_accept: " << listen_addr());
     auto new_socket(std::make_shared<AsioStreamReact>(
@@ -761,8 +776,13 @@ void gu::AsioAcceptorReact::async_accept(
                                        asio::placeholders::error));
 
 }
+catch (const asio::system_error& e)
+{
+    gu_throw_error(e.code().value()) << "Failed to accept: " << e.what();
+}
+
 
-std::shared_ptr<gu::AsioSocket> gu::AsioAcceptorReact::accept()
+std::shared_ptr<gu::AsioSocket> gu::AsioAcceptorReact::accept() try
 {
     auto socket(std::make_shared<AsioStreamReact>(io_service_, scheme_,
                                                   nullptr));
@@ -787,6 +807,10 @@ std::shared_ptr<gu::AsioSocket> gu::AsioAcceptorReact::accept()
     }
     return socket;
 }
+catch (const asio::system_error& e)
+{
+    gu_throw_error(e.code().value()) << "Failed to accept: " << e.what();
+}
 
 std::string gu::AsioAcceptorReact::listen_addr() const try
 {
diff --git a/galerautils/tests/gu_asio_test.cpp b/galerautils/tests/gu_asio_test.cpp
index f1af7a4..a76022c 100644
--- a/galerautils/tests/gu_asio_test.cpp
+++ b/galerautils/tests/gu_asio_test.cpp
@@ -383,6 +383,29 @@ START_TEST(test_tcp_acceptor_listen)
 }
 END_TEST
 
+START_TEST(test_tcp_acceptor_listen_already_bound)
+{
+    gu::AsioIoService io_service;
+    gu::URI uri("tcp://127.0.0.1:0");
+    auto acceptor_handler(std::make_shared<MockAcceptorHandler>());
+    auto acceptor(io_service.make_acceptor(uri));
+    acceptor->listen(uri);
+    auto listen_addr(acceptor->listen_addr());
+    ck_assert(listen_addr.find("tcp://127.0.0.1") != std::string::npos);
+
+    auto acceptor2(io_service.make_acceptor(acceptor->listen_addr()));
+    try
+    {
+        acceptor2->listen(acceptor->listen_addr());
+        ck_abort_msg("Exception not thrown for address already in use");
+    }
+    catch (const gu::Exception& e)
+    {
+        ck_assert(e.get_errno() == EADDRINUSE);
+    }
+}
+END_TEST
+
 START_TEST(test_tcp_acceptor_receive_buffer_size_unopened)
 {
     gu::AsioIoService io_service;
@@ -2032,6 +2055,10 @@ Suite* gu_asio_suite()
     tcase_add_test(tc, test_tcp_acceptor_listen);
     suite_add_tcase(s, tc);
 
+    tc = tcase_create("test_tcp_acceptor_listen_already_bound");
+    tcase_add_test(tc, test_tcp_acceptor_listen_already_bound);
+    suite_add_tcase(s, tc);
+
     tc = tcase_create("test_tcp_acceptor_receive_buffer_size_unopened");
     tcase_add_test(tc, test_tcp_acceptor_receive_buffer_size_unopened);
     suite_add_tcase(s, tc);
@@ -2275,6 +2302,11 @@ Suite* gu_asio_suite()
     tcase_add_test(tc, test_datagram_open_connect);
     suite_add_tcase(s, tc);
 
+    tc = tcase_create("test_datagram_send_to_and_async_read");
+    tcase_add_test(tc, test_datagram_send_to_and_async_read);
+    suite_add_tcase(s, tc);
+
+#if defined(GALERA_ASIO_TEST_MULTICAST)
     tc = tcase_create("test_datagram_connect_multicast");
     tcase_add_test(tc, test_datagram_connect_multicast);
     suite_add_tcase(s, tc);
@@ -2283,22 +2315,19 @@ Suite* gu_asio_suite()
     tcase_add_test(tc, test_datagram_connect_multicast_local_if);
     suite_add_tcase(s, tc);
 
-    tc = tcase_create("test_datagram_send_to_and_async_read");
-    tcase_add_test(tc, test_datagram_send_to_and_async_read);
-    suite_add_tcase(s, tc);
-
-#if defined(__FreeBSD__)
-    /* fails on FreeBSD with EADDRNOTAVAIL, disable temporarily */
-    (void)test_datagram_send_to_and_async_read_multicast;
-#else
     tc = tcase_create("test_datagram_send_to_and_async_read_multicast");
     tcase_add_test(tc, test_datagram_send_to_and_async_read_multicast);
     suite_add_tcase(s, tc);
-#endif /* FreeBSD */
 
     tc = tcase_create("test_datagram_write_multicast");
     tcase_add_test(tc, test_datagram_write_multicast);
     suite_add_tcase(s, tc);
+#else
+    (void)test_datagram_connect_multicast;
+    (void)test_datagram_connect_multicast_local_if;
+    (void)test_datagram_send_to_and_async_read_multicast;
+    (void)test_datagram_write_multicast;
+#endif /* GALERA_ASIO_TEST_MULTICAST */
 
     //
     // Steady timer
diff --git a/gcache/src/GCache_memops.cpp b/gcache/src/GCache_memops.cpp
index 865cbff..fa333d3 100644
--- a/gcache/src/GCache_memops.cpp
+++ b/gcache/src/GCache_memops.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2020 Codership Oy <info@codership.com>
+ * Copyright (C) 2009-2021 Codership Oy <info@codership.com>
  */
 
 #include "GCache.hpp"
@@ -29,7 +29,7 @@ namespace gcache
 #ifndef NDEBUG
         seqno_t const begin(params.debug() ?
                             (seqno2ptr.empty() ?
-                             seqno2ptr.index_begin() : SEQNO_NONE) : SEQNO_NONE);
+                             SEQNO_NONE : seqno2ptr.index_begin()) : SEQNO_NONE);
         if (params.debug())
         {
             assert(begin > 0);
@@ -181,13 +181,6 @@ namespace gcache
         }
         rb.assert_size_free();
 
-#ifndef NDEBUG
-        if (params.debug())
-        {
-            log_info << "GCache::free_common(): seqno_released: "
-                     << seqno_released << " -> " << new_released;
-        }
-#endif
         seqno_released = new_released;
     }
 
@@ -201,8 +194,16 @@ namespace gcache
 
 #ifndef NDEBUG
             if (params.debug()) { log_info << "GCache::free() " << bh; }
+            seqno_t const old_sr(seqno_released);
 #endif
             free_common (bh);
+#ifndef NDEBUG
+            if (params.debug())
+            {
+                log_info << "GCache::free() seqno_released: "
+                         << old_sr << " -> " << seqno_released;
+            }
+#endif
         }
         else {
             log_warn << "Attempt to free a null pointer";
diff --git a/gcache/src/GCache_seqno.cpp b/gcache/src/GCache_seqno.cpp
index 5fdec4f..28adc40 100644
--- a/gcache/src/GCache_seqno.cpp
+++ b/gcache/src/GCache_seqno.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2020 Codership Oy <info@codership.com>
+ * Copyright (C) 2009-2021 Codership Oy <info@codership.com>
  */
 
 #include "gcache_bh.hpp"
@@ -169,13 +169,25 @@ namespace gcache
         size_t old_gap(-1);
         int    batch_size(min_batch_size);
 
-        bool   loop(seqno >= seqno_released);
+        bool   loop(true);
 
         while(loop)
         {
             gu::Lock lock(mtx);
 
-            assert(seqno >= seqno_released);
+            if (seqno < seqno_released || seqno >= seqno_locked)
+            {
+#ifndef NDEBUG
+                if (params.debug())
+                {
+                    log_info << "GCache::seqno_release(" << seqno
+                             << "): seqno_released: " << seqno_released
+                             << ", seqno_locked: " << seqno_locked
+                             << ": exiting.";
+                }
+#endif
+                break;
+            }
 
             seqno_t idx(seqno2ptr.upper_bound(seqno_released));
 
@@ -211,6 +223,7 @@ namespace gcache
                          << (seqno - start) << " buffers, batch_size: "
                          << batch_size << ", end: " << end;
             }
+            seqno_t const old_sr(seqno_released);
 #endif
             while((loop = (idx < seqno2ptr.index_end())) && idx <= end)
             {
@@ -242,6 +255,14 @@ namespace gcache
 
             loop = (end < seqno) && loop;
 
+#ifndef NDEBUG
+            if (params.debug())
+            {
+                log_info << "GCache::seqno_release(" << seqno
+                         << ") seqno_released: "
+                         << old_sr << " -> " << seqno_released;
+            }
+#endif
             /* if we're doing this loop repeatedly, allow other threads to run*/
             if (loop) sched_yield();
         }
diff --git a/gcache/src/gcache_rb_store.cpp b/gcache/src/gcache_rb_store.cpp
index 26163eb..d9d4aaf 100644
--- a/gcache/src/gcache_rb_store.cpp
+++ b/gcache/src/gcache_rb_store.cpp
@@ -723,22 +723,9 @@ namespace gcache
                 if (gu_likely(seqno_g > 0))
                 {
                     bool const collision(
-                        seqno_g > seqno_max
-                        ?
-                        (
-                            seqno_max = seqno_g,
-                            seqno2ptr_.insert(seqno_g, bh + 1), false
-                        )
-                        :
-                        (
-                            (seqno_g >= seqno2ptr_.index_begin() &&
-                             seqno2ptr_[seqno_g])
-                            ?
-                            true /* already exists */
-                            :
-                            (seqno2ptr_.insert(seqno_g, bh + 1), false)
-                         )
-                    );
+                        seqno_g <= seqno_max &&
+                        seqno_g >= seqno2ptr_.index_begin() &&
+                        seqno2ptr_[seqno_g] != seqno2ptr_t::null_value());
 
                     if (gu_unlikely(collision))
                     {
@@ -805,6 +792,26 @@ namespace gcache
                             log_info << "Contents differ. Discarding both.";
                         }
                     }
+                    else
+                    {
+                        try
+                        {
+                            seqno2ptr_.insert(seqno_g, bh + 1);
+                        }
+                        catch (std::exception& e)
+                        {
+                            seqno_t const sb(seqno2ptr_.empty() ? SEQNO_ILL :
+                                             seqno2ptr_.index_begin());
+                            seqno_t const se(seqno2ptr_.empty() ? SEQNO_ILL :
+                                             seqno2ptr_.index_end());
+                            log_warn << "Exception while mapping writeset "
+                                     << seqno_g << " into [" << sb << ", " << se
+                                     << "): '" << e.what()
+                                     << "'. Aborting GCache recovery.";
+                            goto out;
+                        }
+                        seqno_max = std::max(seqno_g, seqno_max);
+                    }
                 }
 
                 progress.update(bh->size);
@@ -894,7 +901,7 @@ namespace gcache
             }
 #undef GCACHE_SCAN_BUFFER_TEST
         } // while (segment_scans < 2)
-
+    out:
         progress.finish();
 
         return erase_up_to;
diff --git a/gcs/src/gcs.cpp b/gcs/src/gcs.cpp
index 11597ae..177c203 100644
--- a/gcs/src/gcs.cpp
+++ b/gcs/src/gcs.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2020 Codership Oy <info@codership.com>
+ * Copyright (C) 2008-2021 Codership Oy <info@codership.com>
  *
  * $Id$
  */
@@ -713,7 +713,8 @@ _release_flow_control (gcs_conn_t* conn)
 static void
 gcs_become_primary (gcs_conn_t* conn)
 {
-    assert(conn->join_gtid.seqno() == GCS_SEQNO_ILL ||
+    assert(conn->join_gtid.seqno() <= 0      ||
+           conn->state == GCS_CONN_PRIMARY   ||
            conn->state == GCS_CONN_JOINER    ||
            conn->state == GCS_CONN_OPEN /* joiner that has received NON_PRIM */);
 
@@ -1787,6 +1788,12 @@ long gcs_caused(gcs_conn_t* conn, gu::GTID& gtid)
     return gcs_core_caused(conn->core, gtid);
 }
 
+static inline bool
+fc_active(gcs_conn_t* conn)
+{
+    return conn->stop_count > 0;
+}
+
 /* Puts action in the send queue and returns after it is replicated */
 long gcs_replv (gcs_conn_t*          const conn,      //!<in
                 const struct gu_buf* const act_in,    //!<in
@@ -1828,9 +1835,8 @@ long gcs_replv (gcs_conn_t*          const conn,      //!<in
             // if (conn->state >= GCS_CONN_CLOSE) or (act_ptr == NULL)
             // ret will be -ENOTCONN
             if ((ret = -EAGAIN,
-                 conn->upper_limit >= conn->queue_len ||
-                 act->type         != GCS_ACT_WRITESET)         &&
-                (ret = -ENOTCONN, GCS_CONN_OPEN >= conn->state) &&
+                 !fc_active(conn) || act->type != GCS_ACT_WRITESET) &&
+                (ret = -ENOTCONN, GCS_CONN_OPEN >= conn->state)     &&
                 (act_ptr = (struct gcs_repl_act**)gcs_fifo_lite_get_tail (conn->repl_q)))
             {
                 *act_ptr = &repl_act;
@@ -2325,7 +2331,7 @@ gcs_get_stats (gcs_conn_t* conn, struct gcs_stats* stats)
     stats->fc_ssent    = conn->stats_fc_stop_sent;
     stats->fc_csent    = conn->stats_fc_cont_sent;
     stats->fc_received = conn->stats_fc_received;
-    stats->fc_active   = conn->stop_count > 0;
+    stats->fc_active   = fc_active(conn);
     stats->fc_requested= conn->stop_sent_ > 0;
 }
 
diff --git a/scripts/packages/codership-galera.spec b/scripts/packages/codership-galera.spec
deleted file mode 100644
index 6f9ef98..0000000
--- a/scripts/packages/codership-galera.spec
+++ /dev/null
@@ -1,375 +0,0 @@
-# Copyright (c) 2011-2020, Codership Oy <info@codership.com>.
-# All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License or later.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; see the file COPYING. If not, write to the
-# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
-# MA  02110-1301  USA.
-
-# If without_crypto == 1, the library will be built without
-# SSL/TLS support.
-%{!?without_crypto: %global without_crypto 0}
-
-%define name galera-4
-%define wsrep_api 26
-%{!?version: %define version 26.4.8}
-%{!?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}
-%define docs /usr/share/doc/%{name}
-
-# Avoid debuginfo RPMs, leaves binaries unstripped
-
-%global _enable_debug_package 0
-%global debug_package %{nil}
-%global __os_install_post /usr/lib/rpm/brp-compress %{nil}
-%define ssl_package_devel openssl-devel
-# Define dist tag if not given by platform
-
-# For suse versions see:
-# https://en.opensuse.org/openSUSE:Build_Service_cross_distribution_howto
-%if 0%{?suse_version} == 1110
-%define dist .sle11
-%endif
-%if 0%{?suse_version} == 1310
-%define dist .suse13.1
-%endif
-%if 0%{?suse_version} == 1315
-%define dist .sle12
-%endif
-%if 0%{?suse_version} == 1320
-%define dist .suse13.2
-%endif
-%if 0%{?sle_version} == 150000 && 0%{?is_opensuse}
-%define dist .lp151
-%define ssl_package_devel libopenssl-devel
-%endif
-%if 0%{?sle_version} == 120500 && !0%{?is_opensuse}
-%define dist .sl12
-%endif
-%if 0%{?sle_version} == 150000 && !0%{?is_opensuse}
-%define dist .sl15
-%define ssl_package_devel libopenssl-devel
-%endif
-%if 0%{?sle_version} == 150100 && !0%{?is_opensuse}
-%define dist .sl15_1
-%define ssl_package_devel libopenssl-devel
-%endif
-%if 0%{?sle_version} == 150200 && !0%{?is_opensuse}
-%define dist .sl15_2
-%define ssl_package_devel libopenssl-devel
-%endif
-
-
-
-
-Name:          %{name}
-Summary:       Galera: a synchronous multi-master wsrep provider (replication engine)
-Group:         System Environment/Libraries
-Version:       %{version}
-Release:       %{release}%{dist}
-License:       GPL-2.0
-Source:        %{name}-%{version}.tar.gz
-URL:           http://www.codership.com/
-Packager:      Codership Oy
-Vendor:        Codership Oy
-
-BuildRoot:     %{_tmppath}/%{name}_%{version}-build
-
-BuildRequires: boost-devel >= 1.41
-BuildRequires: check-devel
-BuildRequires: glibc-devel
-BuildRequires: %{ssl_package_devel}
-BuildRequires: cmake
-
-%if 0%{?suse_version} == 1110
-# On SLES11 SPx use the linked gcc47 to build instead of default gcc43
-BuildRequires: gcc47 gcc47-c++
-# On SLES11 SP2 the libgfortran.3.so provider must be explicitly defined
-BuildRequires: libgfortran3
-# On SLES11 we got error "conflict for provider of libgcc_s1 >= 4.7.4_20140612-2.1
-# needed by gcc47, (provider libgcc_s1 conflicts with installed libgcc43),
-# conflict for provider of libgomp1 >= 4.7.4_20140612-2.1 needed by gcc47,
-# (provider libgomp1 conflicts with installed libgomp43), conflict for provider
-# of libstdc++6 >= 4.7.4_20140612-2.1 needed by libstdc++47-devel,
-# (provider libstdc++6 conflicts with installed libstdc++43)
-# therefore:
-BuildRequires: libgcc_s1
-BuildRequires: libgomp1
-BuildRequires: libstdc++6
-#!BuildIgnore: libgcc43
-%else
-BuildRequires: gcc-c++
-%endif
-
-%if %{defined fedora}
-BuildRequires: python
-%endif
-
-# Systemd
-%if 0%{?suse_version} >= 1220 || 0%{?centos} >= 7 || 0%{?rhel} >= 7
-%define systemd 1
-BuildRequires: systemd
-%else
-%define systemd 0
-%endif
-
-%if 0%{?systemd}
-%{?systemd_requires}
-%if 0%{?suse_version}
-BuildRequires: systemd-rpm-macros
-# RedHat seems not to need this (or an equivalent).
-%endif
-
-%else
-# NOT systemd
-
-%if 0%{?suse_version}
-PreReq:        %insserv_prereq %fillup_prereq
-%else
-Requires(post): chkconfig
-Requires(preun): chkconfig
-Requires(preun): initscripts
-%endif
-%endif # systemd
-
-Requires:      openssl
-
-Provides:      wsrep, %{name} = %{version}-%{release}
-Provides:      galera, galera4, Percona-XtraDB-Cluster-galera-%{wsrep_api}
-
-%description
-Galera is a fast synchronous multimaster wsrep provider (replication engine)
-for transactional databases and similar applications. For more information
-about wsrep API see https://github.com/codership/wsrep-API. For a description
-of Galera replication engine see https://www.galeracluster.com.
-
-%{copyright}
-
-This software comes with ABSOLUTELY NO WARRANTY. This is free software,
-and you are welcome to modify and redistribute it under the GPLv2 license.
-
-%prep
-%setup -q -n %{name}-%{version}
-# When downloading from GitHub the contents is in a folder
-# that is named by the branch it was exported from.
-
-%build
-# Debug info:
-echo "suse_version: %{suse_version}"
-# 1110 = SLE-11 SPx
-%if 0%{?suse_version} == 1110
-export CC=gcc-4.7
-export CXX=g++-4.7
-%endif
-%if 0%{?suse_version} == 1120
-export CC=gcc-4.6
-export CXX=g++-4.6
-%endif
-%if 0%{?suse_version} == 1130
-export CC=gcc-4.7
-export CXX=g++-4.7
-%endif
-
-NUM_JOBS=${NUM_JOBS:-$(ncpu=$(cat /proc/cpuinfo | grep processor | wc -l) && echo $(($ncpu > 4 ? 4 : $ncpu)))}
-
-%if 0%{?without_crypto}
-%define crypto_opt -DGALERA_WITH_SSL:BOOL=OFF
-%endif
-
-cmake -DCMAKE_BUILD_TYPE=Release %{?crypto_opt} .
-make -j$(echo $NUM_JOBS) VERBOSE=1
-make test ARGS=-V
-
-%install
-RBR=$RPM_BUILD_ROOT # eg. rpmbuild/BUILDROOT/galera-3-3.x-33.1.x86_64
-RBD=$RPM_BUILD_DIR/%{name}-%{version}
-# When downloading from GitHub the contents is in a folder
-# that is named by the branch it was exported from.
-
-# Clean up the BuildRoot first
-[ "$RBR" != "/" ] && [ -d $RBR ] && rm -rf $RBR;
-mkdir -p $RBR
-
-%if 0%{?systemd}
-install -D -m 644 $RBD/garb/files/garb.service $RBR%{_unitdir}/garb.service
-install -D -m 755 $RBD/garb/files/garb-systemd $RBR%{_bindir}/garb-systemd
-%else
-install -d $RBR%{_sysconfdir}/init.d
-install -m 755 $RBD/garb/files/garb.sh  $RBR%{_sysconfdir}/init.d/garb
-%endif
-
-# Symlink required by SUSE policy for SysV init, still supported with systemd
-%if 0%{?suse_version}
-%if 0%{?systemd}
-install -d %{buildroot}%{_sbindir}
-ln -sf /usr/sbin/service %{buildroot}%{_sbindir}/rcgarb
-%else
-install -d $RBR/usr/sbin
-ln -sf /etc/init.d/garb $RBR/usr/sbin/rcgarb
-%endif # systemd
-%endif # suse_version
-
-%if 0%{?suse_version}
-install -d $RBR/var/adm/fillup-templates/
-install -m 644 $RBD/garb/files/garb.cnf $RBR/var/adm/fillup-templates/sysconfig.garb
-%else
-install -d $RBR%{_sysconfdir}/sysconfig
-install -m 644 $RBD/garb/files/garb.cnf $RBR%{_sysconfdir}/sysconfig/garb
-%endif # suse_version
-
-install -d $RBR%{_bindir}
-install -m 755 $RBD/garb/garbd                    $RBR%{_bindir}/garbd
-
-install -d $RBR%{libs}
-install -m 755 $RBD/libgalera_smm.so              $RBR%{libs}/libgalera_smm.so
-
-install -d $RBR%{docs}
-install -m 644 $RBD/COPYING                       $RBR%{docs}/COPYING
-install -m 644 $RBD/asio/LICENSE_1_0.txt          $RBR%{docs}/LICENSE.asio
-install -m 644 $RBD/scripts/packages/README       $RBR%{docs}/README
-install -m 644 $RBD/scripts/packages/README-MySQL $RBR%{docs}/README-MySQL
-
-install -d $RBR%{_mandir}/man8
-install -m 644 $RBD/man/garbd.8        $RBR%{_mandir}/man8/garbd.8
-
-
-%if 0%{?systemd}
-
-%if 0%{?suse_version}
-
-%post
-%service_add_post garb
-
-%preun
-%service_del_preun garb
-
-%else
-# Not SuSE - so it must be RedHat, CentOS, Fedora
-
-%post
-%systemd_post garb.service
-
-%preun
-%systemd_preun garb.service
-
-%postun
-%systemd_postun_with_restart garb.service
-
-%endif
-# SuSE versus Fedora/RedHat/CentOS
-
-%else
-# NOT systemd
-
-%if 0%{?suse_version}
-# For the various macros and their parameters, see here:
-# https://en.opensuse.org/openSUSE:Packaging_Conventions_RPM_Macros
-
-%post
-%fillup_and_insserv garb
-
-%preun
-%stop_on_removal garb
-rm -f $(find %{libs} -type l)
-
-%postun
-%restart_on_update garb
-%insserv_cleanup
-
-%else
-# Not SuSE - so it must be RedHat, CentOS, Fedora
-
-%post
-/sbin/chkconfig --add garb
-
-%preun
-if [ "$1" = "0" ]
-then
-    /sbin/service garb stop
-    /sbin/chkconfig --del garb
-fi
-
-%postun
-# >=1 packages after uninstall -> pkg was updated -> restart
-if [ "$1" -ge "1" ]
-then
-    /sbin/service garb restart
-fi
-
-%endif
-# SuSE versus Fedora/RedHat/CentOS
-
-%endif
-# systemd ?
-
-
-%files
-%defattr(-,root,root,0755)
-%if 0%{?suse_version}
-%config(noreplace,missingok) /var/adm/fillup-templates/sysconfig.garb
-%else
-%config(noreplace,missingok) %{_sysconfdir}/sysconfig/garb
-%endif
-
-
-%if 0%{?systemd}
-%attr(0644,root,root) %{_unitdir}/garb.service
-%attr(0755,root,root) %{_bindir}/garb-systemd
-%else
-%attr(0755,root,root) %{_sysconfdir}/init.d/garb
-%endif
-
-# Symlink required by SUSE policy for SysV init, still supported with systemd
-%if 0%{?suse_version}
-%attr(0755,root,root) /usr/sbin/rcgarb
-%endif
-
-%attr(0755,root,root) %{_bindir}/garbd
-
-%attr(0755,root,root) %dir %{libs}
-%attr(0755,root,root) %{libs}/libgalera_smm.so
-
-%attr(0755,root,root) %dir %{docs}
-%doc %attr(0644,root,root) %{docs}/COPYING
-%doc %attr(0644,root,root) %{docs}/LICENSE.asio
-%doc %attr(0644,root,root) %{docs}/README
-%doc %attr(0644,root,root) %{docs}/README-MySQL
-
-%doc %attr(644, root, man) %{_mandir}/man8/garbd.8*
-
-%clean
-[ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT;
-
-%changelog
-* Mon Nov 9 2020 Teemu Ollakka <teemu.ollakka@galeracluster.com>
-- Changed build system to CMake.
-- Name and version are generated by CMake.
-
-* Fri Feb 27 2015 Joerg Bruehe <joerg.bruehe@fromdual.com>
-- Service name is "garb", reflect that in the config file (SuSE only, galera#235, Release 2)
-
-* Fri Feb 20 2015 Joerg Bruehe <joerg.bruehe@fromdual.com>
-- Update copyright year.
-- Make the man page file name consistent with its section.
-
-* Wed Feb 11 2015 Joerg Bruehe <joerg.bruehe@fromdual.com>
-- Add missing "prereq" directive and arguments for the various service control macros.
-- Handle the difference between SuSE and Fedora/RedHat/CentOS.
-- Fix systemd stuff, using info from these pages:
-  https://en.opensuse.org/openSUSE:Systemd_packaging_guidelines
-  http://fedoraproject.org/wiki/Packaging:Systemd
-  http://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd
-
-* Tue Sep 30 2014 Otto Kekäläinen <otto@seravo.fi> - 3.x
-- Initial OBS packaging created
-
diff --git a/tests/scripts/action.sh b/tests/scripts/action.sh
index 4393a09..fa43e8a 100644
--- a/tests/scripts/action.sh
+++ b/tests/scripts/action.sh
@@ -172,7 +172,7 @@ wait_sync()
     local node
     for node in $nodes
     do
-        mysql_query "$node" "set wsrep_causal_reads=1; select 0;" 1>/dev/null
+        mysql_query "$node" "SET SESSION wsrep_sync_wait=1; select 0;" 1>/dev/null
     done
 }
 
