Re: Code review
I'm posting the complete constructor this time. I've reworked
it since the previous post. The primary difference is pulling
out the check for activity from the CMW to be certain that is
always checked first. This version eliminates two of the
continue statements that were in the previous version.
I've added a comment to the post near the code where I have
a question. The question follows below.
cmwAmbassador::cmwAmbassador(char const* configfile) :
sendbuf(200000), buf(40000),
localsendbuf(4096),
#ifdef BIG_ENDIANS
byteOrder(most_significant_first),
#else
byteOrder(least_significant_first),
#endif
configData(configfile)
{
fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select()
FD_ZERO(&master);
FD_ZERO(&read_fds);
sock_type CMWfd = login();
sock_type listener = serverPrep(configData.portnumber);
// Add the listener to the master set
FD_SET(CMWfd, &master);
FD_SET(listener, &master);
#undef max // for Windows
int32_t fdmax = std::max(listener, CMWfd);
for (;;) {
read_fds = master;
if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) {
if (EINTR == errno) {
continue;
}
throw failure("select() failed with errno of ") << errno;
}
if (FD_ISSET(CMWfd, &read_fds)) {
try {
if (buf.GotPacket()) {
int32_t localsock = mediateResponse();
if (localsock != 0) {
closeSocket(localsock);
FD_CLR(localsock, &master);
}
}
} catch(eof const& ex) {
closeSocket(CMWfd);
FD_CLR(CMWfd, &master);
flex_string<char> errorMsg = "CMW crashed before your request
was processed.";
transactions_t::iterator itr = pendingTransactions.begin();
transactions_t::iterator endit = pendingTransactions.end();
for (; itr != endit; ++itr) {
localsendbuf.sock_ = (*itr).second.sock;
msg_shepherd::Send(localsendbuf, false, errorMsg);
closeSocket((*itr).second.sock);
FD_CLR((*itr).second.sock, &master);
}
pendingTransactions.clear();
CMWfd = login(); // question relates to
this line and the next two.
FD_SET(CMWfd, &master);
fdmax = std::max(listener, CMWfd);
}
}
for (int32_t sock = 0; sock <= fdmax; ++sock) {
if (FD_ISSET(sock, &read_fds)) {
if (sock == listener) {
int newsock;
sockaddr_in amb_addr;
socklen_t amblen = sizeof(amb_addr);
if ((newsock = accept(listener, (sockaddr*) &amb_addr,
&amblen)) < 0) {
throw failure("accept() failed with errno of ") << errno;
}
FD_SET(newsock, &master);
if (newsock > fdmax) {
fdmax = newsock;
}
PersistentWrite(newsock, &byteOrder, 1);
} else {
if (sock != CMWfd) {
if (!mediateRequest(sock)) {
closeSocket(sock);
FD_CLR(sock, &master);
}
}
}
}
}
}
}
In that catch block I'm calling login() which can throw
so the ambassador could be abruptly terminated. I don't think
there's any other option though but to attempt to reestablish
the connection with the CMW though. Would you suggest adding
logging calls before and after the call to login? Do you call
functions in catch blocks that can throw?