2018-06-25 10:07:52 +03:00

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;
}