mirror of
				https://github.com/codership/wsrep-lib.git
				synced 2025-11-03 05:33:11 +03:00 
			
		
		
		
	Removed calls to assert() from public headers to have full control when assertions are enabled in wsrep-lib code regardless of parent project build configuration. Moved methods containing assertions and non-trivial code from headers into compilation units.
		
			
				
	
	
		
			507 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			507 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C) 2018 Codership Oy <info@codership.com>
 | 
						|
 *
 | 
						|
 * This file is part of wsrep-lib.
 | 
						|
 *
 | 
						|
 * Wsrep-lib 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, either version 2 of the License, or
 | 
						|
 * (at your option) any later version.
 | 
						|
 *
 | 
						|
 * Wsrep-lib 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 wsrep-lib.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef WSREP_PROVIDER_HPP
 | 
						|
#define WSREP_PROVIDER_HPP
 | 
						|
 | 
						|
#include "gtid.hpp"
 | 
						|
#include "key.hpp"
 | 
						|
#include "buffer.hpp"
 | 
						|
#include "client_id.hpp"
 | 
						|
#include "transaction_id.hpp"
 | 
						|
#include "compiler.hpp"
 | 
						|
 | 
						|
#include <cstring>
 | 
						|
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
#include <ostream>
 | 
						|
 | 
						|
/**
 | 
						|
 * Empty provider magic. If none provider is passed to make_provider(),
 | 
						|
 * a dummy provider is loaded.
 | 
						|
 */
 | 
						|
#define WSREP_LIB_PROVIDER_NONE "none"
 | 
						|
 | 
						|
