if (!reconnected) {
/* reconnect failed, we give up */
DEBUGLOG("reconnect failed, we give up");
- conn->notifyAllQueriesFailed(now);
+ ++conn->d_ds->tcpGaveUp;
+ conn->notifyAllQueriesFailed(now, FailureReason::gaveUp);
}
}
void TCPConnectionToBackend::handleTimeout(const struct timeval& now, bool write)
{
+ /* in some cases we could retry, here, reconnecting and sending our pending responses again */
if (write) {
++d_ds->tcpWriteTimeouts;
}
d_ioState->reset();
}
- notifyAllQueriesFailed(now, true);
+ notifyAllQueriesFailed(now, FailureReason::timeout);
}
-void TCPConnectionToBackend::notifyAllQueriesFailed(const struct timeval& now, bool timeout)
+void TCPConnectionToBackend::notifyAllQueriesFailed(const struct timeval& now, FailureReason reason)
{
d_connectionDied = true;
return;
}
- if (timeout) {
+ if (reason == FailureReason::timeout) {
++clientConn->d_ci.cs->tcpDownstreamTimeouts;
}
+ else if (reason == FailureReason::gaveUp) {
+ ++clientConn->d_ci.cs->tcpGaveUp;
+ }
if (d_state == State::sendingQueryToBackend) {
clientConn->notifyIOError(clientConn, std::move(d_currentQuery.d_idstate), now);
}
catch (const std::exception& e) {
DEBUGLOG("Unable to get query ID");
- notifyAllQueriesFailed(now);
+ notifyAllQueriesFailed(now, FailureReason::unexpectedQueryID);
throw;
}
auto it = d_pendingResponses.find(queryId);
if (it == d_pendingResponses.end()) {
DEBUGLOG("could not find any corresponding query for ID "<<queryId<<". This is likely a duplicated ID over the same TCP connection, giving up!");
- notifyAllQueriesFailed(now);
+ notifyAllQueriesFailed(now, FailureReason::unexpectedQueryID);
return IOState::Done;
}
void setProxyProtocolPayloadAdded(bool added);
private:
+ /* waitingForResponseFromBackend is a state where we have not yet started reading the size,
+ so we can still switch to sending instead */
+ enum class State : uint8_t { idle, doingHandshake, sendingQueryToBackend, waitingForResponseFromBackend, readingResponseSizeFromBackend, readingResponseFromBackend };
+ enum class FailureReason : uint8_t { /* too many attempts */ gaveUp, timeout, unexpectedQueryID };
+
static void handleIO(std::shared_ptr<TCPConnectionToBackend>& conn, const struct timeval& now);
static void handleIOCallback(int fd, FDMultiplexer::funcparam_t& param);
static IOState queueNextQuery(std::shared_ptr<TCPConnectionToBackend>& conn);
IOState handleResponse(std::shared_ptr<TCPConnectionToBackend>& conn, const struct timeval& now);
uint16_t getQueryIdFromResponse();
bool reconnect();
- void notifyAllQueriesFailed(const struct timeval& now, bool timeout = false);
+ void notifyAllQueriesFailed(const struct timeval& now, FailureReason reason);
boost::optional<struct timeval> getBackendReadTTD(const struct timeval& now) const
{
return res;
}
- /* waitingForResponseFromBackend is a state where we have not yet started reading the size,
- so we can still switch to sending instead */
- enum class State { idle, doingHandshake, sendingQueryToBackend, waitingForResponseFromBackend, readingResponseSizeFromBackend, readingResponseFromBackend };
static const uint16_t s_xfrID;
std::vector<uint8_t> d_responseBuffer;