1 /*Copyright (c) Brian B.
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Lesser General Public
5 License as published by the Free Software Foundation; either
6 version 3 of the License, or (at your option) any later version.
7 See the file LICENSE included with this distribution for more
10 #include "libpgcli/pgpool.h"
12 pgpool_t
*pgpool_create () {
13 pgpool_t
*pool
= malloc(sizeof(pgpool_t
));
15 pool
->pg_free
= lst_alloc(NULL
);
16 pool
->pg_busy
= lst_alloc(NULL
);
17 pthread_mutex_init(&pool
->locker
, NULL
);
18 pthread_condattr_init(&pool
->cond_attr
);
19 pthread_condattr_setclock(&pool
->cond_attr
, CLOCK_MONOTONIC
);
20 pthread_cond_init(&pool
->cond
, &pool
->cond_attr
);
24 void pgpool_setopt_pchar (pgpool_t
*pool
, pgpool_opt_t opt
, char *arg
) {
25 if (PGPOOL_CONNINFO
== opt
)
26 pool
->conn_info
= arg
;
29 void pgpool_setopt_time (pgpool_t
*pool
, pgpool_opt_t opt
, time_t arg
) {
30 pool
->livingtime
= arg
;
33 void pgpool_setopt_int (pgpool_t
*pool
, pgpool_opt_t opt
, uintptr_t arg
) {
34 if (PGPOOL_LIVINGTIME
== opt
)
35 pool
->livingtime
= arg
;
38 static void *_on_pgpool (void *param
) {
39 pgpool_t
*pool
= (pgpool_t
*)param
;
40 while (pool
->is_alive
) {
41 struct timespec to_time
;
42 clock_gettime(CLOCK_MONOTONIC
, &to_time
);
43 to_time
.tv_sec
+= pool
->livingtime
;
44 pthread_mutex_lock(&pool
->locker
);
45 if (ETIMEDOUT
== pthread_cond_timedwait(&pool
->cond
, &pool
->locker
, &to_time
)) {
48 if ((li
= pool
->pg_free
->head
)) {
50 list_item_t
*li_n
= li
->next
;
51 pgconn_t
*conn
= (pgconn_t
*)li
->ptr
;
52 if (conn
->tm_released
+ pool
->livingtime
< t0
) {
57 } while (li
!= pool
->pg_free
->head
);
60 pthread_mutex_unlock(&pool
->locker
);
65 int pgpool_start (pgpool_t
*pool
) {
66 if (0 == pool
->livingtime
)
69 return pthread_create(&pool
->th
, NULL
, _on_pgpool
, (void*)pool
);
72 static int _on_disconnect (list_item_t
*li
, void *dummy
) {
73 pgconn_t
*conn
= (pgconn_t
*)li
->ptr
;
78 void pgpool_free (pgpool_t
*pool
) {
80 pthread_mutex_lock(&pool
->locker
);
82 pthread_cond_signal(&pool
->cond
);
83 pthread_mutex_unlock(&pool
->locker
);
84 pthread_join(pool
->th
, NULL
);
86 lst_enum(pool
->pg_free
, _on_disconnect
, NULL
, 0);
87 lst_enum(pool
->pg_busy
, _on_disconnect
, NULL
, 0);
88 lst_free(pool
->pg_free
);
89 lst_free(pool
->pg_busy
);
90 free(pool
->conn_info
);
91 pthread_condattr_destroy(&pool
->cond_attr
);
92 pthread_cond_destroy(&pool
->cond
);
93 pthread_mutex_destroy(&pool
->locker
);
97 static pgconn_t
*_connect (pgpool_t
*pool
) {
98 pgconn_t
*conn
= pg_connect(pool
->conn_info
);
99 if (conn
->error
|| conn
->intr_error
) {
101 pool
->on_error(conn
);
105 conn
->li
= lst_adde(pool
->pg_busy
, conn
);
106 conn
->tm_released
= 0;
108 pthread_mutex_unlock(&pool
->locker
);
112 pgconn_t
*pgpool_get (pgpool_t
*pool
) {
113 list_item_t
*li
= pool
->pg_free
->head
;
115 pthread_mutex_lock(&pool
->locker
);
117 return _connect(pool
);
118 conn
= (pgconn_t
*)li
->ptr
;
120 conn
->tm_released
= 0;
121 conn
->li
= lst_add(pool
->pg_busy
, conn
);
122 pthread_mutex_unlock(&pool
->locker
);
126 void pgpool_release (pgconn_t
*conn
) {
127 pthread_mutex_lock(&conn
->pool
->locker
);
129 conn
->tm_released
= time(0);
130 conn
->li
= lst_adde(conn
->pool
->pg_free
, conn
);
131 pthread_mutex_unlock(&conn
->pool
->locker
);
134 static void _check (pgpool_t
*pool
, list_item_t
*x
, time_t t0
) {
135 pgconn_t
*conn
= (pgconn_t
*)x
->ptr
;
136 if (conn
->tm_released
+ pool
->livingtime
< t0
) {
142 void pgpool_check (pgpool_t
*pool
) {
143 if (pool
->livingtime
<= 0)
145 list_t
*lst
= pool
->pg_free
;
146 list_item_t
*x
= lst
->head
;
150 list_item_t
*y
= x
->next
;
153 } while (x
!= lst
->head
);