1
0
Fork 0

Fix SimpleHttpClient for the n+1 time.

Still with debugging output.
This commit is contained in:
Max Neunhoeffer 2014-12-03 23:31:20 +01:00
parent e4b51f616c
commit 0fb6ef1968
8 changed files with 55 additions and 31 deletions

View File

@ -174,6 +174,7 @@ bool ClientConnection::prepare (const double timeout, const bool isWrite) const
int sockn = (int) (TRI_get_fd_or_handle_of_socket(_socket) + 1); int sockn = (int) (TRI_get_fd_or_handle_of_socket(_socket) + 1);
int res = select(sockn, readFds, writeFds, NULL, &tv); int res = select(sockn, readFds, writeFds, NULL, &tv);
std::cout << "select: " << res << " " << errno << std::endl;
if (res > 0) { if (res > 0) {
return true; return true;
@ -233,14 +234,17 @@ bool ClientConnection::writeClientConnection (void* buffer, size_t length, size_
/// @brief read data from the connection /// @brief read data from the connection
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool ClientConnection::readClientConnection (StringBuffer& stringBuffer, bool& progress) { bool ClientConnection::readClientConnection (StringBuffer& stringBuffer,
bool& connectionClosed) {
if (! checkSocket()) { if (! checkSocket()) {
std::cout << "checkSocket was false\n";
connectionClosed = true;
return false; return false;
} }
TRI_ASSERT(TRI_isvalidsocket(_socket)); TRI_ASSERT(TRI_isvalidsocket(_socket));
progress = false; connectionClosed = false;
do { do {
@ -256,15 +260,17 @@ bool ClientConnection::readClientConnection (StringBuffer& stringBuffer, bool& p
if (lenRead == -1) { if (lenRead == -1) {
// error occurred // error occurred
std::cout << "An error occurred!" << std::endl; std::cout << "An error occurred!" << std::endl;
connectionClosed = true;
return false; return false;
} }
if (lenRead == 0) { if (lenRead == 0) {
std::cout << "length 0 received!" << std::endl;
connectionClosed = true;
disconnect(); disconnect();
return true; return true;
} }
progress = true;
stringBuffer.increaseLength(lenRead); stringBuffer.increaseLength(lenRead);
} }
while (readable()); while (readable());

View File

@ -118,7 +118,8 @@ namespace triagens {
/// @brief read data from the connection /// @brief read data from the connection
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool readClientConnection (triagens::basics::StringBuffer&, bool& progress); bool readClientConnection (triagens::basics::StringBuffer&,
bool& connectionClosed);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief return whether the connection is readable /// @brief return whether the connection is readable

View File

@ -137,7 +137,7 @@ void GeneralClientConnection::disconnect () {
/// (regardless of whether there was an error or not). The return value /// (regardless of whether there was an error or not). The return value
/// indicates, whether an error has happened. Note that the other side /// indicates, whether an error has happened. Note that the other side
/// closing the connection is not considered to be an error! The call to /// closing the connection is not considered to be an error! The call to
/// prepare() does a select and the call to readClientCollection does /// prepare() does a select and the call to readClientConnection does
/// what is described here. /// what is described here.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -156,9 +156,9 @@ bool GeneralClientConnection::handleWrite (const double timeout, void* buffer, s
/// Read data from endpoint, this uses select to block until some /// Read data from endpoint, this uses select to block until some
/// data has arrived. Then it reads as much as it can without further /// data has arrived. Then it reads as much as it can without further
/// blocking, using select multiple times. What has happened is /// blocking, using select multiple times. What has happened is
/// indicated by two flags, the return value and the progress flag, /// indicated by two flags, the return value and the connectionClosed flag,
/// which is always set by this method. The progress flag indicates /// which is always set by this method. The connectionClosed flag indicates
/// whether or not at least one byte has been appended to the buffer /// whether or not the connection has been closed by the other side
/// (regardless of whether there was an error or not). The return value /// (regardless of whether there was an error or not). The return value
/// indicates, whether an error has happened. Note that the other side /// indicates, whether an error has happened. Note that the other side
/// closing the connection is not considered to be an error! The call to /// closing the connection is not considered to be an error! The call to
@ -166,13 +166,14 @@ bool GeneralClientConnection::handleWrite (const double timeout, void* buffer, s
/// what is described here. /// what is described here.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool GeneralClientConnection::handleRead (double timeout, StringBuffer& buffer, bool& progress) { bool GeneralClientConnection::handleRead (double timeout, StringBuffer& buffer, bool& connectionClosed) {
progress = false; connectionClosed = false;
if (prepare(timeout, false)) { if (prepare(timeout, false)) {
return this->readClientConnection(buffer, progress); return this->readClientConnection(buffer, connectionClosed);
} }
connectionClosed = true;
return false; return false;
} }

View File

@ -164,7 +164,8 @@ namespace triagens {
/// @brief read data from endpoint /// @brief read data from endpoint
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool handleRead (double, triagens::basics::StringBuffer&, bool& progress); bool handleRead (double, triagens::basics::StringBuffer&,
bool& connectionClosed);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- protected virtual methods // --SECTION-- protected virtual methods

View File

@ -148,7 +148,7 @@ namespace triagens {
// but the following read runs into an error. In that case we try // but the following read runs into an error. In that case we try
// to reconnect one and then give up if this does not work. // to reconnect one and then give up if this does not work.
std::cout << "Simple: Main loop, state " << _state << " remaining time " std::cout << "Simple: Main loop, state " << _state << " remaining time "
<< remainingTime << std::endl; << remainingTime << " code:" << _result->getHttpReturnCode() << std::endl;
switch (_state) { switch (_state) {
case (IN_CONNECT): { case (IN_CONNECT): {
handleConnect(); handleConnect();
@ -173,7 +173,7 @@ namespace triagens {
setErrorMessage(TRI_last_error(), false); setErrorMessage(TRI_last_error(), false);
} }
this->close(); // this sets _state to IN_CONNECT for a retry this->close(); // this sets _state to IN_CONNECT for a retry
} }
else { else {
_written += bytesWritten; _written += bytesWritten;
@ -192,13 +192,14 @@ namespace triagens {
case (IN_READ_CHUNKED_BODY): { case (IN_READ_CHUNKED_BODY): {
TRI_set_errno(TRI_ERROR_NO_ERROR); TRI_set_errno(TRI_ERROR_NO_ERROR);
// we need to read a at least one byte to make progress // we need to notice if the other side has closed the connection:
bool progress; bool connectionClosed;
std::cout << "ReadBufV:" << (unsigned long) _readBuffer.c_str() << " " std::cout << "ReadBufV:" << (unsigned long) _readBuffer.c_str() << " "
<< _readBuffer.length() << " " << _readBuffer.length() << " "
<< _readBufferOffset << std::endl; << _readBufferOffset << std::endl;
bool res = _connection->handleRead(remainingTime, _readBuffer, progress); bool res = _connection->handleRead(remainingTime, _readBuffer,
connectionClosed);
std::cout << "ReadBufN:" << (unsigned long) _readBuffer.c_str() << " " std::cout << "ReadBufN:" << (unsigned long) _readBuffer.c_str() << " "
<< _readBuffer.length() << " " << _readBuffer.length() << " "
@ -207,17 +208,17 @@ namespace triagens {
// If there was an error, then we are doomed: // If there was an error, then we are doomed:
if (! res) { if (! res) {
std::cout << "doomed\n"; std::cout << "doomed\n";
this->close(); // this sets the state to IN_CONNECT for a retry this->close(); // this sets the state to IN_CONNECT for a retry
break; break;
} }
if (! progress) { if (connectionClosed) {
std::cout << "no progress\n"; std::cout << "connection closed\n";
// write might have succeeded even if the server has closed // write might have succeeded even if the server has closed
// the connection, this will then show up here with us being // the connection, this will then show up here with us being
// in state IN_READ_HEADER but nothing read. // in state IN_READ_HEADER but nothing read.
if (_state == IN_READ_HEADER && 0 == _readBuffer.length()) { if (_state == IN_READ_HEADER && 0 == _readBuffer.length()) {
this->close(); // sets _state to IN_CONNECT again for a retry this->close(); // sets _state to IN_CONNECT again for a retry
continue; continue;
} }
@ -228,24 +229,25 @@ namespace triagens {
// that the server has closed the connection and we must // that the server has closed the connection and we must
// process the body one more time: // process the body one more time:
_result->setContentLength(_readBuffer.length() - _readBufferOffset); _result->setContentLength(_readBuffer.length() - _readBufferOffset);
std::cout << "SetContentLength: " << _readBuffer.length() - _readBufferOffset << std::endl;
processBody(); processBody();
if (_state != FINISHED) { if (_state != FINISHED) {
// If the body was not fully found we give up: // If the body was not fully found we give up:
this->close(); // this sets the state to retry this->close(); // this sets the state IN_CONNECT to retry
} }
break; break;
} }
else { else {
// In all other cases of no progress, we are doomed: // In all other cases of closed connection, we are doomed:
this->close(); // this sets the state to retry this->close(); // this sets the state to IN_CONNECT retry
break; break;
} }
} }
// we made progress, we process whatever we are in progress to do // the connection is still alive:
switch (_state) { switch (_state) {
case (IN_READ_HEADER): case (IN_READ_HEADER):
processHeader(); processHeader();

View File

@ -64,6 +64,7 @@ namespace triagens {
_returnMessage = ""; _returnMessage = "";
_contentLength = 0; _contentLength = 0;
_returnCode = 0; _returnCode = 0;
_foundHeader = false;
_hasContentLength = false; _hasContentLength = false;
_chunked = false; _chunked = false;
_deflated = false; _deflated = false;
@ -130,6 +131,7 @@ namespace triagens {
--valueLength; --valueLength;
} }
std::cout << "Header: " << keyString << ": " << std::string(value, valueLength) << std::endl;
if (keyString[0] == 'h') { if (keyString[0] == 'h') {
if (! _foundHeader && if (! _foundHeader &&
(keyString == "http/1.1" || keyString == "http/1.0")) { (keyString == "http/1.1" || keyString == "http/1.0")) {
@ -142,6 +144,7 @@ namespace triagens {
(value[2] >= '0' && value[2] <= '9')) { (value[2] >= '0' && value[2] <= '9')) {
// set response code // set response code
setHttpReturnCode(100 * (value[0] - '0') + 10 * (value[1] - '0') + (value[2] - '0')); setHttpReturnCode(100 * (value[0] - '0') + 10 * (value[1] - '0') + (value[2] - '0'));
std::cout << "setHttpReturnCode: " << getHttpReturnCode() << "\n";
} }
if (valueLength >= 4) { if (valueLength >= 4) {

View File

@ -217,7 +217,9 @@ bool SslClientConnection::prepare (const double timeout, const bool isWrite) con
} }
int sockn = (int) (TRI_get_fd_or_handle_of_socket(_socket) + 1); int sockn = (int) (TRI_get_fd_or_handle_of_socket(_socket) + 1);
if (select(sockn, readFds, writeFds, NULL, &tv) > 0) { int res = select(sockn, readFds, writeFds, NULL, &tv);
std::cout << "selectSSL " << res << " " << errno << std::endl;
if (res > 0) {
return true; return true;
} }
@ -262,12 +264,17 @@ bool SslClientConnection::writeClientConnection (void* buffer, size_t length, si
/// @brief read data from the connection /// @brief read data from the connection
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool SslClientConnection::readClientConnection (StringBuffer& stringBuffer, bool& progress) { bool SslClientConnection::readClientConnection (StringBuffer& stringBuffer,
if (_ssl == nullptr || ! _isConnected) { bool& connectionClosed) {
connectionClosed = true;
if (_ssl == nullptr) {
return false; return false;
} }
if (! _isConnected) {
return true;
}
progress = false; connectionClosed = false;
do { do {
@ -283,11 +290,12 @@ again:
switch (SSL_get_error(_ssl, lenRead)) { switch (SSL_get_error(_ssl, lenRead)) {
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
progress = true;
stringBuffer.increaseLength(lenRead); stringBuffer.increaseLength(lenRead);
break; break;
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
std::cout << "SSL_ERROR_ZERO_RETURN\n";
connectionClosed = true;
SSL_shutdown(_ssl); SSL_shutdown(_ssl);
_isConnected = false; _isConnected = false;
return true; return true;
@ -300,6 +308,7 @@ again:
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
default: default:
/* unexpected */ /* unexpected */
connectionClosed = true;
return false; return false;
} }
} }

View File

@ -113,7 +113,8 @@ namespace triagens {
/// @brief read data from the connection /// @brief read data from the connection
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool readClientConnection (triagens::basics::StringBuffer&, bool& progress); bool readClientConnection (triagens::basics::StringBuffer&,
bool& connectionClosed);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief return whether the connection is readable /// @brief return whether the connection is readable