Ejemplo n.º 1
0
/**
 * free all entries of the pool
 *
 */
void network_connection_pool_free(network_connection_pool *pool) {
	if (pool) {
		network_connection_pool_entry *entry = NULL;
		while ((entry = g_queue_pop_head(pool))) network_connection_pool_entry_free(entry, TRUE);
		g_queue_free(pool);
	}
}
Ejemplo n.º 2
0
/**
 * free all pool entries of the queue
 *
 * used as GDestroyFunc in the user-hash of the pool
 *
 * @param q a GQueue to free
 *
 * @see network_connection_pool_new
 * @see GDestroyFunc
 */
static void g_queue_free_all(gpointer q) {
	GQueue *queue = q;
	network_connection_pool_entry *entry;

	while ((entry = g_queue_pop_head(queue))) network_connection_pool_entry_free(entry, TRUE);

	g_queue_free(queue);
}
Ejemplo n.º 3
0
/**
 * remove the connection referenced by entry from the pool 
 */
void network_connection_pool_remove(network_connection_pool *pool, network_connection_pool_entry *entry) {
	network_socket *sock = entry->sock;

	if (sock->response == NULL) {
		g_critical("%s: (remove) remove socket from pool, response is NULL, src is %s, dst is %s", G_STRLOC, sock->src->name->str, sock->dst->name->str);
	}

	network_connection_pool_entry_free(entry, TRUE);

	g_queue_remove(pool, entry);
}
Ejemplo n.º 4
0
/**
 * remove the connection referenced by entry from the pool 
 */
void network_connection_pool_remove(network_connection_pool *pool, network_connection_pool_entry *entry) {
	network_socket *sock = entry->sock;
	GQueue *conns;

	if (NULL == (conns = g_hash_table_lookup(pool->users, sock->response->username))) {
		return;
	}

	network_connection_pool_entry_free(entry, TRUE);

	g_queue_remove(conns, entry);
}
Ejemplo n.º 5
0
void garbage_connection_pool_free(network_garbage_connection_pool *gc_pool) {
	if (gc_pool != NULL) {
		if (gc_pool->entries != NULL) {
			network_connection_pool_entry *entry = NULL;
			while ( (entry = g_queue_pop_head(gc_pool->entries)) != NULL ) {
				network_connection_pool_entry_free(entry, FALSE);
			}
			g_queue_free(gc_pool->entries);
		}
		g_mutex_clear(&(gc_pool->mutex));
		g_free(gc_pool);
	}
	return;
}
Ejemplo n.º 6
0
guint garbage_connection_pool_clean_old_entries(network_garbage_connection_pool *gc_pool, gint grace_secs) {
	guint count = 0;
	guint i = 0;
	network_connection_pool_entry *entry = NULL;
	GTimeVal now_tv;
	guint q_len_before = 0;
	guint q_len_after = 0;

	g_assert(gc_pool);

	g_get_current_time(&now_tv);

	g_mutex_lock(&(gc_pool->mutex));
	q_len_before = g_queue_get_length(gc_pool->entries);

	for (i = 0; i < g_queue_get_length(gc_pool->entries); ) {
		entry = g_queue_peek_nth(gc_pool->entries, i);
		if (entry == NULL) {
			i++;
			continue;
		}
		if (now_tv.tv_sec > (entry->added_ts).tv_sec + grace_secs) {
			//remove this entry
			entry = g_queue_pop_nth(gc_pool->entries, i);
			network_connection_pool_entry_free(entry, TRUE);
			entry = NULL;
			count++;
		} else {
			i++;
		}
	}

	q_len_after = g_queue_get_length(gc_pool->entries);

	g_mutex_unlock(&(gc_pool->mutex));

#ifdef DEBUG_CONN_POOL
	if (q_len_before > 0) {
		g_debug("[%s]: gc_pool length before: %d, after: %d, removed: %d",
				G_STRLOC, q_len_before, q_len_after, count);
	}
#endif

	return count;
}
Ejemplo n.º 7
0
/**
 * get a connection from the pool
 *
 * make sure we have at lease <min-conns> for each user
 * if we have more, reuse a connect to reauth it to another user
 *
 * @param pool connection pool to get the connection from
 * @param username (optional) name of the auth connection
 * @param default_db (unused) unused name of the default-db
 */
