Пример #1
0
static void acl_xml_node_reset(ACL_XML_NODE *node)
{
    ACL_VSTRING_RESET(node->ltag);
    ACL_VSTRING_RESET(node->rtag);
    ACL_VSTRING_RESET(node->text);
    ACL_VSTRING_TERMINATE(node->ltag);
    ACL_VSTRING_TERMINATE(node->rtag);
    ACL_VSTRING_TERMINATE(node->text);

    node->id = NULL;

    if (node->attr_list)
        acl_array_clean(node->attr_list,
                        (void (*)(void*)) acl_xml_attr_free);
    node->parent = NULL;
    acl_ring_init(&node->children);
    node->depth = 0;

    acl_ring_init(&node->node);
    node->curr_attr = NULL;
    node->quote = 0;
    node->last_ch = 0;
    node->nlt = 0;
    node->meta[0] = 0;
    node->flag = 0;
    node->status = ACL_XML_S_NXT;
}
Пример #2
0
static void fiber_check(void)
{
	if (__thread_fiber != NULL)
		return;

	acl_assert(acl_pthread_once(&__once_control, thread_init) == 0);

	__thread_fiber = (FIBER_TLS *) acl_mycalloc(1, sizeof(FIBER_TLS));
#ifdef	USE_JMP
	/* set context NULL when using setjmp that setcontext will not be
	 * called in fiber_swap.
	 */
	__thread_fiber->original.context = NULL;
#else
	__thread_fiber->original.context = (ucontext_t *)
		acl_mycalloc(1, sizeof(ucontext_t));
#endif
	__thread_fiber->fibers = NULL;
	__thread_fiber->size   = 0;
	__thread_fiber->slot   = 0;
	__thread_fiber->idgen  = 0;
	__thread_fiber->count  = 0;

	acl_ring_init(&__thread_fiber->ready);
	acl_ring_init(&__thread_fiber->dead);

	if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) {
		__main_fiber = __thread_fiber;
		atexit(fiber_schedule_main_free);
	} else if (acl_pthread_setspecific(__fiber_key, __thread_fiber) != 0)
		acl_msg_fatal("acl_pthread_setspecific error!");
}
Пример #3
0
ACL_FIBER_MUTEX *acl_fiber_mutex_create(void)
{
	ACL_FIBER_MUTEX *lk = (ACL_FIBER_MUTEX *)
		acl_mymalloc(sizeof(ACL_FIBER_MUTEX));

	lk->owner = NULL;
	acl_ring_init(&lk->me);
	acl_ring_init(&lk->waiting);
	return lk;
}
Пример #4
0
ACL_FIBER_RWLOCK *acl_fiber_rwlock_create(void)
{
	ACL_FIBER_RWLOCK *lk = (ACL_FIBER_RWLOCK *)
		acl_mymalloc(sizeof(ACL_FIBER_RWLOCK));

	lk->readers = 0;
	lk->writer  = NULL;
	acl_ring_init(&lk->rwaiting);
	acl_ring_init(&lk->wwaiting);

	return lk;
}
Пример #5
0
static void test(void)
{
	ACL_RING ring;

	acl_ring_init(&ring);
	for (int i = 0; i < 10; i++)
	{
		A* a = new A;
		a->m = i;
		acl_ring_prepend(&ring, &a->entry);
		printf("put %d\r\n", i);
	}

	printf("-------------------------------------------------------\r\n");

	while (true)
	{
		ACL_RING* head = acl_ring_pop_head(&ring);
		if (head == NULL)
			break;
		A* a = ACL_RING_TO_APPL(head, A, entry);
		printf("pop %d\r\n", a->m);
		delete a;
	}

	exit (0);
}
Пример #6
0
static void event_init(ACL_EVENT *eventp, int fdsize,
	int delay_sec, int delay_usec)
{
	eventp->fdsize = fdsize;
	/* eventp->fdtab_free_cnt = 0; */
	eventp->fdcnt  = 0;
	eventp->fdcnt_ready  = 0;
	eventp->fdtabs = (ACL_EVENT_FDTABLE **)
		acl_mycalloc(fdsize,sizeof(ACL_EVENT_FDTABLE *));
	eventp->fdtabs_ready = (ACL_EVENT_FDTABLE **)
		acl_mycalloc(fdsize, sizeof(ACL_EVENT_FDTABLE *));

	eventp->maxfd  = 0;
	eventp->nested = 0;

	eventp->delay_sec  = delay_sec + delay_usec / 1000000;
	eventp->delay_usec = delay_usec % 1000000;

	acl_ring_init(&eventp->timer_head);
	eventp->timer_keep = 0;
	SET_TIME(eventp->present);
	SET_TIME(eventp->last_debug);

	eventp->check_inter = 100000;  /* default: 100 ms */

	if (eventp->init_fn)
		eventp->init_fn(eventp);
}
Пример #7
0
void fiber_io_check(void)
{
	if (__thread_fiber != NULL)
		return;

	acl_assert(acl_pthread_once(&__once_control, thread_init) == 0);

	__maxfd = acl_open_limit(0);
	if (__maxfd <= 0)
		__maxfd = MAXFD;

	__thread_fiber = (FIBER_TLS *) acl_mymalloc(sizeof(FIBER_TLS));
	__thread_fiber->event = event_create(__maxfd);
	__thread_fiber->io_fibers = (ACL_FIBER **)
		acl_mycalloc(__maxfd, sizeof(ACL_FIBER *));
	__thread_fiber->ev_fiber = acl_fiber_create(fiber_io_loop,
			__thread_fiber->event, STACK_SIZE);
	__thread_fiber->io_count = 0;
	__thread_fiber->nsleeping = 0;
	__thread_fiber->io_stop = 0;
	acl_ring_init(&__thread_fiber->ev_timer);

	if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) {
		__main_fiber = __thread_fiber;
		atexit(fiber_io_main_free);
	} else if (acl_pthread_setspecific(__fiber_key, __thread_fiber) != 0)
		acl_msg_fatal("acl_pthread_setspecific error!");
}
Пример #8
0
ICMP_CHAT *icmp_chat_create(ACL_AIO* aio, int check_tid)
{
	ICMP_CHAT *chat;

	chat = (ICMP_CHAT*) acl_mycalloc(1, sizeof(ICMP_CHAT));
	chat->aio = aio;
	acl_ring_init(&chat->host_head);
	chat->is = icmp_stream_open(aio);
	chat->seq_no = 0;
	chat->count = 0;
#ifdef ACL_UNIX
	chat->pid = getpid();
#elif defined(ACL_WINDOWS)
	chat->pid = _getpid();
#endif
	chat->tid = (unsigned long) acl_pthread_self();
	chat->check_tid = check_tid;

	if (aio != NULL)
		icmp_chat_aio_init(chat, aio);
	else
		icmp_chat_sio_init(chat);

	return (chat);
}
Пример #9
0
ACL_FIBER_SEM *acl_fiber_sem_create(int num)
{
	ACL_FIBER_SEM *sem = (ACL_FIBER_SEM *)
		acl_mymalloc(sizeof(ACL_FIBER_SEM));

	sem->num = num;
	acl_ring_init(&sem->waiting);
	sem->tid = acl_pthread_self();
	return sem;
}
Пример #10
0
ACL_XML_NODE *acl_xml_node_alloc(ACL_XML *xml)
{
    ACL_XML_NODE *node;

    if (xml->node_cache) {
        node = (ACL_XML_NODE*)
               xml->node_cache->pop_back(xml->node_cache);
        if (node) {
            acl_xml_node_reset(node);
            node->xml = xml;
            xml->node_cnt++;
            return (node);
        }
    }

    if (xml->slice)
        node = (ACL_XML_NODE*) acl_slice_pool_calloc(__FILE__, __LINE__,
                xml->slice, 1, sizeof(ACL_XML_NODE));
    else
        node = (ACL_XML_NODE*) acl_mycalloc(1, sizeof(ACL_XML_NODE));
    acl_ring_init(&node->children);
    acl_ring_init(&node->node);

    node->xml = xml;
    node->status = ACL_XML_S_NXT;
    node->ltag = acl_vstring_slice_alloc(xml->slice, 16);
    node->rtag = acl_vstring_slice_alloc(xml->slice, 16);
    node->text = acl_vstring_slice_alloc(xml->slice, 16);
    node->attr_list = acl_array_create(5);
    xml->node_cnt++;

    node->iter_head = node_iter_head;
    node->iter_next = node_iter_next;
    node->iter_tail = node_iter_tail;
    node->iter_prev = node_iter_prev;
    return (node);
}
Пример #11
0
static void event_loop(ACL_EVENT *eventp)
{
	const char *myname = "event_loop";
	EVENT_SELECT_THR *event_thr = (EVENT_SELECT_THR *) eventp;
	ACL_EVENT_NOTIFY_FN worker_fn;
	void    *worker_arg;
	ACL_SOCKET sockfd;
	ACL_EVENT_TIMER *timer;
	int   select_delay, nready, i;
	ACL_EVENT_FDTABLE *fdp;
	ACL_RING timer_ring, *entry_ptr;
	struct timeval tv, *tvp;
	fd_set rmask;  /* enabled read events */
	fd_set wmask;  /* enabled write events */
	fd_set xmask;  /* for bad news mostly */

	acl_ring_init(&timer_ring);

	SET_TIME(eventp->event_present);
	THREAD_LOCK(&event_thr->event.tm_mutex);

	/*
	 * Find out when the next timer would go off. Timer requests are sorted.
	 * If any timer is scheduled, adjust the delay appropriately.
	 */
	if ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) {
		select_delay = (int) (timer->when - eventp->event_present + 1000000 - 1) / 1000000;
		if (select_delay < 0) {
			select_delay = 0;
		} else if (eventp->delay_sec >= 0 && select_delay > eventp->delay_sec) {
			select_delay = eventp->delay_sec;
		}
	} else {
		select_delay = eventp->delay_sec;
	}

	THREAD_UNLOCK(&event_thr->event.tm_mutex);

	THREAD_LOCK(&event_thr->event.tb_mutex);

	if (event_thr_prepare(eventp) == 0) {
		if (eventp->fdcnt_ready == 0) {
			if (select_delay <= 0)
				select_delay = 1;
			sleep(select_delay);
		}

		THREAD_UNLOCK(&event_thr->event.tb_mutex);
		goto TAG_DONE;
	}

	if (eventp->fdcnt_ready > 0) {
		tv.tv_sec  = 0;
		tv.tv_usec = 0;
		tvp = &tv;
	} else if (select_delay < 0) {
		tvp = NULL;
	} else {
		tv.tv_sec  = select_delay;
		tv.tv_usec = eventp->delay_usec;
		tvp = &tv;
	}

	rmask = event_thr->rmask;
	wmask = event_thr->wmask;
	xmask = event_thr->xmask;

	THREAD_UNLOCK(&event_thr->event.tb_mutex);

	event_thr->event.blocked = 1;
	nready = select(eventp->maxfd + 1, &rmask, &wmask, &xmask, tvp);
	event_thr->event.blocked = 0;

	if (nready < 0) {
		if (acl_last_error() != ACL_EINTR) {
			char  ebuf[256];
			acl_msg_fatal("%s(%d), %s: event_loop: select: %s",
				__FILE__, __LINE__, myname,
				acl_last_strerror(ebuf, sizeof(ebuf)));
		}
		goto TAG_DONE;
	} else if (nready == 0)
		goto TAG_DONE;

	THREAD_LOCK(&event_thr->event.tb_mutex);

	for (i = 0; i < eventp->fdcnt; i++) {
		fdp = eventp->fdtabs[i];

		/* if fdp has been set in eventp->fdtabs_ready ? */
		if ((fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT)))
			continue;

		sockfd = ACL_VSTREAM_SOCK(fdp->stream);

		if (FD_ISSET(sockfd, &xmask)) {
			fdp->event_type |= ACL_EVENT_XCPT;
			fdp->fdidx_ready = eventp->fdcnt_ready;
			eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp;
			continue;
		}

		if (FD_ISSET(sockfd, &rmask)) {
			fdp->stream->sys_read_ready = 1;
			/* has been set in fdtabs_ready ? */
			if ((fdp->event_type & ACL_EVENT_READ) == 0) {
				fdp->event_type |= ACL_EVENT_READ;
				fdp->fdidx_ready = eventp->fdcnt_ready;
				eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp;
			}
		} else if (fdp->w_callback && FD_ISSET(sockfd, &wmask)) {
			fdp->event_type |= ACL_EVENT_WRITE;
			fdp->fdidx_ready = eventp->fdcnt_ready;
			eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp;
		}
	}

	THREAD_UNLOCK(&event_thr->event.tb_mutex);

