Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions include/AuroraMonitorDecision.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @file AuroraMonitorDecision.h
* @brief Pure decision functions for Aurora monitor blue/green detection.
*
* Extracted from MySQL_Monitor_Connection_Pool for unit testability.
* These functions have no global state dependencies.
*/

#ifndef __CLASS_AURORA_MONITOR_DECISION_H
#define __CLASS_AURORA_MONITOR_DECISION_H

/**
* @brief Determine if a returned connection should be rejected based on
* switchover timing.
*
* A connection is considered stale (pre-switchover) if it was checked out
* before the switchover was detected for its hostname.
*
* @param checkout_time Monotonic timestamp when the connection was checked out or created.
* 0 means unknown (non-Aurora monitor thread); always accepted.
* @param switchover_time Timestamp when the switchover was detected for the hostname.
* 0 means no switchover recorded.
* @return true if the connection should be rejected (stale), false if it can be re-pooled.
*/
inline bool should_reject_pooled_connection(
unsigned long long checkout_time,
unsigned long long switchover_time
) {
if (switchover_time == 0) return false;
if (checkout_time == 0) return false;
return checkout_time < switchover_time;
}

#endif // __CLASS_AURORA_MONITOR_DECISION_H
10 changes: 10 additions & 0 deletions include/DNS_Cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ class DNS_Cache {
void clear();
bool empty() const;
std::string lookup(const std::string& hostname, size_t* ip_count) const;
/**
* @brief Check if a hostname's cached IPs include the given IP.
* @param hostname The hostname to look up in the cache.
* @param ip The IP address to search for.
* @return true if the IP is found, or if the cache is disabled, or if
* the hostname is not in the cache (no evidence of mismatch).
* Returns false only when the hostname IS cached and the IP is
* NOT among its resolved addresses.
*/
bool contains_ip(const std::string& hostname, const std::string& ip) const;

private:
struct IP_ADDR {
Expand Down
6 changes: 6 additions & 0 deletions include/MySQL_Monitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,12 @@ class MySQL_Monitor_State_Data {
* @details Currently only used by 'group_replication'.
*/
uint64_t init_time = 0;
/**
* @brief Monotonic time when a pooled connection was checked out via get_connection().
* @details Used by blue/green switchover detection to reject pre-switchover connections.
* Set once at checkout, never modified. 0 if connection was newly created.
*/
unsigned long long pool_checkout_time = 0;
/**
* @brief Used by GroupReplication to determine if servers reported by cluster 'members' are already monitored.
* @details This way we avoid non-needed locking on 'MySQL_HostGroups_Manager' for server search.
Expand Down
30 changes: 30 additions & 0 deletions lib/DNS_Cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,33 @@ bool DNS_Cache::empty() const {

return result;
}

/**
* @brief Check if a hostname's cached IPs include the given IP.
* @param hostname The hostname to look up in the cache.
* @param ip The IP address to search for.
* @return true if found, cache disabled, or hostname not cached. false only
* when hostname IS cached and ip is NOT among its resolved addresses.
*/
bool DNS_Cache::contains_ip(const std::string& hostname, const std::string& ip) const {
if (!enabled) return true;

int rc = pthread_rwlock_rdlock(&rwlock_);
assert(rc == 0);

bool found = true;
auto itr = records.find(hostname);
if (itr != records.end()) {
found = false;
for (const auto& cached_ip : itr->second.ips) {
if (cached_ip == ip) {
found = true;
break;
}
}
}

rc = pthread_rwlock_unlock(&rwlock_);
assert(rc == 0);
return found;
}
Loading