network_socket *network_connection_pool_get(network_connection_pool *pool,
		GString *username,
		GString *UNUSED_PARAM(default_db)) {

	network_connection_pool_entry *entry = NULL;
	network_socket *sock = NULL;

	GQueue *conns = network_connection_pool_get_conns(pool, username, NULL);

	/**
	 * if we know this use, return a authed connection 
	 */
	if (conns) {
		entry = g_queue_pop_head(conns);

		if (conns->length == 0) {
			/**
			 * all connections are gone, remove it from the hash
			 */
			g_hash_table_remove(pool->users, username);
		}
	}

	if (!entry) {
#ifdef DEBUG_CONN_POOL
		g_debug("%s: (get) no entry for user '%s' -> %p", G_STRLOC, username ? username->str : "", conns);
#endif
		return NULL;
	}

	sock = entry->sock;

	network_connection_pool_entry_free(entry, FALSE);

	/* remove the idle handler from the socket */	
	event_del(&(sock->event));
		
#ifdef DEBUG_CONN_POOL
	g_debug("%s: (get) got socket for user '%s' -> %p", G_STRLOC, username ? username->str : "", sock);
#endif

	return sock;
}
Ejemplo n.º 8
0
/**
 * get a connection from the pool
 *
 * make sure we have at lease <min-conns> for each user
 * if we have more, reuse a connect to reauth it to another user
 *
 * @param pool connection pool to get the connection from
 * @param username (optional) name of the auth connection
 * @param default_db (unused) unused name of the default-db
 */
network_socket *network_connection_pool_get(network_connection_pool *pool) {
	network_connection_pool_entry *entry = NULL;

	if (pool->length > 0) {
	//	entry = g_queue_pop_head(pool);
		entry = g_queue_pop_tail(pool);
	}

	/**
	 * if we know this use, return a authed connection 
	 */

	if (!entry) return NULL;

	network_socket *sock = entry->sock;

	network_connection_pool_entry_free(entry, FALSE);

	/* remove the idle handler from the socket */	
	event_del(&(sock->event));
		
	return sock;
}
Ejemplo n.º 9
0
/**
 * get a connection from the pool
 *
 * make sure we have at lease <min-conns> for each user
 * if we have more, reuse a connect to reauth it to another user
 *
 * @param pool connection pool to get the connection from
 * @param username (optional) name of the auth connection
 * @param default_db (unused) unused name of the default-db
 */
