int get_chunk_body_buffer(struct worker_context *ctx, struct connection *conn, char **p_start, int *p_len) { int flag = 0; struct body_buffer *buffer; if ( DLIST_EMPTY(&conn->_client._body) ) { flag = 1; } else { __dlist_t *cur = DLIST_PRE(&conn->_client._body); buffer = GET_OWNER(cur, struct body_buffer, _list); if ( buffer->_data_len - buffer->_curpos == 0 ) { flag = 1; } } if ( flag ) { buffer = (struct body_buffer *)mp_alloc(ctx->_body_pool); if ( NULL == buffer ) { WARNING("failed to alloc mem for body buffer."); return -1; } DLIST_INIT(&buffer->_list); buffer->_curpos = 0; buffer->_data_len = ctx->_data_len; DLIST_INSERT_B(&buffer->_list, &conn->_client._body); } *p_start = buffer->_data + buffer->_curpos; *p_len = buffer->_data_len - buffer->_curpos; return 0; }
void Worker::run() { int ret; __dlist_t head; __dlist_t *next; Connection *conn; NOTICE("worker is running now."); while (!_stopped) { DLIST_INIT(&head); pthread_mutex_lock(&_mutex); while (DLIST_EMPTY(&_queue)) pthread_cond_wait(&_cond, &_mutex); next = DLIST_NEXT(&_queue); DLIST_REMOVE(&_queue); pthread_mutex_unlock(&_mutex); DLIST_INSERT_B(&head, next); while (!DLIST_EMPTY(&head)) { next = DLIST_NEXT(&head); DLIST_REMOVE(next); conn = GET_OWNER(next, Connection, _list); TRACE("start to process conn, sock[%d].", conn->_sock_fd); try { ret = conn->on_process(); if (ret == 0) { conn->_status = Connection::ST_PROCESSING_REQUEST_OK; TRACE("process conn ok, sock[%d].", conn->_sock_fd); } else { conn->_status = Connection::ST_PROCESSING_REQUEST_FAIL; WARNING("failed to process conn, sock[%d], ret=%d.", conn->_sock_fd, ret); } } catch (...) { WARNING("failed to process conn, sock[%d], exception catched.", conn->_sock_fd); } _server_manager->done(conn); } } NOTICE("worker is stopped by user, exiting now."); }
inline static void* __d_fp_malloc_from_list(struct fixed_dmem_pool* pool) { if(!DLIST_EMPTY(&pool->head)){ struct dlist_node* node = pool->head.next; dlist_del(node); return container_of(node, struct dmem_node, node); } return NULL; }
void Worker::post(Connection *conn) { if (!conn) return ; DLIST_REMOVE(&conn->_list); int empty = 0; pthread_mutex_lock(&_mutex); if (DLIST_EMPTY(&_queue)) empty = 1; DLIST_INSERT_B(&conn->_list, &_queue); if (empty) pthread_cond_signal(&_cond); pthread_mutex_unlock(&_mutex); }
void NetProxy::detach(NetStub *st) { if (st->_cancel) return ; st->_cancel = 1; { AutoLock __lock(_mutex); if (!DLIST_EMPTY(&st->_att_list)) { DLIST_REMOVE(&st->_att_list);/* still in _attach_list */ } else return ; } this->done(st); }
void NetProxy::run() { #define SET_ERROR(errno) \ do \ { \ st->_errno = errno; \ epex_detach(_epex, st->_talk->_sock, NULL); \ } while(0) ssize_t ret; netresult_t results[20]; __dlist_t attach_ok_list; __dlist_t attach_fail_list; __dlist_t *ptr; NetStub *st; int sock; int tm_left; int elasp_tm; struct timeval now; _stop = false; while (!_stop) { DLIST_INIT(&attach_ok_list); DLIST_INIT(&attach_fail_list); { AutoLock __lock(_mutex); while (!DLIST_EMPTY(&_attach_list)) { ptr = DLIST_NEXT(&_attach_list); st = GET_OWNER(ptr, NetStub, _att_list); DLIST_REMOVE(ptr); if (epex_attach(_epex, st->_talk->_sock, st, -1)) DLIST_INSERT_B(&st->_tmp_list, &attach_ok_list); else DLIST_INSERT_B(&st->_tmp_list, &attach_fail_list); } } gettimeofday(&now, NULL); while (!DLIST_EMPTY(&attach_fail_list)) { ptr = DLIST_NEXT(&attach_fail_list); st = GET_OWNER(ptr, NetStub, _tmp_list); DLIST_REMOVE(ptr); st->_errno = NET_ERR_ATTACH_FAIL; this->done(st, &now); } while (!DLIST_EMPTY(&attach_ok_list)) { ptr = DLIST_NEXT(&attach_ok_list); st = GET_OWNER(ptr, NetStub, _tmp_list); DLIST_REMOVE(ptr); st->_talk->_req_head._magic_num = MAGIC_NUM; st->_talk->_req_head._body_len = st->_talk->_req_len; st->_status = NET_ST_SEND_HEAD; if (epex_write(_epex, st->_talk->_sock, &st->_talk->_req_head, sizeof(st->_talk->_req_head), NULL, st->_timeout)) { TRACE("try to send head to sock[%d]", st->_talk->_sock); } else { SET_ERROR(NET_ERR_WRITE); } } ret = epex_poll(_epex, results, sizeof(results)/sizeof(results[0])); gettimeofday(&now, NULL); for (long i = 0; i < ret; ++i) { const netresult_t &res = results[i]; st = (NetStub *)res._user_ptr2; if (NET_OP_NOTIFY == res._op_type) { this->done(st, &now); continue; } switch (res._status) { case NET_DONE: break; case NET_ECLOSED: SET_ERROR(NET_ERR_CLOSED); continue; case NET_ETIMEOUT: SET_ERROR(NET_ERR_TIMEOUT); continue; case NET_ERROR: st->_errno = res._errno; /* fall through */ case NET_EDETACHED: continue; default: WARNING("should not be here, res._status=%hd", res._status); continue; } sock = st->_talk->_sock; if (st->_cancel) /* canceled by user */ { TRACE("sock[%d] is canceled by user", sock); epex_detach(_epex, sock, NULL); continue; } elasp_tm = (now.tv_sec - st->_start_tm.tv_sec) * 1000 + (now.tv_usec - st->_start_tm.tv_usec) / 1000; if (st->_timeout < 0) tm_left = -1; else if (st->_timeout > elasp_tm) tm_left = st->_timeout - elasp_tm; else tm_left = 0; switch (st->_status) { case NET_ST_SEND_HEAD: TRACE("send head to sock[%d] ok", sock); st->_tm._send_head = elasp_tm; st->_status = NET_ST_SEND_BODY; if (tm_left == 0) { SET_ERROR(NET_ERR_TIMEOUT); continue; } if (!epex_write(_epex, sock, st->_talk->_req_buf, st->_talk->_req_len, NULL, tm_left)) { SET_ERROR(NET_ERR_WRITE); continue; } TRACE("try to send body[%u] to sock[%d]", st->_talk->_req_len, sock); break; case NET_ST_SEND_BODY: TRACE("send body[%u] to sock[%d] ok", st->_talk->_req_len, sock); st->_tm._send_body = elasp_tm - st->_tm._send_head; st->_status = NET_ST_RECV_HEAD; if (tm_left == 0) { SET_ERROR(NET_ERR_TIMEOUT); continue; } if (!epex_read(_epex, sock, &st->_talk->_res_head, sizeof(st->_talk->_res_head), NULL, tm_left)) { SET_ERROR(NET_ERR_READ); continue; } TRACE("try to recv head from sock[%d]", sock); break; case NET_ST_RECV_HEAD: TRACE("recv head from sock[%d] ok", sock); st->_tm._recv_head = elasp_tm - st->_tm._send_body - st->_tm._send_head; if (st->_talk->_res_head._magic_num != MAGIC_NUM) { SET_ERROR(NET_ERR_MAGIC_NUM); continue; } if (st->_talk->_res_head._body_len > st->_talk->_res_len) { SET_ERROR(NET_ERR_BIG_RESP); continue; } st->_status = NET_ST_RECV_BODY; if (tm_left == 0) { SET_ERROR(NET_ERR_TIMEOUT); continue; } if (!epex_read(_epex, sock, st->_talk->_res_buf, st->_talk->_res_head._body_len, NULL, tm_left)) { SET_ERROR(NET_ERR_READ); continue; } TRACE("try to recv body[%u] from sock[%d]", st->_talk->_res_head._body_len, sock); break; case NET_ST_RECV_BODY: TRACE("recv body[%u] from sock[%d] ok", st->_talk->_res_head._body_len, sock); st->_tm._recv_body = elasp_tm - st->_tm._recv_head - st->_tm._send_body - st->_tm._send_head; st->_status = NET_ST_DONE; epex_detach(_epex, sock, NULL); TRACE("talk with sock[%d] ok", sock); break; default: WARNING("should not be here"); break; } } } NOTICE("NetPoller is stoped now"); #undef SET_ERROR }