2 * PgBouncer - Lightweight connection pooler for PostgreSQL.
4 * Copyright (c) 2007 Marko Kreen, Skype Technologies OÜ
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 #define FULLVER PACKAGE_NAME " version " PACKAGE_VERSION " (" DBGVER ")"
30 #define FULLVER PACKAGE_NAME " version " PACKAGE_VERSION
33 /* each state corresponts to a list */
35 CL_FREE, /* free_client_list */
36 CL_JUSTFREE, /* justfree_client_list */
37 CL_LOGIN, /* login_client_list */
38 CL_WAITING, /* pool->waiting_client_list */
39 CL_ACTIVE, /* pool->active_client_list */
40 CL_CANCEL, /* pool->cancel_req_list */
42 SV_FREE, /* free_server_list */
43 SV_JUSTFREE, /* justfree_server_list */
44 SV_LOGIN, /* pool->new_server_list */
45 SV_IDLE, /* pool->idle_server_list */
46 SV_ACTIVE, /* pool->active_server_list */
47 SV_USED, /* pool->used_server_list */
48 SV_TESTED /* pool->tested_server_list */
52 P_NONE = 0, /* active pooling */
53 P_PAUSE = 1, /* wait for client to finish work */
54 P_SUSPEND = 2 /* wait for buffers to be empty */
57 #define is_server_socket(sk) ((sk)->state >= SV_FREE)
60 typedef struct PgSocket PgSocket;
61 typedef struct PgUser PgUser;
62 typedef struct PgDatabase PgDatabase;
63 typedef struct PgPool PgPool;
64 typedef struct PgStats PgStats;
65 typedef struct PgAddr PgAddr;
66 typedef enum SocketState SocketState;
67 typedef struct PktHdr PktHdr;
91 /* to avoid allocations will use static buffers */
93 #define MAX_USERNAME 64
94 #define MAX_PASSWORD 64
96 /* auth modes, should match PG's */
97 #define AUTH_ANY -1 /* same as trust but without username check */
104 /* type codes for weird pkts */
105 #define PKT_STARTUP 0x30000
106 #define PKT_CANCEL 80877102
107 #define PKT_SSLREQ 80877103
109 #define POOL_SESSION 0
113 /* old style V2 header: len:4b code:4b */
114 #define OLD_HEADER_LEN 8
115 /* new style V3 packet header len - type:1b, len:4b */
116 #define NEW_HEADER_LEN 5
118 #define BACKENDKEY_LEN 8
121 * Remote/local address
124 struct in_addr ip_addr;
130 * Stats, kept per-pool.
133 uint64_t request_count;
134 uint64_t server_bytes;
135 uint64_t client_bytes;
136 usec_t query_time; /* total req time in us */
140 * Contains connections for one db+user pair.
143 * ->stats is updated online.
144 * for each stats_period:
145 * ->older_stats = ->newer_stats
146 * ->newer_stats = ->stats
149 List head; /* entry in global pool_list */
150 List map_head; /* entry in user->pool_list */
152 PgDatabase *db; /* corresponging database */
153 PgUser *user; /* user logged in as */
155 StatList active_client_list; /* waiting events logged in clients */
156 StatList waiting_client_list; /* client waits for a server to be available */
157 StatList cancel_req_list; /* closed client connections with server key */
159 StatList active_server_list; /* servers linked with clients */
160 StatList idle_server_list; /* servers ready to be linked with clients */
161 StatList used_server_list; /* server just unlinked from clients */
162 StatList tested_server_list; /* server in testing process */
163 StatList new_server_list; /* servers in login phase */
169 /* database info to be sent to client */
170 uint8_t welcome_msg[256]; /* ServerParams without VarCache ones */
171 unsigned welcome_msg_len;
173 VarCache orig_vars; /* default params from server */
175 usec_t last_lifetime_disconnect;/* last time when server_lifetime was applied */
177 /* if last connect failed, there should be delay before next */
178 usec_t last_connect_time;
179 unsigned last_connect_failed:1;
181 unsigned welcome_msg_ready:1;
184 #define pool_server_count(pool) ( \
185 statlist_count(&(pool)->active_server_list) + \
186 statlist_count(&(pool)->idle_server_list) + \
187 statlist_count(&(pool)->new_server_list) + \
188 statlist_count(&(pool)->tested_server_list) + \
189 statlist_count(&(pool)->used_server_list))
191 #define pool_client_count(pool) ( \
192 statlist_count(&(pool)->active_client_list) + \
193 statlist_count(&(pool)->waiting_client_list))
196 * A user in login db.
198 * fixme: remove ->head as ->tree_node should be enough.
200 * For databases where remote user is forced, the pool is:
201 * first(db->forced_user->pool_list), where pool_list has only one entry.
203 * Otherwise, ->pool_list contains multiple pools, for all PgDatabases
204 * whis user has logged in.
207 List head; /* used to attach user to list */
208 List pool_list; /* list of pools where pool->user == this user */
209 Node tree_node; /* used to attach user to tree */
210 char name[MAX_USERNAME];
211 char passwd[MAX_PASSWORD];
215 * A database entry from config.
219 char name[MAX_DBNAME]; /* db name for clients */
221 bool db_paused; /* PAUSE <db>; was issued */
222 bool db_dead; /* used on RELOAD/SIGHUP to later detect removed dbs */
223 bool admin; /* internal console db */
225 uint8_t startup_params[256]; /* partial StartupMessage (without user) be sent to server */
226 unsigned startup_params_len;
228 PgUser *forced_user; /* if not NULL, the user/psw is forced */
230 PgAddr addr; /* address prepared for connect() */
231 char unix_socket_dir[UNIX_PATH_MAX]; /* custom unix socket dir */
233 int pool_size; /* max server connections in one pool */
235 const char *dbname; /* server-side name, pointer to inside startup_msg */
237 /* startup commands to send to server after connect. malloc-ed */
238 const char *connect_query;
243 * A client or server connection.
245 * ->state corresponds to various lists the struct can be at.
248 List head; /* list header */
249 PgSocket *link; /* the dest of packets */
250 PgPool *pool; /* parent pool, if NULL not yet assigned */
252 PgUser *auth_user; /* presented login, for client it may differ from pool->user */
254 SocketState state:8; /* this also specifies socket location */
256 bool ready:1; /* server: accepts new query */
257 bool close_needed:1; /* server: this socket must be closed ASAP */
258 bool setting_vars:1; /* server: setting client vars */
259 bool exec_on_connect:1; /* server: executing connect_query */
261 bool wait_for_welcome:1;/* client: no server yet in pool, cannot send welcome msg */
263 bool suspended:1; /* client/server: if the socket is suspended */
265 bool admin_user:1; /* console client: has admin rights */
266 bool own_user:1; /* console client: client with same uid on unix socket */
267 bool wait_for_response:1;/* console client: waits for completion of PAUSE/SUSPEND cmd */
269 usec_t connect_time; /* when connection was made */
270 usec_t request_time; /* last activity time */
271 usec_t query_start; /* query start moment */
273 uint8_t cancel_key[BACKENDKEY_LEN]; /* client: generated, server: remote */
274 PgAddr remote_addr; /* ip:port for remote endpoint */
275 PgAddr local_addr; /* ip:port for local endpoint */
277 VarCache vars; /* state of interesting server parameters */
279 SBuf sbuf; /* stream buffer, must be last */
282 #define RAW_IOBUF_SIZE offsetof(IOBuf, buf)
283 #define IOBUF_SIZE (RAW_IOBUF_SIZE + cf_sbuf_len)
285 /* where to store old fd info during SHOW FDS result processing */
286 #define tmp_sk_oldfd request_time
287 #define tmp_sk_linkfd query_start
288 /* takeover_clean_socket() needs to clean those up */
290 /* where the salt is temporarly stored */
291 #define tmp_login_salt cancel_key
294 extern int cf_verbose;
295 extern int cf_daemon;
298 extern char *cf_jobname;
299 extern int cf_syslog;
300 extern char *cf_syslog_facility;
302 extern char *cf_unix_socket_dir;
303 extern char *cf_listen_addr;
304 extern int cf_listen_port;
306 extern int cf_pool_mode;
307 extern int cf_max_client_conn;
308 extern int cf_default_pool_size;
310 extern usec_t cf_suspend_timeout;
311 extern usec_t cf_server_lifetime;
312 extern usec_t cf_server_idle_timeout;
313 extern char * cf_server_reset_query;
314 extern char * cf_server_check_query;
315 extern usec_t cf_server_check_delay;
316 extern usec_t cf_server_connect_timeout;
317 extern usec_t cf_server_login_retry;
318 extern usec_t cf_query_timeout;
319 extern usec_t cf_client_idle_timeout;
320 extern usec_t cf_client_login_timeout;
321 extern int cf_server_round_robin;
323 extern int cf_auth_type;
324 extern char *cf_auth_file;
326 extern char *cf_logfile;
327 extern char *cf_pidfile;
329 extern char *cf_ignore_startup_params;
331 extern char *cf_admin_users;
332 extern char *cf_stats_users;
333 extern int cf_stats_period;
335 extern int cf_pause_mode;
336 extern int cf_shutdown;
337 extern int cf_reboot;
339 extern int cf_sbuf_loopcnt;
340 extern int cf_sbuf_len;
341 extern int cf_tcp_keepalive;
342 extern int cf_tcp_keepcnt;
343 extern int cf_tcp_keepidle;
344 extern int cf_tcp_keepintvl;
345 extern int cf_tcp_socket_buffer;
346 extern int cf_tcp_defer_accept;
348 extern int cf_log_connections;
349 extern int cf_log_disconnections;
350 extern int cf_log_pooler_errors;
352 extern ConfElem bouncer_params[];
354 extern usec_t g_suspend_start;
356 static inline PgSocket * _MUSTCHECK
357 pop_socket(StatList *slist)
359 List *item = statlist_pop(slist);
362 return container_of(item, PgSocket, head);
365 static inline PgSocket *
366 first_socket(StatList *slist)
368 if (statlist_empty(slist))
370 return container_of(slist->head.next, PgSocket, head);
373 void load_config(bool reload);