network_socket *network_connection_pool_get(network_connection_pool *pool,
		GString *username,
		GString *UNUSED_PARAM(default_db), conn_ctl_info *info) {

    guint32  cur;
    guint    len, i;
	network_socket *sock = NULL;
	network_connection_pool_entry *entry, *found_entry = NULL;

	GQueue *conns = network_connection_pool_get_conns(pool, username, NULL);

	/**
	 * if we know this use, return a authed connection 
	 */
	if (conns) {
        cur = time(0);
        len = g_queue_get_length(conns);
        for (i = 0; i < len; i++) {
            entry = g_queue_peek_nth(conns, i);
            if (entry->key == info->key) {
                if (!entry->shared) {
                    found_entry = entry;
                    g_queue_pop_nth (conns, i);
                    break;
                }
            }
        }

        if (!found_entry && len > 0) {
            entry = g_queue_peek_nth(conns, 0);
            found_entry = entry;
            g_queue_pop_nth (conns, 0);
            g_debug("%s: (get) entry for user '%s' -> %p, cur:%u",
                    G_STRLOC, username ? username->str : "", entry, cur);
        }

		if (conns->length == 0) {
			/**
			 * all connections are gone, remove it from the hash
			 */
			g_hash_table_remove(pool->users, username);
		}
	}

    if (!found_entry) {
		g_debug("%s: (get) no entry for user '%s' -> %p", G_STRLOC, username ? username->str : "", conns);
		return NULL;
	}

	sock = found_entry->sock;

    g_debug("%s: recv queue length:%d, sock:%p", 
                        G_STRLOC, sock->recv_queue->chunks->length, sock);

	network_connection_pool_entry_free(found_entry, FALSE);

	/* remove the idle handler from the socket */	
	event_del(&(sock->event));
		
	g_debug("%s: (get) got socket for user '%s' -> %p", G_STRLOC, username ? username->str : "", sock);

	return sock;
}
Ejemplo n.º 10
0
network_socket *network_connection_pool_get_new(chassis *chas,
		network_backend_t *backend, proxy_rw type,
		network_connection_pool *pool, const GString *username,
		user_pool_config *user_pool_conf,
		connection_scaler_pool_statistics *pool_stats) {
	guint pool_conn_current_using_sum = 0;
	GQueue *conns = NULL;
	network_connection_pool_entry *entry = NULL;
	GTimeVal now_tv;
	guint removed = 0;
	network_socket *sock = NULL;

	g_assert(chas);
	g_assert(backend);
	g_assert(type == PROXY_TYPE_WRITE || type == PROXY_TYPE_READ);
	g_assert(pool);
	g_assert(username);
	g_assert(user_pool_conf);
	g_assert(pool_stats);
	g_assert(backend->pool[type] == pool);

	/**
	 * 取用户连接池
	 */
	g_mutex_lock(&(pool->connection_pool_mutex));
	conns = network_connection_pool_get_conns(pool, username, NULL );
	if (conns == NULL ) {
		pool_stats->conn_nopool++;
		goto NETWORK_CONNECTION_POOL_GET_NEW_EXIT;
	}
	pool_stats->conn_length = g_queue_get_length(conns);

	/**
	 * 删除空的用户连接池
	 * 比如最小连接数等于零
	 */
	if (pool_stats->conn_length == 0) {
		pool_stats->conn_zerosize++;
		g_hash_table_remove(pool->users, username);
		goto NETWORK_CONNECTION_POOL_GET_NEW_EXIT;
	}

	/**
	 * 取用户连接池当前连接数,包括未决的和已用的,不包括空闲的(空闲数量应该约等于连接池长度)
	 */
	pool_conn_current_using_sum = get_conn_using_pending_count(pool, username->str);

	/**
	 * 是否[连接池当前连接]大于[最大连接数]
	 */
	if (pool_conn_current_using_sum > user_pool_conf->max_connections) {
		pool_stats->conn_toomany++;
		goto NETWORK_CONNECTION_POOL_GET_NEW_EXIT;
	}

	g_get_current_time(&now_tv);

	/**取出一个连接*/
	for (entry = g_queue_pop_head(conns); conns != NULL && entry != NULL ;
			entry = g_queue_pop_head(conns)) {
		pool_stats->conn_checked++;
		/**proxy_get_server_connection_list()这里idle--*/
		//update_conn_pool_status_in_state(pool, username->str, POOL_STATUS_STATE_REMOVE_FROM_POOL);

		/**
		 * 检查时间间隔未到,不需要检查,退出(此用户连接池)循环
		 */
		if (check_pool_entry_connectivity_timeout(entry, &now_tv) == FALSE) {
			pool_stats->conn_again++;
			break;
		}

		/**
		 * 是否断开
		 */
		if (check_pool_entry_connectivity(entry) == FALSE) {
			update_conn_pool_status_in_state(pool, username->str, POOL_STATUS_STATE_REMOVE_FROM_POOL);
			garbage_connection_pool_add_entry(pool->garbage_connection_pool,
					entry);
			pool_stats->conn_disconnected++;
			entry = NULL;
			pool_conn_current_using_sum = get_conn_using_pending_count(pool, username->str);
			continue;
		}

		/**
		 * 正常的连接
		 */
		if (entry != NULL) {
			pool_stats->conn_good++;
			break;
		}

	}

	NETWORK_CONNECTION_POOL_GET_NEW_EXIT:
	g_mutex_unlock(
			&(pool->connection_pool_mutex));

	removed += pool_stats->conn_disconnected;

	if (entry == NULL ) {
#ifdef DEBUG_CONN_POOL
		g_debug("%s: (get) no entry for user '%s' -> %p", G_STRLOC, username ? username->str : "", conns);
#endif
		return NULL ;
	} else {
		sock = entry->sock;
		network_connection_pool_entry_free(entry, FALSE);
#ifdef DEBUG_CONN_POOL
		g_debug("%s: (get) got socket for user '%s' -> %p", G_STRLOC, username ? username->str : "", sock);
#endif
	}

	return sock;
}
Ejemplo n.º 11
0
/**
 * get a connection from the pool
 * 从连接池头部取出一个连接
 *
 * make sure we have at lease <min-conns> for each user
 * if we have more, reuse a connect to reauth it to another user
 *
 * @param pool connection pool to get the connection from
 * @param username (optional) name of the auth connection
 * @param default_db (unused) unused name of the default-db
 */
