The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Data Structures | Typedefs | Enumerations | Functions | Variables
cluster.h File Reference

Common functions for interacting with Redis cluster via Hiredis. More...

#include <freeradius-devel/server/pool.h>
+ Include dependency graph for cluster.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  fr_redis_cluster_state_t
 Redis connection sequence state. More...
 

Typedefs

typedef struct fr_redis_cluster_key_slot_s fr_redis_cluster_key_slot_t
 
typedef struct fr_redis_cluster_node_s fr_redis_cluster_node_t
 
typedef struct fr_redis_cluster fr_redis_cluster_t
 

Enumerations

enum  fr_redis_cluster_rcode_t {
  FR_REDIS_CLUSTER_RCODE_IGNORED = 1 ,
  FR_REDIS_CLUSTER_RCODE_SUCCESS = 0 ,
  FR_REDIS_CLUSTER_RCODE_FAILED = -1 ,
  FR_REDIS_CLUSTER_RCODE_NO_CONNECTION = -2 ,
  FR_REDIS_CLUSTER_RCODE_BAD_INPUT = -3
}
 Return values for internal functions. More...
 

Functions

fr_redis_cluster_tfr_redis_cluster_alloc (TALLOC_CTX *ctx, CONF_SECTION *module, fr_redis_conf_t *conf, bool enable_triggers, char const *log_prefix, char const *trigger_prefix, fr_pair_list_t *trigger_args)
 Allocate and initialise a new cluster structure. More...
 
