int swTimer_del(swTimer *timer, swTimer_node *tnode) { if (tnode->remove) { return SW_FALSE; } if (SwooleG.timer._current_id > 0 && tnode->id == SwooleG.timer._current_id) { tnode->remove = 1; return SW_TRUE; } if (swHashMap_del_int(timer->map, tnode->id) < 0) { return SW_ERR; } //remove from min-heap swHeap_remove(timer->heap, tnode->heap_node); if (tnode->heap_node) { sw_free(tnode->heap_node); } sw_free(tnode); timer->num --; return SW_TRUE; }
int swDataBuffer_clear(swDataBuffer *data_buffer, int fd) { swDataBuffer_item *item = NULL; swHashMap_add_int(&data_buffer->map, fd, item); if (item == NULL) { swTrace("buffer item not found\n"); return SW_ERR; } else { swDataBuffer_trunk *trunk = item->head; swDataBuffer_trunk *will_free_trunk; //保存trunk的指针,用于释放内存 while (trunk != NULL) { sw_free(trunk->data); will_free_trunk = trunk; trunk = trunk->next; sw_free(will_free_trunk); } swHashMap_del_int(&data_buffer->map, fd); sw_free(item); } return SW_OK; }
static void http_onClose(swServer *serv, int fd, int from_id) { swHashMap_del_int(php_sw_http_clients, fd); if (php_sw_callback[SW_SERVER_CB_onClose] != NULL) { php_swoole_onClose(serv, fd, from_id); } }
int swTimer_select(swTimer *timer) { int64_t now_msec = swTimer_get_relative_msec(); if (now_msec < 0) { return SW_ERR; } swTimer_node *tnode = NULL; swHeap_node *tmp; long timer_id; while ((tmp = swHeap_top(timer->heap))) { tnode = tmp->data; if (tnode->exec_msec > now_msec) { break; } timer_id = timer->_current_id = tnode->id; if (!tnode->remove) { tnode->callback(timer, tnode); } timer->_current_id = -1; //persistent timer if (tnode->interval > 0 && !tnode->remove) { while (tnode->exec_msec <= now_msec) { tnode->exec_msec += tnode->interval; } swHeap_change_priority(timer->heap, tnode->exec_msec, tmp); continue; } timer->num--; swHeap_pop(timer->heap); swHashMap_del_int(timer->map, timer_id); sw_free(tnode); } if (!tnode || !tmp) { timer->_next_msec = -1; timer->set(timer, -1); } else { timer->set(timer, tnode->exec_msec - now_msec); } return SW_OK; }
void swTimeWheel_update(swTimeWheel *tw, swConnection *conn) { uint16_t new_index = swTimeWheel_new_index(tw); swHashMap *new_set = tw->wheel[new_index]; swHashMap_add_int(new_set, conn->fd, conn); swHashMap *old_set = tw->wheel[conn->timewheel_index]; swHashMap_del_int(old_set, conn->fd); swTraceLog(SW_TRACE_REACTOR, "current=%d, fd=%d, old_index=%d, new_index=%d.", tw->current, conn->fd, new_index, conn->timewheel_index); conn->timewheel_index = new_index; }
static void* swTimer_del(swTimer *timer, int interval_ms, int id) { swTimer_node *node = swTimer_node_find(&timer->root, interval_ms, id); if (!node) { return NULL; } if (interval_ms) { swHashMap_del_int(timer->list, interval_ms); } node->remove = 1; return node->data; }
pid_t swProcessPool_spawn(swWorker *worker) { pid_t pid = fork(); swProcessPool *pool = worker->pool; switch (pid) { //child case 0: /** * Process start */ if (pool->onWorkerStart != NULL) { pool->onWorkerStart(pool, worker->id); } /** * Process main loop */ int ret_code = pool->main_loop(pool, worker); /** * Process stop */ if (pool->onWorkerStop != NULL) { pool->onWorkerStop(pool, worker->id); } exit(ret_code); break; case -1: swWarn("fork() failed. Error: %s [%d]", strerror(errno), errno); break; //parent default: //remove old process if (worker->pid) { swHashMap_del_int(pool->map, worker->pid); } worker->deleted = 0; worker->pid = pid; //insert new process swHashMap_add_int(pool->map, pid, worker); break; } return pid; }
int swProcessPool_wait(swProcessPool *pool) { int pid, new_pid; int reload_worker_i = 0; int ret; int status; swWorker *reload_workers; reload_workers = sw_calloc(pool->worker_num, sizeof(swWorker)); if (reload_workers == NULL) { swError("[manager] malloc[reload_workers] fail.\n"); return SW_ERR; } while (SwooleG.running) { pid = wait(&status); if (pid < 0) { if (pool->reloading == 0) { swTrace("[Manager] wait failed. Error: %s [%d]", strerror(errno), errno); } else if (pool->reload_flag == 0) { swTrace("[Manager] reload workers."); memcpy(reload_workers, pool->workers, sizeof(swWorker) * pool->worker_num); pool->reload_flag = 1; goto reload_worker; } else if (SwooleG.running == 0) { break; } } swTrace("[Manager] worker stop.pid=%d", pid); if (SwooleG.running == 1) { swWorker *exit_worker = swHashMap_find_int(pool->map, pid); if (exit_worker == NULL) { if (pool->onWorkerNotFound) { pool->onWorkerNotFound(pool, pid, status); } else { swWarn("[Manager]unknow worker[pid=%d]", pid); } continue; } if (!WIFEXITED(status)) { swWarn("worker#%d abnormal exit, status=%d, signal=%d", exit_worker->id, WEXITSTATUS(status), WTERMSIG(status)); } new_pid = swProcessPool_spawn(exit_worker); if (new_pid < 0) { swWarn("Fork worker process failed. Error: %s [%d]", strerror(errno), errno); sw_free(reload_workers); return SW_ERR; } swHashMap_del_int(pool->map, pid); } //reload worker reload_worker: if (pool->reloading == 1) { //reload finish if (reload_worker_i >= pool->worker_num) { pool->reloading = 0; reload_worker_i = 0; continue; } ret = kill(reload_workers[reload_worker_i].pid, SIGTERM); if (ret < 0) { swSysError("[Manager]kill(%d) failed.", reload_workers[reload_worker_i].pid); continue; } reload_worker_i++; } } sw_free(reload_workers); return SW_OK; }
int swProcessPool_wait(swProcessPool *pool) { int pid, new_pid; int reload_worker_i = 0; int ret, i; swWorker *reload_workers; reload_workers = sw_calloc(pool->worker_num, sizeof(swWorker)); if (reload_workers == NULL) { swError("[manager] malloc[reload_workers] fail.\n"); return SW_ERR; } while (1) { pid = wait(NULL); swTrace("[manager] worker stop.pid=%d\n", pid); if (pid < 0) { if (pool->reloading == 0) { swTrace("[Manager] wait fail. Error: %s [%d]", strerror(errno), errno); } else if (pool->reload_flag == 0) { memcpy(reload_workers, pool->workers, sizeof(swWorker) * pool->worker_num); pool->reload_flag = 1; goto reload_worker; } } if (SwooleG.running == 1) { swWorker *exit_worker = swHashMap_find_int(&pool->map, pid); if (exit_worker == NULL) { swWarn("[Manager]unknow worker[pid=%d]", pid); continue; } new_pid = swProcessPool_spawn(exit_worker); if (new_pid < 0) { swWarn("Fork worker process fail. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } swHashMap_del_int(&pool->map, pid); } //reload worker reload_worker: if (pool->reloading == 1) { //reload finish if (reload_worker_i >= pool->worker_num) { pool->reloading = 0; reload_worker_i = 0; continue; } ret = kill(reload_workers[reload_worker_i].pid, SIGTERM); if (ret < 0) { swWarn("[Manager]kill fail.pid=%d. Error: %s [%d]", reload_workers[reload_worker_i].pid, strerror(errno), errno); continue; } reload_worker_i++; } } return SW_OK; }
void swTimer_del(swTimer *timer, int ms) { swHashMap_del_int(timer->list, ms); }
static void http_onClose(swServer *serv, int fd, int from_id) { swHashMap_del_int(php_sw_http_clients, fd); }
static void php_swoole_aio_onComplete(swAio_event *event) { int isEOF = SW_FALSE; int64_t ret; zval *retval = NULL, *zcallback = NULL, *zwriten = NULL; zval *zcontent = NULL; zval **args[2]; file_request *file_req = NULL; dns_request *dns_req = NULL; #if PHP_MAJOR_VERSION < 7 TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); #else zval _zcontent; zval _zwriten; bzero(&_zcontent, sizeof(zval)); bzero(&_zwriten, sizeof(zval)); #endif if (event->type == SW_AIO_GETHOSTBYNAME) { dns_req = (dns_request *) event->req; if (dns_req->callback == NULL) { swoole_php_error(E_WARNING, "swoole_async: onAsyncComplete callback not found[0]"); return; } zcallback = dns_req->callback; } else { file_req = swHashMap_find_int(php_swoole_aio_request, event->task_id); if (!file_req) { swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete callback not found[1]"); return; } if (file_req->callback == NULL && file_req->type == SW_AIO_READ) { swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete callback not found[2]"); return; } zcallback = file_req->callback; } ret = event->ret; if (ret < 0) { SwooleG.error = event->error; swoole_php_error(E_WARNING, "Aio Error: %s[%d]", strerror(event->error), event->error); } else if (file_req != NULL) { if (ret == 0) { bzero(event->buf, event->nbytes); isEOF = SW_TRUE; } else if (file_req->once == 1 && ret < file_req->length) { swoole_php_fatal_error(E_WARNING, "ret_length[%d] < req->length[%d].", (int ) ret, file_req->length); } else if (event->type == SW_AIO_READ) { file_req->offset += event->ret; } } if (event->type == SW_AIO_READ) { args[0] = &file_req->filename; args[1] = &zcontent; #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zcontent); #else zcontent = &_zcontent; #endif if (ret < 0) { SW_ZVAL_STRING(zcontent, "", 1); } else { SW_ZVAL_STRINGL(zcontent, event->buf, ret, 1); } } else if (event->type == SW_AIO_WRITE) { #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zwriten); #else zwriten = &_zwriten; #endif args[0] = &file_req->filename; args[1] = &zwriten; ZVAL_LONG(zwriten, ret); } else if(event->type == SW_AIO_GETHOSTBYNAME) { args[0] = &dns_req->domain; #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zcontent); #else zcontent = &_zcontent; #endif if (ret < 0) { SW_ZVAL_STRING(zcontent, "", 1); } else { SW_ZVAL_STRING(zcontent, event->buf, 1); } args[1] = &zcontent; } else { swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete unknown event type[%d].", event->type); return; } if (zcallback) { if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE) { swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete handler error"); return; } if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } } //file io if (file_req) { if (file_req->once == 1) { close_file: close(event->fd); swHashMap_del_int(php_swoole_aio_request, event->task_id); } else if(file_req->type == SW_AIO_WRITE) { if (retval != NULL && !ZVAL_IS_NULL(retval) && !Z_BVAL_P(retval)) { swHashMap_del(php_swoole_open_files, Z_STRVAL_P(file_req->filename), Z_STRLEN_P(file_req->filename)); goto close_file; } else { swHashMap_del_int(php_swoole_aio_request, event->task_id); } } else { if ((retval != NULL && !ZVAL_IS_NULL(retval) && !Z_BVAL_P(retval)) || isEOF) { goto close_file; } //Less than expected, at the end of the file else if (event->ret < event->nbytes) { event->ret = 0; php_swoole_aio_onComplete(event); } //continue to read else { int ret = SwooleAIO.read(event->fd, event->buf, event->nbytes, file_req->offset); if (ret < 0) { swoole_php_fatal_error(E_WARNING, "swoole_async: continue to read failed. Error: %s[%d]", strerror(event->error), event->error); goto close_file; } else { swHashMap_move_int(php_swoole_aio_request, event->task_id, ret); } } } } else if (dns_req) { sw_zval_ptr_dtor(&dns_req->callback); sw_zval_ptr_dtor(&dns_req->domain); efree(dns_req); efree(event->buf); } if (zcontent) { sw_zval_ptr_dtor(&zcontent); } if (zwriten) { sw_zval_ptr_dtor(&zwriten); } if (retval) { sw_zval_ptr_dtor(&retval); } }
void swTimeWheel_remove(swTimeWheel *tw, swConnection *conn) { swHashMap *set = tw->wheel[conn->timewheel_index]; swHashMap_del_int(set, conn->fd); swTraceLog(SW_TRACE_REACTOR, "current=%d, fd=%d.", tw->current, conn->fd); }
static void php_swoole_aio_onComplete(swAio_event *event) { int isEOF = SW_FALSE; int64_t ret; zval *retval = NULL, *zcallback = NULL, *zwriten = NULL; zval *zcontent = NULL; zval **args[2]; file_request *file_req = NULL; dns_request *dns_req = NULL; #if PHP_MAJOR_VERSION < 7 TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); #else zval _zcontent; zval _zwriten; #endif if (event->type == SW_AIO_DNS_LOOKUP) { dns_req = (dns_request *) event->req; if (dns_req->callback == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete callback not found[0]"); return; } zcallback = dns_req->callback; } else { file_req = swHashMap_find_int(php_swoole_aio_request, event->fd); if (!file_req) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete callback not found[1]"); return; } if (file_req->callback == NULL && file_req->type == SW_AIO_READ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete callback not found[2]"); return; } zcallback = file_req->callback; } ret = event->ret; if (ret < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: Aio Error: %s[%d]", strerror(event->error), event->error); } else if (file_req != NULL) { if (ret == 0) { bzero(event->buf, event->nbytes); isEOF = SW_TRUE; } else if (file_req->once == 1 && ret < file_req->content_length) { swoole_php_fatal_error(E_WARNING, "swoole_async: ret_length[%d] < req->length[%d].", (int) ret, file_req->content_length); } else if (event->type == SW_AIO_READ) { file_req->offset += event->ret; } } if (event->type == SW_AIO_READ) { args[0] = &file_req->filename; args[1] = &zcontent; #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zcontent); #else zcontent = &_zcontent; #endif memset(event->buf + ret, 0, 1); SW_ZVAL_STRINGL(zcontent, event->buf, ret, 1); } else if (event->type == SW_AIO_WRITE) { #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zwriten); #else zwriten = &_zwriten; #endif args[0] = &file_req->filename; args[1] = &zwriten; ZVAL_LONG(zwriten, ret); if (file_req->once != 1) { swoole_aio_free(event->buf); } } else if(event->type == SW_AIO_DNS_LOOKUP) { args[0] = &dns_req->domain; #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zcontent); #else zcontent = &_zcontent; #endif if (ret < 0) { SW_ZVAL_STRING(zcontent, "", 1); } else { SW_ZVAL_STRING(zcontent, event->buf, 1); } args[1] = &zcontent; } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete unknow event type"); return; } if (zcallback) { if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete handler error"); return; } } //readfile/writefile if (file_req != NULL) { if (file_req->once == 1) { close_file: sw_zval_ptr_dtor(&file_req->callback); sw_zval_ptr_dtor(&file_req->filename); swoole_aio_free(event->buf); close(event->fd); swHashMap_del_int(php_swoole_aio_request, event->fd); efree(file_req); } else if(file_req->type == SW_AIO_WRITE) { if (retval != NULL && !Z_BVAL_P(retval)) { swHashMap_del(php_swoole_open_files, Z_STRVAL_P(file_req->filename), Z_STRLEN_P(file_req->filename)); goto close_file; } } else { if (!Z_BVAL_P(retval) || isEOF) { goto close_file; } else if (SwooleAIO.read(event->fd, event->buf, event->nbytes, file_req->offset) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: continue to read failed. Error: %s[%d]", strerror(event->error), event->error); } } } else if (dns_req != NULL) { sw_zval_ptr_dtor(&dns_req->callback); sw_zval_ptr_dtor(&dns_req->domain); efree(dns_req); efree(event->buf); } if (zcontent != NULL) { sw_zval_ptr_dtor(&zcontent); } if (zwriten != NULL) { sw_zval_ptr_dtor(&zwriten); } if (retval != NULL) { sw_zval_ptr_dtor(&retval); } }