File: netwrite.cc

package info (click to toggle)
crossroads 2.65-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 2,664 kB
  • ctags: 355
  • sloc: cpp: 4,212; perl: 1,658; xml: 269; makefile: 186; sh: 46
file content (83 lines) | stat: -rw-r--r-- 2,255 bytes parent folder | download | duplicates (2)
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;
}