1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
#include "netbuffer"
#include "balancer/balancer"
unsigned Netbuffer::netwrite (int fd, int timeout) const {
PROFILE("Netbuffer::netwrite");
debugmsg((Mstr("About to write ") + buf_sz) +
(Mstr(" bytes to fd ") + fd) +
(Mstr(", timeout ") + timeout) + "\n");
if (!buf_sz)
return (0);
// Log to dump directory if requested
if (config.dumpdir().length()) {
ostringstream of;
of << config.dumpdir() << "/" << balancer.requestnr() << "." << fd;
FILE *f;
if ( (!(f = fopen (of.str().c_str(), "a"))) &&
(!(f = fopen (of.str().c_str(), "w"))) )
warnmsg ("Cannot write traffic log " + of.str() + ": " +
strerror(errno) + "\n");
else {
fwrite (buf_data, 1, buf_sz, f);
fclose (f);
}
}
// Send to the socket
unsigned totwritten = 0, ntries = 0;
while (totwritten < buf_sz) {
// Don't go beyond 5 tries.
if (++ntries > 4) {
ostringstream o;
o << "Network writing to fd " << fd << " failed, "
<< totwritten << " bytes sent of " << buf_sz;
throw Error(o.str());
}
// Wait for the socket to become writeable.
if (timeout) {
Fdset set (timeout);
set.add (fd);
set.wait_w();
if (! set.writeable(fd)) {
ostringstream o;
o << "Fd " << fd << " failed to become writable within "
<< timeout << " sec";
throw Error(o.str());
}
}
// Push bytes
ssize_t nwritten;
nwritten = write (fd, buf_data + totwritten, buf_sz - totwritten);
// If any bytes were written, we're ok
// EINVAL / EINPROGRESS errors are handled as: retry
// All other errors mean the link is broken
if (nwritten >= 1) {
ntries = 0;
if (config.debug()) {
ostringstream o;
o << "Sent " << nwritten << " bytes to fd " << fd << ": ";
for (unsigned i = totwritten; i < totwritten + nwritten; i++)
o << printable(buf_data[i]);
o << "\n";
_debugmsg (o.str());
}
totwritten += nwritten;
} else if (errno == EINVAL || errno == EINPROGRESS) {
msg(Mstr("Write warning: ") + Mstr(strerror(errno)) + "\n");
} else {
ostringstream o;
o << "Write/send failed: errno=" << int(errno) << ", "
<< strerror(errno) << ", result=" << int(nwritten);
throw Error(o.str());
}
}
return buf_sz;
}
|