The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
cluster_async.h
Go to the documentation of this file.
1#pragma once
2
3/*
4 * This program is is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19/**
20 * $Id: 7cca41aec89c787bd208a12e1bb9856ce4021d52 $
21 * @file lib/redis/cluster_async.h
22 * @brief Redis asynchronous cluster management
23 *
24 * @copyright 2026 The FreeRADIUS server project
25 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
26 *
27 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
28 */
29RCSIDH(redis_cluster_async_h, "$Id: 7cca41aec89c787bd208a12e1bb9856ce4021d52 $")
30
31#include <freeradius-devel/server/trunk.h>
32#include <freeradius-devel/io/coord_pair.h>
33#include "base.h"
34#include "pipeline.h"
35
36#define KEY_SLOTS 16384 //!< Maximum number of keyslots (should not change).
37
41
42/** Convenience macro to reduce boilerplate
43 *
44 * @param _rcode to process.
45 * @param _cluster Redis cluster thread.
46 * @param _cw Coordinator worker for cluster bootstrapping.
47 * @param _coord_pair_reg Coordinator pair reg for cluster bootstrapping.
48 * @param _error_msg Message to report on error.
49 * @param _error_ret Return value on error.
50 */
51#define REDIS_ASYNC_START_RCODE_PROCESS(_rcode, _cluster, _cw, _coord_pair_reg, _error_msg, _error_ret) \
52switch (_rcode) { \
53case REDIS_ASYNC_RCODE_BOOTSTRAP: \
54 fr_redis_ct_map_bootstrap(_cluster, _cw, _coord_pair_reg); \
55 break; \
56case REDIS_ASYNC_RCODE_GETMAP: \
57 fr_redis_ct_map_get(_cluster, _cw, _coord_pair_reg, false); \
58 break; \
59case REDIS_ASYNC_RCODE_FAIL: \
60case REDIS_ASYNC_RCODE_ERROR: \
61 RPERROR(_error_msg); \
62 return _error_ret; \
63default: \
64 break; \
65}
66
67#define REDIS_ASYNC_COORD_CALLBACKS(_thread_type) \
68typedef enum { \
69 REDIS_COORD_PAIR_CALLBACK_ID = 0, \
70} rlm_redis_coord_t; \
71static void cluster_map_update(UNUSED fr_coord_worker_t *cw, UNUSED fr_coord_pair_reg_t *coord_pair_reg, \
72 fr_pair_list_t const *list, UNUSED fr_time_t now, \
73 module_ctx_t *mctx, UNUSED void *uctx) \
74{ \
75 _thread_type *t = talloc_get_type_abort(mctx->thread, _thread_type); \
76 module_thread_instance_t *mt; \
77 if (fr_redis_ct_map_update(t->rtcluster, list) < 0) return; \
78 mt = module_thread(mctx->mi); \
79 module_thread_force(mt, RLM_MODULE_NOT_SET); \
80 return; \
81} \
82static void cluster_map_fail(UNUSED fr_coord_worker_t *cw, UNUSED fr_coord_pair_reg_t *coord_pair_reg, \
83 fr_pair_list_t const *list, UNUSED fr_time_t now, \
84 module_ctx_t *mctx, UNUSED void *uctx) \
85{ \
86 _thread_type *t = talloc_get_type_abort(mctx->thread, _thread_type); \
87 module_thread_instance_t *mt; \
88 fr_redis_ct_map_fail(t->rtcluster, list); \
89 mt = module_thread(mctx->mi); \
90 module_thread_force(mt, RLM_MODULE_FAIL); \
91 return; \
92} \
93static fr_coord_cb_reg_t coord_callbacks[] = { \
94 FR_COORD_PAIR_CALLBACK(REDIS_COORD_PAIR_CALLBACK_ID), \
95 FR_COORD_CALLBACK_TERMINATOR \
96}; \
97static fr_coord_worker_cb_reg_t worker_callbacks[] = { \
98 FR_COORD_WORKER_PAIR_CALLBACK(REDIS_COORD_PAIR_CALLBACK_ID), \
99 FR_COORD_CALLBACK_TERMINATOR \
100}; \
101static fr_coord_worker_pair_cb_reg_t worker_pair_callbacks[] = { \
102 { .packet_type = FR_REDIS_CLUSTER_MAP_UPDATE, .callback = cluster_map_update }, \
103 { .packet_type = FR_REDIS_CLUSTER_MAP_FAIL, .callback = cluster_map_fail }, \
104 FR_COORD_CALLBACK_TERMINATOR \
105}
106
108 uint8_t const *key, size_t key_len);
109
111
113 fr_redis_ct_key_slot_t const *key_slot, uint8_t replica_num);
114
115char const *fr_redis_ct_ipaddr(fr_redis_ct_node_t const *node);
116
118
121 void *active_uctx, bool active_oneshot);
122
124
126
127#ifdef HAVE_REDIS_SSL
128SSL_CTX *fr_redis_ct_ssl_ctx(fr_redis_ct_t *rtcluster);
129#endif
130
132 fr_coord_pair_reg_t *coord_pair_reg);
133
135 fr_coord_pair_reg_t *coord_pair_reg, bool force);
136
137int fr_redis_ct_map_update(fr_redis_ct_t *thread, fr_pair_list_t const *list);
138
140
142 fr_redis_ct_t *rtcluster, uint8_t const *key, size_t key_len,
144
146
148
150
152
154
156
158 fr_redis_ct_t *rtcluster, bool is_master, bool is_replica);
159
#define RCSIDH(h, id)
Definition build.h:561
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
bool read_only
Should this command be run read only.
request_t * request
Request this command set relates to.
size_t key_len
Length of key.
fr_redis_ct_node_t * node
Specific node to run command set on.
fr_redis_ct_key_slot_t const * key_slot
Key slot identified from the command key.
fr_redis_ct_t * rtcluster
Cluster this command set is running on.
uint8_t const * key
Key used to identify key slot.
fr_redis_command_set_t * cmds
Command set to run.
Structure for holding the state of an async redis command set.
Thread local state for a cluster.
int fr_redis_ct_map_update(fr_redis_ct_t *thread, fr_pair_list_t const *list)
Update a Redis cluster map from a pair list returned from a coordinator.
void fr_redis_ct_request_yield(TALLOC_CTX *ctx, fr_redis_ct_t *rtcluster, request_t *request)
Add a request to the list of those waiting for the cluster map.
int fr_redis_ct_map_bootstrap(fr_redis_ct_t *rtcluster, fr_coord_worker_t *cw, fr_coord_pair_reg_t *coord_pair_reg)
Initiate bootstrapping of the cluster map.
fr_redis_async_cmd_t * fr_redis_async_cmd_start(TALLOC_CTX *ctx, request_t *request, fr_redis_async_rcode_t *rcode, fr_redis_ct_t *rtcluster, uint8_t const *key, size_t key_len, fr_redis_command_set_t *cmds, bool read_only, fr_redis_ct_node_t *node)
Start running a command set on an async redis cluster.
trunk_conf_t const * fr_redis_ct_trunk_conf(fr_redis_ct_t *thread)
fr_redis_async_rcode_t fr_redis_ct_node_addr_by_role(TALLOC_CTX *ctx, fr_redis_io_conf_t *out[], uint8_t *count_out, fr_redis_ct_t *rtcluster, bool is_master, bool is_replica)
fr_redis_async_rcode_t fr_redis_ct_map_get(fr_redis_ct_t *rtcluster, fr_coord_worker_t *cw, fr_coord_pair_reg_t *coord_pair_reg, bool force)
Initiate updating of the cluster map.
fr_redis_ct_node_t const * fr_redis_ct_master(fr_redis_ct_t *thread, fr_redis_ct_key_slot_t const *key_slot)
Return the master node that would be used for a particular key slot.
void fr_redis_async_cmd_cancel(fr_redis_async_cmd_t *cmd)
Cancel a Redis async command.
fr_redis_async_rcode_t fr_redis_async_cmd_resend(fr_redis_async_cmd_t *cmd)
Re-submit a redis async command set.
fr_redis_ct_node_t * fr_redis_ct_node_by_addr(fr_redis_ct_t *rtcluster, fr_redis_io_conf_t *addr)
fr_redis_ct_node_t * fr_redis_async_cmd_node(fr_redis_async_cmd_t *cmd)
Fetch the cluster node a command was last sent to.
fr_redis_trunk_t * fr_redis_async_cmd_trunk(fr_redis_async_cmd_t *cmd)
Fetch the redis trunk a command is associated with.
fr_redis_ct_key_slot_t const * fr_redis_ct_slot_by_key(fr_redis_ct_t *rtcluster, request_t *request, uint8_t const *key, size_t key_len)
Resolve key to key slot.
fr_redis_ct_node_t const * fr_redis_ct_replica(fr_redis_ct_t *thread, fr_redis_ct_key_slot_t const *key_slot, uint8_t replica_num)
Return the replica node that would be used for a particular key slot.
fr_redis_async_rcode_t fr_redis_async_cmd_redirect(fr_redis_async_cmd_t *cmd)
Re-submit a redis async command set on a different node.
int fr_redis_ct_map_fail(fr_redis_ct_t *rtcluster, fr_pair_list_t const *list)
int fr_redis_ct_port(uint16_t *out, fr_redis_ct_node_t const *node)
Return the port of a particular node.
fr_redis_ct_t * fr_redis_ct_alloc(TALLOC_CTX *ctx, CONF_SECTION *tls_conf, fr_event_list_t *el, fr_redis_conf_t *conf, fr_redis_trunk_active_t active, void *active_uctx, bool active_oneshot)
Allocate per-thread, per-cluster instance.
fr_event_list_t * fr_redis_ct_el(fr_redis_ct_t *rtcluster)
char const * fr_redis_ct_ipaddr(fr_redis_ct_node_t const *node)
Return the ipaddr of a particular node.
The worker end of worker <-> coordinator communication.
Definition coord.c:73
struct fr_coord_pair_reg_s fr_coord_pair_reg_t
Definition coord_pair.h:32
Stores all information relating to an event list.
Definition event.c:377
unsigned short uint16_t
unsigned char uint8_t
Represents a collection of pipelined commands.
Definition pipeline.c:94
Redis asynchronous command pipelining.
void(* fr_redis_trunk_active_t)(fr_redis_trunk_t *rtrunk, void *uctx)
Definition pipeline.h:55
static rs_t * conf
Definition radsniff.c:52
fr_redis_async_rcode_t
Definition base.h:80
Configuration parameters for a redis connection.
Definition base.h:114
Common configuration parameters for a trunk.
Definition trunk.h:234
static fr_event_list_t * el
Master include file to access all functions and structures in the library.
static size_t char ** out
Definition value.h:1030