TAG_DONE:

	/*
	 * Deliver timer events. Requests are sorted: we can stop when we reach
	 * the future or the list end. Allow the application to update the timer
	 * queue while it is being called back. To this end, we repeatedly pop
	 * the first request off the timer queue before delivering the event to
	 * the application.
	 */

	SET_TIME(eventp->event_present);

	THREAD_LOCK(&event_thr->event.tm_mutex);

	while ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) {
		if (timer->when > eventp->event_present)
			break;

		acl_ring_detach(&timer->ring);          /* first this */
		acl_ring_prepend(&timer_ring, &timer->ring);
	}

	THREAD_UNLOCK(&event_thr->event.tm_mutex);

	while (1) {
		entry_ptr = acl_ring_pop_head(&timer_ring);
		if (entry_ptr == NULL)
			break;

		timer         = ACL_RING_TO_TIMER(entry_ptr);
		worker_fn     = timer->callback;
		worker_arg    = timer->context;

		worker_fn(ACL_EVENT_TIME, worker_arg);

		acl_myfree(timer);
	}

	event_thr_fire(eventp);
}
Пример #12
0
/* 查询DNS信息,采用外挂模块的方式 */
static void thrpool_nslookup(SERVICE *service, CLIENT_ENTRY *entry,
	const char *domain, int port)
{
	const char *myname = "thrpool_nslookup";
	DNS_CTX dns_ctx;
	DNS_RING *list;
	char *ptr;

	entry->tm.stamp = time(NULL);

	memset(&dns_ctx, 0, sizeof(dns_ctx));
	dns_ctx.begin = entry->tm.stamp;
	STRNCPY(dns_ctx.domain_key, domain, sizeof(dns_ctx.domain_key));
	ptr = strchr(dns_ctx.domain_key, ':');
	/* 仅留下域名部分 */
	if (ptr)
		*ptr = 0;

	entry->server_port = port;
	if (entry->server_port <= 0)
		entry->server_port = 80;
	
	/* 将域名字符串都转换成小写,以便于进行哈希查询 */
	acl_lowercase(dns_ctx.domain_key);

	dns_ctx.context = service;
	dns_ctx.callback = thrpool_nslookup_complete;

	STRNCPY(entry->domain_key, dns_ctx.domain_key, sizeof(entry->domain_key));

	/* 先查询DNS查询表中是否已经包含本次需要被查询的域名 */
	list = (DNS_RING *) acl_htable_find(service->dns_table, dns_ctx.domain_key);
	if (list) {
		/* 将本次对同一域名的查询添加进同一个查询链中 */
		acl_ring_prepend(&list->ring, &entry->dns_entry);
		/* 将查询链对象的引用计数加1 */
		list->nrefer++;
		/* 如果该查询链已经存在,说明有查询任务等待返回,其返回后会一同将
		 * 本次任务进行触发,如果此处触发新任务,则会造成内存访问冲突,因为
		 * 查询DNS的过程是由一组线程池进行查询的。
		 * (void) dns_server_lookup(proxy_entry->aio_proxy->dns_server, &dns_ctx);
		 */
		return;
	}

	/* 创建一个新的查询链对象,并将本次查询任务加入该查询链中及将该查询链加入查询表中 */

	list = (DNS_RING *) acl_mycalloc(1, sizeof(DNS_RING));
	acl_ring_init(&list->ring);
	STRNCPY(list->domain_key, dns_ctx.domain_key, sizeof(list->domain_key));

	/* 将本次查询任务加入新的查询链中且将查询链的引用计数加1 */
	acl_ring_prepend(&list->ring, &entry->dns_entry);
	list->nrefer++;

	/* 将新的查询链加入查询表中 */
	if (acl_htable_enter(service->dns_table, list->domain_key, (char *) list) == NULL)
		acl_msg_fatal("%s: add domain(%s) to table error", myname, list->domain_key);

	/* 开始启动DNS查询过程 */
	(void) dns_server_lookup(service->dns_server, &dns_ctx);
}