2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 * @brief Handle pools of connections (threads, sockets, etc.)
20 * @note This API must be used by all modules in the public distribution that
21 * maintain pools of connections.
23 * @copyright 2012 The FreeRADIUS server project
24 * @copyright 2012 Alan DeKok <aland@deployingradius.com>
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/rad_assert.h>
31 typedef struct fr_connection fr_connection_t;
33 static int fr_connection_pool_check(fr_connection_pool_t *pool);
35 extern bool check_config;
39 /* #define PTHREAD_DEBUG (1) */
43 /** An individual connection within the connection pool
45 * Defines connection counters, timestamps, and holds a pointer to the
46 * connection handle itself.
48 * @see fr_connection_pool_t
50 struct fr_connection {
51 fr_connection_t *prev; //!< Previous connection in list.
52 fr_connection_t *next; //!< Next connection in list.
54 time_t created; //!< Time connection was created.
55 time_t last_used; //!< Last time the connection was
58 uint32_t num_uses; //!< Number of times the connection
59 //!< has been reserved.
60 uint64_t number; //!< Unique ID assigned when the
61 //!< connection is created, these will
62 //!< monotonically increase over the
63 //!< lifetime of the connection pool.
64 void *connection; //!< Pointer to whatever the module
65 //!< uses for a connection handle.
66 bool in_use; //!< Whether the connection is currently
69 pthread_t pthread_id; //!< When 'in_use == true'
75 * Defines the configuration of the connection pool, all the counters and
76 * timestamps related to the connection pool, the mutex that stops multiple
77 * threads leaving the pool in an inconsistent state, and the callbacks
78 * required to open, close and check the status of connections within the pool.
82 struct fr_connection_pool_t {
83 uint32_t start; //!< Number of initial connections
84 uint32_t min; //!< Minimum number of concurrent
85 //!< connections to keep open.
86 uint32_t max; //!< Maximum number of concurrent
87 //!< connections to allow.
88 uint32_t spare; //!< Number of spare connections to try
89 uint32_t retry_delay; //!< seconds to delay re-open
90 //!< after a failed open.
91 uint32_t cleanup_interval; //!< Initial timer for how
92 //!< often we sweep the pool
93 //!< for free connections.
95 int delay_interval; //!< When we next do a
96 //!< cleanup. Initialized to
97 //!< cleanup_interval, and increase
98 //!< from there based on the delay.
99 int next_delay; //!< The next delay time.
100 //!< cleanup. Initialized to
101 //!< cleanup_interval, and decays
103 uint64_t max_uses; //!< Maximum number of times a
104 //!< connection can be used before being
106 uint32_t lifetime; //!< How long a connection can be open
107 //!< before being closed (irrespective
108 //!< of whether it's idle or not).
109 uint32_t idle_timeout; //!< How long a connection can be idle
110 //!< before being closed.
112 bool trigger; //!< If true execute connection triggers
113 //!< associated with the connection
116 bool spread; //!< If true requests will be spread
117 //!< across all connections, instead of
118 //!< re-using the most recently used
119 //!< connections first.
121 time_t last_checked; //!< Last time we pruned the connection
123 time_t last_spawned; //!< Last time we spawned a connection.
124 time_t last_failed; //!< Last time we tried to spawn a
125 //!< a connection but failed.
126 time_t last_throttled; //!< Last time we refused to spawn a
127 //!< connection because the last
128 //!< connection failed, or we were
129 //!< already spawning a connection.
130 time_t last_at_max; //!< Last time we hit the maximum number
131 //!< of allowed connections.
133 uint64_t count; //!< Number of connections spawned over
134 //!< the lifetime of the pool.
135 uint32_t num; //!< Number of connections in the pool.
136 int active; //!< Number of currently reserved
139 fr_connection_t *head; //!< Start of the connection list.
140 fr_connection_t *tail; //!< End of the connection list.
142 bool spawning; //!< Whether we are currently attempting
143 //!< to spawn a new connection.
145 #ifdef HAVE_PTHREAD_H
146 pthread_mutex_t mutex; //!< Mutex used to keep consistent state
147 //!< when making modifications in
151 CONF_SECTION *cs; //!< Configuration section holding
152 //!< the section of parsed config file
153 //!< that relates to this pool.
154 void *opaque; //!< Pointer to context data that will
155 //!< be passed to callbacks.
157 char *log_prefix; //!< Log prefix to prepend to all log
158 //!< messages created by the connection
161 fr_connection_create_t create; //!< Function used to create new
163 fr_connection_alive_t alive; //!< Function used to check status
165 fr_connection_delete_t delete; //!< Function used to close existing
169 #define LOG_PREFIX "rlm_%s (%s)"
170 #ifndef HAVE_PTHREAD_H
171 #define pthread_mutex_lock(_x)
172 #define pthread_mutex_unlock(_x)
175 static const CONF_PARSER connection_config[] = {
176 { "start", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_connection_pool_t, start), "5" },
177 { "min", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_connection_pool_t, min), "5" },
178 { "max", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_connection_pool_t, max), "10" },
179 { "spare", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_connection_pool_t, spare), "3" },
180 { "uses", FR_CONF_OFFSET(PW_TYPE_INTEGER64, fr_connection_pool_t, max_uses), "0" },
181 { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_connection_pool_t, lifetime), "0" },
182 { "cleanup_delay", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_connection_pool_t, cleanup_interval), NULL},
183 { "cleanup_interval", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_connection_pool_t, cleanup_interval), "30" },
184 { "idle_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_connection_pool_t, idle_timeout), "60" },
185 { "retry_delay", FR_CONF_OFFSET(PW_TYPE_INTEGER, fr_connection_pool_t, retry_delay), "1" },
186 { "spread", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, fr_connection_pool_t, spread), "no" },
187 { NULL, -1, 0, NULL, NULL }
190 /** Removes a connection from the connection list
192 * @note Must be called with the mutex held.
194 * @param[in,out] pool to modify.
195 * @param[in] this Connection to delete.
197 static void fr_connection_unlink(fr_connection_pool_t *pool,
198 fr_connection_t *this)
201 rad_assert(pool->head != this);
202 this->prev->next = this->next;
204 rad_assert(pool->head == this);
205 pool->head = this->next;
208 rad_assert(pool->tail != this);
209 this->next->prev = this->prev;
211 rad_assert(pool->tail == this);
212 pool->tail = this->prev;
215 this->prev = this->next = NULL;
218 /** Adds a connection to the head of the connection list
220 * @note Must be called with the mutex held.
222 * @param[in,out] pool to modify.
223 * @param[in] this Connection to add.
225 static void fr_connection_link_head(fr_connection_pool_t *pool,
226 fr_connection_t *this)
228 rad_assert(pool != NULL);
229 rad_assert(this != NULL);
230 rad_assert(pool->head != this);
231 rad_assert(pool->tail != this);
234 pool->head->prev = this;
237 this->next = pool->head;
241 rad_assert(this->next == NULL);
244 rad_assert(this->next != NULL);
248 /** Adds a connection to the tail of the connection list
250 * @note Must be called with the mutex held.
252 * @param[in,out] pool to modify.
253 * @param[in] this Connection to add.
255 static void fr_connection_link_tail(fr_connection_pool_t *pool,
256 fr_connection_t *this)
258 rad_assert(pool != NULL);
259 rad_assert(this != NULL);
260 rad_assert(pool->head != this);
261 rad_assert(pool->tail != this);
264 pool->tail->next = this;
266 this->prev = pool->tail;
270 rad_assert(this->prev == NULL);
273 rad_assert(this->prev != NULL);
278 /** Spawns a new connection
280 * Spawns a new connection using the create callback, and returns it for
281 * adding to the connection list.
283 * @note Will call the 'open' trigger.
284 * @note Must be called with the mutex free.
286 * @param[in] pool to modify.
287 * @param[in] now Current time.
288 * @param[in] in_use whether the new connection should be "in_use" or not
289 * @return the new connection struct or NULL on error.
291 static fr_connection_t *fr_connection_spawn(fr_connection_pool_t *pool,
292 time_t now, bool in_use)
296 fr_connection_t *this;
299 rad_assert(pool != NULL);
302 * Prevent all threads from blocking if the resource
303 * were managing connections for appears to be unavailable.
305 if ((pool->num == 0) && pool->spawning) {
309 pthread_mutex_lock(&pool->mutex);
310 rad_assert(pool->num <= pool->max);
313 * Don't spawn multiple connections at the same time.
315 if (pool->spawning) {
316 pthread_mutex_unlock(&pool->mutex);
318 ERROR("%s: Cannot open new connection, "
319 "connection spawning already in "
320 "progress", pool->log_prefix);
325 * If the last attempt failed, wait a bit before
328 if (pool->last_failed && ((pool->last_failed + pool->retry_delay) > now)) {
329 bool complain = false;
331 if (pool->last_throttled != now) {
334 pool->last_throttled = now;
337 pthread_mutex_unlock(&pool->mutex);
339 if (!RATE_LIMIT_ENABLED || complain) {
340 ERROR("%s: Last connection attempt failed, waiting %d seconds before retrying",
341 pool->log_prefix, pool->retry_delay);
347 pool->spawning = true;
350 * Unlock the mutex while we try to open a new
351 * connection. If there are issues with the back-end,
352 * opening a new connection may take a LONG time. In
353 * that case, we want the other connections to continue
356 pthread_mutex_unlock(&pool->mutex);
358 INFO("%s: Opening additional connection (%" PRIu64 ")", pool->log_prefix, pool->count);
361 * Allocate a new top level ctx for the create callback
362 * to hang its memory off of.
364 ctx = talloc_init("fr_connection_ctx");
365 if (!ctx) return NULL;
368 * This may take a long time, which prevents other
369 * threads from releasing connections. We don't care
370 * about other threads opening new connections, as we
371 * already have no free connections.
373 conn = pool->create(ctx, pool->opaque);
375 ERROR("%s: Opening connection failed (%" PRIu64 ")", pool->log_prefix, pool->count);
377 pool->last_failed = now;
378 pool->spawning = false; /* atomic, so no lock is needed */
383 * And lock the mutex again while we link the new
384 * connection back into the pool.
386 pthread_mutex_lock(&pool->mutex);
388 this = talloc_zero(pool, fr_connection_t);
390 pthread_mutex_unlock(&pool->mutex);
393 fr_link_talloc_ctx_free(this, ctx);
396 this->connection = conn;
397 this->in_use = in_use;
399 this->number = pool->count++;
400 this->last_used = now;
401 fr_connection_link_head(pool, this);
403 pool->spawning = false;
404 pool->last_spawned = time(NULL);
405 pool->delay_interval = pool->cleanup_interval;
406 pool->next_delay = pool->cleanup_interval;
407 pool->last_failed = 0;
409 pthread_mutex_unlock(&pool->mutex);
411 if (pool->trigger) exec_trigger(NULL, pool->cs, "open", true);
416 /** Close an existing connection.
418 * Removes the connection from the list, calls the delete callback to close
419 * the connection, then frees memory allocated to the connection.
421 * @note Will call the 'close' trigger.
422 * @note Must be called with the mutex held.
424 * @param[in,out] pool to modify.
425 * @param[in,out] this Connection to delete.
428 static void fr_connection_close(fr_connection_pool_t *pool,
429 fr_connection_t *this)
432 * If it's in use, release it.
436 pthread_t pthread_id = pthread_self();
437 rad_assert(pthread_equal(this->pthread_id, pthread_id) != 0);
439 this->in_use = false;
441 rad_assert(pool->active > 0);
445 if (pool->trigger) exec_trigger(NULL, pool->cs, "close", true);
447 fr_connection_unlink(pool, this);
448 if (pool->delete) pool->delete(pool->opaque, this->connection);
449 rad_assert(pool->num > 0);
454 /** Find a connection handle in the connection list
456 * Walks over the list of connections searching for a specified connection
457 * handle and returns the first connection that contains that pointer.
459 * @note Will lock mutex and only release mutex if connection handle
460 * is not found, so will usually return will mutex held.
461 * @note Must be called with the mutex free.
463 * @param[in] pool to search in.
464 * @param[in] conn handle to search for.
465 * @return the connection containing the specified handle, or NULL if non is
468 static fr_connection_t *fr_connection_find(fr_connection_pool_t *pool, void *conn)
470 fr_connection_t *this;
472 if (!pool || !conn) return NULL;
474 pthread_mutex_lock(&pool->mutex);
477 * FIXME: This loop could be avoided if we passed a 'void
478 * **connection' instead. We could use "offsetof" in
479 * order to find top of the parent structure.
481 for (this = pool->head; this != NULL; this = this->next) {
482 if (this->connection == conn) {
484 pthread_t pthread_id;
486 pthread_id = pthread_self();
487 rad_assert(pthread_equal(this->pthread_id, pthread_id) != 0);
490 rad_assert(this->in_use == true);
495 pthread_mutex_unlock(&pool->mutex);
499 /** Delete a connection from the connection pool.
501 * Resolves the connection handle to a connection, then (if found)
502 * closes, unlinks and frees that connection.
504 * @note Must be called with the mutex free.
506 * @param[in,out] pool Connection pool to modify.
507 * @param[in] conn to delete.
508 * @return 0 if the connection could not be found, else 1.
510 int fr_connection_del(fr_connection_pool_t *pool, void *conn)
512 fr_connection_t *this;
514 this = fr_connection_find(pool, conn);
517 INFO("%s: Deleting connection (%" PRIu64 ")", pool->log_prefix, this->number);
519 fr_connection_close(pool, this);
520 fr_connection_pool_check(pool);
524 /** Delete a connection pool
526 * Closes, unlinks and frees all connections in the connection pool, then frees
527 * all memory used by the connection pool.
529 * @note Will call the 'stop' trigger.
530 * @note Must be called with the mutex free.
532 * @param[in,out] pool to delete.
534 void fr_connection_pool_delete(fr_connection_pool_t *pool)
536 fr_connection_t *this, *next;
540 DEBUG("%s: Removing connection pool", pool->log_prefix);
542 pthread_mutex_lock(&pool->mutex);
544 for (this = pool->head; this != NULL; this = next) {
547 INFO("%s: Closing connection (%" PRIu64 ")", pool->log_prefix, this->number);
549 fr_connection_close(pool, this);
552 if (pool->trigger) exec_trigger(NULL, pool->cs, "stop", true);
554 rad_assert(pool->head == NULL);
555 rad_assert(pool->tail == NULL);
556 rad_assert(pool->num == 0);
561 /** Create a new connection pool
563 * Allocates structures used by the connection pool, initialises the various
564 * configuration options and counters, and sets the callback functions.
566 * Will also spawn the number of connections specified by the 'start'
567 * configuration options.
569 * @note Will call the 'start' trigger.
571 * @param[in] parent configuration section containing a 'pool' subsection.
572 * @param[in] opaque data pointer to pass to callbacks.
573 * @param[in] c Callback to create new connections.
574 * @param[in] a Callback to check the status of connections.
575 * @param[in] d Callback to delete connections.
576 * @param[in] prefix to prepend to all log message, if NULL will create prefix
577 * from parent conf section names.
578 * @return A new connection pool or NULL on error.
580 fr_connection_pool_t *fr_connection_pool_init(CONF_SECTION *parent,
582 fr_connection_create_t c,
583 fr_connection_alive_t a,
584 fr_connection_delete_t d,
588 fr_connection_pool_t *pool;
589 fr_connection_t *this;
590 CONF_SECTION *modules;
592 char const *cs_name1, *cs_name2;
593 time_t now = time(NULL);
595 if (!parent || !opaque || !c) return NULL;
597 cs = cf_section_sub_find(parent, "pool");
598 if (!cs) cs = cf_section_sub_find(parent, "limit");
601 * Pool is allocated in the NULL context as
602 * threads are likely to allocate memory
605 pool = talloc_zero(NULL, fr_connection_pool_t);
606 if (!pool) return NULL;
609 * Ensure the pool is freed at the same time
612 if (fr_link_talloc_ctx_free(cs ? cs : parent, pool) < 0) {
618 pool->opaque = opaque;
623 pool->head = pool->tail = NULL;
625 #ifdef HAVE_PTHREAD_H
626 pthread_mutex_init(&pool->mutex, NULL);
630 modules = cf_item_parent(cf_sectiontoitem(parent));
632 cs_name1 = cf_section_name1(modules);
633 if (cs_name1 && (strcmp(cs_name1, "modules") == 0)) {
634 cs_name1 = cf_section_name1(parent);
635 cs_name2 = cf_section_name2(parent);
640 pool->log_prefix = talloc_typed_asprintf(pool, LOG_PREFIX, cs_name1,
643 } else { /* not a module configuration */
644 cs_name1 = cf_section_name1(parent);
646 pool->log_prefix = talloc_typed_strdup(pool, cs_name1);
649 pool->log_prefix = talloc_typed_strdup(pool, prefix);
652 DEBUG("%s: Initialising connection pool", pool->log_prefix);
655 if (cf_section_parse(cs, pool, connection_config) < 0) {
659 if (cf_section_sub_find(cs, "trigger")) pool->trigger = true;
665 pool->cleanup_interval = 30;
666 pool->idle_timeout = 60;
672 if (pool->max == 0) {
673 cf_log_err_cs(cs, "Cannot set 'max' to zero");
676 if (pool->min > pool->max) {
677 cf_log_err_cs(cs, "Cannot set 'min' to more than 'max'");
681 if (pool->max > 1024) pool->max = 1024;
682 if (pool->start > pool->max) pool->start = pool->max;
683 if (pool->spare > (pool->max - pool->min)) {
684 pool->spare = pool->max - pool->min;
686 if ((pool->lifetime > 0) && (pool->idle_timeout > pool->lifetime)) {
687 pool->idle_timeout = 0;
690 if ((pool->idle_timeout > 0) && (pool->cleanup_interval > pool->idle_timeout)) {
691 pool->cleanup_interval = pool->idle_timeout;
695 * Don't open any connections. Instead, force the limits
696 * to only 1 connection.
700 pool->start = pool->min = pool->max = 1;
705 * Create all of the connections, unless the admin says
708 for (i = 0; i < pool->start; i++) {
709 this = fr_connection_spawn(pool, now, false);
712 fr_connection_pool_delete(pool);
717 if (pool->trigger) exec_trigger(NULL, pool->cs, "start", true);
723 /** Check whether a connection needs to be removed from the pool
725 * Will verify that the connection is within idle_timeout, max_uses, and
726 * lifetime values. If it is not, the connection will be closed.
728 * @note Will only close connections not in use.
729 * @note Must be called with the mutex held.
731 * @param[in,out] pool to modify.
732 * @param[in,out] this Connection to manage.
733 * @param[in] now Current time.
734 * @return 0 if the connection was closed, otherwise 1.
736 static int fr_connection_manage(fr_connection_pool_t *pool,
737 fr_connection_t *this,
740 rad_assert(pool != NULL);
741 rad_assert(this != NULL);
744 * Don't terminated in-use connections
746 if (this->in_use) return 1;
748 if ((pool->max_uses > 0) &&
749 (this->num_uses >= pool->max_uses)) {
750 DEBUG("%s: Closing expired connection (%" PRIu64 "): Hit max_uses limit", pool->log_prefix,
753 if (pool->num <= pool->min) {
754 RATE_LIMIT(WARN("%s: You probably need to lower \"min\"", pool->log_prefix));
756 fr_connection_close(pool, this);
760 if ((pool->lifetime > 0) &&
761 ((this->created + pool->lifetime) < now)) {
762 DEBUG("%s: Closing expired connection (%" PRIu64 ")", pool->log_prefix, this->number);
766 if ((pool->idle_timeout > 0) &&
767 ((this->last_used + pool->idle_timeout) < now)) {
768 INFO("%s: Closing connection (%" PRIu64 "): Hit idle_timeout, was idle for %u seconds",
769 pool->log_prefix, this->number, (int) (now - this->last_used));
777 /** Check whether any connections needs to be removed from the pool
779 * Maintains the number of connections in the pool as per the configuration
780 * parameters for the connection pool.
782 * @note Will only run checks the first time it's called in a given second,
783 * to throttle connection spawning/closing.
784 * @note Will only close connections not in use.
785 * @note Must be called with the mutex held, will release mutex before
788 * @param[in,out] pool to manage.
791 static int fr_connection_pool_check(fr_connection_pool_t *pool)
793 uint32_t spawn, idle, extra;
794 time_t now = time(NULL);
795 fr_connection_t *this, *next;
797 if (pool->last_checked == now) {
798 pthread_mutex_unlock(&pool->mutex);
803 * Some idle connections are OK, if they're within the
804 * configured "spare" range. Any extra connections
805 * outside of that range can be closed.
807 idle = pool->num - pool->active;
808 if (idle <= pool->spare) {
811 extra = idle - pool->spare;
815 * The other end can close connections. If so, we'll
816 * have fewer than "min". When that happens, open more
817 * connections to enforce "min".
819 if (pool->num <= pool->min) {
820 if (pool->spawning) {
823 spawn = pool->min - pool->num;
827 } else if (pool->num >= pool->max) {
829 * Ensure we don't spawn more connections. If
830 * there are extra idle connections, we can
831 * delete all of them.
834 /* leave extra alone from above */
836 } else if (idle <= pool->spare) {
838 * Not enough spare connections. Spawn a few.
839 * But cap the pool size at "max"
841 spawn = pool->spare - idle;
844 if ((pool->num + spawn) > pool->max) {
845 spawn = pool->max - pool->num;
848 } else if ((pool->min + extra) >= pool->num) {
850 * If closing the extra connections would take us
851 * below "min", then don't do that. Cap the
852 * spare connections at the ones which will take
853 * us exactly to "min".
856 extra = pool->num - pool->min;
860 * Closing the "extra" connections won't take us
861 * below "min". It's therefore safe to close
865 /* leave extra alone from above */
869 pthread_mutex_unlock(&pool->mutex);
870 fr_connection_spawn(pool, now, false); /* ignore return code */
871 pthread_mutex_lock(&pool->mutex);
875 * We haven't spawned connections in a while, and there
876 * are too many spare ones. Close the one which has been
877 * unused for the longest.
879 if (extra && (now >= (pool->last_spawned + pool->delay_interval))) {
880 fr_connection_t *found;
883 for (this = pool->tail; this != NULL; this = this->prev) {
884 if (this->in_use) continue;
887 (this->last_used < found->last_used)) {
892 rad_assert(found != NULL);
894 INFO("%s: Closing connection (%" PRIu64 "), from %d unused connections", pool->log_prefix,
895 found->number, extra);
896 fr_connection_close(pool, found);
899 * Decrease the delay for the next time we clean
902 pool->next_delay >>= 1;
903 if (pool->next_delay == 0) pool->next_delay = 1;
904 pool->delay_interval += pool->next_delay;
908 * Pass over all of the connections in the pool, limiting
909 * lifetime, idle time, max requests, etc.
911 for (this = pool->head; this != NULL; this = next) {
913 fr_connection_manage(pool, this, now);
916 pool->last_checked = now;
917 pthread_mutex_unlock(&pool->mutex);
922 /** Get a connection from the connection pool
924 * @param[in,out] pool to reserve the connection from.
925 * @param[in] spawn whether to spawn a new connection
926 * @return a pointer to the connection handle, or NULL on error.
928 static void *fr_connection_get_internal(fr_connection_pool_t *pool, int spawn)
931 fr_connection_t *this, *next;
933 if (!pool) return NULL;
935 pthread_mutex_lock(&pool->mutex);
938 for (this = pool->head; this != NULL; this = next) {
941 if (!this->in_use) goto do_return;
944 if (pool->num == pool->max) {
945 bool complain = false;
948 * Rate-limit complaints.
950 if (pool->last_at_max != now) {
952 pool->last_at_max = now;
955 pthread_mutex_unlock(&pool->mutex);
957 if (!RATE_LIMIT_ENABLED || complain) {
958 ERROR("%s: No connections available and at max connection limit", pool->log_prefix);
964 pthread_mutex_unlock(&pool->mutex);
966 if (!spawn) return NULL;
968 this = fr_connection_spawn(pool, now, true); /* MY connection! */
969 if (!this) return NULL;
970 pthread_mutex_lock(&pool->mutex);
975 this->last_used = now;
979 this->pthread_id = pthread_self();
981 pthread_mutex_unlock(&pool->mutex);
983 DEBUG("%s: Reserved connection (%" PRIu64 ")", pool->log_prefix, this->number);
985 return this->connection;
989 /** Reserve a connection in the connection pool
991 * Will attempt to find an unused connection in the connection pool, if one is
992 * found, will mark it as in in use increment the number of active connections
993 * and return the connection handle.
995 * If no free connections are found will attempt to spawn a new one, conditional
996 * on a connection spawning not already being in progress, and not being at the
997 * 'max' connection limit.
999 * @note fr_connection_release must be called once the caller has finished
1000 * using the connection.
1002 * @see fr_connection_release
1003 * @param[in,out] pool to reserve the connection from.
1004 * @return a pointer to the connection handle, or NULL on error.
1006 void *fr_connection_get(fr_connection_pool_t *pool)
1008 return fr_connection_get_internal(pool, true);
1011 /** Get the number of connections currently in the pool
1013 * @param pool to count connections for.
1014 * @return the number of connections in the pool
1016 int fr_connection_get_num(fr_connection_pool_t *pool)
1021 /** Release a connection
1023 * Will mark a connection as unused and decrement the number of active
1026 * @see fr_connection_get
1027 * @param[in,out] pool to release the connection in.
1028 * @param[in,out] conn to release.
1030 void fr_connection_release(fr_connection_pool_t *pool, void *conn)
1032 fr_connection_t *this;
1034 this = fr_connection_find(pool, conn);
1037 this->in_use = false;
1040 * Determines whether the last used connection gets
1045 * Put it at the tail of the list, so
1046 * that it will get re-used last.
1048 if (this != pool->tail) {
1049 fr_connection_unlink(pool, this);
1050 fr_connection_link_tail(pool, this);
1054 * Put it at the head of the list, so
1055 * that it will get re-used quickly.
1057 if (this != pool->head) {
1058 fr_connection_unlink(pool, this);
1059 fr_connection_link_head(pool, this);
1063 rad_assert(pool->active > 0);
1066 DEBUG("%s: Released connection (%" PRIu64 ")", pool->log_prefix, this->number);
1069 * We mirror the "spawn on get" functionality by having
1070 * "delete on release". If there are too many spare
1071 * connections, go manage the pool && clean some up.
1073 fr_connection_pool_check(pool);
1076 /** Reconnect a suspected inviable connection
1078 * This should be called by the module if it suspects that a connection is
1079 * not viable (e.g. the server has closed it).
1081 * Will attempt to create a new connection handle using the create callback,
1082 * and if this is successful the new handle will be assigned to the existing
1085 * If this is not successful, the connection will be removed from the pool.
1087 * When implementing a module that uses the connection pool API, it is advisable
1088 * to pass a pointer to the pointer to the handle (void **conn)
1089 * to all functions which may call reconnect. This is so that if a new handle
1090 * is created and returned, the handle pointer can be updated up the callstack,
1091 * and a function higher up the stack doesn't attempt to use a now invalid
1092 * connection handle.
1094 * @warning After calling reconnect the caller *MUST NOT* attempt to use
1095 * the old handle in any other operations, as its memory will have been freed.
1097 * @see fr_connection_get
1098 * @param[in,out] pool to reconnect the connection in.
1099 * @param[in,out] conn to reconnect.
1100 * @return new connection handle if successful else NULL.
1102 void *fr_connection_reconnect(fr_connection_pool_t *pool, void *conn)
1105 fr_connection_t *this;
1106 uint64_t conn_number;
1109 if (!pool || !conn) return NULL;
1112 * If fr_connection_find is successful the pool is now locked
1114 this = fr_connection_find(pool, conn);
1115 if (!this) return NULL;
1118 conn_number = this->number;
1121 * Destroy any handles associated with the fr_connection_t
1123 talloc_free_children(this);
1125 DEBUG("%s: Reconnecting (%" PRIu64 ")", pool->log_prefix, conn_number);
1128 * Allocate a new top level ctx for the create callback
1129 * to hang its memory off of.
1131 ctx = talloc_init("fr_connection_ctx");
1132 if (!ctx) return NULL;
1133 fr_link_talloc_ctx_free(this, ctx);
1135 new_conn = pool->create(ctx, pool->opaque);
1138 * We can't create a new connection, so close
1141 fr_connection_close(pool, this);
1144 * Maybe there's a connection which is unused and
1145 * available. If so, return it.
1147 pthread_mutex_unlock(&pool->mutex);
1148 new_conn = fr_connection_get_internal(pool, false);
1149 if (new_conn) return new_conn;
1151 RATE_LIMIT(ERROR("%s: Failed to reconnect (%" PRIu64 "), no free connections are available",
1152 pool->log_prefix, conn_number));
1157 if (pool->trigger) exec_trigger(NULL, pool->cs, "close", true);
1158 pool->delete(pool->opaque, conn);
1159 this->connection = new_conn;
1160 pthread_mutex_unlock(&pool->mutex);