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

270 lines
8.2 KiB
C

#ifndef NODE_H_
#define NODE_H_
#include <common/Common.h>
#include <common/nodes/NumNodeID.h>
#include <common/threading/Condition.h>
#include <common/threading/Mutex.h>
#include <common/threading/RWLock.h>
#include <common/toolkit/StringTk.h>
#include <common/toolkit/Time.h>
#include <linux/kref.h>
#include "NodeConnPool.h"
// forward declaration
struct App;
enum NodeType;
typedef enum NodeType NodeType;
struct Node;
typedef struct Node Node;
extern void Node_init(Node* this, struct App* app, const char* nodeID, NumNodeID nodeNumID,
unsigned short portUDP, unsigned short portTCP, NicAddressList* nicList,
NicAddressList* localRdmaNicList);
extern Node* Node_construct(struct App* app, const char* nodeID, NumNodeID nodeNumID,
unsigned short portUDP, unsigned short portTCP, NicAddressList* nicList,
NicAddressList* localRdmaNicList);
extern void Node_uninit(Node* this);
extern void __Node_destruct(Node* this);
extern void Node_updateLastHeartbeatT(Node* this);
extern bool Node_updateInterfaces(Node* this, unsigned short portUDP, unsigned short portTCP,
NicAddressList* nicList);
/**
* NodeString is a structure to hold a formatted string representation related to a Node.
*
* This structure provides a fixed-size buffer that can store various strings associated with a
* Node, such as the node's alias or a combination of the alias and node type. It is designed to be
* used in functions where thread-safe operations are required to copy or format node-related
* strings into a pre-allocated buffer.
*/
typedef struct NodeString {
// The mgmtd only allows aliases up to 32 characters with characters limited to "a-zA-Z0-9.-_".
// It is also used for the AliasWithTypeStr which may be up to 66 bytes:
//
// `<32 CHARACTER ALIAS> [<undefined/invalid>:4294967295]\0`
//
// Because it is unlikely we ever encounter an <undefined/invalid> node with an ID that is the
// uint32 max and a 32 character alias the buffer size is set to 64 bytes which corresponds to
// the cache line on most architectures. Longer strings will be truncated and end with ellipses.
char buf[64];
} NodeString;
/**
* Node_copyAliasWithTypeStr copies the alias, numerical ID (for servers) and the node type in a
* human-readable string. Intended as a convenient way to get a string identifying a node/client for
* log messages.
*
* @param this is which Node to return an identifying string for.
* @param outStr is where the string should be copied to.
*
* IMPORTANT: With the shift from string IDs to aliases in b8.0, aliases may be updated dynamically.
* Callers MUST use this function to access the alias.
*/
extern void Node_copyAliasWithTypeStr(Node *this, NodeString *outStr);
/**
* Node_copyAlias gets a copy of the node's alias (formerly known as a string ID).
*
* @param this is a pointer to the Node structure with the alias to get.
* @param outStr is where the alias should be copied to.
*
* @return string remains valid until Node_putAlias is called; caller must not free the string.
* IMPORTANT: With the shift from string IDs to aliases in b8.0, aliases may be updated dynamically.
* Callers MUST use this function to access the alias.
*/
extern void Node_copyAlias(Node *this, NodeString *outStr);
// static
extern const char* Node_nodeTypeToStr(NodeType nodeType);
// getters & setters
/**
* Node_setNodeAliasAndType() handles thread safe updates to the alias (formerly node string ID),
* node type, and nodeAliasWithTypeStr. It blocks until other writers (unlikely) have finished
* making updates or readers (more likely) have released these fields with the corresponding
* Node_putX functions.
*
* @param this is a pointer to the Node structure with the alias, nodeType, and
* nodeAliasWithTypeStr.
* @param alias is the alias to set. Copies the alias and does not take ownership of it. The caller
* is responsible for freeing the alias when appropriate.
* @param nodeType the nodeType to set.
*
* The alias or nodeType can be respectively NULL or set to NODETYPE_Invalid to only update one
* field and update the nodeAliasWithTypeStr.
*/
extern bool Node_setNodeAliasAndType(Node* this, const char *alias, NodeType nodeType);
static inline NumNodeID Node_getNumID(Node* this);
static inline void Node_setNumID(Node* this, const NumNodeID numID);
static inline void Node_cloneNicList(Node* this, NicAddressList* nicList);
static inline void Node_updateLocalInterfaces(Node* this, NicAddressList* localNicList,
NicListCapabilities* localNicCaps, NicAddressList* localRdmaNicList);
static inline NodeConnPool* Node_getConnPool(Node* this);
static inline void Node_setIsActive(Node* this, bool isActive);
static inline bool Node_getIsActive(Node* this);
static inline unsigned short Node_getPortUDP(Node* this);
static inline unsigned short Node_getPortTCP(Node* this);
static inline NodeType Node_getNodeType(Node* this);
static inline const char* Node_getNodeTypeStr(Node* this);
enum NodeType
{NODETYPE_Invalid = 0, NODETYPE_Meta = 1, NODETYPE_Storage = 2, NODETYPE_Client = 3,
NODETYPE_Mgmt = 4};
struct Node
{
NumNodeID numID; // numeric ID, assigned by mgmtd server store (unused for clients)
// Must be locked before accessing the alias, nodeType, or nodeAliasWithTypeStr.
RWLock aliasAndTypeMu;
char* alias; // alias (formerly string ID): initially generated locally on each node but thread safe and able to be updated as of b8.0
NodeType nodeType; // set by NodeStore::addOrUpdate()
char* nodeAliasWithTypeStr; // for log messages (initially NULL, initialized when the alias is set/updated)
NodeConnPool* connPool;
unsigned short portUDP;
Time lastHeartbeatT; // last heartbeat receive time
bool isActive; // for internal use by the NodeStore only
Mutex mutex;
Condition changeCond; // for last heartbeat time only
struct kref references;
/* used by node tree */
struct {
struct rb_node rbTreeElement;
} _nodeTree;
};
static inline Node* Node_get(Node* node)
{
kref_get(&node->references);
return node;
}
static inline void __Node_put(struct kref* ref)
{
__Node_destruct(container_of(ref, Node, references) );
}
static inline int Node_put(Node* node)
{
return kref_put(&node->references, __Node_put);
}
NumNodeID Node_getNumID(Node* this)
{
return this->numID;
}
void Node_setNumID(Node* this, const NumNodeID numID)
{
this->numID = numID;
}
/**
* Retrieve NICs for the node.
*
* @param nicList an uninitialized NicAddressList. Caller is responsible for
* memory management.
*/
void Node_cloneNicList(Node* this, NicAddressList* nicList)
{
NodeConnPool_cloneNicList(this->connPool, nicList);
}
/**
* @param localNicList copied
* @param localNicCaps copied
* @param localRdmaNicList copied
*/
void Node_updateLocalInterfaces(Node* this, NicAddressList* localNicList,
NicListCapabilities* localNicCaps, NicAddressList* localRdmaNicList)
{
NodeConnPool_updateLocalInterfaces(this->connPool, localNicList, localNicCaps, localRdmaNicList);
}
NodeConnPool* Node_getConnPool(Node* this)
{
return this->connPool;
}
/**
* Note: For nodes that live inside a NodeStore, this method should only be called by the NodeStore.
*/
void Node_setIsActive(Node* this, bool isActive)
{
Mutex_lock(&this->mutex);
this->isActive = isActive;
Mutex_unlock(&this->mutex);
}
bool Node_getIsActive(Node* this)
{
bool isActive;
Mutex_lock(&this->mutex);
isActive = this->isActive;
Mutex_unlock(&this->mutex);
return isActive;
}
unsigned short Node_getPortUDP(Node* this)
{
unsigned short retVal;
Mutex_lock(&this->mutex);
retVal = this->portUDP;
Mutex_unlock(&this->mutex);
return retVal;
}
unsigned short Node_getPortTCP(Node* this)
{
return NodeConnPool_getStreamPort(this->connPool);
}
NodeType Node_getNodeType(Node* this)
{
NodeType nodeType;
RWLock_readLock(&this->aliasAndTypeMu);
nodeType = this->nodeType;
RWLock_readUnlock(&this->aliasAndTypeMu);
return nodeType;
}
/**
* Returns human-readable node type string.
*
* @return static string (not alloced => don't free it)
*/
const char* Node_getNodeTypeStr(Node* this)
{
const char* nodeType;
RWLock_readLock(&this->aliasAndTypeMu);
nodeType = Node_nodeTypeToStr(this->nodeType);
RWLock_readUnlock(&this->aliasAndTypeMu);
return nodeType;
}
#endif /*NODE_H_*/