Ejemplo n.º 1
0
void HshaServerIO :: IOFunc(int accepted_fd) {
    UThreadSocket_t * socket = scheduler_->CreateSocket(accepted_fd);
    UThreadTcpStream stream;
    stream.Attach(socket);
    UThreadSetSocketTimeout(*socket, config_->GetSocketTimeoutMS()); 
    HshaServerStat::TimeCost time_cost;

    while (true) {
        hsha_server_stat_->io_read_requests_++;
        HttpRequest * request = new HttpRequest;
        int socket_ret = HttpProto::RecvReq(stream, request);
        if (socket_ret != 0) {
            delete request;
            hsha_server_stat_->io_read_fails_++;
            hsha_server_stat_->rpc_time_costs_count_++;
            //phxrpc::log(LOG_ERR, "%s read request fail, fd %d", __func__, accepted_fd);
            break;
        }

        hsha_server_stat_->io_read_bytes_ += request->GetContent().size();

        if (!data_flow_->CanPushRequest(config_->GetMaxQueueLength())) {
            delete request;
            hsha_server_stat_->queue_full_rejected_after_accepted_fds_++;
            break;
        }

        if (!hsha_server_qos_->CanEnqueue()) {
            //fast reject don't cal rpc_time_cost;
            delete request;
            hsha_server_stat_->enqueue_fast_rejects_++;
            //phxrpc::log(LOG_ERR, "%s fast reject, can't enqueue, fd %d", __func__, accepted_fd);
            break;
        }

        //if have enqueue, request will be deleted after pop.
        bool is_keep_alive = request->IsKeepAlive();
        std::string version = string(request->GetVersion() != nullptr ? request->GetVersion() : "");

        hsha_server_stat_->inqueue_push_requests_++;
        data_flow_->PushRequest((void *)socket, request);
        //if is uthread worker mode, need notify.
        worker_pool_->Notify();
        UThreadSetArgs(*socket, nullptr);

        UThreadWait(*socket, config_->GetSocketTimeoutMS());
        if (UThreadGetArgs(*socket) == nullptr) {
            //timeout
            hsha_server_stat_->worker_timeouts_++;
            hsha_server_stat_->rpc_time_costs_count_++;

            //because have enqueue, so socket will be closed after pop.
            socket = stream.DetachSocket(); 
            UThreadLazyDestory(*socket);

            //phxrpc::log(LOG_ERR, "%s timeout, fd %d sockettimeoutms %d", 
                    //__func__, accepted_fd, config_->GetSocketTimeoutMS());
            break;
        }

        hsha_server_stat_->io_write_responses_++;
        HttpResponse * response = (HttpResponse *)UThreadGetArgs(*socket);
        HttpProto::FixRespHeaders(is_keep_alive, version.c_str(), response);
        socket_ret = HttpProto::SendResp(stream, *response);
        hsha_server_stat_->io_write_bytes_ += response->GetContent().size();
        delete response;

        hsha_server_stat_->rpc_time_costs_count_++;

        if (socket_ret != 0) {
            hsha_server_stat_->io_write_fails_++;
        }

        if(!is_keep_alive || (socket_ret != 0)) {
            break;
        } else {
            hsha_server_stat_->rpc_time_costs_ += time_cost.Cost();
        }
    }

    hsha_server_stat_->rpc_time_costs_ += time_cost.Cost();
    hsha_server_stat_->hold_fds_--;
}