namespace wsrep
 | 
						|
{
 | 
						|
    class server_state;
 | 
						|
    class high_priority_service;
 | 
						|
    class thread_service;
 | 
						|
    class tls_service;
 | 
						|
    class allowlist_service;
 | 
						|
    class event_service;
 | 
						|
 | 
						|
    class stid
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        stid()
 | 
						|
            : server_id_()
 | 
						|
            , transaction_id_()
 | 
						|
            , client_id_()
 | 
						|
        { }
 | 
						|
        stid(const wsrep::id& server_id,
 | 
						|
             wsrep::transaction_id transaction_id,
 | 
						|
             wsrep::client_id client_id)
 | 
						|
            : server_id_(server_id)
 | 
						|
            , transaction_id_(transaction_id)
 | 
						|
            , client_id_(client_id)
 | 
						|
        { }
 | 
						|
        const wsrep::id& server_id() const { return server_id_; }
 | 
						|
        wsrep::transaction_id transaction_id() const
 | 
						|
        { return transaction_id_; }
 | 
						|
        wsrep::client_id client_id() const { return client_id_; }
 | 
						|
        bool operator==(const stid& other) const
 | 
						|
        {
 | 
						|
            return (
 | 
						|
                server_id_ == other.server_id_ &&
 | 
						|
                transaction_id_ == other.transaction_id_ &&
 | 
						|
                client_id_ == other.client_id_
 | 
						|
            );
 | 
						|
        }
 | 
						|
    private:
 | 
						|
        wsrep::id server_id_;
 | 
						|
        wsrep::transaction_id transaction_id_;
 | 
						|
        wsrep::client_id client_id_;
 | 
						|
    };
 | 
						|
 | 
						|
    class ws_handle
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        ws_handle()
 | 
						|
            : transaction_id_()
 | 
						|
            , opaque_()
 | 
						|
        { }
 | 
						|
        ws_handle(wsrep::transaction_id id)
 | 
						|
            : transaction_id_(id)
 | 
						|
            , opaque_()
 | 
						|
        { }
 | 
						|
        ws_handle(wsrep::transaction_id id,
 | 
						|
                  void* opaque)
 | 
						|
            : transaction_id_(id)
 | 
						|
            , opaque_(opaque)
 | 
						|
        { }
 | 
						|
 | 
						|
        wsrep::transaction_id transaction_id() const
 | 
						|
        { return transaction_id_; }
 | 
						|
 | 
						|
        void* opaque() const { return opaque_; }
 | 
						|
 | 
						|
        bool operator==(const ws_handle& other) const
 | 
						|
        {
 | 
						|
            return (
 | 
						|
                transaction_id_ == other.transaction_id_ &&
 | 
						|
                opaque_ == other.opaque_
 | 
						|
            );
 | 
						|
        }
 | 
						|
    private:
 | 
						|
        wsrep::transaction_id transaction_id_;
 | 
						|
        void* opaque_;
 | 
						|
    };
 | 
						|
 | 
						|
    class ws_meta
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        ws_meta()
 | 
						|
            : gtid_()
 | 
						|
            , stid_()
 | 
						|
            , depends_on_()
 | 
						|
            , flags_()
 | 
						|
        { }
 | 
						|
        ws_meta(const wsrep::gtid& gtid,
 | 
						|
                const wsrep::stid& stid,
 | 
						|
                wsrep::seqno depends_on,
 | 
						|
                int flags)
 | 
						|
            : gtid_(gtid)
 | 
						|
            , stid_(stid)
 | 
						|
            , depends_on_(depends_on)
 | 
						|
            , flags_(flags)
 | 
						|
        { }
 | 
						|
        ws_meta(const wsrep::stid& stid)
 | 
						|
            : gtid_()
 | 
						|
            , stid_(stid)
 | 
						|
            , depends_on_()
 | 
						|
            , flags_()
 | 
						|
        { }
 | 
						|
        const wsrep::gtid& gtid() const { return gtid_; }
 | 
						|
        const wsrep::id& group_id() const
 | 
						|
        {
 | 
						|
            return gtid_.id();
 | 
						|
        }
 | 
						|
 | 
						|
        wsrep::seqno seqno() const
 | 
						|
        {
 | 
						|
            return gtid_.seqno();
 | 
						|
        }
 | 
						|
 | 
						|
        const wsrep::id& server_id() const
 | 
						|
        {
 | 
						|
            return stid_.server_id();
 | 
						|
        }
 | 
						|
 | 
						|
        wsrep::client_id client_id() const
 | 
						|
        {
 | 
						|
            return stid_.client_id();
 | 
						|
        }
 | 
						|
 | 
						|
        wsrep::transaction_id transaction_id() const
 | 
						|
        {
 | 
						|
            return stid_.transaction_id();
 | 
						|
        }
 | 
						|
 | 
						|
        bool ordered() const { return !gtid_.is_undefined(); }
 | 
						|
 | 
						|
        wsrep::seqno depends_on() const { return depends_on_; }
 | 
						|
 | 
						|
        int flags() const { return flags_; }
 | 
						|
 | 
						|
        bool operator==(const ws_meta& other) const
 | 
						|
        {
 | 
						|
            return (
 | 
						|
                gtid_ == other.gtid_ &&
 | 
						|
                stid_ == other.stid_ &&
 | 
						|
                depends_on_ == other.depends_on_ &&
 | 
						|
                flags_ == other.flags_
 | 
						|
            );
 | 
						|
        }
 | 
						|
    private:
 | 
						|
        wsrep::gtid gtid_;
 | 
						|
        wsrep::stid stid_;
 | 
						|
        wsrep::seqno depends_on_;
 | 
						|
        int flags_;
 | 
						|
    };
 | 
						|
 | 
						|
    std::string flags_to_string(int flags);
 | 
						|
 | 
						|
    std::ostream& operator<<(std::ostream& os, const wsrep::ws_meta& ws_meta);
 | 
						|
 | 
						|
    // Abstract interface for provider implementations
 | 
						|
    class provider
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        class status_variable
 | 
						|
        {
 | 
						|
        public:
 | 
						|
            status_variable(const std::string& name,
 | 
						|
                            const std::string& value)
 | 
						|
                : name_(name)
 | 
						|
                , value_(value)
 | 
						|
            { }
 | 
						|
            const std::string& name() const { return name_; }
 | 
						|
            const std::string& value() const { return value_; }
 | 
						|
        private:
 | 
						|
            std::string name_;
 | 
						|
            std::string value_;
 | 
						|
        };
 | 
						|
 | 
						|
        /**
 | 
						|
         * Return value enumeration
 | 
						|
         *
 | 
						|
         * @todo Convert this to struct ec, get rid of prefixes.
 | 
						|
         */
 | 
						|
        enum status
 | 
						|
        {
 | 
						|
            /** Success */
 | 
						|
            success,
 | 
						|
            /** Warning*/
 | 
						|
            error_warning,
 | 
						|
            /** Transaction was not found from provider */
 | 
						|
            error_transaction_missing,
 | 
						|
            /** Certification failed */
 | 
						|
            error_certification_failed,
 | 
						|
            /** Transaction was BF aborted */
 | 
						|
            error_bf_abort,
 | 
						|
            /** Transaction size exceeded */
 | 
						|
            error_size_exceeded,
 | 
						|
            /** Connectivity to cluster lost */
 | 
						|
            error_connection_failed,
 | 
						|
            /** Internal provider failure or provider was closed,
 | 
						|
                provider must be reinitialized */
 | 
						|
            error_provider_failed,
 | 
						|
            /** Fatal error, server must abort */
 | 
						|
            error_fatal,
 | 
						|
            /** Requested functionality is not implemented by the provider */
 | 
						|
            error_not_implemented,
 | 
						|
            /** Operation is not allowed */
 | 
						|
            error_not_allowed,
 | 
						|
            /** Unknown error code from the provider */
 | 
						|
            error_unknown
 | 
						|
        };
 | 
						|
 | 
						|
        static std::string to_string(enum status);
 | 
						|
 | 
						|
        struct flag
 | 
						|
        {
 | 
						|
            static const int start_transaction = (1 << 0);
 | 
						|
            static const int commit = (1 << 1);
 | 
						|
            static const int rollback = (1 << 2);
 | 
						|
            static const int isolation = (1 << 3);
 | 
						|
            static const int pa_unsafe = (1 << 4);
 | 
						|
            static const int commutative = (1 << 5);
 | 
						|
            static const int native = (1 << 6);
 | 
						|
            static const int prepare = (1 << 7);
 | 
						|
            static const int snapshot = (1 << 8);
 | 
						|
            static const int implicit_deps = (1 << 9);
 | 
						|
        };
 | 
						|
 | 
						|
        /**
 | 
						|
         * Provider capabilities.
 | 
						|
         */
 | 
						|
        struct capability
 | 
						|
        {
 | 
						|
            static const int multi_master = (1 << 0);
 | 
						|
            static const int certification = (1 << 1);
 | 
						|
            static const int parallel_applying = (1 << 2);
 | 
						|
            static const int transaction_replay = (1 << 3);
 | 
						|
            static const int isolation = (1 << 4);
 | 
						|
            static const int pause = (1 << 5);
 | 
						|
            static const int causal_reads = (1 << 6);
 | 
						|
            static const int causal_transaction = (1 << 7);
 | 
						|
            static const int incremental_writeset = (1 << 8);
 | 
						|
            static const int session_locks = (1 << 9);
 | 
						|
            static const int distributed_locks = (1 << 10);
 | 
						|
            static const int consistency_check = (1 << 11);
 | 
						|
            static const int unordered = (1 << 12);
 | 
						|
            static const int annotation = (1 << 13);
 | 
						|
            static const int preordered = (1 << 14);
 | 
						|
            static const int streaming = (1 << 15);
 | 
						|
            static const int snapshot = (1 << 16);
 | 
						|
            static const int nbo = (1 << 17);
 | 
						|
 | 
						|
            /** decipher capability bitmask */
 | 
						|
            static std::string str(int);
 | 
						|
        };
 | 
						|
 | 
						|
        provider(wsrep::server_state& server_state)
 | 
						|
            : server_state_(server_state)
 | 
						|
        { }
 | 
						|
        virtual ~provider() { }
 | 
						|
        // Provider state management
 | 
						|
        virtual enum status connect(const std::string& cluster_name,
 | 
						|
                                    const std::string& cluster_url,
 | 
						|
                                    const std::string& state_donor,
 | 
						|
                                    bool bootstrap) = 0;
 | 
						|
        virtual int disconnect() = 0;
 | 
						|
 | 
						|
        virtual int capabilities() const = 0;
 | 
						|
        virtual int desync() = 0;
 | 
						|
        virtual int resync() = 0;
 | 
						|
 | 
						|
        virtual wsrep::seqno pause() = 0;
 | 
						|
        virtual int resume() = 0;
 | 
						|
 | 
						|
        // Applier interface
 | 
						|
        virtual enum status run_applier(wsrep::high_priority_service*
 | 
						|
                                        applier_ctx) = 0;
 | 
						|
        // Write set replication
 | 
						|
        // TODO: Rename to assing_read_view()
 | 
						|
        virtual int start_transaction(wsrep::ws_handle&) = 0;
 | 
						|
        virtual enum status assign_read_view(
 | 
						|
            wsrep::ws_handle&, const wsrep::gtid*) = 0;
 | 
						|
        virtual int append_key(wsrep::ws_handle&, const wsrep::key&) = 0;
 | 
						|
        virtual enum status append_data(
 | 
						|
            wsrep::ws_handle&, const wsrep::const_buffer&) = 0;
 | 
						|
        virtual enum status
 | 
						|
        certify(wsrep::client_id, wsrep::ws_handle&,
 | 
						|
                int,
 | 
						|
                wsrep::ws_meta&) = 0;
 | 
						|
        /**
 | 
						|
         * BF abort a transaction inside provider.
 | 
						|
         *
 | 
						|
         * @param[in] bf_seqno Seqno of the aborter transaction
 | 
						|
         * @param[in] victim_txt Transaction identifier of the victim
 | 
						|
         * @param[out] victim_seqno Sequence number of the victim transaction
 | 
						|
         * or WSREP_SEQNO_UNDEFINED if the victim was not ordered
 | 
						|
         *
 | 
						|
         * @return wsrep_status_t
 | 
						|
         */
 | 
						|
        virtual enum status bf_abort(wsrep::seqno bf_seqno,
 | 
						|
                                     wsrep::transaction_id victim_trx,
 | 
						|
                                     wsrep::seqno& victim_seqno) = 0;
 | 
						|
        virtual enum status rollback(wsrep::transaction_id) = 0;
 | 
						|
        virtual enum status commit_order_enter(const wsrep::ws_handle&,
 | 
						|
                                               const wsrep::ws_meta&) = 0;
 | 
						|
        virtual int commit_order_leave(const wsrep::ws_handle&,
 | 
						|
                                       const wsrep::ws_meta&,
 | 
						|
                                       const wsrep::mutable_buffer& err) = 0;
 | 
						|
        virtual int release(wsrep::ws_handle&) = 0;
 | 
						|
 | 
						|
        /**
 | 
						|
         * Replay a transaction.
 | 
						|
         *
 | 
						|
         * @todo Inspect if the ws_handle could be made const
 | 
						|
         *
 | 
						|
         * @return Zero in case of success, non-zero on failure.
 | 
						|
         */
 | 
						|
        virtual enum status replay(
 | 
						|
            const wsrep::ws_handle& ws_handle,
 | 
						|
            wsrep::high_priority_service* applier_ctx) = 0;
 | 
						|
 | 
						|
        /**
 | 
						|
         * Enter total order isolation critical section
 | 
						|
         */
 | 
						|
        virtual enum status enter_toi(wsrep::client_id,
 | 
						|
                                      const wsrep::key_array& keys,
 | 
						|
                                      const wsrep::const_buffer& buffer,
 | 
						|
                                      wsrep::ws_meta& ws_meta,
 | 
						|
                                      int flags) = 0;
 | 
						|
        /**
 | 
						|
         * Leave total order isolation critical section
 | 
						|
         */
 | 
						|
        virtual enum status leave_toi(wsrep::client_id,
 | 
						|
                                      const wsrep::mutable_buffer& err) = 0;
 | 
						|
 | 
						|
        /**
 | 
						|
         * Perform a causal read on cluster.
 | 
						|
         *
 | 
						|
         * @param timeout Timeout in seconds
 | 
						|
         *
 | 
						|
         * @return Provider status indicating the result of the call.
 | 
						|
         */
 | 
						|
        virtual std::pair<wsrep::gtid, enum status>
 | 
						|
            causal_read(int timeout) const = 0;
 | 
						|
        virtual enum status wait_for_gtid(const wsrep::gtid&, int timeout) const = 0;
 | 
						|
        /**
 | 
						|
         * Return last committed GTID.
 | 
						|
         */
 | 
						|
        virtual wsrep::gtid last_committed_gtid() const = 0;
 | 
						|
        virtual enum status sst_sent(const wsrep::gtid&, int) = 0;
 | 
						|
        virtual enum status sst_received(const wsrep::gtid&, int) = 0;
 | 
						|
        virtual enum status enc_set_key(const wsrep::const_buffer& key) = 0;
 | 
						|
        virtual std::vector<status_variable> status() const = 0;
 | 
						|
        virtual void reset_status() = 0;
 | 
						|
 | 
						|
        virtual std::string options() const = 0;
 | 
						|
        virtual enum status options(const std::string&) = 0;
 | 
						|
        /**
 | 
						|
         * Get provider name.
 | 
						|
         *
 | 
						|
         * @return Provider name string.
 | 
						|
         */
 | 
						|
        virtual std::string name() const = 0;
 | 
						|
 | 
						|
        /**
 | 
						|
         * Get provider version.
 | 
						|
         *
 | 
						|
         * @return Provider version string.
 | 
						|
         */
 | 
						|
        virtual std::string version() const = 0;
 | 
						|
 | 
						|
        /**
 | 
						|
         * Get provider vendor.
 | 
						|
         *
 | 
						|
         * @return Provider vendor string.
 | 
						|
         */
 | 
						|
        virtual std::string vendor() const = 0;
 | 
						|
 | 
						|
        /**
 | 
						|
         * Return pointer to native provider handle.
 | 
						|
         */
 | 
						|
        virtual void* native() const = 0;
 | 
						|
 | 
						|
        /**
 | 
						|
         * Services argument passed to make_provider. This struct contains
 | 
						|
         * optional services which are passed to the provider.
 | 
						|
         */
 | 
						|
        struct services
 | 
						|
        {
 | 
						|
            wsrep::thread_service* thread_service;
 | 
						|
            wsrep::tls_service* tls_service;
 | 
						|
            wsrep::allowlist_service* allowlist_service;
 | 
						|
            wsrep::event_service* event_service;
 | 
						|
 | 
						|
            // some GCC and clang versions don't support C++11 default
 | 
						|
            // initializers fully, so we need to use explicit constructors
 | 
						|
            // instead:
 | 
						|
            // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88165
 | 
						|
            // https://bugs.llvm.org/show_bug.cgi?id=36684
 | 
						|
            services()
 | 
						|
                : thread_service()
 | 
						|
                , tls_service()
 | 
						|
                , allowlist_service()
 | 
						|
                , event_service()
 | 
						|
            {
 | 
						|
            }
 | 
						|
 | 
						|
            services(wsrep::thread_service* thr,
 | 
						|
                     wsrep::tls_service*    tls,
 | 
						|
                     wsrep::allowlist_service* all,
 | 
						|
                     wsrep::event_service*  event)
 | 
						|
                : thread_service(thr)
 | 
						|
                , tls_service(tls)
 | 
						|
                , allowlist_service(all)
 | 
						|
                , event_service(event)
 | 
						|
            {
 | 
						|
            }
 | 
						|
        };
 | 
						|
        /**
 | 
						|
         * Create a new provider.
 | 
						|
         *
 | 
						|
         * @param provider_spec Provider specification
 | 
						|
         * @param provider_options Initial options to provider
 | 
						|
         * @param thread_service Optional thread service implementation.
 | 
						|
         */
 | 
						|
        static provider* make_provider(wsrep::server_state&,
 | 
						|
                                       const std::string& provider_spec,
 | 
						|
                                       const std::string& provider_options,
 | 
						|
                                       const wsrep::provider::services& services
 | 
						|
                                       = wsrep::provider::services());
 | 
						|
 | 
						|
    protected:
 | 
						|
        wsrep::server_state& server_state_;
 | 
						|
    };
 | 
						|
 | 
						|
    static inline bool starts_transaction(int flags)
 | 
						|
    {
 | 
						|
        return (flags & wsrep::provider::flag::start_transaction);
 | 
						|
    }
 | 
						|
 | 
						|
    static inline bool commits_transaction(int flags)
 | 
						|
    {
 | 
						|
        return (flags & wsrep::provider::flag::commit);
 | 
						|
    }
 | 
						|
 | 
						|
    static inline bool rolls_back_transaction(int flags)
 | 
						|
    {
 | 
						|
        return (flags & wsrep::provider::flag::rollback);
 | 
						|
    }
 | 
						|
 | 
						|
    static inline bool prepares_transaction(int flags)
 | 
						|
    {
 | 
						|
        return (flags & wsrep::provider::flag::prepare);
 | 
						|
    }
 | 
						|
 | 
						|
    static inline bool is_toi(int flags)
 | 
						|
    {
 | 
						|
        return (flags & wsrep::provider::flag::isolation);
 | 
						|
    }
 | 
						|
 | 
						|
    static inline bool is_commutative(int flags)
 | 
						|
    {
 | 
						|
        return (flags & wsrep::provider::flag::commutative);
 | 
						|
    }
 | 
						|
 | 
						|
    static inline bool is_native(int flags)
 | 
						|
    {
 | 
						|
        return (flags & wsrep::provider::flag::native);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#endif // WSREP_PROVIDER_HPP
 |