23RCSID(
"$Id: ec016b71088a9227871f7a05f0089a2daf98acf3 $")
25#include <freeradius-devel/server/base.h>
26#include <freeradius-devel/io/control.h>
27#include <freeradius-devel/util/debug.h>
28#include <freeradius-devel/util/syserror.h>
29#include <freeradius-devel/util/talloc.h>
30#include <freeradius-devel/util/semaphore.h>
40#define MEM(x) if (!(x)) { fprintf(stderr, "%s[%u] OUT OF MEMORY\n", __FILE__, __LINE__); _exit(EXIT_FAILURE); }
41#define MPRINT1 if (debug_lvl) printf
42#define MPRINT2 if (debug_lvl >= 2) printf
43#define MPRINT3 if (debug_lvl >= 3) printf
44#define CONTROL_MAGIC 0xabcd6809
65 fprintf(stderr,
"usage: control_test [OPTS]\n");
66 fprintf(stderr,
" -m <messages> Send number of messages.\n");
67 fprintf(stderr,
" -w <workers> Number of workers.\n");
68 fprintf(stderr,
" -q Use per-worker atomic queues.\n");
69 fprintf(stderr,
" -x Debugging mode.\n");
111 for (i = 0; i <
num_aq; i++) {
116 sem_post(master_sem);
125 if (num_events < 0) {
126 fprintf(stderr,
"Failed reading kevent: %s\n",
fr_syserror(errno));
129 if (num_events > 0) {
133 MPRINT1(
"Master exiting. Seen %zu messages. %.2f per second\n",
153 MPRINT1(
"\tWorker %ld started using queue %ld.\n", wa->
id, aq_num);
166 MPRINT1(
"\tWorker %ld retrying message %zu\n", wa->
id, i);
175 MPRINT2(
"\tWorker %ld sent message %zu\n", wa->
id, i);
178 MPRINT1(
"\tWorker %ld exiting.\n", wa->
id);
187int main(
int argc,
char *argv[])
199 while ((c = getopt(argc, argv,
"hm:qw:x")) != -1)
switch (c) {
222 argc -= (optind - 1);
223 argv += (optind - 1);
232 for (i = 0; i <
num_aq; i++) {
238 for (i = 0; i <
num_aq; i++) {
241 fprintf(stderr,
"control_test: Failed to create control plane\n");
249 (void) pthread_attr_init(&attr);
250 (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
254 (void) pthread_create(&master_id, &attr,
control_master, master_sem);
260 worker_args[i].
id = i;
265 (void) pthread_join(master_id, NULL);
fr_atomic_queue_t * fr_atomic_queue_alloc(TALLOC_CTX *ctx, size_t size)
Create fixed-size atomic queue.
Structure to hold the atomic queue.
static TALLOC_CTX * autofree
#define NEVER_RETURNS
Should be placed before the function return type.
#define FR_CONTROL_ID_CHANNEL
static fr_control_t * control_worker
static fr_control_t * control_master
#define FR_CONTROL_MAX_SIZE
#define FR_CONTROL_MAX_MESSAGES
int main(int argc, char *argv[])
static size_t num_workers
static void recv_control_callback(void *ctx, void const *data, size_t data_size, UNUSED fr_time_t now)
static fr_event_list_t * el
static fr_control_t ** control
static size_t max_messages
static NEVER_RETURNS void usage(void)
static fr_atomic_queue_t ** aq
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
fr_control_t * fr_control_create(TALLOC_CTX *ctx, fr_event_list_t *el, fr_atomic_queue_t *aq, size_t num_callbacks)
Create a control-plane signaling path.
int fr_control_callback_add(fr_control_t **c, uint32_t id, void *ctx, fr_control_callback_t callback)
Register a callback for an ID.
int fr_control_open(fr_control_t *c)
Open the control-plane signalling path.
int fr_control_message_send(fr_control_t *c, fr_ring_buffer_t *rb, uint32_t id, void *data, size_t data_size)
Send a control-plane message.
void fr_event_service(fr_event_list_t *el)
Service any outstanding timer or file descriptor events.
int fr_event_corral(fr_event_list_t *el, fr_time_t now, bool wait)
Gather outstanding timer and file descriptor events.
Stores all information relating to an event list.
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
int main_loop_init(void)
Initialise the main event loop, setting up signal handlers.
void main_loop_free(void)
fr_ring_buffer_t * fr_ring_buffer_create(TALLOC_CTX *ctx, size_t size)
Create a ring buffer.
static _Thread_local int worker_id
Internal ID of the current worker thread.
void fr_sem_free(fr_sem_t *sem)
fr_sem_t * fr_sem_alloc(void)
#define SEM_WAIT_INTR(_x)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
int fr_time_start(void)
Initialize the local time.
static fr_time_delta_t fr_time_sub_time_time(fr_time_t a, fr_time_t b)
static int64_t fr_time_delta_to_usec(fr_time_delta_t delta)
char const * fr_strerror_pop(void)
Pop the last library error.