acl/app/jaws/global/conn_cache.c

338 lines
8.4 KiB
C
Raw Normal View History

#include "lib_acl.h"
#include "conn_cache.h"
/* <20><>Ӧij<D3A6><C4B3> IP:PORT <20><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ӳؽṹ<D8BD><E1B9B9><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD> */
typedef struct CONN_POOL {
CONN_CACHE *conn_cache; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD>ӳػ<D3B3><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
ACL_AIO *aio; /* <20><><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>첽IO<49><4F><EFBFBD><EFBFBD> */
ACL_FIFO conns; /* <20><><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3>е<EFBFBD><D0B5><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD>(CONN)<29><><EFBFBD><EFBFBD> */
char key[256]; /* <20><><EFBFBD><EFBFBD><EFBFBD>ӳض<D3B3><D8B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>Ĵ洢<C4B4><E6B4A2><EFBFBD><EFBFBD><EFBFBD>ӳػ<D3B3><D8BB><EFBFBD><EFBFBD>еĴ洢<C4B4><E6B4A2> */
} CONN_POOL;
/* <20><><EFBFBD>ӳ<EFBFBD><D3B3>е<EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD> */
struct CONN {
CONN_POOL *conn_pool; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD>ӳض<D3B3><D8B6><EFBFBD> */
ACL_ASTREAM *stream; /* <20><><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><ECB2BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
void (*free_fn)(ACL_ASTREAM *stream, void*); /* <20>ͷŸ<CDB7><C5B8><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
void *ctx; /* free_fn <20>Բ<EFBFBD><D4B2><EFBFBD>֮һ */
ACL_FIFO_INFO *info; /* <20><><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD>(conn_pool)<29>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD>еĶ<D0B5><C4B6><EFBFBD>ָ<EFBFBD><D6B8> */
};
/* <20><><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>õ<EFBFBD><C3B5>ڴ棬<DAB4><E6A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
static void conn_free(CONN *conn)
{
CONN_POOL *conns = conn->conn_pool;
/* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ӳض<D3B3><D8B6><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE> */
if (conn->info)
acl_fifo_delete_info(&conns->conns, conn->info);
/* <20><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD> */
if (conn->free_fn)
conn->free_fn(conn->stream, conn->ctx);
/* <20>ͷ<EFBFBD><CDB7>ڴ<EFBFBD><DAB4>ռ<EFBFBD> */
acl_myfree(conn);
}
/* <20>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6>󲢹ر<F3B2A2B9><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
static void conn_close(CONN *conn)
{
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD>ֹ<EFBFBD><EFBFBD><ECB2BD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD> */
acl_aio_disable_read(conn->stream);
/* <20><EFBFBD>رո<D8B1><D5B8><EFBFBD><EFBFBD><EFBFBD>, Ȼ<><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB2BD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD> read_close_callback */
acl_aio_iocp_close(conn->stream);
}
/* <20><><EFBFBD><EFBFBD><EFBFBD>ӳض<D3B3><D8B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ô˻ص<CBBB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
static void conn_pool_free(CONN_POOL *conns)
{
CONN *conn;
/* <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6>ͷ<EFBFBD> */
while ((conn = acl_fifo_pop(&conns->conns)) != NULL) {
if (conn->stream) {
if (conn->free_fn)
conn->free_fn(conn->stream, conn->ctx);
acl_aio_clean_hooks(conn->stream);
acl_aio_iocp_close(conn->stream);
}
acl_myfree(conn);
}
acl_myfree(conns);
}
/* <20>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>ӳض<D3B3>ʱ<EFBFBD><CAB1><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD> */
static void conn_pool_free_timer(int event_type acl_unused, void *context)
{
CONN_POOL *conns = (CONN_POOL*) context;
conn_pool_free(conns);
}
/* <20><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>ӳصĶ<D8B5>ʱ<EFBFBD><CAB1>, ֮<><D6AE><EFBFBD>Բ<EFBFBD><D4B2>ö<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>ӳض<D3B3><D8B6><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
* ʹ<EFBFBD>ͷŹ<EFBFBD><EFBFBD>̲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵݹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ͷ<EFBFBD>
*/
static void set_conn_pool_free_timer(CONN_POOL *conns)
{
acl_aio_request_timer(conns->aio, conn_pool_free_timer, conns, 1, 1);
}
static void conn_pool_stat_timer(int event_type acl_unused, void *context)
{
const char *myname = "conn_pool_stat_timer";
CONN_CACHE *cache = (CONN_CACHE*) context;
/* only for test */
if (0)
acl_msg_info("%s(%d): nset: %d, nget: %d, nclose: %d, inter: %d",
myname, __LINE__, cache->nset, cache->nget,
cache->nclose, cache->nset - cache->nget - cache->nclose);
}
static void set_conn_pool_stat_timer(CONN_CACHE *cache)
{
/* <20><><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1> */
acl_aio_request_timer(cache->aio, conn_pool_stat_timer, cache, 2, 1);
}
CONN_CACHE *conn_cache_create(ACL_AIO *aio, int conn_limit)
{
const char *myname = "conn_cache_create";
CONN_CACHE *cache = (CONN_CACHE*) acl_mycalloc(1, sizeof(CONN_CACHE));
cache->aio = aio;
cache->conn_limit = conn_limit;
cache->cache = acl_htable_create(1024, 0);
acl_msg_info("%s(%d): ok, conn_limit: %d", myname, __LINE__, conn_limit);
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳػ<D3B3><D8BB><EFBFBD>״̬<D7B4><CCAC>Ϣ<EFBFBD>Ķ<EFBFBD>ʱ<EFBFBD><CAB1> */
set_conn_pool_stat_timer(cache);
return (cache);
}
/* <20><><EFBFBD>ɶ<EFBFBD>ʱ<EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
static int read_callback(ACL_ASTREAM *stream acl_unused, void *ctx acl_unused,
char *data acl_unused, int dlen acl_unused)
{
const char *myname = "read_callback";
acl_msg_info("%s(%d), %s: can read connection from server, dlen(%d), data(%s)",
__FILE__, __LINE__, myname, dlen, data);
/* <20><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ݿɶ<DDBF><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿɶ<DDBF><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ
* <EFBFBD>޷<EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>رո<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
/* <20><><EFBFBD><EFBFBD> -1 <20>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>رջص<D5BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
return (-1);
}
/* <20><><EFBFBD>ر<EFBFBD>ʱ<EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
static int read_close_callback(ACL_ASTREAM *stream acl_unused, void *ctx)
{
CONN *conn = (CONN*) ctx;
CONN_POOL *conns = conn->conn_pool;
/* <20>ͷŸ<CDB7><C5B8><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ռ<D5BC><E4A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>رո<D8B1><D5B8><EFBFBD><EFBFBD>ӣ<EFBFBD>
* <EFBFBD>رչ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD>ر<EFBFBD>
*/
conn_free(conn);
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ͷŸ<CDB7><C5B8><EFBFBD><EFBFBD>ӳ<EFBFBD> */
if (acl_fifo_size(&conns->conns) == 0) {
acl_htable_delete(conns->conn_cache->cache, conns->key, NULL);
set_conn_pool_free_timer(conns);
}
conns->conn_cache->nclose++;
/* <20><><EFBFBD><EFBFBD> acl_aio_iocp_close <20><><EFBFBD><EFBFBD> */
return (-1);
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱʱ<CAB1>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
static int read_timeout_callback(ACL_ASTREAM *stream acl_unused, void *ctx acl_unused)
{
/* <20><><EFBFBD><EFBFBD> -1 <20>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>رջص<D5BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
return (-1);
}
void conn_cache_push_stream(CONN_CACHE *cache, ACL_ASTREAM *stream,
int timeout, void (*free_fn)(ACL_ASTREAM*, void*), void *ctx)
{
const char *key = ACL_VSTREAM_PEER(acl_aio_vstream(stream));
CONN_POOL *conns;
CONN *conn;
#if 0
acl_aio_clean_hooks(stream);
#endif
/* <20><EFBFBD><E9BFB4>KEY<45><59><EFBFBD><EFBFBD><EFBFBD>ӳؾ<D3B3><D8BE><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>򴴽<EFBFBD><F2B4B4BD>µ<EFBFBD> */
conns = (CONN_POOL*) acl_htable_find(cache->cache, key);
if (conns == NULL) {
conns = (CONN_POOL*) acl_mymalloc(sizeof(CONN_POOL));
conns->conn_cache = cache;
conns->aio = acl_aio_handle(stream);
acl_fifo_init(&conns->conns);
ACL_SAFE_STRNCPY(conns->key, key, sizeof(conns->key));
acl_htable_enter(cache->cache, key, conns);
}
#if 0
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>ɵ<EFBFBD><C9B5><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD> */
if (acl_fifo_size(&conns->conns) >= cache->conn_limit) {
conn = acl_fifo_pop(&conns->conns);
if (conn) {
conn->info = NULL;
conn_close(conn);
}
}
#endif
cache->nset++;
/* <20><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><ECB2BD><EFBFBD><EFBFBD><EFBFBD>ӻ<EFBFBD><D3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
conn = (CONN*) acl_mymalloc(sizeof(CONN));
conn->stream = stream;
conn->ctx = ctx;
conn->free_fn = free_fn;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD> */
conn->info = acl_fifo_push(&conns->conns, conn);
conn->conn_pool = conns;
/* <20><><EFBFBD>ø<EFBFBD><C3B8><EFBFBD><EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
acl_aio_ctl(stream,
ACL_AIO_CTL_READ_HOOK_ADD, read_callback, conn,
ACL_AIO_CTL_CLOSE_HOOK_ADD, read_close_callback, conn,
ACL_AIO_CTL_TIMEO_HOOK_ADD, read_timeout_callback, conn,
ACL_AIO_CTL_TIMEOUT, timeout,
ACL_AIO_CTL_END);
/* <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
acl_aio_read(stream);
}
CONN *conn_cache_get_conn(CONN_CACHE *cache, const char *key)
{
CONN_POOL *conns;
CONN *conn;
/* <20>Ȳ鿴<C8B2><E9BFB4>KEY<45><59><EFBFBD><EFBFBD><EFBFBD>ӳض<D3B3><D8B6><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򷵻<EFBFBD>NULL */
conns = (CONN_POOL*) acl_htable_find(cache->cache, key);
if (conns == NULL) {
return (NULL);
}
/* <20>Ӹ<EFBFBD>KEY<45><59><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD>ȡ<EFBFBD><C8A1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>ΪNULL<4C><4C><EFBFBD>ͷŸ<CDB7><C5B8><EFBFBD><EFBFBD>ӳض<D3B3><D8B6><EFBFBD> */
conn = acl_fifo_pop(&conns->conns);
if (conn == NULL) {
/* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ӳػ<D3B3><D8BB><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE> */
acl_htable_delete(cache->cache, conns->key, NULL);
/* <20><><EFBFBD><EFBFBD><EFBFBD>ͷſյ<C5BF><D5B5><EFBFBD><EFBFBD>ӳض<D3B3><D8B6><EFBFBD><EFBFBD>Ķ<EFBFBD>ʱ<EFBFBD><CAB1> */
set_conn_pool_free_timer(conns);
return (NULL);
}
/* <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD>õĻص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
#if 1
acl_aio_del_read_hook(conn->stream, read_callback, conn);
acl_aio_del_close_hook(conn->stream, read_close_callback, conn);
acl_aio_del_timeo_hook(conn->stream, read_timeout_callback, conn);
#else
acl_aio_clean_hooks(conn->stream);
#endif
if (conn->free_fn)
conn->free_fn(conn->stream, conn->ctx);
/* ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
acl_aio_disable_read(conn->stream);
cache->nget++;
return (conn);
}
ACL_ASTREAM *conn_cache_get_stream(CONN_CACHE *cache, const char *key, void **ctx_pptr)
{
CONN *conn;
ACL_ASTREAM *stream;
conn = conn_cache_get_conn(cache, key);
if (conn == NULL) {
if (ctx_pptr)
*ctx_pptr = NULL;
return (NULL);
}
if (ctx_pptr)
*ctx_pptr = conn->ctx;
stream = conn->stream;
acl_myfree(conn); /* <20><>Ϊ<EFBFBD>Ѿ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD>ͷ<EFBFBD> CONN <20><><EFBFBD><EFBFBD> */
return (stream);
}
void conn_cache_delete_key(CONN_CACHE *cache, const char *key)
{
CONN_POOL *conns;
ACL_ITER iter;
conns = (CONN_POOL*) acl_htable_find(cache->cache, key);
if (conns == NULL)
return;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һһ<D2BB>ر<EFBFBD> */
acl_foreach(iter, &conns->conns) {
CONN *conn = (CONN*) iter.data;
if (conn->stream) {
acl_aio_iocp_close(conn->stream);
conn->stream = NULL;
}
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳش<D3B3><D8B4><EFBFBD><EFBFBD>ӳػ<D3B3><D8BB><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE> */
acl_htable_delete(cache->cache, conns->key, NULL);
/* <20><><EFBFBD><EFBFBD><EFBFBD>ͷųض<C5B3><D8B6><EFBFBD><EFBFBD>Ķ<EFBFBD>ʱ<EFBFBD><CAB1> */
set_conn_pool_free_timer(conns);
}
void conn_cache_delete_conn(CONN *conn)
{
/* <20>ͷŲ<CDB7><C5B2>رո<D8B1><D5B8><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD> */
conn_close(conn);
}
void conn_cache_delete_stream(CONN_CACHE *cache, ACL_ASTREAM *stream)
{
const char *key = ACL_VSTREAM_PEER(acl_aio_vstream(stream));
CONN_POOL *conns;
CONN *conn;
ACL_ITER iter;
conns = acl_htable_find(cache->cache, key);
if (conns == NULL)
return;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳض<D3B3><D8B6><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
acl_foreach(iter, &conns->conns) {
conn = (CONN*) iter.data;
if (conn->stream == stream) {
/* <20>ͷŲ<CDB7><C5B2>رո<D8B1><D5B8><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD> */
conn_close(conn);
break;
}
}
}