void * fr_redis_cluster_conn_create (TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
 Create a new connection to a Redis node. More...
 
int fr_redis_cluster_ipaddr (fr_ipaddr_t *out, fr_redis_cluster_node_t const *node)
 Return the ipaddr of a particular node. More...
 
fr_redis_cluster_node_t const * fr_redis_cluster_master (fr_redis_cluster_t *cluster, fr_redis_cluster_key_slot_t const *key_slot)
 Return the master node that would be used for a particular key. More...
 
bool fr_redis_cluster_min_version (fr_redis_cluster_t *cluster, char const *min_version)
 Check if members of the cluster are above a certain version. More...
 
ssize_t fr_redis_cluster_node_addr_by_role (TALLOC_CTX *ctx, fr_socket_t *out[], fr_redis_cluster_t *cluster, bool is_master, bool is_slave)
 Return an array of IP addresses belonging to masters or slaves. More...
 
int fr_redis_cluster_pool_by_node_addr (fr_pool_t **pool, fr_redis_cluster_t *cluster, fr_socket_t *node, bool create)
 Get the pool associated with a node in the cluster. More...
 
int fr_redis_cluster_port (uint16_t *out, fr_redis_cluster_node_t const *node)
 Return the port of a particular node. More...
 
fr_redis_cluster_rcode_t fr_redis_cluster_remap (request_t *request, fr_redis_cluster_t *cluster, fr_redis_conn_t *conn)
 Perform a runtime remap of the cluster. More...
 
fr_redis_cluster_node_t const * fr_redis_cluster_slave (fr_redis_cluster_t *cluster, fr_redis_cluster_key_slot_t const *key_slot, uint8_t slave_num)
 Return the slave node that would be used for a particular key. More...
 
fr_redis_cluster_key_slot_t const * fr_redis_cluster_slot_by_key (fr_redis_cluster_t *cluster, request_t *request, uint8_t const *key, size_t key_len)
 Implements the key slot selection scheme used by freeradius. More...
 
fr_redis_rcode_t fr_redis_cluster_state_init (fr_redis_cluster_state_t *state, fr_redis_conn_t **conn, fr_redis_cluster_t *cluster, request_t *request, uint8_t const *key, size_t key_len, bool read_only)
 Resolve a key to a pool, and reserve a connection in that pool. More...
 
fr_redis_rcode_t fr_redis_cluster_state_next (fr_redis_cluster_state_t *state, fr_redis_conn_t **conn, fr_redis_cluster_t *cluster, request_t *request, fr_redis_rcode_t status, redisReply **reply)
 Get the next connection to attempt a command against. More...
 

Variables

fr_table_num_sorted_t const fr_redis_cluster_rcodes_table []
 
size_t fr_redis_cluster_rcodes_table_len
 

Detailed Description

Common functions for interacting with Redis cluster via Hiredis.

Id
f0a0aaf99fa4c22e26d1d8c7a71b3257c6e0a39a
Author
Arran Cudbard-Bell
Id
31f45df57f6ae956d692be5048c904442b170ace
Author
Arran Cudbard-Bell

Definition in file cluster.h.


Data Structure Documentation

◆ fr_redis_cluster_state_t

struct fr_redis_cluster_state_t

Redis connection sequence state.

Tracks how many operations we've performed attempting to execute a single command.

Used by callers of the cluster code. Allocated on the stack and passed to fr_redis_cluster_state_init and fr_redis_cluster_state_next.

Definition at line 49 of file cluster.h.

+ Collaboration diagram for fr_redis_cluster_state_t:
Data Fields
bool close_conn Set by caller of fr_redis_cluster_state_next, to indicate that connection must be closed, as it's now in an unknown state.
uint32_t in_pool How many available connections are there in the pool.
uint8_t const * key Key we performed hashing on.
size_t key_len Length of the key.
fr_redis_cluster_node_t * node Node we're communicating with.
uint32_t reconnects How many connections we've tried in this pool.
uint32_t redirects How many redirects have we followed.
uint32_t retries How many times we've received TRYAGAIN.

Typedef Documentation

◆ fr_redis_cluster_key_slot_t

Definition at line 1 of file cluster.h.

◆ fr_redis_cluster_node_t

Definition at line 1 of file cluster.h.

◆ fr_redis_cluster_t

Definition at line 1 of file cluster.h.

Enumeration Type Documentation

◆ fr_redis_cluster_rcode_t

Return values for internal functions.

Enumerator
FR_REDIS_CLUSTER_RCODE_IGNORED 

Operation ignored.

FR_REDIS_CLUSTER_RCODE_SUCCESS 

Operation completed successfully.

FR_REDIS_CLUSTER_RCODE_FAILED 

Operation failed.

FR_REDIS_CLUSTER_RCODE_NO_CONNECTION 

Operation failed because we couldn't find a live connection.

FR_REDIS_CLUSTER_RCODE_BAD_INPUT 

Validation error.

Definition at line 67 of file cluster.h.

Function Documentation

◆ fr_redis_cluster_alloc()

fr_redis_cluster_t* fr_redis_cluster_alloc ( TALLOC_CTX *  ctx,
CONF_SECTION module,
fr_redis_conf_t conf,
bool  triggers_enabled,
char const *  log_prefix,
char const *  trigger_prefix,
fr_pair_list_t trigger_args 
)

Allocate and initialise a new cluster structure.

This holds all the data necessary to manage a pool of pools for a specific redis cluster.

Note
Will not error out unless cs.pool.start > 0. This is consistent with other pool based modules/code.
Parameters
ctxto link the lifetime of the cluster structure to.
moduleConfiguration section to search for 'server' conf pairs in.
confBase redis server configuration. Cluster nodes share database number and password.
triggers_enabledWhether triggers should be enabled.
log_prefixCustom log prefix. Defaults to
rlm_<module> (<instance>) 
.
trigger_prefixCustom trigger prefix. Defaults to
modules.<module>.pool 
.
trigger_argsArgument pairs to pass to the trigger in addition to Connection-Pool-Server, and Connection-Pool-Port (which are always set by the cluster code).
Returns

Definition at line 2257 of file cluster.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_redis_cluster_conn_create()

void* fr_redis_cluster_conn_create ( TALLOC_CTX *  ctx,
void *  instance,
fr_time_delta_t  timeout 
)

Create a new connection to a Redis node.

Parameters
[in]ctxto allocate connection structure in. Will be freed at the same time as the pool.
[in]instancedata of type fr_redis_cluster_node_t. Holds parameters for establishing new connection.
[in]timeoutThe maximum time allowed to complete the connection.
Returns

Definition at line 1464 of file cluster.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_redis_cluster_ipaddr()

int fr_redis_cluster_ipaddr ( fr_ipaddr_t out,
fr_redis_cluster_node_t const *  node 
)

Return the ipaddr of a particular node.

Parameters
[out]outIpaddr of the node.
[in]nodeto get ip address from.
Returns
  • 0 on success.
  • -1 on failure (node is NULL).

Definition at line 1668 of file cluster.c.

+ Here is the caller graph for this function:

◆ fr_redis_cluster_master()

fr_redis_cluster_node_t const* fr_redis_cluster_master ( fr_redis_cluster_t cluster,
fr_redis_cluster_key_slot_t const *  key_slot 
)

Return the master node that would be used for a particular key.

Parameters
[in]clusterTo resolve key in.
[in]key_slotto resolve to node.
Returns
  • The current master node.
  • NULL if no master node is currently assigned to a particular key slot.

Definition at line 1635 of file cluster.c.

+ Here is the caller graph for this function:

◆ fr_redis_cluster_min_version()

bool fr_redis_cluster_min_version ( fr_redis_cluster_t cluster,
char const *  min_version 
)

Check if members of the cluster are above a certain version.

Parameters
clusterto perform check on.
min_versionthat must be found on each node for the check to succeed. Must be in the format
<major>.<minor>.<release> 
.
Returns
  • true if all contactable members are above min_version.
  • false if at least one member if not above minimum version (use fr_strerror to retrieve node information).

Definition at line 2198 of file cluster.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_redis_cluster_node_addr_by_role()

ssize_t fr_redis_cluster_node_addr_by_role ( TALLOC_CTX *  ctx,
fr_socket_t out[],
fr_redis_cluster_t cluster,
bool  is_master,
bool  is_slave 
)

Return an array of IP addresses belonging to masters or slaves.

Note
We return IP addresses as they're safe to use across cluster remaps.
Result array must be freed (talloc_free()) after use.
Parameters
[in]ctxto allocate array of IP addresses in.
[out]outWhere to write the addresses of the nodes.
[in]clusterto search for nodes in.
[in]is_masterIf true, include the addresses of all the master nodes.
[in]is_slaveIf true, include the addresses of all the slaves nodes.
Returns
the number of ip addresses written to out.

Definition at line 2134 of file cluster.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_redis_cluster_pool_by_node_addr()

int fr_redis_cluster_pool_by_node_addr ( fr_pool_t **  pool,
fr_redis_cluster_t cluster,
fr_socket_t node_addr,
bool  create 
)

Get the pool associated with a node in the cluster.

Note
This is used for testing only. It's not ifdef'd out because tests need to run against production builds too.
Parameters
[out]poolassociated with the node.
[in]clusterto search for node in.
[in]node_addrto retrieve pool for. Specifies IP and port of node.
[in]createEstablish a connection to the specified node if it was previously unknown to the cluster client.
Returns
  • 0 on success.
  • -1 if no such node exists.

Definition at line 2066 of file cluster.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_redis_cluster_port()

int fr_redis_cluster_port ( uint16_t out,
fr_redis_cluster_node_t const *  node 
)

Return the port of a particular node.

Parameters
[out]outPort of the node.
[in]nodeto get ip address from.
Returns
  • 0 on success.
  • -1 on failure (node is NULL).

Definition at line 1685 of file cluster.c.

+ Here is the caller graph for this function:

◆ fr_redis_cluster_remap()

fr_redis_cluster_rcode_t fr_redis_cluster_remap ( request_t request,
fr_redis_cluster_t cluster,
fr_redis_conn_t conn 
)

Perform a runtime remap of the cluster.

Note
Errors may be retrieved with fr_strerror().
Must be called with the cluster mutex free.
Parameters
[in]requestThe current request.
[in,out]clusterto remap.
[in]connto use to query the cluster.
Returns
  • FR_REDIS_CLUSTER_RCODE_IGNORED if 'cluster slots' returned an error (indicating clustering not supported).
  • FR_REDIS_CLUSTER_RCODE_SUCCESS on success.
  • FR_REDIS_CLUSTER_RCODE_FAILED if issuing the 'cluster slots' command resulted in a protocol error.
  • FR_REDIS_CLUSTER_RCODE_NO_CONNECTION connection failure.
  • FR_REDIS_CLUSTER_RCODE_BAD_INPUT on validation failure (bad data returned from Redis).

Definition at line 1005 of file cluster.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_redis_cluster_slave()

fr_redis_cluster_node_t const* fr_redis_cluster_slave ( fr_redis_cluster_t cluster,
fr_redis_cluster_key_slot_t const *  key_slot,
uint8_t  slave_num 
)

Return the slave node that would be used for a particular key.

Parameters
[in]clusterTo resolve key in.
[in]key_slotTo resolve to node.
[in]slave_num0..n.
Returns
  • A slave node.
  • NULL if no slave node is assigned, or is at the specific key slot.

Definition at line 1651 of file cluster.c.

+ Here is the caller graph for this function:

◆ fr_redis_cluster_slot_by_key()

fr_redis_cluster_key_slot_t const* fr_redis_cluster_slot_by_key ( fr_redis_cluster_t cluster,
request_t request,
uint8_t const *  key,
size_t  key_len 
)

Implements the key slot selection scheme used by freeradius.

Like the scheme in the clustering specification but with some differences if the key is NULL or zero length, then a random keyslot is chosen.

If there's only a single node in the cluster, then we avoid the CRC16 and just use key slot 0.

Parameters
clusterto determine key slot for.
requestThe current request.
keythe key to resolve.
key_lenthe length of the key.
Returns
pointer to key slot key resolves to.

Definition at line 1599 of file cluster.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_redis_cluster_state_init()

fr_redis_rcode_t fr_redis_cluster_state_init ( fr_redis_cluster_state_t state,
fr_redis_conn_t **  conn,
fr_redis_cluster_t cluster,
request_t request,
uint8_t const *  key,
size_t  key_len,
bool  read_only 
)

Resolve a key to a pool, and reserve a connection in that pool.

This should be used with fr_redis_cluster_state_next, and fr_redis_command_status, to transparently locate the cluster node we need to perform the operation on.

Example code below shows how this function is used in conjunction with fr_redis_cluster_state_next to follow redirects, and reconnect handles.

int s_ret;
redis_conn_state state;
redisReply *reply;
for (s_ret = fr_redis_cluster_state_init(&state, &conn, cluster, key, key_len, false);
s_ret = fr_redis_cluster_state_next(&state, &conn, cluster, request, status, &reply)) {
reply = redisCommand(conn->handle, "SET foo bar");
status = fr_redis_command_status(conn, reply);
}
// Reply is freed if ret == REDIS_RCODE_TRY_AGAIN, but left in all other cases to allow error
// processing, or extraction of results.
if (s_ret != REDIS_RCODE_SUCCESS) {
// Error
}
// Success
fr_redis_rcode_t fr_redis_cluster_state_next(fr_redis_cluster_state_t *state, fr_redis_conn_t **conn, fr_redis_cluster_t *cluster, request_t *request, fr_redis_rcode_t status, redisReply **reply)
Get the next connection to attempt a command against.
Definition: cluster.c:1859
fr_redis_rcode_t fr_redis_cluster_state_init(fr_redis_cluster_state_t *state, fr_redis_conn_t **conn, fr_redis_cluster_t *cluster, request_t *request, uint8_t const *key, size_t key_len, bool read_only)
Resolve a key to a pool, and reserve a connection in that pool.
Definition: cluster.c:1737
redisContext * handle
Hiredis context used when issuing commands.
Definition: base.h:101
static void fr_redis_reply_free(redisReply **reply)
Wrap freeReplyObject so we consistently check for NULL pointers.
Definition: base.h:64
fr_redis_rcode_t fr_redis_command_status(fr_redis_conn_t *conn, redisReply *reply)
Check the reply for errors.
Definition: redis.c:71
fr_redis_rcode_t
Codes are ordered inversely by priority.
Definition: base.h:87
@ REDIS_RCODE_SUCCESS
Operation was successful.
Definition: base.h:88
@ REDIS_RCODE_TRY_AGAIN
Try the operation again.
Definition: base.h:90
Connection handle, holding a redis context.
Definition: base.h:100
Parameters
[out]stateto track current pool and various counters, will be initialised.
[out]connWhere to write the reserved connection to.
[in]clusterof pools.
[in]requestThe current request.
[in]keyto resolve to a cluster node/pool. If no key is NULL or key_len is 0 a random slot will be chosen.
[in]key_lenLength of the key.
[in]read_onlyIf true, will use random slave pool in preference to the master, falling back to the master if no slaves are available.
Returns
  • REDIS_RCODE_TRY_AGAIN - try your command with this connection (provided via command).
  • REDIS_RCODE_RECONNECT - when no additional connections available.

Definition at line 1737 of file cluster.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_redis_cluster_state_next()

fr_redis_rcode_t fr_redis_cluster_state_next ( fr_redis_cluster_state_t state,
fr_redis_conn_t **  conn,
fr_redis_cluster_t cluster,
request_t request,
fr_redis_rcode_t  status,
redisReply **  reply 
)

Get the next connection to attempt a command against.

Will process reconnect and redirect states performing the actions necessary.

If a remap is in progress, has occurred within the last second, has recently failed, or fails, the '-MOVE' will be treated as a temporary redirect (-ASK).

This allows the server to be more responsive during remaps, as unless the worker has been redirected to a node we don't currently have a pool for, it can grab a connection for the node it was redirected to, and continue.

Note
Irrespective of return code, the connection passed via conn will be released, A new connection to attempt command on will be provided via conn.
reply will be automatically freed and set to NULL if a new connection is provided in all other cases, the caller is responsible for freeing the reply.
Parameters
[in,out]statecontaining the current pool, and various counters which control retries, and limit redirects.
[in,out]connwe received the '-ASK' or '-MOVE' redirect on. Will be replaced with a connection in the new pool the key points to.
[in]requestThe current request.
[in]clusterof pools.
[in]statusof the last command, must be REDIS_RCODE_MOVE or REDIS_RCODE_ASK.
[in]replyfrom last command. Freed if 0 is returned, else caller must free.
Returns
  • REDIS_RCODE_SUCCESS - on success.
  • REDIS_RCODE_TRY_AGAIN - try new connection (provided via conn). Will free reply.
  • REDIS_RCODE_ERROR - on failure or command error.
  • REDIS_RCODE_RECONNECT - when no additional connections available.

Definition at line 1859 of file cluster.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ fr_redis_cluster_rcodes_table

fr_table_num_sorted_t const fr_redis_cluster_rcodes_table[]
extern

Definition at line 277 of file cluster.c.

◆ fr_redis_cluster_rcodes_table_len

size_t fr_redis_cluster_rcodes_table_len
extern

Definition at line 284 of file cluster.c.