The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
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: 1abb83a907bcb36c62334f7e97027dd84c908915 $
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: 1abb83a907bcb36c62334f7e97027dd84c908915 $")
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) \
52do { \
53 switch (_rcode) { \
54 case REDIS_ASYNC_RCODE_BOOTSTRAP: \
55 fr_redis_ct_map_bootstrap(_cluster, _cw, _coord_pair_reg); \
56 break; \
57 case REDIS_ASYNC_RCODE_GETMAP: \
58 fr_redis_ct_map_get(_cluster, _cw, _coord_pair_reg, false); \
59 break; \
60 case REDIS_ASYNC_RCODE_FAIL: \
61 case REDIS_ASYNC_RCODE_ERROR: \
62 RPERROR(_error_msg); \
63 return _error_ret; \
64 default: \
65 break; \
66 } \
67} while (0)
68
69#define REDIS_ASYNC_COORD_CALLBACKS(_thread_type) \
70typedef enum : uint8_t { \
71 REDIS_COORD_PAIR_CALLBACK_ID = 0, \
72} rlm_redis_coord_t; \
73static void cluster_map_update(UNUSED fr_coord_worker_t *cw, UNUSED fr_coord_pair_reg_t *coord_pair_reg, \
74 fr_pair_list_t const *list, UNUSED fr_time_t now, \
75 module_ctx_t *mctx, UNUSED void *uctx) \
76{ \
77 _thread_type *t = talloc_get_type_abort(mctx->thread, _thread_type); \
78 module_thread_instance_t *mt; \
79 if (fr_redis_ct_map_update(t->rtcluster, list) < 0) return; \
80 mt = module_thread(mctx->mi); \
81 module_thread_force(mt, RLM_MODULE_NOT_SET); \
82 return; \
83} \
84static void cluster_map_fail(UNUSED fr_coord_worker_t *cw, UNUSED fr_coord_pair_reg_t *coord_pair_reg, \
85 fr_pair_list_t const *list, UNUSED fr_time_t now, \
86 module_ctx_t *mctx, UNUSED void *uctx) \
87{ \
88 _thread_type *t = talloc_get_type_abort(mctx->thread, _thread_type); \
89 module_thread_instance_t *mt; \
90 fr_redis_ct_map_fail(t->rtcluster, list); \
91 mt = module_thread(mctx->mi); \
92 module_thread_force(mt, RLM_MODULE_FAIL); \
93 return; \
94} \
95static fr_coord_cb_reg_t coord_callbacks[] = { \
96 FR_COORD_PAIR_CALLBACK(REDIS_COORD_PAIR_CALLBACK_ID), \
97 FR_COORD_CALLBACK_TERMINATOR \
98}; \
99static fr_coord_worker_cb_reg_t worker_callbacks[] = { \
100 FR_COORD_WORKER_PAIR_CALLBACK(REDIS_COORD_PAIR_CALLBACK_ID), \
101 FR_COORD_CALLBACK_TERMINATOR \
102}; \
103static fr_coord_worker_pair_cb_reg_t worker_pair_callbacks[] = { \
104 { .packet_type = FR_REDIS_CLUSTER_MAP_UPDATE, .callback = cluster_map_update }, \
105 { .packet_type = FR_REDIS_CLUSTER_MAP_FAIL, .callback = cluster_map_fail }, \
106 FR_COORD_CALLBACK_TERMINATOR \
107}
108
110 uint8_t const *key, size_t key_len);
111
113
115 fr_redis_ct_key_slot_t const *key_slot, uint8_t replica_num);
116
117char const *fr_redis_ct_ipaddr(fr_redis_ct_node_t const *node);
118
120
123 void *active_uctx, bool active_oneshot);
124
126
128
130
131#ifdef HAVE_REDIS_SSL
132SSL_CTX *fr_redis_ct_ssl_ctx(fr_redis_ct_t *rtcluster);
133#endif
134
136 fr_coord_pair_reg_t *coord_pair_reg);
137
139 fr_coord_pair_reg_t *coord_pair_reg, bool force);
140
141int fr_redis_ct_map_update(fr_redis_ct_t *thread, fr_pair_list_t const *list);
142
144
146 fr_redis_ct_t *rtcluster, uint8_t const *key, size_t key_len,
148
150
152
154
156
158
160
162 fr_redis_ct_t *rtcluster, bool is_master, bool is_replica);
163
static uint8_t request[4]
#define RCSIDH(h, id)
Definition build.h:604
bool read_only
Should this command be run read only.
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.
uint8_t fr_redis_ct_max_redirects(fr_redis_ct_t *rtcluster)
How many times a command set running on this cluster may be redirected.
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_ct_t * fr_redis_ct_alloc(TALLOC_CTX *ctx, 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_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_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:375
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:90
Configuration parameters for a redis connection.
Definition base.h:124
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 fr_sbuff_err_t char ** out
Definition value.h:1061