diff options
Diffstat (limited to 'fbench/src/httpclient/httpclient.cpp')
-rw-r--r-- | fbench/src/httpclient/httpclient.cpp | 142 |
1 files changed, 140 insertions, 2 deletions
diff --git a/fbench/src/httpclient/httpclient.cpp b/fbench/src/httpclient/httpclient.cpp index ce2157335e4..1a9564c5dd4 100644 --- a/fbench/src/httpclient/httpclient.cpp +++ b/fbench/src/httpclient/httpclient.cpp @@ -187,6 +187,103 @@ HTTPClient::Connect(const char *url) return false; } +bool +HTTPClient::ConnectForPost(const char *url, const char *content, int cLen) +{ + char tmp[4096]; + char *req = NULL; + uint32_t req_max = 0; + uint32_t url_len = strlen(url); + uint32_t host_len = _hostname.size(); + + // Add additional headers + std::string headers = _extraHeaders; + + // this is always requested to get robust info on total hit count. + headers += "X-Yahoo-Vespa-Benchmarkdata: true\r\n"; + + if ( _headerBenchmarkdataCoverage ) { + headers += "X-Yahoo-Vespa-Benchmarkdata-Coverage: true\r\n"; + } + + if (url_len + host_len + headers.length() + FIXED_REQ_MAX < sizeof(tmp)) { + req = tmp; + req_max = sizeof(tmp); + } else { + req_max = url_len + host_len + headers.length() + FIXED_REQ_MAX; + req = new char[req_max]; + assert(req != NULL); + } + + // create request + if(_keepAlive) { + snprintf(req, req_max, + "POST %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Content-Length: %d\r\n" + "User-Agent: fbench/4.2.10\r\n" + "%s" + "\r\n", + url, _authority.c_str(), cLen, headers.c_str()); + } else { + snprintf(req, req_max, + "POST %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Connection: close\r\n" + "Content-Length: %d\r\n" + "User-Agent: fbench/4.2.10\r\n" + "%s" + "\r\n", + url, _authority.c_str(), cLen, headers.c_str()); + } + + // try to reuse connection if keep-alive is enabled + if (_keepAlive + && _socket->IsOpened() + && _socket->Write(req, strlen(req)) == (ssize_t)strlen(req) + && _socket->Write(content, cLen) == (ssize_t)cLen + && FillBuffer() > 0) { + + // DEBUG + // printf("Socket Connection reused!\n"); + _reuseCount++; + if (req != tmp) { + delete [] req; + } + return true; + } else { + _socket->Close(); + ResetBuffer(); + } + + // try to open new connection to server + if (_socket->SetSoBlocking(true) + && _socket->Connect() + && _socket->SetNoDelay(true) + && _socket->SetSoLinger(false, 0) + && _socket->Write(req, strlen(req)) == (ssize_t)strlen(req) + && _socket->Write(content, cLen) == (ssize_t)cLen) + { + + // DEBUG + // printf("New Socket connection!\n"); + if (req != tmp) { + delete [] req; + } + return true; + } else { + _socket->Close(); + } + + // DEBUG + // printf("Connect FAILED!\n"); + if (req != tmp) { + delete [] req; + } + return false; +} + + char * HTTPClient::SplitString(char *input, int &argc, char **argv, int maxargs) { @@ -338,7 +435,7 @@ HTTPClient::ReadChunkHeader() } bool -HTTPClient::Open(const char *url) +HTTPClient::Open(const char *url, bool usePost, const char *content, int cLen) { if (_isOpen) Close(); @@ -346,7 +443,7 @@ HTTPClient::Open(const char *url) ResetBuffer(); _dataRead = 0; _dataDone = false; - _isOpen = Connect(url); + _isOpen = usePost ? ConnectForPost(url, content, cLen) : Connect(url); if(!_isOpen || !ReadHTTPHeader()) { Close(); return false; @@ -547,3 +644,44 @@ HTTPClient::Fetch(const char *url, std::ostream *file) _totalHitCount, written); } + +HTTPClient::FetchStatus +HTTPClient::Post(const char *url, const char *content, int contentLen, std::ostream *file) +{ + size_t buflen = FETCH_BUFLEN; + char buf[FETCH_BUFLEN]; // NB: ensure big enough thread stack. + ssize_t readRes = 0; + ssize_t written = 0; + + if (!Open(url, true, content, contentLen)) { + return FetchStatus(false, _requestStatus, _totalHitCount, 0); + } + + // Write headerinfo + if (file) { + file->write(_headerinfo.c_str(), _headerinfo.length()); + if (file->fail()) { + Close(); + return FetchStatus(false, _requestStatus, _totalHitCount, 0); + } + file->write("\r\n", 2); + // Reset header data. + _headerinfo = ""; + } + + while((readRes = Read(buf, buflen)) > 0) { + if(file != NULL) { + if (!file->write(buf, readRes)) { + Close(); + return FetchStatus(false, _requestStatus, _totalHitCount, written); + } + } + written += readRes; + } + Close(); + + return FetchStatus(_requestStatus == 200 && readRes == 0 && _totalHitCount >= 0, + _requestStatus, + _totalHitCount, + written); +} |