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>
30 #include <freeradius-devel/connection.h>
32 #include <freeradius-devel/rad_assert.h>
34 typedef struct fr_connection fr_connection_t;
36 static int fr_connection_pool_check(fr_connection_pool_t *pool);
38 /** An individual connection within the connection pool
40 * Defines connection counters, timestamps, and holds a pointer to the
41 * connection handle itself.
43 * @see fr_connection_pool_t
45 struct fr_connection {
46 fr_connection_t *prev; //!< Previous connection in list.
47 fr_connection_t *next; //!< Next connection in list.
49 time_t created; //!< Time connection was created.
50 time_t last_used; //!< Last time the connection was
53 int num_uses; //!< Number of times the connection
54 //!< has been reserved.
55 int in_use; //!< Whether the connection is currently
57 int number; //!< Unique ID assigned when the
58 //!< connection is created, these will
59 //!< monotonically increase over the
60 //!< lifetime of the connection pool.
61 void *connection; //!< Pointer to whatever the module
62 //!< uses for a connection handle.
67 * Defines the configuration of the connection pool, all the counters and
68 * timestamps related to the connection pool, the mutex that stops multiple
69 * threads leaving the pool in an inconsistent state, and the callbacks
70 * required to open, close and check the status of connections within the pool.
74 struct fr_connection_pool_t {
75 int start; //!< Number of initial connections
76 int min; //!< Minimum number of concurrent
77 //!< connections to keep open.
78 int max; //!< Maximum number of concurrent
79 //!< connections to allow.
80 int spare; //!< Number of spare connections to try
82 int cleanup_delay; //!< How long a connection can go unused
83 //!< for before it's closed
85 int max_uses; //!< Maximum number of times a
86 //!< connection can be used before being
88 int lifetime; //!< How long a connection can be open
89 //!< before being closed (irrespective
90 //!< of whether it's idle or not).
91 int idle_timeout; //!< How long a connection can be idle
92 //!< before being closed.
94 int trigger; //!< If true execute connection triggers
95 //!< associated with the connection
98 int spread; //!< If true requests will be spread
99 //!< across all connections, instead of
100 //!< re-using the most recently used
101 //!< connections first.
103 time_t last_checked; //!< Last time we pruned the connection
105 time_t last_spawned; //!< Last time we spawned a connection.
106 time_t last_failed; //!< Last time we tried to spawn a
107 //!< a connection but failed.
108 time_t last_complained;//!< Last time we complained about
109 //!< configuration parameters.
110 time_t last_throttled; //!< Last time we refused to spawn a
111 //!< connection because the last
112 //!< connection failed, or we were
113 //!< already spawning a connection.
114 time_t last_at_max; //!< Last time we hit the maximum number
115 //!< of allowed connections.
117 unsigned int count; //!< Number of connections spawned over
118 //!< the lifetime of the pool.
119 int num; //!< Number of connections in the pool.
120 int active; //!< Number of currently reserved
123 fr_connection_t *head; //!< Start of the connection list.
124 fr_connection_t *tail; //!< End of the connection list.
126 int spawning; //!< Whether we are currently attempting
127 //!< to spawn a new connection.
129 #ifdef HAVE_PTHREAD_H
130 pthread_mutex_t mutex; //!< Mutex used to keep consistent state
131 //!< when making modifications in
135 CONF_SECTION *cs; //!< Configuration section holding
136 //!< the section of parsed config file
137 //!< that relates to this pool.
138 void *ctx; //!< Pointer to context data that will
139 //!< be passed to callbacks.
141 char *log_prefix; //!< Log prefix to prepend to all log
142 //!< messages created by the connection
145 fr_connection_create_t create; //!< Function used to create new
147 fr_connection_alive_t alive; //!< Function used to check status
149 fr_connection_delete_t delete; //!< Function used to close existing
153 #define LOG_PREFIX "rlm_%s (%s)"
154 #ifndef HAVE_PTHREAD_H
155 #define pthread_mutex_lock(_x)
156 #define pthread_mutex_unlock(_x)
159 static const CONF_PARSER connection_config[] = {
160 { "start", PW_TYPE_INTEGER, offsetof(fr_connection_pool_t, start),
162 { "min", PW_TYPE_INTEGER, offsetof(fr_connection_pool_t, min),
164 { "max", PW_TYPE_INTEGER, offsetof(fr_connection_pool_t, max),
166 { "spare", PW_TYPE_INTEGER, offsetof(fr_connection_pool_t, spare),
168 { "uses", PW_TYPE_INTEGER, offsetof(fr_connection_pool_t, max_uses),
170 { "lifetime", PW_TYPE_INTEGER, offsetof(fr_connection_pool_t, lifetime),
172 { "cleanup_delay", PW_TYPE_INTEGER, offsetof(fr_connection_pool_t, cleanup_delay),
174 { "idle_timeout", PW_TYPE_INTEGER, offsetof(fr_connection_pool_t, idle_timeout),
176 { "spread", PW_TYPE_BOOLEAN, offsetof(fr_connection_pool_t, spread),
178 { NULL, -1, 0, NULL, NULL }
181 /** Removes a connection from the connection list
183 * @note Must be called with the mutex held.
185 * @param[in,out] pool to modify.
186 * @param[in] this Connection to delete.
188 static void fr_connection_unlink(fr_connection_pool_t *pool,
189 fr_connection_t *this)
192 rad_assert(pool->head != this);
193 this->prev->next = this->next;
195 rad_assert(pool->head == this);
196 pool->head = this->next;
199 rad_assert(pool->tail != this);
200 this->next->prev = this->prev;
202 rad_assert(pool->tail == this);
203 pool->tail = this->prev;
206 this->prev = this->next = NULL;
209 /** Adds a connection to the head of the connection list
211 * @note Must be called with the mutex held.
213 * @param[in,out] pool to modify.
214 * @param[in] this Connection to add.
216 static void fr_connection_link_head(fr_connection_pool_t *pool,
217 fr_connection_t *this)
219 rad_assert(pool != NULL);
220 rad_assert(this != NULL);
221 rad_assert(pool->head != this);
222 rad_assert(pool->tail != this);
225 pool->head->prev = this;
228 this->next = pool->head;
232 rad_assert(this->next == NULL);
235 rad_assert(this->next != NULL);
239 /** Adds a connection to the tail of the connection list
241 * @note Must be called with the mutex held.
243 * @param[in,out] pool to modify.
244 * @param[in] this Connection to add.
246 static void fr_connection_link_tail(fr_connection_pool_t *pool,
247 fr_connection_t *this)
249 rad_assert(pool != NULL);
250 rad_assert(this != NULL);
251 rad_assert(pool->head != this);
252 rad_assert(pool->tail != this);
255 pool->tail->next = this;
257 this->prev = pool->tail;
261 rad_assert(this->prev == NULL);
264 rad_assert(this->prev != NULL);
269 /** Spawns a new connection
271 * Spawns a new connection using the create callback, and returns it for
272 * adding to the connection list.
274 * @note Will call the 'open' trigger.
275 * @note Must be called with the mutex free.
277 * @param[in] pool to modify.
278 * @param[in] now Current time.
279 * @return the new connection struct or NULL on error.
281 static fr_connection_t *fr_connection_spawn(fr_connection_pool_t *pool,
284 fr_connection_t *this;
287 rad_assert(pool != NULL);
290 * Prevent all threads from blocking if the resource
291 * were managing connections for appears to be unavailable.
293 if ((pool->num == 0) && pool->spawning) {
297 pthread_mutex_lock(&pool->mutex);
298 rad_assert(pool->num <= pool->max);
300 if ((pool->last_failed == now) || pool->spawning) {
301 int complain = false;
303 if (pool->last_throttled != now) {
306 pool->last_throttled = now;
309 pthread_mutex_unlock(&pool->mutex);
312 if (pool->spawning) {
313 ERROR("%s: Cannot open new connection, "
314 "connection spawning already in "
315 "progress", pool->log_prefix);
317 ERROR("%s: Last connection failed, "
318 "throttling connection spawn",
326 pool->spawning = true;
329 * Unlock the mutex while we try to open a new
330 * connection. If there are issues with the back-end,
331 * opening a new connection may take a LONG time. In
332 * that case, we want the other connections to continue
335 pthread_mutex_unlock(&pool->mutex);
337 INFO("%s: Opening additional connection (%i)",
338 pool->log_prefix, pool->count);
340 this = rad_malloc(sizeof(*this));
341 memset(this, 0, sizeof(*this));
344 * This may take a long time, which prevents other
345 * threads from releasing connections. We don't care
346 * about other threads opening new connections, as we
347 * already have no free connections.
349 conn = pool->create(pool->ctx);
351 ERROR("%s: Opening connection failed (%i)",
352 pool->log_prefix, pool->count);
354 pool->last_failed = now;
356 pool->spawning = false; /* atomic, so no lock is needed */
361 this->connection = conn;
364 * And lock the mutex again while we link the new
365 * connection back into the pool.
367 pthread_mutex_lock(&pool->mutex);
369 this->number = pool->count++;
370 this->last_used = now;
371 fr_connection_link_head(pool, this);
373 pool->spawning = false;
374 pool->last_spawned = time(NULL);
376 pthread_mutex_unlock(&pool->mutex);
378 if (pool->trigger) exec_trigger(NULL, pool->cs, "open", true);
383 /** Add a new connection to the pool
385 * If conn is not NULL will attempt to add that connection handle to the pool.
386 * If conn is NULL will attempt to spawn a new connection using the create
389 * @note Will call the 'open' trigger.
391 * @param[in,out] pool to add connection to.
392 * @param[in] conn to add.
393 * @return 0 if the connection wasn't added else 1.
395 int fr_connection_add(fr_connection_pool_t *pool, void *conn)
397 fr_connection_t *this;
401 pthread_mutex_lock(&pool->mutex);
404 conn = pool->create(pool->ctx);
406 pthread_mutex_unlock(&pool->mutex);
410 INFO("%s: Opening connection successful (%i)",
411 pool->log_prefix, pool->count);
415 * Too many connections: can't add it.
417 if (pool->num >= pool->max) {
418 pthread_mutex_unlock(&pool->mutex);
422 this = rad_malloc(sizeof(*this));
423 memset(this, 0, sizeof(*this));
425 this->created = time(NULL);
426 this->connection = conn;
428 this->number = pool->count++;
429 this->last_used = time(NULL);
430 fr_connection_link_head(pool, this);
433 pthread_mutex_unlock(&pool->mutex);
435 if (pool->trigger) exec_trigger(NULL, pool->cs, "open", true);
440 /** Close an existing connection.
442 * Removes the connection from the list, calls the delete callback to close
443 * the connection, then frees memory allocated to the connection.
445 * @note Will call the 'close' trigger.
446 * @note Must be called with the mutex held.
448 * @param[in,out] pool to modify.
449 * @param[in,out] this Connection to delete.
452 static void fr_connection_close(fr_connection_pool_t *pool,
453 fr_connection_t *this)
455 if (pool->trigger) exec_trigger(NULL, pool->cs, "close", true);
457 rad_assert(this->in_use == false);
459 fr_connection_unlink(pool, this);
460 pool->delete(pool->ctx, this->connection);
461 rad_assert(pool->num > 0);
466 /** Find a connection handle in the connection list
468 * Walks over the list of connections searching for a specified connection
469 * handle and returns the first connection that contains that pointer.
471 * @note Will lock mutex and only release mutex if connection handle
472 * is not found, so will usually return will mutex held.
473 * @note Must be called with the mutex free.
475 * @param[in] pool to search in.
476 * @param[in] conn handle to search for.
477 * @return the connection containing the specified handle, or NULL if non is
480 static fr_connection_t *fr_connection_find(fr_connection_pool_t *pool, void *conn)
482 fr_connection_t *this;
484 if (!pool || !conn) return NULL;
486 pthread_mutex_lock(&pool->mutex);
489 * FIXME: This loop could be avoided if we passed a 'void
490 * **connection' instead. We could use "offsetof" in
491 * order to find top of the parent structure.
493 for (this = pool->head; this != NULL; this = this->next) {
494 if (this->connection == conn) return this;
497 pthread_mutex_unlock(&pool->mutex);
501 /** Delete a connection from the connection pool.
503 * Resolves the connection handle to a connection, then (if found)
504 * closes, unlinks and frees that connection.
506 * @note Must be called with the mutex free.
508 * @param[in,out] pool Connection pool to modify.
509 * @param[in] conn to delete.
510 * @return 0 if the connection could not be found, else 1.
512 int fr_connection_del(fr_connection_pool_t *pool, void *conn)
514 fr_connection_t *this;
516 this = fr_connection_find(pool, conn);
520 * If it's in use, release it.
523 rad_assert(this->in_use == true);
524 this->in_use = false;
526 rad_assert(pool->active > 0);
530 INFO("%s: Deleting connection (%i)", pool->log_prefix,
533 fr_connection_close(pool, this);
534 fr_connection_pool_check(pool);
538 /** Delete a connection pool
540 * Closes, unlinks and frees all connections in the connection pool, then frees
541 * all memory used by the connection pool.
543 * @note Will call the 'stop' trigger.
544 * @note Must be called with the mutex free.
546 * @param[in,out] pool to delete.
548 void fr_connection_pool_delete(fr_connection_pool_t *pool)
550 fr_connection_t *this, *next;
554 DEBUG("%s: Removing connection pool", pool->log_prefix);
556 pthread_mutex_lock(&pool->mutex);
558 for (this = pool->head; this != NULL; this = next) {
561 INFO("%s: Closing connection (%i)", pool->log_prefix,
564 fr_connection_close(pool, this);
567 if (pool->trigger) exec_trigger(NULL, pool->cs, "stop", true);
569 rad_assert(pool->head == NULL);
570 rad_assert(pool->tail == NULL);
571 rad_assert(pool->num == 0);
573 free(pool->log_prefix);
577 /** Create a new connection pool
579 * Allocates structures used by the connection pool, initialises the various
580 * configuration options and counters, and sets the callback functions.
582 * Will also spawn the number of connections specified by the 'start'
583 * configuration options.
585 * @note Will call the 'start' trigger.
587 * @param[in] parent configuration section containing a 'pool' subsection.
588 * @param[in] ctx pointer to pass to callbacks.
589 * @param[in] c Callback to create new connections.
590 * @param[in] a Callback to check the status of connections.
591 * @param[in] d Callback to delete connections.
592 * @param[in] prefix to prepend to all log message, if NULL will create prefix
593 * from parent conf section names.
594 * @return A new connection pool or NULL on error.
596 fr_connection_pool_t *fr_connection_pool_init(CONF_SECTION *parent,
598 fr_connection_create_t c,
599 fr_connection_alive_t a,
600 fr_connection_delete_t d,
604 fr_connection_pool_t *pool;
605 fr_connection_t *this;
606 CONF_SECTION *modules;
608 char const *cs_name1, *cs_name2;
609 time_t now = time(NULL);
611 if (!parent || !ctx || !c || !d) return NULL;
613 cs = cf_section_sub_find(parent, "pool");
614 if (!cs) cs = cf_section_sub_find(parent, "limit");
616 pool = rad_malloc(sizeof(*pool));
617 memset(pool, 0, sizeof(*pool));
625 pool->head = pool->tail = NULL;
627 #ifdef HAVE_PTHREAD_H
628 pthread_mutex_init(&pool->mutex, NULL);
632 modules = cf_item_parent(cf_sectiontoitem(parent));
634 cs_name1 = cf_section_name1(modules);
635 if (cs_name1 && (strcmp(cs_name1, "modules") == 0)) {
636 cs_name1 = cf_section_name1(parent);
637 cs_name2 = cf_section_name2(parent);
642 lp_len = (sizeof(LOG_PREFIX) - 4) + strlen(cs_name1) + strlen(cs_name2);
643 pool->log_prefix = rad_malloc(lp_len);
644 snprintf(pool->log_prefix, lp_len, LOG_PREFIX, cs_name1,
647 } else { /* not a module configuration */
648 cs_name1 = cf_section_name1(parent);
650 pool->log_prefix = strdup(cs_name1);
653 pool->log_prefix = strdup(prefix);
656 DEBUG("%s: Initialising connection pool", pool->log_prefix);
659 if (cf_section_parse(cs, pool, connection_config) < 0) {
663 if (cf_section_sub_find(cs, "trigger")) pool->trigger = true;
669 pool->cleanup_delay = 5;
670 pool->idle_timeout = 60;
676 if (pool->max > 1024) pool->max = 1024;
677 if (pool->start > pool->max) pool->start = pool->max;
678 if (pool->spare > (pool->max - pool->min)) {
679 pool->spare = pool->max - pool->min;
681 if ((pool->lifetime > 0) && (pool->idle_timeout > pool->lifetime)) {
682 pool->idle_timeout = 0;
686 * Create all of the connections, unless the admin says
689 for (i = 0; i < pool->start; i++) {
690 this = fr_connection_spawn(pool, now);
693 fr_connection_pool_delete(pool);
698 if (pool->trigger) exec_trigger(NULL, pool->cs, "start", true);
704 /** Check whether a connection needs to be removed from the pool
706 * Will verify that the connection is within idle_timeout, max_uses, and
707 * lifetime values. If it is not, the connection will be closed.
709 * @note Will only close connections not in use.
710 * @note Must be called with the mutex held.
712 * @param[in,out] pool to modify.
713 * @param[in,out] this Connection to manage.
714 * @param[in] now Current time.
715 * @return 0 if the connection was closed, otherwise 1.
717 static int fr_connection_manage(fr_connection_pool_t *pool,
718 fr_connection_t *this,
721 rad_assert(pool != NULL);
722 rad_assert(this != NULL);
725 * Don't terminated in-use connections
727 if (this->in_use) return 1;
729 if ((pool->max_uses > 0) &&
730 (this->num_uses >= pool->max_uses)) {
731 DEBUG("%s: Closing expired connection (%i): Hit max_uses limit",
732 pool->log_prefix, this->number);
734 if ((pool->num <= pool->min) &&
735 (pool->last_complained < now)) {
736 WARN("%s: You probably need to lower \"min\"", pool->log_prefix);
738 pool->last_complained = now;
740 fr_connection_close(pool, this);
744 if ((pool->lifetime > 0) &&
745 ((this->created + pool->lifetime) < now)) {
746 DEBUG("%s: Closing expired connection (%i) ", pool->log_prefix,
751 if ((pool->idle_timeout > 0) &&
752 ((this->last_used + pool->idle_timeout) < now)) {
753 INFO("%s: Closing connection (%i): Hit idle_timeout, "
754 "was idle for %u seconds", pool->log_prefix, this->number,
755 (int) (now - this->last_used));
763 /** Check whether any connections needs to be removed from the pool
765 * Maintains the number of connections in the pool as per the configuration
766 * parameters for the connection pool.
768 * @note Will only run checks the first time it's called in a given second,
769 * to throttle connection spawning/closing.
770 * @note Will only close connections not in use.
771 * @note Must be called with the mutex held, will release mutex before
774 * @param[in,out] pool to manage.
777 static int fr_connection_pool_check(fr_connection_pool_t *pool)
780 time_t now = time(NULL);
781 fr_connection_t *this, *next;
783 if (pool->last_checked == now) {
784 pthread_mutex_unlock(&pool->mutex);
788 spare = pool->num - pool->active;
791 if ((pool->num < pool->max) && (spare < pool->spare)) {
792 spawn = pool->spare - spare;
793 if ((spawn + pool->num) > pool->max) {
794 spawn = pool->max - pool->num;
796 if (pool->spawning) spawn = 0;
799 pthread_mutex_unlock(&pool->mutex);
800 fr_connection_spawn(pool, now); /* ignore return code */
801 pthread_mutex_lock(&pool->mutex);
806 * We haven't spawned connections in a while, and there
807 * are too many spare ones. Close the one which has been
808 * idle for the longest.
810 if ((now >= (pool->last_spawned + pool->cleanup_delay)) &&
811 (spare > pool->spare)) {
812 fr_connection_t *idle;
815 for (this = pool->tail; this != NULL; this = this->prev) {
816 if (this->in_use) continue;
819 (this->last_used < idle->last_used)) {
824 rad_assert(idle != NULL);
826 INFO("%s: Closing connection (%i): Too many "
827 "free connections (%d > %d)", pool->log_prefix,
828 idle->number, spare, pool->spare);
829 fr_connection_close(pool, idle);
833 * Pass over all of the connections in the pool, limiting
834 * lifetime, idle time, max requests, etc.
836 for (this = pool->head; this != NULL; this = next) {
838 fr_connection_manage(pool, this, now);
841 pool->last_checked = now;
842 pthread_mutex_unlock(&pool->mutex);
847 /** Trigger connection check for a given connection or all connections
849 * If conn is not NULL then we call fr_connection_manage on the connection.
850 * If conn is NULL we call fr_connection_pool_check on the pool.
852 * @note Only connections that are not in use will be closed.
854 * @see fr_connection_manage
855 * @see fr_connection_pool_check
856 * @param[in,out] pool to manage.
857 * @param[in,out] conn to check.
858 * @return 0 if the connection was closed, else 1.
860 int fr_connection_check(fr_connection_pool_t *pool, void *conn)
862 fr_connection_t *this;
869 pthread_mutex_lock(&pool->mutex);
871 if (!conn) return fr_connection_pool_check(pool);
873 for (this = pool->head; this != NULL; this = this->next) {
874 if (this->connection == conn) {
875 ret = fr_connection_manage(pool, conn, now);
880 pthread_mutex_unlock(&pool->mutex);
885 /** Reserve a connection in the connection pool
887 * Will attempt to find an unused connection in the connection pool, if one is
888 * found, will mark it as in in use increment the number of active connections
889 * and return the connection handle.
891 * If no free connections are found will attempt to spawn a new one, conditional
892 * on a connection spawning not already being in progress, and not being at the
893 * 'max' connection limit.
895 * @note fr_connection_release must be called once the caller has finished
896 * using the connection.
898 * @see fr_connection_release
899 * @param[in,out] pool to reserve the connection from.
900 * @return a pointer to the connection handle, or NULL on error.
902 void *fr_connection_get(fr_connection_pool_t *pool)
905 fr_connection_t *this, *next;
907 if (!pool) return NULL;
909 pthread_mutex_lock(&pool->mutex);
912 for (this = pool->head; this != NULL; this = next) {
915 if (!this->in_use) goto do_return;
918 if (pool->num == pool->max) {
919 int complain = false;
922 * Rate-limit complaints.
924 if (pool->last_at_max != now) {
926 pool->last_at_max = now;
929 pthread_mutex_unlock(&pool->mutex);
932 ERROR("%s: No connections available and at max "
933 "connection limit", pool->log_prefix);
939 pthread_mutex_unlock(&pool->mutex);
940 this = fr_connection_spawn(pool, now);
941 if (!this) return NULL;
942 pthread_mutex_lock(&pool->mutex);
947 this->last_used = now;
950 pthread_mutex_unlock(&pool->mutex);
952 DEBUG("%s: Reserved connection (%i)", pool->log_prefix, this->number);
954 return this->connection;
957 /** Release a connection
959 * Will mark a connection as unused and decrement the number of active
962 * @see fr_connection_get
963 * @param[in,out] pool to release the connection in.
964 * @param[in,out] conn to release.
966 void fr_connection_release(fr_connection_pool_t *pool, void *conn)
968 fr_connection_t *this;
970 this = fr_connection_find(pool, conn);
973 rad_assert(this->in_use == true);
974 this->in_use = false;
977 * Determines whether the last used connection gets
982 * Put it at the tail of the list, so
983 * that it will get re-used last.
985 if (this != pool->tail) {
986 fr_connection_unlink(pool, this);
987 fr_connection_link_tail(pool, this);
991 * Put it at the head of the list, so
992 * that it will get re-used quickly.
994 if (this != pool->head) {
995 fr_connection_unlink(pool, this);
996 fr_connection_link_head(pool, this);
1000 rad_assert(pool->active > 0);
1003 DEBUG("%s: Released connection (%i)", pool->log_prefix, this->number);
1006 * We mirror the "spawn on get" functionality by having
1007 * "delete on release". If there are too many spare
1008 * connections, go manage the pool && clean some up.
1010 fr_connection_pool_check(pool);
1013 /** Reconnect a suspected inviable connection
1015 * This should be called by the module if it suspects that a connection is
1016 * not viable (e.g. the server has closed it).
1018 * Will attempt to create a new connection handle using the create callback,
1019 * and if this is successful the new handle will be assigned to the existing
1022 * If this is not successful, the connection will be removed from the pool.
1024 * When implementing a module that uses the connection pool API, it is advisable
1025 * to pass a pointer to the pointer to the handle (void **conn)
1026 * to all functions which may call reconnect. This is so that if a new handle
1027 * is created and returned, the handle pointer can be updated up the callstack,
1028 * and a function higher up the stack doesn't attempt to use a now invalid
1029 * connection handle.
1031 * @warning After calling reconnect the caller *MUST NOT* attempt to use
1032 * the old handle in any other operations, as its memory will have been freed.
1034 * @see fr_connection_get
1035 * @param[in,out] pool to reconnect the connection in.
1036 * @param[in,out] conn to reconnect.
1037 * @return ew connection handle if successful else NULL.
1039 void *fr_connection_reconnect(fr_connection_pool_t *pool, void *conn)
1042 fr_connection_t *this;
1045 if (!pool || !conn) return NULL;
1047 this = fr_connection_find(pool, conn);
1048 if (!this) return NULL;
1050 conn_number = this->number;
1052 rad_assert(this->in_use == true);
1054 DEBUG("%s: Reconnecting (%i)", pool->log_prefix, conn_number);
1056 new_conn = pool->create(pool->ctx);
1058 time_t now = time(NULL);
1060 if (pool->last_complained == now) {
1063 pool->last_complained = now;
1066 this->in_use = false;
1068 rad_assert(pool->active > 0);
1071 fr_connection_close(pool, this);
1072 pthread_mutex_unlock(&pool->mutex);
1075 * Can't create a new socket.
1076 * Try grabbing a pre-existing one.
1078 new_conn = fr_connection_get(pool);
1079 if (new_conn) return new_conn;
1081 if (!now) return NULL;
1083 ERROR("%s: Failed to reconnect (%i), and no other "
1084 "connections available", pool->log_prefix, conn_number);
1089 pool->delete(pool->ctx, conn);
1090 this->connection = new_conn;
1091 pthread_mutex_unlock(&pool->mutex);