81 bufP = (char *)malloc((size_t)buflen);
82 if (bufP == NULL) {
83 bufP = BUF;
84 buflen = MAX_BUFFER_LEN;
85 }
86 }
87
88 while(len > 0) {
89 int loff = 0;
90 int chunkLen = min(buflen, len);
91 int llen = chunkLen;
92 int retry = 0;
93
94 (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
95 if ((*env)->ExceptionCheck(env)) {
96 break;
97 } else {
98 while(llen > 0) {
99 int n = send(fd, bufP + loff, llen, 0);
100 if (n > 0) {
101 llen -= n;
102 loff += n;
103 continue;
104 }
105
106 /*
107 * Due to a bug in Windows Sockets (observed on NT and Windows
108 * 2000) it may be necessary to retry the send. The issue is that
109 * on blocking sockets send/WSASend is supposed to block if there
110 * is insufficient buffer space available. If there are a large
111 * number of threads blocked on write due to congestion then it's
112 * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
113 * The workaround we use is to retry the send. If we have a
114 * large buffer to send (>2k) then we retry with a maximum of
115 * 2k buffer. If we hit the issue with <=2k buffer then we backoff
116 * for 1 second and retry again. We repeat this up to a reasonable
117 * limit before bailing out and throwing an exception. In load
118 * conditions we've observed that the send will succeed after 2-3
119 * attempts but this depends on network buffers associated with
120 * other sockets draining.
|
81 bufP = (char *)malloc((size_t)buflen);
82 if (bufP == NULL) {
83 bufP = BUF;
84 buflen = MAX_BUFFER_LEN;
85 }
86 }
87
88 while(len > 0) {
89 int loff = 0;
90 int chunkLen = min(buflen, len);
91 int llen = chunkLen;
92 int retry = 0;
93
94 (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
95 if ((*env)->ExceptionCheck(env)) {
96 break;
97 } else {
98 while(llen > 0) {
99 int n = send(fd, bufP + loff, llen, 0);
100 if (n > 0) {
101 JVM_callFileWriteBytes(env, n);
102 llen -= n;
103 loff += n;
104 continue;
105 }
106
107 /*
108 * Due to a bug in Windows Sockets (observed on NT and Windows
109 * 2000) it may be necessary to retry the send. The issue is that
110 * on blocking sockets send/WSASend is supposed to block if there
111 * is insufficient buffer space available. If there are a large
112 * number of threads blocked on write due to congestion then it's
113 * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
114 * The workaround we use is to retry the send. If we have a
115 * large buffer to send (>2k) then we retry with a maximum of
116 * 2k buffer. If we hit the issue with <=2k buffer then we backoff
117 * for 1 second and retry again. We repeat this up to a reasonable
118 * limit before bailing out and throwing an exception. In load
119 * conditions we've observed that the send will succeed after 2-3
120 * attempts but this depends on network buffers associated with
121 * other sockets draining.
|