| 238 | } |
| 239 | |
| 240 | void ThriftClosure::DoRun() { |
| 241 | // Recycle itself after `Run' |
| 242 | std::unique_ptr<ThriftClosure> recycle_ctx(this); |
| 243 | const Server* server = _controller.server(); |
| 244 | |
| 245 | ControllerPrivateAccessor accessor(&_controller); |
| 246 | auto span = accessor.span(); |
| 247 | if (span) { |
| 248 | span->set_start_send_us(butil::cpuwide_time_us()); |
| 249 | } |
| 250 | Socket* sock = accessor.get_sending_socket(); |
| 251 | MethodStatus* method_status = (server->options().thrift_service ? |
| 252 | server->options().thrift_service->_status : NULL); |
| 253 | ConcurrencyRemover concurrency_remover(method_status, &_controller, _received_us); |
| 254 | if (!method_status) { |
| 255 | // Judge errors belongings. |
| 256 | // may not be accurate, but it does not matter too much. |
| 257 | const int error_code = _controller.ErrorCode(); |
| 258 | if (error_code == ENOSERVICE || |
| 259 | error_code == ENOMETHOD || |
| 260 | error_code == EREQUEST || |
| 261 | error_code == ECLOSE || |
| 262 | error_code == ELOGOFF || |
| 263 | error_code == ELIMIT) { |
| 264 | ServerPrivateAccessor(server).AddError(); |
| 265 | } |
| 266 | } |
| 267 | |
| 268 | if (_controller.IsCloseConnection() || |
| 269 | // seq_id is not read yet, no valid response can be sent back |
| 270 | !_controller.has_log_id()) { |
| 271 | sock->SetFailed(); |
| 272 | return; |
| 273 | } |
| 274 | |
| 275 | const std::string& method_name = _controller.thrift_method_name(); |
| 276 | if (method_name.empty() || method_name[0] == ' ') { |
| 277 | _controller.SetFailed(ENOMETHOD, "Invalid thrift_method_name!"); |
| 278 | } |
| 279 | if (method_name.size() > MAX_THRIFT_METHOD_NAME_LENGTH) { |
| 280 | _controller.SetFailed(ENOMETHOD, "thrift_method_name is too long"); |
| 281 | } |
| 282 | if (_controller.log_id() > (uint64_t)0xffffffff) { |
| 283 | _controller.SetFailed(ERESPONSE, "Invalid thrift seq_id=%" PRIu64, |
| 284 | _controller.log_id()); |
| 285 | } |
| 286 | const uint32_t seq_id = (uint32_t)_controller.log_id(); |
| 287 | |
| 288 | butil::IOBuf write_buf; |
| 289 | |
| 290 | // The following code was taken and modified from thrift auto generated code |
| 291 | if (_controller.Failed()) { |
| 292 | auto out_buffer = |
| 293 | THRIFT_STDCXX::make_shared<apache::thrift::transport::TMemoryBuffer>(); |
| 294 | apache::thrift::protocol::TBinaryProtocolT<apache::thrift::transport::TMemoryBuffer> oprot(out_buffer); |
| 295 | ::apache::thrift::TApplicationException x(_controller.ErrorText()); |
| 296 | oprot.writeMessageBegin( |
| 297 | method_name, ::apache::thrift::protocol::T_EXCEPTION, seq_id); |
nothing calls this directly
no test coverage detected