2025-08-10 01:34:16 +02:00

227 lines
7.5 KiB
C

#ifndef NODECONNPOOL_H_
#define NODECONNPOOL_H_
#include <app/log/Logger.h>
#include <app/App.h>
#include <common/net/sock/NetworkInterfaceCard.h>
#include <common/net/sock/StandardSocket.h>
#include <common/net/sock/NicAddressStatsList.h>
#include <common/threading/Mutex.h>
#include <common/threading/Condition.h>
#include <common/toolkit/ListTk.h>
#include <common/toolkit/SocketTk.h>
#include <common/Common.h>
#include "ConnectionList.h"
#include "ConnectionListIter.h"
#include "DevicePriorityContext.h"
// forward declaration
struct App;
struct Node;
struct NodeConnPoolStats;
typedef struct NodeConnPoolStats NodeConnPoolStats;
struct NodeConnPoolErrorState;
typedef struct NodeConnPoolErrorState NodeConnPoolErrorState;
struct NodeConnPool;
typedef struct NodeConnPool NodeConnPool;
extern void NodeConnPool_init(NodeConnPool* this, struct App* app, struct Node* parentNode,
unsigned short streamPort, NicAddressList* nicList, NicAddressList* localRdmaNicList);
extern NodeConnPool* NodeConnPool_construct(struct App* app, struct Node* parentNode,
unsigned short streamPort, NicAddressList* nicList, NicAddressList* localRdmaNicList);
extern void NodeConnPool_uninit(NodeConnPool* this);
extern void NodeConnPool_destruct(NodeConnPool* this);
extern Socket* NodeConnPool_acquireStreamSocket(NodeConnPool* this);
extern Socket* NodeConnPool_acquireStreamSocketEx(NodeConnPool* this, bool allowWaiting,
DevicePriorityContext* devPrioCtx);
extern void NodeConnPool_releaseStreamSocket(NodeConnPool* this, Socket* sock);
extern void NodeConnPool_invalidateStreamSocket(NodeConnPool* this, Socket* sock);
extern unsigned NodeConnPool_disconnectAvailableStreams(NodeConnPool* this);
extern unsigned NodeConnPool_disconnectAndResetIdleStreams(NodeConnPool* this);
extern bool NodeConnPool_updateInterfaces(NodeConnPool* this, unsigned short streamPort,
NicAddressList* nicList);
extern void __NodeConnPool_invalidateSpecificStreamSocket(NodeConnPool* this, Socket* sock);
extern unsigned __NodeConnPool_invalidateAvailableStreams(NodeConnPool* this,
bool idleStreamsOnly, bool closeOnRelease);
extern void __NodeConnPool_resetStreamsIdleFlag(NodeConnPool* this);
extern bool __NodeConnPool_applySocketOptionsPreConnect(NodeConnPool* this, Socket* sock);
extern bool __NodeConnPool_applySocketOptionsConnected(NodeConnPool* this, Socket* sock);
extern void __NodeConnPool_statsAddNic(NodeConnPool* this, NicAddrType_t nicType);
extern void __NodeConnPool_statsRemoveNic(NodeConnPool* this, NicAddrType_t nicType);
extern void __NodeConnPool_setCompleteFail(NodeConnPool* this);
extern void __NodeConnPool_setConnSuccess(NodeConnPool* this, struct in_addr lastSuccessPeerIP,
NicAddrType_t lastSuccessNicType);
extern bool __NodeConnPool_equalsLastSuccess(NodeConnPool* this, struct in_addr lastSuccessPeerIP,
NicAddrType_t lastSuccessNicType);
extern bool __NodeConnPool_isLastSuccessInitialized(NodeConnPool* this);
extern bool __NodeConnPool_shouldPrintConnectedLogMsg(NodeConnPool* this,
struct in_addr currentPeerIP, NicAddrType_t currentNicType);
extern bool __NodeConnPool_shouldPrintConnectFailedLogMsg(NodeConnPool* this,
struct in_addr currentPeerIP, NicAddrType_t currentNicType);
extern void NodeConnPool_getStats(NodeConnPool* this, NodeConnPoolStats* outStats);
extern unsigned NodeConnPool_getFirstPeerName(NodeConnPool* this, NicAddrType_t nicType,
ssize_t outBufLen, char* outBuf, bool* outIsNonPrimary);
/**
* @param localNicList copied
* @param localNicCaps copied
* @param localRdmaNicList copied
*/
extern void NodeConnPool_updateLocalInterfaces(NodeConnPool* this, NicAddressList* localNicList,
NicListCapabilities* localNicCaps, NicAddressList* localRdmaNicList);
// getters & setters
/**
* Called to lock the internal mute when accessing resources that may be
* modified by other threads. Case in point: NodeConnPool_getNicListLocked.
*/
static inline void NodeConnPool_lock(NodeConnPool* this);
/**
* Release the lock acquired by NodeConnPool_lock.
*/
static inline void NodeConnPool_unlock(NodeConnPool* this);
static inline void NodeConnPool_cloneNicList(NodeConnPool* this, NicAddressList* nicList);
static inline NicAddressList* NodeConnPool_getNicListLocked(NodeConnPool* this);
static inline void NodeConnPool_setLocalNicCaps(NodeConnPool* this,
NicListCapabilities* localNicCaps);
static inline unsigned short NodeConnPool_getStreamPort(NodeConnPool* this);
static inline void NodeConnPool_setLogConnErrors(NodeConnPool* this, bool logConnErrors);
static inline bool __NodeConnPool_getWasLastTimeCompleteFail(NodeConnPool* this);
/**
* Holds statistics about currently established connections.
*/
struct NodeConnPoolStats
{
unsigned numEstablishedStd;
unsigned numEstablishedRDMA;
};
/**
* Holds state of failed connects to avoid log spamming with conn errors.
*/
struct NodeConnPoolErrorState
{
struct in_addr lastSuccessPeerIP; // the last IP that we connected to successfully
NicAddrType_t lastSuccessNicType; // the last nic type that we connected to successfully
bool wasLastTimeCompleteFail; // true if last attempt failed on all routes
};
/**
* This class represents a pool of stream connections to a certain node.
*/
struct NodeConnPool
{
struct App* app;
NicAddressList nicList;
NicAddressList localRdmaNicList;
NicAddressStatsList rdmaNicStatsList;
ConnectionList connList;
struct Node* parentNode; // backlink to the node object which to which this conn pool belongs
unsigned short streamPort;
NicListCapabilities localNicCaps;
unsigned availableConns; // available established conns
unsigned establishedConns; // not equal to connList.size!!
unsigned maxConns;
unsigned fallbackExpirationSecs; // expiration time for conns to fallback interfaces
unsigned maxConcurrentAttempts;
int rdmaNicCount;
NodeConnPoolStats stats;
NodeConnPoolErrorState errState;
bool logConnErrors; // false to disable logging during acquireStream()
bool enableTCPFallback;
Mutex mutex;
Condition changeCond;
struct semaphore connSemaphore;
};
void NodeConnPool_lock(NodeConnPool* this)
{
Mutex_lock(&this->mutex); // L O C K
}
void NodeConnPool_unlock(NodeConnPool* this)
{
Mutex_unlock(&this->mutex); // U N L O C K
}
/**
* Mutex lock must be held while using the returned pointer.
*/
NicAddressList* NodeConnPool_getNicListLocked(NodeConnPool* this)
{
return &this->nicList;
}
/**
* Retrieve NICs for the connection pool.
*
* @param nicList an uninitialized NicAddressList. Caller is responsible for
* memory management.
*/
void NodeConnPool_cloneNicList(NodeConnPool* this, NicAddressList* nicList)
{
Mutex_lock(&this->mutex); // L O C K
ListTk_cloneNicAddressList(&this->nicList, nicList, true);
Mutex_unlock(&this->mutex); // U N L O C K
}
/**
* @param localNicCaps will be copied
*/
void NodeConnPool_setLocalNicCaps(NodeConnPool* this, NicListCapabilities* localNicCaps)
{
Mutex_lock(&this->mutex); // L O C K
this->localNicCaps = *localNicCaps;
Mutex_unlock(&this->mutex); // U N L O C K
}
unsigned short NodeConnPool_getStreamPort(NodeConnPool* this)
{
unsigned short retVal;
Mutex_lock(&this->mutex); // L O C K
retVal = this->streamPort;
Mutex_unlock(&this->mutex); // U N L O C K
return retVal;
}
void NodeConnPool_setLogConnErrors(NodeConnPool* this, bool logConnErrors)
{
this->logConnErrors = logConnErrors;
}
/**
* @return true if connection on all available routes failed last time we tried.
*/
bool __NodeConnPool_getWasLastTimeCompleteFail(NodeConnPool* this)
{
return this->errState.wasLastTimeCompleteFail;
}
#endif /*NODECONNPOOL_H_*/