Move GenerateSelectSet logic to private method.

This separates the socket event collection logic from the logic
deciding which events we're interested in at all.
This commit is contained in:
Patrick Strateman 2018-09-25 15:32:07 -04:00 committed by Alexander Block
parent 7a38df4f76
commit ccc3f267ba
2 changed files with 63 additions and 47 deletions

View File

@ -1344,40 +1344,10 @@ void CConnman::InactivityCheck(CNode *pnode)
} }
} }
void CConnman::SocketHandler() bool CConnman::GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
{ {
//
// Find which sockets have data to receive
//
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = SELECT_TIMEOUT_MILLISECONDS * 1000; // frequency to poll pnode->vSend
fd_set fdsetRecv;
fd_set fdsetSend;
fd_set fdsetError;
FD_ZERO(&fdsetRecv);
FD_ZERO(&fdsetSend);
FD_ZERO(&fdsetError);
SOCKET hSocketMax = 0;
bool have_fds = false;
#ifndef WIN32
// We add a pipe to the read set so that the select() call can be woken up from the outside
// This is done when data is available for sending and at the same time optimistic sending was disabled
// when pushing the data.
// This is currently only implemented for POSIX compliant systems. This means that Windows will fall back to
// timing out after 50ms and then trying to send. This is ok as we assume that heavy-load daemons are usually
// run on Linux and friends.
FD_SET(wakeupPipe[0], &fdsetRecv);
hSocketMax = std::max(hSocketMax, (SOCKET)wakeupPipe[0]);
have_fds = true;
#endif
for (const ListenSocket& hListenSocket : vhListenSocket) { for (const ListenSocket& hListenSocket : vhListenSocket) {
FD_SET(hListenSocket.socket, &fdsetRecv); recv_set.insert(hListenSocket.socket);
hSocketMax = std::max(hSocketMax, hListenSocket.socket);
have_fds = true;
} }
{ {
@ -1406,36 +1376,81 @@ void CConnman::SocketHandler()
if (pnode->hSocket == INVALID_SOCKET) if (pnode->hSocket == INVALID_SOCKET)
continue; continue;
FD_SET(pnode->hSocket, &fdsetError); error_set.insert(pnode->hSocket);
hSocketMax = std::max(hSocketMax, pnode->hSocket);
have_fds = true;
if (select_send) { if (select_send) {
FD_SET(pnode->hSocket, &fdsetSend); send_set.insert(pnode->hSocket);
continue; continue;
} }
if (select_recv) { if (select_recv) {
FD_SET(pnode->hSocket, &fdsetRecv); recv_set.insert(pnode->hSocket);
} }
} }
} }
return !recv_set.empty() || !send_set.empty() || !error_set.empty();
}
void CConnman::SocketHandler()
{
std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
return;
}
//
// Find which sockets have data to receive
//
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = SELECT_TIMEOUT_MILLISECONDS * 1000; // frequency to poll pnode->vSend
fd_set fdsetRecv;
fd_set fdsetSend;
fd_set fdsetError;
FD_ZERO(&fdsetRecv);
FD_ZERO(&fdsetSend);
FD_ZERO(&fdsetError);
SOCKET hSocketMax = 0;
for (SOCKET hSocket : recv_select_set) {
FD_SET(hSocket, &fdsetRecv);
hSocketMax = std::max(hSocketMax, hSocket);
}
for (SOCKET hSocket : send_select_set) {
FD_SET(hSocket, &fdsetSend);
hSocketMax = std::max(hSocketMax, hSocket);
}
for (SOCKET hSocket : error_select_set) {
FD_SET(hSocket, &fdsetError);
hSocketMax = std::max(hSocketMax, hSocket);
}
#ifndef WIN32
// We add a pipe to the read set so that the select() call can be woken up from the outside
// This is done when data is available for sending and at the same time optimistic sending was disabled
// when pushing the data.
// This is currently only implemented for POSIX compliant systems. This means that Windows will fall back to
// timing out after 50ms and then trying to send. This is ok as we assume that heavy-load daemons are usually
// run on Linux and friends.
FD_SET(wakeupPipe[0], &fdsetRecv);
hSocketMax = std::max(hSocketMax, (SOCKET)wakeupPipe[0]);
#endif
wakeupSelectNeeded = true; wakeupSelectNeeded = true;
int nSelect = select(have_fds ? hSocketMax + 1 : 0, int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
&fdsetRecv, &fdsetSend, &fdsetError, &timeout);
wakeupSelectNeeded = false; wakeupSelectNeeded = false;
if (interruptNet) if (interruptNet)
return; return;
if (nSelect == SOCKET_ERROR) if (nSelect == SOCKET_ERROR)
{
if (have_fds)
{ {
int nErr = WSAGetLastError(); int nErr = WSAGetLastError();
LogPrintf("socket select error %s\n", NetworkErrorString(nErr)); LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
for (unsigned int i = 0; i <= hSocketMax; i++) for (unsigned int i = 0; i <= hSocketMax; i++)
FD_SET(i, &fdsetRecv); FD_SET(i, &fdsetRecv);
}
FD_ZERO(&fdsetSend); FD_ZERO(&fdsetSend);
FD_ZERO(&fdsetError); FD_ZERO(&fdsetError);
if (!interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS))) if (!interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS)))

View File

@ -477,6 +477,7 @@ private:
void DisconnectNodes(); void DisconnectNodes();
void NotifyNumConnectionsChanged(); void NotifyNumConnectionsChanged();
void InactivityCheck(CNode *pnode); void InactivityCheck(CNode *pnode);
bool GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set);
void SocketHandler(); void SocketHandler();
void ThreadSocketHandler(); void ThreadSocketHandler();
void ThreadDNSAddressSeed(); void ThreadDNSAddressSeed();