Beispiel #1
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;
}
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;
}
/**
 * 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;
}
/**
 * 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;
}