364 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			364 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#pragma once
 | 
						|
/*
 | 
						|
 * Copyright (c) 2016 MariaDB Corporation Ab
 | 
						|
 *
 | 
						|
 * Use of this software is governed by the Business Source License included
 | 
						|
 * in the LICENSE.TXT file and at www.mariadb.com/bsl11.
 | 
						|
 *
 | 
						|
 * Change Date: 2020-01-01
 | 
						|
 *
 | 
						|
 * On the date above, in accordance with the Business Source License, use
 | 
						|
 * of this software will be governed by version 2 or later of the General
 | 
						|
 * Public License.
 | 
						|
 */
 | 
						|
 | 
						|
#include <maxscale/cppdefs.hh>
 | 
						|
 | 
						|
#include <list>
 | 
						|
#include <string>
 | 
						|
#include <tr1/memory>
 | 
						|
 | 
						|
#include <maxscale/service.h>
 | 
						|
#include <maxscale/session_command.hh>
 | 
						|
 | 
						|
 | 
						|
namespace maxscale
 | 
						|
{
 | 
						|
 | 
						|
 | 
						|
class Backend
 | 
						|
{
 | 
						|
    Backend(const Backend&);
 | 
						|
    Backend& operator =(const Backend&);
 | 
						|
public:
 | 
						|
 | 
						|
    /**
 | 
						|
     * How is the backend being closed
 | 
						|
     */
 | 
						|
    enum close_type
 | 
						|
    {
 | 
						|
        CLOSE_NORMAL,
 | 
						|
        CLOSE_FATAL
 | 
						|
    };
 | 
						|
 | 
						|
    /**
 | 
						|
     * What type of a response we expect from the backend
 | 
						|
     */
 | 
						|
    enum response_type
 | 
						|
    {
 | 
						|
        EXPECT_RESPONSE,
 | 
						|
        NO_RESPONSE
 | 
						|
    };
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Create new Backend
 | 
						|
     *
 | 
						|
     * @param ref Server reference used by this backend
 | 
						|
     */
 | 
						|
    Backend(SERVER_REF* ref);
 | 
						|
 | 
						|
    virtual ~Backend();
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Execute the next session command in the queue
 | 
						|
     *
 | 
						|
     * @return True if the command was executed successfully
 | 
						|
     */
 | 
						|
    virtual bool execute_session_command();
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Add a new session command to the tail of the command queue
 | 
						|
     *
 | 
						|
     * @param buffer   Session command to add
 | 
						|
     * @param sequence Sequence identifier of this session command, returned when
 | 
						|
     *                 the session command is completed
 | 
						|
     */
 | 
						|
    void append_session_command(GWBUF* buffer, uint64_t sequence);
 | 
						|
    void append_session_command(const SSessionCommand& sescmd);
 | 
						|
    void append_session_command(const SessionCommandList& sescmdlist);
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Mark the current session command as successfully executed
 | 
						|
     *
 | 
						|
     * This should be called when the response to the command is received
 | 
						|
     *
 | 
						|
     * @return The sequence identifier for this session command
 | 
						|
     */
 | 
						|
    uint64_t complete_session_command();
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Get number of session commands
 | 
						|
     *
 | 
						|
     * @return Number of session commands
 | 
						|
     */
 | 
						|
    size_t session_command_count() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if there are session commands waiting to be executed
 | 
						|
     *
 | 
						|
     * @return True if there are session commands waiting to be executed
 | 
						|
     */
 | 
						|
    inline bool has_session_commands() const
 | 
						|
    {
 | 
						|
        return !m_session_commands.empty();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Get the first session command
 | 
						|
     *
 | 
						|
     * Returns the first session command in the list of session commands
 | 
						|
     * to be executed.
 | 
						|
     *
 | 
						|
     * This should only be called when at least one session command has been
 | 
						|
     * added to the backend. If no session commands have been added, behavior
 | 
						|
     * is undefined.
 | 
						|
     *
 | 
						|
     * @return The first session command
 | 
						|
     */
 | 
						|
    const SSessionCommand& next_session_command() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Get pointer to server reference
 | 
						|
     *
 | 
						|
     * @return Pointer to server reference
 | 
						|
     */
 | 
						|
    inline SERVER_REF* backend() const
 | 
						|
    {
 | 
						|
        ss_dassert(m_backend);
 | 
						|
        return m_backend;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Get pointer to server
 | 
						|
     *
 | 
						|
     * @return Pointer to server
 | 
						|
     */
 | 
						|
    inline SERVER* server() const
 | 
						|
    {
 | 
						|
        ss_dassert(m_backend);
 | 
						|
        return m_backend->server;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if a connection to this backend can be made
 | 
						|
     *
 | 
						|
     * @return True if the backend has not failed and a connection can be attempted
 | 
						|
     */
 | 
						|
    inline bool can_connect() const
 | 
						|
    {
 | 
						|
        return !has_failed() && SERVER_IS_RUNNING(m_backend->server);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Create a new connection
 | 
						|
     *
 | 
						|
     * @param session The session to which the connection is linked
 | 
						|
     * @param sescmd  Pointer to a list of session commands to execute
 | 
						|
     *
 | 
						|
     * @return True if connection was successfully created
 | 
						|
     */
 | 
						|
    bool connect(MXS_SESSION* session, SessionCommandList* sescmd = NULL);
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Close the backend
 | 
						|
     *
 | 
						|
     * This will close all active connections created by the backend.
 | 
						|
     */
 | 
						|
    virtual void close(close_type type = CLOSE_NORMAL);
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Get a pointer to the internal DCB
 | 
						|
     *
 | 
						|
     * @return Pointer to DCB or NULL if not connected
 | 
						|
     */
 | 
						|
    inline DCB* dcb() const
 | 
						|
    {
 | 
						|
        return m_dcb;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Write data to the backend server
 | 
						|
     *
 | 
						|
     * @param buffer          Buffer containing the data to write
 | 
						|
     * @param expect_response Whether to expect a response to the query
 | 
						|
     *
 | 
						|
     * @return True if data was written successfully
 | 
						|
     */
 | 
						|
    virtual bool write(GWBUF* buffer, response_type type = EXPECT_RESPONSE);
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Write an authentication switch request to the backend server
 | 
						|
     *
 | 
						|
     * @param buffer Buffer containing the authentication switch request
 | 
						|
     *
 | 
						|
     * @return True if request was successfully written
 | 
						|
     */
 | 
						|
    bool auth(GWBUF* buffer);
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Mark that a reply to a query was received and processed
 | 
						|
     */
 | 
						|
    void ack_write();
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Store a command
 | 
						|
     *
 | 
						|
     * The command is stored and executed once the session can execute
 | 
						|
     * the next command.
 | 
						|
     *
 | 
						|
     * @param buffer Buffer to store
 | 
						|
     */
 | 
						|
    void store_command(GWBUF* buffer);
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Write the stored command to the backend server
 | 
						|
     *
 | 
						|
     * @return True if command was written successfully
 | 
						|
     */
 | 
						|
    bool write_stored_command();
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if backend is in use
 | 
						|
     *
 | 
						|
     * @return True if backend is in use
 | 
						|
     */
 | 
						|
    inline bool in_use() const
 | 
						|
    {
 | 
						|
        return m_state & IN_USE;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if the backend server reference is active
 | 
						|
     *
 | 
						|
     * @return True if the server reference is active
 | 
						|
     */
 | 
						|
    inline bool is_active() const
 | 
						|
    {
 | 
						|
        return SERVER_REF_IS_ACTIVE(m_backend);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if backend is waiting for a result
 | 
						|
     *
 | 
						|
     * @return True if backend is waiting for a result
 | 
						|
     */
 | 
						|
    inline bool is_waiting_result() const
 | 
						|
    {
 | 
						|
        return m_state & WAITING_RESULT;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if the backend is closed
 | 
						|
     *
 | 
						|
     * @return True if the backend is closed
 | 
						|
     */
 | 
						|
    inline bool is_closed() const
 | 
						|
    {
 | 
						|
        return m_closed;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if the server is a master
 | 
						|
     *
 | 
						|
     * @return True if server is a master
 | 
						|
     */
 | 
						|
    inline bool is_master() const
 | 
						|
    {
 | 
						|
        return SERVER_IS_MASTER(m_backend->server);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if the server is a slave
 | 
						|
     *
 | 
						|
     * @return True if the server is a slave
 | 
						|
     */
 | 
						|
    inline bool is_slave() const
 | 
						|
    {
 | 
						|
        return SERVER_IS_SLAVE(m_backend->server);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if the server is a relay server
 | 
						|
     *
 | 
						|
     * @return True if the server is a relay server
 | 
						|
     */
 | 
						|
    inline bool is_relay() const
 | 
						|
    {
 | 
						|
        return SERVER_IS_RELAY_SERVER(m_backend->server);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Check if the backend has failed fatally
 | 
						|
     *
 | 
						|
     * When a fatal failure occurs in a backend, the backend server can no longer
 | 
						|
     * be used by this session. Fatal failures can occur when the execution of
 | 
						|
     * a session command fails on the backend but the expected result is different.
 | 
						|
     *
 | 
						|
     * @return True if a fatal failure has occurred in the backend server
 | 
						|
     */
 | 
						|
    inline bool has_failed() const
 | 
						|
    {
 | 
						|
        return m_state & FATAL_FAILURE;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Get the object name of this server
 | 
						|
     *
 | 
						|
     * @return The unique object name of this server
 | 
						|
     */
 | 
						|
    inline const char* name() const
 | 
						|
    {
 | 
						|
        return m_backend->server->name;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Get the address and port as a string
 | 
						|
     *
 | 
						|
     * @return The address and port combined into one string
 | 
						|
     */
 | 
						|
    inline const char* uri() const
 | 
						|
    {
 | 
						|
        return m_uri.c_str();
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    /**
 | 
						|
     * Internal state of the backend
 | 
						|
     */
 | 
						|
    enum backend_state
 | 
						|
    {
 | 
						|
        IN_USE           = 0x01, /**< Backend has been taken into use */
 | 
						|
        WAITING_RESULT   = 0x02, /**< Waiting for a reply */
 | 
						|
        FATAL_FAILURE    = 0x04  /**< Backend references that should be dropped */
 | 
						|
    };
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Clear state
 | 
						|
     *
 | 
						|
     * @param state State to clear
 | 
						|
     */
 | 
						|
    void clear_state(backend_state state);
 | 
						|
 | 
						|
    /**
 | 
						|
     * @brief Set state
 | 
						|
     *
 | 
						|
     * @param state State to set
 | 
						|
     */
 | 
						|
    void set_state(backend_state state);
 | 
						|
 | 
						|
 | 
						|
    bool               m_closed;           /**< True if a connection has been opened and closed */
 | 
						|
    SERVER_REF*        m_backend;          /**< Backend server */
 | 
						|
    DCB*               m_dcb;              /**< Backend DCB */
 | 
						|
    mxs::Buffer        m_pending_cmd;      /**< Pending commands */
 | 
						|
    int                m_state;            /**< State of the backend */
 | 
						|
    SessionCommandList m_session_commands; /**< List of session commands that are
 | 
						|
                                            * to be executed on this backend server */
 | 
						|
    std::string        m_uri;              /**< The combined address and port */
 | 
						|
};
 | 
						|
 | 
						|
typedef std::tr1::shared_ptr<Backend> SBackend;
 | 
						|
typedef std::list<SBackend> BackendList;
 | 
						|
}
 |