📄 main.c
字号:
/* TDSPool - Connection pooling for TDS based databases * Copyright (C) 2001 Brian Bruns * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *//* * Note on terminology: a pool member is a connection to the database, * a pool user is a client connection that is temporarily assigned to a * pool member. */#if HAVE_CONFIG_H#include <config.h>#endif /* HAVE_CONFIG_H */#include <stdarg.h>#include <stdio.h>#include <signal.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif /* HAVE_STDLIB_H */#if HAVE_STRING_H#include <string.h>#endif /* HAVE_STRING_H */#if HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif /* HAVE_SYS_SOCKET_H */#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif /* HAVE_NETINET_IN_H */#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif /* HAVE_ARPA_INET_H */#include "pool.h"TDS_RCSID(var, "$Id: main.c,v 1.24 2007/09/17 08:46:03 freddy77 Exp $");/* to be set by sig term */static int term = 0;/* number of users in wait state */int waiters = 0;static void term_handler(int sig);static void pool_schedule_waiters(TDS_POOL * pool);static TDS_POOL *pool_init(char *name);static void pool_main_loop(TDS_POOL * pool);static voidterm_handler(int sig){ fprintf(stdout, "Shutdown Requested\n"); term = 1;}/* * pool_init creates a named pool and opens connections to the database */static TDS_POOL *pool_init(char *name){ TDS_POOL *pool; /* initialize the pool */ pool = (TDS_POOL *) malloc(sizeof(TDS_POOL)); memset(pool, '\0', sizeof(TDS_POOL)); /* FIXME -- read this from the conf file */ if (!pool_read_conf_file(name, pool)) { fprintf(stderr, "Configuration for pool ``%s'' not found.\n", name); exit(EXIT_FAILURE); } pool->num_members = pool->max_open_conn; pool->name = strdup(name); pool_mbr_init(pool); pool_user_init(pool); return pool;}static voidpool_schedule_waiters(TDS_POOL * pool){ TDS_POOL_USER *puser; TDS_POOL_MEMBER *pmbr; int i, free_mbrs; /* first see if there are free members to do the request */ free_mbrs = 0; for (i = 0; i < pool->num_members; i++) { pmbr = (TDS_POOL_MEMBER *) & pool->members[i]; if (pmbr->tds && pmbr->state == TDS_IDLE) free_mbrs++; } if (!free_mbrs) return; for (i = 0; i < pool->max_users; i++) { puser = (TDS_POOL_USER *) & pool->users[i]; if (puser->user_state == TDS_SRV_WAIT) { /* place back in query state */ puser->user_state = TDS_SRV_QUERY; waiters--; /* now try again */ pool_user_query(pool, puser); return; } }}/* * pool_main_loop * Accept new connections from clients, and handle all input from clients and * pool members. */static voidpool_main_loop(TDS_POOL * pool){ TDS_POOL_USER *puser; TDS_POOL_MEMBER *pmbr; struct sockaddr_in sin; int s, maxfd, i; int retval; fd_set rfds; int socktrue = 1; /* FIXME -- read the interfaces file and bind accordingly */ sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(pool->port); sin.sin_family = AF_INET; if (TDS_IS_SOCKET_INVALID(s = socket(AF_INET, SOCK_STREAM, 0))) { perror("socket"); exit(1); } /* don't keep addr in use from s.craig@andronics.com */ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const void *) &socktrue, sizeof(socktrue)); fprintf(stderr, "Listening on port %d\n", pool->port); if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { perror("bind"); exit(1); } listen(s, 5); FD_ZERO(&rfds); FD_SET(s, &rfds); maxfd = s; while (!term) { /* fprintf(stderr, "waiting for a connect\n"); */ retval = select(maxfd + 1, &rfds, NULL, NULL, NULL); if (term) break; /* process the sockets */ if (FD_ISSET(s, &rfds)) { pool_user_create(pool, s, &sin); } pool_process_users(pool, &rfds); pool_process_members(pool, &rfds); /* back from members */ if (waiters) { pool_schedule_waiters(pool); } FD_ZERO(&rfds); /* add the listening socket to the read list */ FD_SET(s, &rfds); maxfd = s; /* add the user sockets to the read list */ for (i = 0; i < pool->max_users; i++) { puser = (TDS_POOL_USER *) & pool->users[i]; /* skip dead connections */ if (!IS_TDSDEAD(puser->tds)) { if (puser->tds->s > maxfd) maxfd = puser->tds->s; FD_SET(puser->tds->s, &rfds); } } /* add the pool member sockets to the read list */ for (i = 0; i < pool->num_members; i++) { pmbr = (TDS_POOL_MEMBER *) & pool->members[i]; if (!IS_TDSDEAD(pmbr->tds)) { if (pmbr->tds->s > maxfd) maxfd = pmbr->tds->s; FD_SET(pmbr->tds->s, &rfds); } } } /* while !term */ CLOSESOCKET(s); for (i = 0; i < pool->max_users; i++) { puser = (TDS_POOL_USER *) & pool->users[i]; if (!IS_TDSDEAD(puser->tds)) { fprintf(stderr, "Closing user %d\n", i); tds_close_socket(puser->tds); } } for (i = 0; i < pool->num_members; i++) { pmbr = (TDS_POOL_MEMBER *) & pool->members[i]; if (!IS_TDSDEAD(pmbr->tds)) { fprintf(stderr, "Closing member %d\n", i); tds_close_socket(pmbr->tds); } }}intmain(int argc, char **argv){ TDS_POOL *pool; signal(SIGTERM, term_handler); signal(SIGINT, term_handler); if (argc < 2) { fprintf(stderr, "Usage: tdspool <pool name>\n"); return 1; } pool = pool_init(argv[1]); pool_main_loop(pool); fprintf(stdout, "tdspool Shutdown\n"); return EXIT_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -