acl/app/jaws/global/client_entry.c
2014-11-19 00:25:21 +08:00

146 lines
4.1 KiB
C

#include "lib_acl.h"
#include "service.h"
#ifdef ACL_BCB_COMPILER
#pragma hdrstop
#endif
void client_entry_free(CLIENT_ENTRY *entry)
{
acl_myfree(entry);
}
/* 当客户端异步流被关闭时的回调函数 */
static void onclose_client_stream(ACL_VSTREAM *stream, void *arg)
{
const char *myname = "onclose_client_stream";
CLIENT_ENTRY *entry = (CLIENT_ENTRY*) arg;
acl_msg_info("%s(%d), fd: %d, nrefer: %d, nrefer: %d, addr: %lx, %lx, domain(%s)",
__FUNCTION__, __LINE__, ACL_VSTREAM_SOCK(stream),
stream->nrefer, entry->nrefer,
(long) entry, (long) entry->client, entry->domain_key);
if (stream->nrefer != 0)
acl_msg_fatal("%s: stream->nrefer(%d) != 0", myname, stream->nrefer);
/* 需要提前设置为空, 以防在调用 acl_aio_iocp_close 后又要操作该流指针 */
entry->client = NULL;
if (entry->server)
acl_aio_iocp_close(entry->server);
/* 需要放在 acl_aio_iocp_lose() 后面,以防止 entry 对象提前释放 */
entry->nrefer--;
if (entry->nrefer > 0)
return;
if (entry->server != NULL)
acl_msg_fatal("%s(%d): server not null", myname, __LINE__);
entry->free_fn(entry);
}
CLIENT_ENTRY *client_entry_new(SERVICE *service, size_t size, ACL_ASTREAM *client)
{
const char *myname = "client_entry_new";
CLIENT_ENTRY *entry;
ACL_VSTREAM *stream;
if (size < sizeof(CLIENT_ENTRY))
acl_msg_fatal("%s(%d): size(%d) invalid", myname, __LINE__, size);
entry = (CLIENT_ENTRY* ) acl_mycalloc(1, size);
entry->service = service;
entry->client = client;
entry->nrefer++;
stream = acl_aio_vstream(client);
acl_vstream_add_close_handle(stream, onclose_client_stream, entry);
return (entry);
}
/* 当服务端异步流被关闭时的回调函数 */
static void onclose_server_stream(ACL_VSTREAM *stream, void *arg)
{
const char *myname = "onclose_server_stream";
CLIENT_ENTRY *entry = (CLIENT_ENTRY*) arg;
acl_msg_info("%s(%d), nrefer: %d", __FUNCTION__, __LINE__, stream->nrefer);
if (stream->nrefer != 0)
acl_msg_fatal("%s: stream->nrefer(%d) != 0", myname, stream->nrefer);
/* 需要提前设置为空, 以防在调用 acl_aio_iocp_close 后又要操作该流指针 */
entry->server = NULL;
if (entry->client) {
acl_aio_iocp_close(entry->client);
}
/* 需要放在 acl_aio_iocp_lose() 后面,以防止 entry 对象提前释放 */
entry->nrefer--;
if (entry->nrefer > 0)
return;
if (entry->client != NULL)
acl_msg_fatal("%s(%d): client not null", myname, __LINE__);
entry->free_fn(entry);
}
void client_entry_set_server(CLIENT_ENTRY *entry, ACL_ASTREAM *server)
{
const char *myname = "client_entry_set_server";
ACL_VSTREAM *stream;
if (entry->server != NULL)
acl_msg_fatal("%s(%d): entry->server not null", myname, __LINE__);
entry->server = server;
entry->nrefer++;
stream = acl_aio_vstream(server);
acl_vstream_add_close_handle(stream, onclose_server_stream, entry);
}
int client_entry_detach(CLIENT_ENTRY *entry, ACL_VSTREAM *stream)
{
return (client_entry_detach3(entry, stream, 1));
}
int client_entry_detach3(CLIENT_ENTRY *entry, ACL_VSTREAM *stream, int auto_free)
{
const char *myname = "client_entry_detach";
/* 必须取消在关闭流时的回调函数 */
if (entry->client && acl_aio_vstream(entry->client) == stream) {
/* 删除流的关闭回调函数句柄,这样仅清除与该应用相关的删除回调 */
acl_vstream_delete_close_handle(stream, onclose_client_stream, entry);
entry->client = NULL;
entry->nrefer--;
} else if (entry->server && acl_aio_vstream(entry->server) == stream) {
/* 删除流的关闭回调函数句柄,这样仅清除与该应用相关的删除回调 */
acl_vstream_delete_close_handle(stream, onclose_server_stream, entry);
entry->server = NULL;
entry->nrefer--;
} else {
acl_msg_fatal("%s(%d): unknown stream", myname, __LINE__);
}
/* 如果 entry 引用对象计数为0则需要释放掉该对象 */
if (entry->nrefer == 0) {
if (auto_free)
entry->free_fn(entry);
/* 告诉调用者, entry 资源已经被释放,不能再使用 */
return (1);
} else if (entry->client == NULL && entry->server == NULL) {
acl_msg_warn("%s(%d): nrefer=%d, client %s, server %s\n",
myname, __LINE__, entry->nrefer,
entry->client ? "not null" : "null",
entry->server ? "not null" : "null");
}
return (0);
}