
At runtime the Clustrix monitor will save to an sqlite3 database information about detected nodes and delete that information if a node disappears. At startup, if the monitor fails to connect to a bootstrap node, it will try to connect any of the persisted nodes and start from there. This means that in general it is sufficient if the Clustrix monitor at the very first startup can connect to a bootstrap node; thereafter it will get by even if the bootstrap node would disappear for good.
247 lines
5.5 KiB
C++
247 lines
5.5 KiB
C++
/*
|
|
* Copyright (c) 2018 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.
|
|
*/
|
|
#pragma once
|
|
|
|
#include "clustrixmon.hh"
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include "clustrix.hh"
|
|
#include "clustrixmembership.hh"
|
|
|
|
class ClustrixNode
|
|
{
|
|
public:
|
|
class Persister
|
|
{
|
|
public:
|
|
virtual void persist(const ClustrixNode& node) = 0;
|
|
virtual void unpersist(const ClustrixNode& node) = 0;
|
|
};
|
|
|
|
enum
|
|
{
|
|
DEFAULT_MYSQL_PORT = 3306,
|
|
DEFAULT_HEALTH_PORT = 3581,
|
|
};
|
|
|
|
enum approach_t
|
|
{
|
|
APPROACH_OVERRIDE,
|
|
APPROACH_DEFAULT
|
|
};
|
|
|
|
ClustrixNode(Persister* pPersister,
|
|
const ClustrixMembership& membership,
|
|
const std::string& ip,
|
|
int mysql_port,
|
|
int health_port,
|
|
int health_check_threshold,
|
|
SERVER* pServer)
|
|
: m_persister(*pPersister)
|
|
, m_id(membership.id())
|
|
, m_status(membership.status())
|
|
, m_substate(membership.substate())
|
|
, m_instance(membership.instance())
|
|
, m_ip(ip)
|
|
, m_mysql_port(mysql_port)
|
|
, m_health_port(health_port)
|
|
, m_health_check_threshold(health_check_threshold)
|
|
, m_nRunning(m_health_check_threshold)
|
|
, m_pServer(pServer)
|
|
, m_pCon(nullptr)
|
|
{
|
|
m_pServer->set_status(SERVER_MASTER | SERVER_RUNNING);
|
|
m_persister.persist(*this);
|
|
}
|
|
|
|
~ClustrixNode()
|
|
{
|
|
if (m_pCon)
|
|
{
|
|
mysql_close(m_pCon);
|
|
}
|
|
}
|
|
|
|
int id() const
|
|
{
|
|
return m_id;
|
|
}
|
|
|
|
Clustrix::Status status() const
|
|
{
|
|
return m_status;
|
|
}
|
|
|
|
Clustrix::SubState substate() const
|
|
{
|
|
return m_substate;
|
|
}
|
|
|
|
int instance() const
|
|
{
|
|
return m_instance;
|
|
}
|
|
|
|
const std::string& ip() const
|
|
{
|
|
return m_ip;
|
|
}
|
|
|
|
int mysql_port() const
|
|
{
|
|
return m_mysql_port;
|
|
}
|
|
|
|
int health_port() const
|
|
{
|
|
return m_health_port;
|
|
}
|
|
|
|
bool is_running() const
|
|
{
|
|
return m_nRunning > 0;
|
|
}
|
|
|
|
void set_running(bool running, approach_t approach = APPROACH_DEFAULT)
|
|
{
|
|
if (running)
|
|
{
|
|
if (m_nRunning == 0)
|
|
{
|
|
m_pServer->set_status(SERVER_MASTER | SERVER_RUNNING);
|
|
m_persister.persist(*this);
|
|
}
|
|
|
|
m_nRunning = m_health_check_threshold;
|
|
}
|
|
else
|
|
{
|
|
if (m_nRunning > 0)
|
|
{
|
|
if (approach == APPROACH_OVERRIDE)
|
|
{
|
|
m_nRunning = 0;
|
|
}
|
|
else
|
|
{
|
|
--m_nRunning;
|
|
}
|
|
|
|
if (m_nRunning == 0)
|
|
{
|
|
m_pServer->clear_status(SERVER_MASTER | SERVER_RUNNING);
|
|
m_persister.unpersist(*this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void update(const std::string& ip,
|
|
int mysql_port,
|
|
int health_port)
|
|
{
|
|
bool changed = false;
|
|
|
|
if (ip != m_ip)
|
|
{
|
|
m_ip = ip;
|
|
changed = true;
|
|
}
|
|
|
|
if (mysql_port != m_mysql_port)
|
|
{
|
|
m_mysql_port = mysql_port;
|
|
m_pServer->update_port(m_mysql_port);
|
|
changed = true;
|
|
}
|
|
|
|
if (health_port != m_health_port)
|
|
{
|
|
m_health_port = health_port;
|
|
changed = true;
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
m_persister.persist(*this);
|
|
}
|
|
}
|
|
|
|
void update(Clustrix::Status status, Clustrix::SubState substate, int instance)
|
|
{
|
|
m_status = status;
|
|
m_substate = substate;
|
|
m_instance = instance;
|
|
}
|
|
|
|
void deactivate_server()
|
|
{
|
|
m_pServer->is_active = false;
|
|
m_persister.unpersist(*this);
|
|
}
|
|
|
|
bool can_be_used_as_hub(const char* zName,
|
|
const mxs::MonitorServer::ConnectionSettings& settings,
|
|
Clustrix::Softfailed softfailed);
|
|
|
|
SERVER* server() const
|
|
{
|
|
return m_pServer;
|
|
}
|
|
|
|
MYSQL* connection() const
|
|
{
|
|
return m_pCon;
|
|
}
|
|
|
|
MYSQL* release_connection()
|
|
{
|
|
MYSQL* pCon = m_pCon;
|
|
m_pCon = nullptr;
|
|
return pCon;
|
|
}
|
|
|
|
std::string to_string() const
|
|
{
|
|
std::stringstream ss;
|
|
ss << "{" << m_id << ", " << m_ip << ", " << m_mysql_port << ", " << m_health_port << "}";
|
|
return ss.str();
|
|
}
|
|
|
|
void print(std::ostream& o) const
|
|
{
|
|
o << to_string();
|
|
}
|
|
|
|
private:
|
|
Persister& m_persister;
|
|
int m_id;
|
|
Clustrix::Status m_status;
|
|
Clustrix::SubState m_substate;
|
|
int m_instance;
|
|
std::string m_ip;
|
|
int m_mysql_port { DEFAULT_MYSQL_PORT };
|
|
int m_health_port { DEFAULT_HEALTH_PORT };
|
|
int m_health_check_threshold { DEFAULT_HEALTH_CHECK_THRESHOLD_VALUE };
|
|
int m_nRunning { 0 };
|
|
SERVER* m_pServer { nullptr };
|
|
MYSQL* m_pCon { nullptr };
|
|
};
|
|
|
|
inline std::ostream& operator << (std::ostream& out, const ClustrixNode& x)
|
|
{
|
|
x.print(out);
|
|
return out;
|
|
}
|