#include "conev.h" #include #include #include #include #include "error.h" struct poolhd *init_pool(int count) { struct poolhd *pool = calloc(1, sizeof(struct poolhd)); if (!pool) { uniperror("init pool"); return 0; } pool->max = count; pool->count = 0; pool->iters = 0; #ifndef NOEPOLL int efd = epoll_create(count); if (efd < 0) { free(pool); return 0; } pool->efd = efd; #endif pool->pevents = malloc(sizeof(*pool->pevents) * count); pool->links = malloc(sizeof(*pool->links) * count); pool->items = malloc(sizeof(*pool->items) * count); if (!pool->pevents || !pool->links || !pool->items) { uniperror("init pool"); destroy_pool(pool); return 0; } for (int i = 0; i < count; i++) { pool->links[i] = &(pool->items[i]); } memset(pool->items, 0, sizeof(*pool->items)); return pool; } struct eval *add_event(struct poolhd *pool, evcb_t cb, int fd, int e) { assert(fd > 0); if (pool->count >= pool->max) { LOG(LOG_E, "add_event: pool is full\n"); return 0; } struct eval *val = pool->links[pool->count]; memset(val, 0, sizeof(*val)); val->mod_iter = pool->iters; val->fd = fd; val->index = pool->count; val->cb = cb; #ifndef NOEPOLL struct epoll_event ev = { .events = EPOLLRDHUP | e, .data = {val} }; if (epoll_ctl(pool->efd, EPOLL_CTL_ADD, fd, &ev)) { uniperror("add event"); return 0; } #else struct pollfd *pfd = &(pool->pevents[pool->count]); pfd->fd = fd; pfd->events = POLLRDHUP | e; pfd->revents = 0; #endif pool->count++; return val; } void del_event(struct poolhd *pool, struct eval *val) { assert(val->fd >= -1 && val->mod_iter <= pool->iters); LOG(LOG_S, "close: fd=%d (pair=%d), recv: %zd, rounds: %d\n", val->fd, val->pair ? val->pair->fd : -1, val->recv_count, val->round_count); if (val->fd == -1) { return; } #ifdef NOEPOLL assert(val->fd == pool->pevents[val->index].fd); #else epoll_ctl(pool->efd, EPOLL_CTL_DEL, val->fd, 0); #endif if (val->buff && val->buff->lock) { val->buff->lock = 0; val->buff->offset = 0; } close(val->fd); val->fd = -1; val->mod_iter = pool->iters; pool->count--; struct eval *ev = pool->links[pool->count]; if (ev != val) { int index = val->index; pool->links[index] = ev; pool->links[pool->count] = val; #ifdef NOEPOLL pool->pevents[index] = pool->pevents[pool->count]; #endif ev->index = index; } if (val->pair) { if (val->pair->pair == val) { val->pair->pair = 0; } struct eval *e = val->pair; val->pair = 0; del_event(pool, e); } assert(pool->count >= 0); } void destroy_pool(struct poolhd *pool) { for (int x = 0; x < pool->count; x++) { struct eval *val = pool->links[x]; if (val->fd) { close(val->fd); val->fd = 0; } } free(pool->items); free(pool->links); free(pool->pevents); #ifndef NOEPOLL if (pool->efd) close(pool->efd); #endif buff_destroy(pool->root_buff); memset(pool, 0, sizeof(*pool)); free(pool); } #ifndef NOEPOLL struct eval *next_event(struct poolhd *pool, int *offs, int *type) { while (1) { int i = *offs; assert(i >= -1 && i < pool->max); if (i < 0) { i = (epoll_wait(pool->efd, pool->pevents, pool->max, -1) - 1); if (i < 0) { return 0; } pool->iters++; } struct eval *val = pool->pevents[i].data.ptr; *offs = i - 1; if (val->mod_iter == pool->iters) { continue; } *type = pool->pevents[i].events; return val; } } int mod_etype(struct poolhd *pool, struct eval *val, int type) { assert(val->fd > 0); struct epoll_event ev = { .events = EPOLLRDHUP | type, .data = {val} }; return epoll_ctl(pool->efd, EPOLL_CTL_MOD, val->fd, &ev); } #else struct eval *next_event(struct poolhd *pool, int *offs, int *typel) { for (int i = *offs; ; i--) { assert(i >= -1 && i < pool->max); if (i < 0) { if (poll(pool->pevents, pool->count, -1) <= 0) { return 0; } i = pool->count - 1; pool->iters++; } short type = pool->pevents[i].revents; if (!type) { continue; } struct eval *val = pool->links[i]; assert((i < pool->count) || (val->mod_iter == pool->iters)); if (val->mod_iter == pool->iters) { continue; } pool->pevents[i].revents = 0; *offs = i - 1; *typel = type; return val; } } int mod_etype(struct poolhd *pool, struct eval *val, int type) { assert(val->index >= 0 && val->index < pool->count); pool->pevents[val->index].events = POLLRDHUP | type; return 0; } #endif void loop_event(struct poolhd *pool) { struct eval *val; int i = -1, etype; while (!pool->brk) { val = next_event(pool, &i, &etype); if (!val) { if (get_e() == EINTR) continue; uniperror("(e)poll"); break; } int ret = (*val->cb)(pool, val, etype); if (ret < 0) { del_event(pool, val); } } } struct buffer *buff_get(struct buffer *root, size_t size) { struct buffer *prev = root; while (root) { if (!root->lock) { return root; } prev = root; root = root->next; } struct buffer *buff = malloc(sizeof(struct buffer) + size); if (!buff) { uniperror("malloc"); return 0; } LOG(LOG_S, "alloc new buffer\n"); memset(buff, 0, sizeof(struct buffer)); buff->data = (char *)buff + sizeof(struct buffer); buff->size = size; if (prev) { prev->next = buff; } return buff; } void buff_destroy(struct buffer *root) { while (root) { struct buffer *c = root; root = root->next; free(c); } }