365 lines
9.0 KiB
C++
365 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: 2022-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
|
|
{
|
|
ss_dassert(in_use());
|
|
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;
|
|
}
|