DBPoolConn *dbpool_conn_consume(DBPool *p) { DBPoolConn *pc; gw_assert(p != NULL && p->pool != NULL); /* check for max connections and if 0 return NULL */ if (p->max_size < 1) return NULL; /* check if we have any connection */ while (p->curr_size < 1) { debug("dbpool", 0, "DBPool has no connections, reconnecting up to maximum..."); /* dbpool_increase ensure max_size is not exceeded so don't lock */ dbpool_increase(p, p->max_size - p->curr_size); if (p->curr_size < 1) gwthread_sleep(0.1); } /* garantee that you deliver a valid connection to the caller */ while ((pc = gwlist_consume(p->pool)) != NULL) { /* * XXX check that the connection is still existing. * Is this a performance bottle-neck?! */ if (!pc->conn || (p->db_ops->check && p->db_ops->check(pc->conn) != 0)) { /* something was wrong, reinitialize the connection */ /* lock dbpool for update */ gwlist_lock(p->pool); dbpool_conn_destroy(pc); p->curr_size--; /* unlock dbpool for update */ gwlist_unlock(p->pool); /* * maybe not needed, just try to get next connection, but it * can be dangeros if all connections where broken, then we will * block here for ever. */ while (p->curr_size < 1) { debug("dbpool", 0, "DBPool has too few connections, reconnecting up to maximum..."); /* dbpool_increase ensure max_size is not exceeded so don't lock */ dbpool_increase(p, p->max_size - p->curr_size); if (p->curr_size < 1) gwthread_sleep(0.1); } } else { break; } } return (pc->conn != NULL ? pc : NULL); }
DBPool *dbpool_create(enum db_type db_type, DBConf *conf, unsigned int connections) { DBPool *p; if (conf == NULL) return NULL; p = gw_malloc(sizeof(DBPool)); gw_assert(p != NULL); p->pool = gwlist_create(); gwlist_add_producer(p->pool); p->max_size = connections; p->curr_size = 0; p->conf = conf; p->db_type = db_type; switch(db_type) { #ifdef HAVE_MYSQL case DBPOOL_MYSQL: p->db_ops = &mysql_ops; break; #endif #ifdef HAVE_ORACLE case DBPOOL_ORACLE: p->db_ops = &oracle_ops; break; #endif #ifdef HAVE_SQLITE case DBPOOL_SQLITE: p->db_ops = &sqlite_ops; break; #endif #ifdef HAVE_SQLITE3 case DBPOOL_SQLITE3: p->db_ops = &sqlite3_ops; break; #endif #ifdef HAVE_SDB case DBPOOL_SDB: p->db_ops = &sdb_ops; break; #endif #ifdef HAVE_PGSQL case DBPOOL_PGSQL: p->db_ops = &pgsql_ops; break; #endif default: panic(0, "Unknown dbpool type defined."); } /* * XXX what is todo here if not all connections * where established ??? */ dbpool_increase(p, connections); return p; }
static void inc_dec_thread(void *arg) { DBPool *pool = arg; int ret; /* decrease */ info(0,"Decreasing pool by half of size, which is %d connections", abs(pool_size/2)); ret = dbpool_decrease(pool, abs(pool_size/2)); debug("",0,"Decreased by %d connections", ret); debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool)); /* increase */ info(0,"Increasing pool again by %d connections", pool_size); ret = dbpool_increase(pool, pool_size); debug("",0,"Increased by %d connections", ret); debug("",0,"Connections within pool: %ld", dbpool_conn_count(pool)); }
unsigned int dbpool_check(DBPool *p) { long i, len, n = 0, reinit = 0; gw_assert(p != NULL && p->pool != NULL && p->db_ops != NULL); /* * First check if db_ops->check function pointer is here. * NOTE: db_ops->check is optional, so if it is not there, then * we have nothing todo and we simple return list length. */ if (p->db_ops->check == NULL) return gwlist_len(p->pool); gwlist_lock(p->pool); len = gwlist_len(p->pool); for (i = 0; i < len; i++) { DBPoolConn *pconn; pconn = gwlist_get(p->pool, i); if (p->db_ops->check(pconn->conn) != 0) { /* something was wrong, reinitialize the connection */ gwlist_delete(p->pool, i, 1); dbpool_conn_destroy(pconn); p->curr_size--; reinit++; len--; i--; } else { n++; } } gwlist_unlock(p->pool); /* reinitialize brocken connections */ if (reinit > 0) n += dbpool_increase(p, reinit); return n; }