Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
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);    
}
Ejemplo n.º 4
0
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);    
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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());
}
Ejemplo n.º 7
0
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());
    }
}
Ejemplo n.º 8
0
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());
}
Ejemplo n.º 9
0
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);
}