network_socket *network_connection_pool_get(network_connection_pool *pool,
		GString *username,
		GString *UNUSED_PARAM(default_db)) {

	GQueue *conns = NULL;
	network_connection_pool_entry *entry = NULL;
	network_socket *sock = NULL;

	g_mutex_lock(&(pool->connection_pool_mutex));

	conns = network_connection_pool_get_conns(pool, username, NULL);

	/**
	 * if we know this use, return a authed connection 
	 */
#ifndef CONNECTION_POOL_REGISTER_EVENTS_ENABLED
	if (conns) {

		entry = g_queue_pop_head(conns);

		/**
		 * 取出一个状态正常的连接,将状态异常的连接放入垃圾回收池
		 * @todo 这里可以不用检查了?因为已有单独scaler线程定期(若干秒)检查连接状态
		 */
		while (entry != NULL ) {
			if (check_pool_entry_status(entry) == TRUE) {
				break;
			} else {
				garbage_connection_pool_add_entry(pool->garbage_connection_pool, entry);
			}
			entry = g_queue_pop_head(conns);
		}
		if (conns->length == 0) {
			/**
			 * all connections are gone, remove it from the hash
			 */
			g_hash_table_remove(pool->users, username);
		}
	}

#else
	if (conns) {
		entry = g_queue_pop_head(conns);

		if (conns->length == 0) {
			/**
			 * all connections are gone, remove it from the hash
			 */
			g_hash_table_remove(pool->users, username);
		}
	}

#endif

	if (!entry) {
#ifdef DEBUG_CONN_POOL
		g_debug("%s: (get) no entry for user '%s' -> %p", G_STRLOC, username ? username->str : "", conns);
#endif
		g_mutex_unlock(&(pool->connection_pool_mutex));
		return NULL;
	}

	sock = entry->sock;

	network_connection_pool_entry_free(entry, FALSE);

	/**连接加入连接池时没有注册事件,所以取出时也不需要删除事件*/
//	struct event *ev = &(sock->event);
//	/* remove the idle handler from the socket */
//	if(sock->event.ev_base) {
//		g_debug("[%s]: fd: %d, events: %x, callback: %p network_mysqld_pool_con_idle_handle: %p, network_mysqld_cache_con_idle_handle: %p",
//				G_STRLOC, event_get_fd(ev), event_get_events(ev),
//				event_get_callback(ev),
//				network_mysqld_pool_con_idle_handle,
//				network_mysqld_cache_con_idle_handle);
//		event_del(&(sock->event));
//	}
//	g_debug("[%s]: fd: %d, events: %x, callback: %p network_mysqld_pool_con_idle_handle: %p, network_mysqld_cache_con_idle_handle: %p",
//			G_STRLOC, event_get_fd(ev), event_get_events(ev),
//			event_get_callback(ev),
//			network_mysqld_pool_con_idle_handle,
//			network_mysqld_cache_con_idle_handle);

#ifdef DEBUG_CONN_POOL
	g_debug("%s: (get) got socket for user '%s' -> %p", G_STRLOC, username ? username->str : "", sock);
#endif

	g_mutex_unlock(&(pool->connection_pool_mutex));
	return sock;
}