void PProfService::contention( ::google::protobuf::RpcController* controller_base, const ::brpc::ProfileRequest* /*request*/, ::brpc::ProfileResponse* /*response*/, ::google::protobuf::Closure* done) { ClosureGuard done_guard(done); Controller* cntl = static_cast<Controller*>(controller_base); cntl->http_response().set_content_type("text/plain"); int sleep_sec = ReadSeconds(cntl); if (sleep_sec <= 0) { if (!cntl->Failed()) { cntl->SetFailed(EINVAL, "You have to specify ?seconds=N. If you're " "using pprof, add --seconds=N"); } return; } // Log requester std::ostringstream client_info; client_info << cntl->remote_side(); if (cntl->auth_context()) { client_info << "(auth=" << cntl->auth_context()->user() << ')'; } else { client_info << "(no auth)"; } LOG(INFO) << client_info.str() << " requests for contention profile for " << sleep_sec << " seconds"; char prof_name[256]; if (MakeProfName(PROFILING_CONTENTION, prof_name, sizeof(prof_name)) != 0) { cntl->SetFailed(errno, "Fail to create .prof file, %s", berror()); return; } if (!bthread::ContentionProfilerStart(prof_name)) { cntl->SetFailed(EAGAIN, "Another profiler is running, try again later"); return; } if (bthread_usleep(sleep_sec * 1000000L) != 0) { PLOG(WARNING) << "Profiling has been interrupted"; } bthread::ContentionProfilerStop(); butil::fd_guard fd(open(prof_name, O_RDONLY)); if (fd < 0) { cntl->SetFailed(ENOENT, "Fail to open %s", prof_name); return; } butil::IOPortal portal; portal.append_from_file_descriptor(fd, ULONG_MAX); cntl->response_attachment().swap(portal); }
int Sender::IssueRPC(int64_t start_realtime_us) { _main_cntl->_current_call.need_feedback = false; LoadBalancer::SelectIn sel_in = { start_realtime_us, true, _main_cntl->has_request_code(), _main_cntl->_request_code, _main_cntl->_accessed }; ChannelBalancer::SelectOut sel_out; const int rc = static_cast<ChannelBalancer*>(_main_cntl->_lb.get()) ->SelectChannel(sel_in, &sel_out); if (rc != 0) { _main_cntl->SetFailed(rc, "Fail to select channel, %s", berror(rc)); return -1; } DLOG(INFO) << "Selected channel=" << sel_out.channel() << ", size=" << (_main_cntl->_accessed ? _main_cntl->_accessed->size() : 0); _main_cntl->_current_call.need_feedback = sel_out.need_feedback; _main_cntl->_current_call.peer_id = sel_out.fake_sock->id(); Resource r = PopFree(); if (r.sub_done == NULL) { CHECK(false) << "Impossible!"; _main_cntl->SetFailed("Impossible happens"); return -1; } r.sub_done->_cid = _main_cntl->current_id(); r.sub_done->_peer_id = sel_out.fake_sock->id(); Controller* sub_cntl = &r.sub_done->_cntl; // No need to count timeout. We already managed timeout in schan. If // timeout occurs, sub calls are canceled with ERPCTIMEDOUT. sub_cntl->_timeout_ms = -1; // Inherit following fields of _main_cntl. // TODO(gejun): figure out a better way to maintain these fields. sub_cntl->set_connection_type(_main_cntl->connection_type()); sub_cntl->set_type_of_service(_main_cntl->_tos); sub_cntl->set_request_compress_type(_main_cntl->request_compress_type()); sub_cntl->set_log_id(_main_cntl->log_id()); sub_cntl->set_request_code(_main_cntl->request_code()); // Forward request attachment to the subcall sub_cntl->request_attachment().append(_main_cntl->request_attachment()); sel_out.channel()->CallMethod(_main_cntl->_method, &r.sub_done->_cntl, _request, r.response, r.sub_done); return 0; }
void PProfService::growth( ::google::protobuf::RpcController* controller_base, const ::brpc::ProfileRequest* /*request*/, ::brpc::ProfileResponse* /*response*/, ::google::protobuf::Closure* done) { ClosureGuard done_guard(done); Controller* cntl = static_cast<Controller*>(controller_base); MallocExtension* malloc_ext = MallocExtension::instance(); if (malloc_ext == NULL) { cntl->SetFailed(ENOMETHOD, "%s, to enable growth profiler, check out " "docs/cn/heap_profiler.md", berror(ENOMETHOD)); return; } // Log requester std::ostringstream client_info; client_info << cntl->remote_side(); if (cntl->auth_context()) { client_info << "(auth=" << cntl->auth_context()->user() << ')'; } else { client_info << "(no auth)"; } LOG(INFO) << client_info.str() << " requests for growth profile"; std::string obj; malloc_ext->GetHeapGrowthStacks(&obj); cntl->http_response().set_content_type("text/plain"); cntl->response_attachment().append(obj); }
void PProfService::heap( ::google::protobuf::RpcController* controller_base, const ::brpc::ProfileRequest* /*request*/, ::brpc::ProfileResponse* /*response*/, ::google::protobuf::Closure* done) { ClosureGuard done_guard(done); Controller* cntl = static_cast<Controller*>(controller_base); MallocExtension* malloc_ext = MallocExtension::instance(); if (malloc_ext == NULL || !has_TCMALLOC_SAMPLE_PARAMETER()) { const char* extra_desc = ""; if (malloc_ext != NULL) { extra_desc = " (no TCMALLOC_SAMPLE_PARAMETER in env)"; } cntl->SetFailed(ENOMETHOD, "Heap profiler is not enabled%s," "check out http://wiki.baidu.com/display/RPC", extra_desc); return; } // Log requester std::ostringstream client_info; client_info << cntl->remote_side(); if (cntl->auth_context()) { client_info << "(auth=" << cntl->auth_context()->user() << ')'; } else { client_info << "(no auth)"; } LOG(INFO) << client_info.str() << " requests for heap profile"; std::string obj; malloc_ext->GetHeapSample(&obj); cntl->http_response().set_content_type("text/plain"); cntl->response_attachment().append(obj); }
void PProfService::cmdline(::google::protobuf::RpcController* controller_base, const ::brpc::ProfileRequest* /*request*/, ::brpc::ProfileResponse* /*response*/, ::google::protobuf::Closure* done) { ClosureGuard done_guard(done); Controller* cntl = static_cast<Controller*>(controller_base); cntl->http_response().set_content_type("text/plain" /*FIXME*/); char buf[1024]; // should be enough? const ssize_t nr = ReadCommandLine(buf, sizeof(buf), true); if (nr < 0) { cntl->SetFailed(ENOENT, "Fail to read /proc/self/cmdline"); return; } cntl->response_attachment().append(buf, nr); }
void ProtobufsService::default_method(::google::protobuf::RpcController* cntl_base, const ProtobufsRequest*, ProtobufsResponse*, ::google::protobuf::Closure* done) { ClosureGuard done_guard(done); Controller *cntl = static_cast<Controller*>(cntl_base); butil::IOBufBuilder os; const std::string& filter = cntl->http_request().unresolved_path(); if (filter.empty()) { const bool use_html = UseHTML(cntl->http_request()); cntl->http_response().set_content_type( use_html ? "text/html" : "text/plain"); if (use_html) { os << "<!DOCTYPE html><html><head></head><body>\n"; } // list all structures. for (Map::iterator it = _map.begin(); it != _map.end(); ++it) { if (use_html) { os << "<p><a href=\"/protobufs/" << it->first << "\">"; } os << it->first; if (use_html) { os << "</a></p>"; } os << '\n'; } if (use_html) { os << "</body></html>"; } } else { // already text. cntl->http_response().set_content_type("text/plain"); Map::iterator it = _map.find(filter); if (it == _map.end()) { cntl->SetFailed(ENOMETHOD, "Fail to find any protobuf message by `%s'", filter.c_str()); return; } os << it->second; } os.move_to(cntl->response_attachment()); }
void SelectiveChannel::CallMethod( const google::protobuf::MethodDescriptor* method, google::protobuf::RpcController* controller_base, const google::protobuf::Message* request, google::protobuf::Message* response, google::protobuf::Closure* user_done) { Controller* cntl = static_cast<Controller*>(controller_base); if (!initialized()) { cntl->SetFailed(EINVAL, "SelectiveChannel=%p is not initialized yet", this); } schan::Sender* sndr = new schan::Sender(cntl, request, response, user_done); cntl->_sender = sndr; cntl->add_flag(Controller::FLAGS_DESTROY_CID_IN_DONE); const CallId cid = cntl->call_id(); _chan.CallMethod(method, cntl, request, response, sndr); if (user_done == NULL) { Join(cid); cntl->OnRPCEnd(butil::gettimeofday_us()); } }
void BthreadsService::default_method(::google::protobuf::RpcController* cntl_base, const ::brpc::BthreadsRequest*, ::brpc::BthreadsResponse*, ::google::protobuf::Closure* done) { ClosureGuard done_guard(done); Controller *cntl = static_cast<Controller*>(cntl_base); cntl->http_response().set_content_type("text/plain"); butil::IOBufBuilder os; const std::string& constraint = cntl->http_request().unresolved_path(); if (constraint.empty()) { os << "Use /bthreads/<bthread_id>"; } else { char* endptr = NULL; bthread_t tid = strtoull(constraint.c_str(), &endptr, 10); if (*endptr == '\0' || *endptr == '/') { ::bthread::print_task(os, tid); } else { cntl->SetFailed(ENOMETHOD, "path=%s is not a bthread id", constraint.c_str()); } } os.move_to(cntl->response_attachment()); }
void PProfService::profile( ::google::protobuf::RpcController* controller_base, const ::brpc::ProfileRequest* /*request*/, ::brpc::ProfileResponse* /*response*/, ::google::protobuf::Closure* done) { ClosureGuard done_guard(done); Controller* cntl = static_cast<Controller*>(controller_base); cntl->http_response().set_content_type("text/plain"); if ((void*)ProfilerStart == NULL || (void*)ProfilerStop == NULL) { cntl->SetFailed(ENOMETHOD, "%s, to enable cpu profiler, check out " "docs/cn/cpu_profiler.md", berror(ENOMETHOD)); return; } int sleep_sec = ReadSeconds(cntl); if (sleep_sec <= 0) { if (!cntl->Failed()) { cntl->SetFailed(EINVAL, "You have to specify ?seconds=N. If you're " "using pprof, add --seconds=N"); } return; } // Log requester std::ostringstream client_info; client_info << cntl->remote_side(); if (cntl->auth_context()) { client_info << "(auth=" << cntl->auth_context()->user() << ')'; } else { client_info << "(no auth)"; } LOG(INFO) << client_info.str() << " requests for cpu profile for " << sleep_sec << " seconds"; char prof_name[256]; if (MakeProfName(PROFILING_CPU, prof_name, sizeof(prof_name)) != 0) { cntl->SetFailed(errno, "Fail to create .prof file, %s", berror()); return; } butil::File::Error error; const butil::FilePath dir = butil::FilePath(prof_name).DirName(); if (!butil::CreateDirectoryAndGetError(dir, &error)) { cntl->SetFailed(EPERM, "Fail to create directory=`%s'",dir.value().c_str()); return; } if (!ProfilerStart(prof_name)) { cntl->SetFailed(EAGAIN, "Another profiler is running, try again later"); return; } if (bthread_usleep(sleep_sec * 1000000L) != 0) { PLOG(WARNING) << "Profiling has been interrupted"; } ProfilerStop(); butil::fd_guard fd(open(prof_name, O_RDONLY)); if (fd < 0) { cntl->SetFailed(ENOENT, "Fail to open %s", prof_name); return; } butil::IOPortal portal; portal.append_from_file_descriptor(fd, ULONG_MAX); cntl->response_attachment().swap(portal); }