You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by sh...@apache.org on 2016/05/27 16:22:55 UTC

[trafficserver] branch master updated: TS-4309: Simplify read/write loops to address upload/download speed problems. This closes #629.

This is an automated email from the ASF dual-hosted git repository.

shinrich pushed a commit to branch master
in repository https://git-dual.apache.org/repos/asf/trafficserver.git

The following commit(s) were added to refs/heads/master by this push:
       new  a647412   TS-4309: Simplify read/write loops to address upload/download speed problems.  This closes #629.
a647412 is described below

commit a647412f20f3a8858c3fa4fc1cc4e9c623b68e92
Author: Susan Hinrichs <sh...@ieee.org>
AuthorDate: Wed May 11 23:29:02 2016 +0000

    TS-4309: Simplify read/write loops to address upload/download speed problems.  This closes #629.
---
 iocore/net/P_SSLNetVConnection.h  |   3 +-
 iocore/net/P_UnixNetVConnection.h |   3 +-
 iocore/net/SSLNetVConnection.cc   | 261 +++++++++++++++++---------------------
 iocore/net/UnixNetVConnection.cc  |  70 ++++------
 4 files changed, 146 insertions(+), 191 deletions(-)

diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h
index a4ae8b3..005e581 100644
--- a/iocore/net/P_SSLNetVConnection.h
+++ b/iocore/net/P_SSLNetVConnection.h
@@ -120,8 +120,7 @@ public:
   int sslServerHandShakeEvent(int &err);
   int sslClientHandShakeEvent(int &err);
   virtual void net_read_io(NetHandler *nh, EThread *lthread);
-  virtual int64_t load_buffer_and_write(int64_t towrite, int64_t &wattempted, int64_t &total_written, MIOBufferAccessor &buf,
-                                        int &needs);
+  virtual int64_t load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs);
   void registerNextProtocolSet(const SSLNextProtocolSet *);
   virtual void do_io_close(int lerrno = -1);
 
diff --git a/iocore/net/P_UnixNetVConnection.h b/iocore/net/P_UnixNetVConnection.h
index 14786eb..d09ba49 100644
--- a/iocore/net/P_UnixNetVConnection.h
+++ b/iocore/net/P_UnixNetVConnection.h
@@ -208,8 +208,7 @@ public:
     (void)state;
   }
   virtual void net_read_io(NetHandler *nh, EThread *lthread);
-  virtual int64_t load_buffer_and_write(int64_t towrite, int64_t &wattempted, int64_t &total_written, MIOBufferAccessor &buf,
-                                        int &needs);
+  virtual int64_t load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs);
   void readDisable(NetHandler *nh);
   void readSignalError(NetHandler *nh, int err);
   int readSignalDone(int event, NetHandler *nh);
diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index 27dc985..c6e0e5a 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -193,131 +193,121 @@ ssl_read_from_net(SSLNetVConnection *sslvc, EThread *lthread, int64_t &ret)
 {
   NetState *s = &sslvc->read;
   MIOBufferAccessor &buf = s->vio.buffer;
-  IOBufferBlock *b = buf.writer()->first_write_block();
   int event = SSL_READ_ERROR_NONE;
   int64_t bytes_read = 0;
-  int64_t block_write_avail = 0;
   ssl_error_t sslErr = SSL_ERROR_NONE;
   int64_t nread = 0;
 
   bool trace = sslvc->getSSLTrace();
   Debug("ssl", "trace=%s", trace ? "TRUE" : "FALSE");
 
-  for (bytes_read = 0; (b != 0) && (sslErr == SSL_ERROR_NONE); b = b->next.get()) {
-    block_write_avail = b->write_avail();
+  bytes_read = 0;
+  while (sslErr == SSL_ERROR_NONE) {
+    int64_t block_write_avail = buf.writer()->block_write_avail();
+    if (block_write_avail <= 0) {
+      buf.writer()->add_block();
+      block_write_avail = buf.writer()->block_write_avail();
+      if (block_write_avail <= 0) {
+        Warning("Cannot add new block");
+        break;
+      }
+    }
 
     Debug("ssl", "[SSL_NetVConnection::ssl_read_from_net] b->write_avail()=%" PRId64, block_write_avail);
+    char *current_block = buf.writer()->end();
+    sslErr = SSLReadBuffer(sslvc->ssl, current_block, block_write_avail, nread);
 
-    int64_t offset = 0;
-    // while can be replaced with if - need to test what works faster with openssl
-    while (block_write_avail > 0) {
-      sslErr = SSLReadBuffer(sslvc->ssl, b->end() + offset, block_write_avail, nread);
-
-      Debug("ssl", "[SSL_NetVConnection::ssl_read_from_net] nread=%d", (int)nread);
-      if (!sslvc->origin_trace) {
-        TraceIn((0 < nread && trace), sslvc->get_remote_addr(), sslvc->get_remote_port(), "WIRE TRACE\tbytes=%d\n%.*s", (int)nread,
-                (int)nread, b->end() + offset);
-      } else {
-        char origin_trace_ip[INET6_ADDRSTRLEN];
-        ats_ip_ntop(sslvc->origin_trace_addr, origin_trace_ip, sizeof(origin_trace_ip));
-        TraceIn((0 < nread && trace), sslvc->get_remote_addr(), sslvc->get_remote_port(), "CLIENT %s:%d\ttbytes=%d\n%.*s",
-                origin_trace_ip, sslvc->origin_trace_port, (int)nread, (int)nread, b->end() + offset);
-      }
+    Debug("ssl", "[SSL_NetVConnection::ssl_read_from_net] nread=%d", (int)nread);
+    if (!sslvc->origin_trace) {
+      TraceIn((0 < nread && trace), sslvc->get_remote_addr(), sslvc->get_remote_port(), "WIRE TRACE\tbytes=%d\n%.*s", (int)nread,
+              (int)nread, current_block);
+    } else {
+      char origin_trace_ip[INET6_ADDRSTRLEN];
+      ats_ip_ntop(sslvc->origin_trace_addr, origin_trace_ip, sizeof(origin_trace_ip));
+      TraceIn((0 < nread && trace), sslvc->get_remote_addr(), sslvc->get_remote_port(), "CLIENT %s:%d\ttbytes=%d\n%.*s",
+              origin_trace_ip, sslvc->origin_trace_port, (int)nread, (int)nread, current_block);
+    }
 
-      switch (sslErr) {
-      case SSL_ERROR_NONE:
+    switch (sslErr) {
+    case SSL_ERROR_NONE:
 
 #if DEBUG
-        SSLDebugBufferPrint("ssl_buff", b->end() + offset, nread, "SSL Read");
+      SSLDebugBufferPrint("ssl_buff", current_block, nread, "SSL Read");
 #endif
-
-        ink_assert(nread);
-
-        bytes_read += nread;
-        offset += nread;
-        block_write_avail -= nread;
-        ink_assert(block_write_avail >= 0);
-
-        continue;
-
-      case SSL_ERROR_WANT_WRITE:
-        event = SSL_WRITE_WOULD_BLOCK;
-        SSL_INCREMENT_DYN_STAT(ssl_error_want_write);
-        Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_WOULD_BLOCK(write)");
-        break;
-      case SSL_ERROR_WANT_READ:
-        event = SSL_READ_WOULD_BLOCK;
-        SSL_INCREMENT_DYN_STAT(ssl_error_want_read);
-        Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_WOULD_BLOCK(read)");
-        break;
-      case SSL_ERROR_WANT_X509_LOOKUP:
-        TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "Want X509 lookup");
-        event = SSL_READ_WOULD_BLOCK;
-        SSL_INCREMENT_DYN_STAT(ssl_error_want_x509_lookup);
-        Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_WOULD_BLOCK(read/x509 lookup)");
-        break;
-      case SSL_ERROR_SYSCALL:
-        TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "Syscall Error: %s", strerror(errno));
-        SSL_INCREMENT_DYN_STAT(ssl_error_syscall);
-        if (nread != 0) {
-          // not EOF
-          event = SSL_READ_ERROR;
-          ret = errno;
-          Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_SYSCALL, underlying IO error: %s", strerror(errno));
-          TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "Underlying IO error: %d", errno);
-        } else {
-          // then EOF observed, treat it as EOS
-          event = SSL_READ_EOS;
-          Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_SYSCALL, EOF observed violating SSL protocol");
-          TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "EOF observed violating SSL protocol");
-        }
-        break;
-      case SSL_ERROR_ZERO_RETURN:
-        TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "Connection closed by peer");
-        event = SSL_READ_EOS;
-        SSL_INCREMENT_DYN_STAT(ssl_error_zero_return);
-        Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_ZERO_RETURN");
-        break;
-      case SSL_ERROR_SSL:
-      default: {
-        Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_SSL and default case");
-        char buf[512];
-        unsigned long e = ERR_peek_last_error();
-        ERR_error_string_n(e, buf, sizeof(buf));
-        TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "SSL Error: sslErr=%d, ERR_get_error=%ld (%s) errno=%d",
-                sslErr, e, buf, errno);
+      ink_assert(nread);
+      bytes_read += nread;
+      if (nread > 0) {
+        buf.writer()->fill(nread); // Tell the buffer, we've used the bytes
+      }
+      break;
+    case SSL_ERROR_WANT_WRITE:
+      event = SSL_WRITE_WOULD_BLOCK;
+      SSL_INCREMENT_DYN_STAT(ssl_error_want_write);
+      Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_WOULD_BLOCK(write)");
+      break;
+    case SSL_ERROR_WANT_READ:
+      event = SSL_READ_WOULD_BLOCK;
+      SSL_INCREMENT_DYN_STAT(ssl_error_want_read);
+      Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_WOULD_BLOCK(read)");
+      break;
+    case SSL_ERROR_WANT_X509_LOOKUP:
+      TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "Want X509 lookup");
+      event = SSL_READ_WOULD_BLOCK;
+      SSL_INCREMENT_DYN_STAT(ssl_error_want_x509_lookup);
+      Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_WOULD_BLOCK(read/x509 lookup)");
+      break;
+    case SSL_ERROR_SYSCALL:
+      TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "Syscall Error: %s", strerror(errno));
+      SSL_INCREMENT_DYN_STAT(ssl_error_syscall);
+      if (nread != 0) {
+        // not EOF
         event = SSL_READ_ERROR;
         ret = errno;
-        SSL_CLR_ERR_INCR_DYN_STAT(sslvc, ssl_error_ssl, "[SSL_NetVConnection::ssl_read_from_net]: errno=%d", errno);
-      } break;
-      } // switch
+        Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_SYSCALL, underlying IO error: %s", strerror(errno));
+        TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "Underlying IO error: %d", errno);
+      } else {
+        // then EOF observed, treat it as EOS
+        // Error("[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_SYSCALL, EOF observed violating SSL protocol");
+        TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "EOF observed violating SSL protocol");
+      }
+      break;
+    case SSL_ERROR_ZERO_RETURN:
+      TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "Connection closed by peer");
+      event = SSL_READ_EOS;
+      SSL_INCREMENT_DYN_STAT(ssl_error_zero_return);
+      Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_ZERO_RETURN");
       break;
-    } // while( block_write_avail > 0 )
-  }   // for ( bytes_read = 0; (b != 0); b = b->next)
+    case SSL_ERROR_SSL:
+    default: {
+      char buf[512];
+      unsigned long e = ERR_peek_last_error();
+      ERR_error_string_n(e, buf, sizeof(buf));
+      TraceIn(trace, sslvc->get_remote_addr(), sslvc->get_remote_port(), "SSL Error: sslErr=%d, ERR_get_error=%ld (%s) errno=%d",
+              sslErr, e, buf, errno);
+      event = SSL_READ_ERROR;
+      ret = errno;
+      SSL_CLR_ERR_INCR_DYN_STAT(sslvc, ssl_error_ssl, "[SSL_NetVConnection::ssl_read_from_net]: errno=%d", errno);
+    } break;
+    } // switch
+  }   // while
 
   if (bytes_read > 0) {
     Debug("ssl", "[SSL_NetVConnection::ssl_read_from_net] bytes_read=%" PRId64, bytes_read);
 
-    buf.writer()->fill(bytes_read);
     s->vio.ndone += bytes_read;
     sslvc->netActivity(lthread);
 
     ret = bytes_read;
 
-    if (s->vio.ntodo() <= 0) {
-      event = SSL_READ_COMPLETE;
-    } else {
-      event = SSL_READ_READY;
-    }
-  } else // if( bytes_read > 0 )
-  {
+    event = (s->vio.ntodo() <= 0) ? SSL_READ_COMPLETE : SSL_READ_READY;
+  } else { // if( bytes_read > 0 )
 #if defined(_DEBUG)
     if (bytes_read == 0) {
       Debug("ssl", "[SSL_NetVConnection::ssl_read_from_net] bytes_read == 0");
     }
 #endif
   }
-  return (event);
+  return event;
 }
 
 /**
@@ -647,17 +637,14 @@ SSLNetVConnection::net_read_io(NetHandler *nh, EThread *lthread)
 }
 
 int64_t
-SSLNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, int64_t &total_written, MIOBufferAccessor &buf,
-                                         int &needs)
+SSLNetVConnection::load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs)
 {
-  int64_t r = 0;
+  int64_t try_to_write;
+  int64_t num_really_written = 0;
   int64_t l = 0;
   uint32_t dynamic_tls_record_size = 0;
   ssl_error_t err = SSL_ERROR_NONE;
-
-  // XXX Rather than dealing with the block directly, we should use the IOBufferReader API.
-  int64_t offset = buf.reader()->start_offset;
-  IOBufferBlock *b = buf.reader()->block.get();
+  char *current_block = buf.reader()->start();
 
   // Dynamic TLS record sizing
   ink_hrtime now = 0;
@@ -674,21 +661,17 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, i
   }
 
   if (HttpProxyPort::TRANSPORT_BLIND_TUNNEL == this->attributes) {
-    return this->super::load_buffer_and_write(towrite, wattempted, total_written, buf, needs);
+    return this->super::load_buffer_and_write(towrite, buf, total_written, needs);
   }
 
   bool trace = getSSLTrace();
   Debug("ssl", "trace=%s", trace ? "TRUE" : "FALSE");
 
   do {
-    // check if we have done this block
-    l = b->read_avail();
-    l -= offset;
-    if (l <= 0) {
-      offset = -l;
-      b = b->next.get();
-      continue;
-    }
+    // What is remaining left in the next block?
+    l = buf.reader()->block_read_avail();
+    current_block = buf.reader()->start();
+
     // check if to amount to write exceeds that in this buffer
     int64_t wavail = towrite - total_written;
 
@@ -699,7 +682,6 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, i
     // TS-2365: If the SSL max record size is set and we have
     // more data than that, break this into smaller write
     // operations.
-    int64_t orig_l = l;
     if (SSLConfigParams::ssl_maxrecord > 0 && l > SSLConfigParams::ssl_maxrecord) {
       l = SSLConfigParams::ssl_maxrecord;
     } else if (SSLConfigParams::ssl_maxrecord == -1) {
@@ -719,50 +701,39 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, i
       break;
     }
 
-    wattempted = l;
-    total_written += l;
+    try_to_write = l;
+    num_really_written = 0;
     Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite, before SSLWriteBuffer, l=%" PRId64 ", towrite=%" PRId64 ", b=%p", l,
-          towrite, b);
-    err = SSLWriteBuffer(ssl, b->start() + offset, l, r);
+          towrite, current_block);
+    err = SSLWriteBuffer(ssl, current_block, l, num_really_written);
 
     if (!origin_trace) {
-      TraceOut((0 < r && trace), get_remote_addr(), get_remote_port(), "WIRE TRACE\tbytes=%d\n%.*s", (int)r, (int)r,
-               b->start() + offset);
+      TraceOut((0 < num_really_written && trace), get_remote_addr(), get_remote_port(), "WIRE TRACE\tbytes=%d\n%.*s",
+               (int)num_really_written, (int)num_really_written, current_block);
     } else {
       char origin_trace_ip[INET6_ADDRSTRLEN];
       ats_ip_ntop(origin_trace_addr, origin_trace_ip, sizeof(origin_trace_ip));
-      TraceOut((0 < r && trace), get_remote_addr(), get_remote_port(), "CLIENT %s:%d\ttbytes=%d\n%.*s", origin_trace_ip,
-               origin_trace_port, (int)r, (int)r, b->start() + offset);
+      TraceOut((0 < num_really_written && trace), get_remote_addr(), get_remote_port(), "CLIENT %s:%d\ttbytes=%d\n%.*s",
+               origin_trace_ip, origin_trace_port, (int)num_really_written, (int)num_really_written, current_block);
     }
 
-    if (r == l) {
-      wattempted = total_written;
-    }
-    if (l == orig_l) {
-      // on to the next block
-      offset = 0;
-      b = b->next.get();
-    } else {
-      offset += l;
+    // We wrote all that we thought we should
+    if (num_really_written > 0) {
+      total_written += num_really_written;
+      buf.reader()->consume(num_really_written);
     }
 
-    Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite,Number of bytes written=%" PRId64 " , total=%" PRId64 "", r,
-          total_written);
+    Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite,Number of bytes written=%" PRId64 " , total=%" PRId64 "",
+          num_really_written, total_written);
     NET_INCREMENT_DYN_STAT(net_calls_to_write_stat);
-  } while (r == l && total_written < towrite && b);
+  } while (num_really_written == try_to_write && total_written < towrite);
 
-  if (r > 0) {
+  if (total_written > 0) {
     sslLastWriteTime = now;
     sslTotalBytesSent += total_written;
-    if (total_written != wattempted) {
-      Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite, wrote some bytes, but not all requested.");
-      // I'm not sure how this could happen. We should have tried and hit an EAGAIN.
-      needs |= EVENTIO_WRITE;
-      return (r);
-    } else {
-      Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite, write successful.");
-      return (total_written);
-    }
+  }
+  if (num_really_written > 0) {
+    needs |= EVENTIO_WRITE;
   } else {
     switch (err) {
     case SSL_ERROR_NONE:
@@ -770,7 +741,7 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, i
       break;
     case SSL_ERROR_WANT_READ:
       needs |= EVENTIO_READ;
-      r = -EAGAIN;
+      num_really_written = -EAGAIN;
       SSL_INCREMENT_DYN_STAT(ssl_error_want_read);
       Debug("ssl.error", "SSL_write-SSL_ERROR_WANT_READ");
       break;
@@ -784,20 +755,20 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, i
       }
 
       needs |= EVENTIO_WRITE;
-      r = -EAGAIN;
+      num_really_written = -EAGAIN;
       Debug("ssl.error", "SSL_write-SSL_ERROR_WANT_WRITE");
       break;
     }
     case SSL_ERROR_SYSCALL:
       TraceOut(trace, get_remote_addr(), get_remote_port(), "Syscall Error: %s", strerror(errno));
-      r = -errno;
+      num_really_written = -errno;
       SSL_INCREMENT_DYN_STAT(ssl_error_syscall);
       Debug("ssl.error", "SSL_write-SSL_ERROR_SYSCALL");
       break;
     // end of stream
     case SSL_ERROR_ZERO_RETURN:
       TraceOut(trace, get_remote_addr(), get_remote_port(), "SSL Error: zero return");
-      r = -errno;
+      num_really_written = -errno;
       SSL_INCREMENT_DYN_STAT(ssl_error_zero_return);
       Debug("ssl.error", "SSL_write-SSL_ERROR_ZERO_RETURN");
       break;
@@ -808,12 +779,12 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, i
       ERR_error_string_n(e, buf, sizeof(buf));
       TraceIn(trace, get_remote_addr(), get_remote_port(), "SSL Error: sslErr=%d, ERR_get_error=%ld (%s) errno=%d", err, e, buf,
               errno);
-      r = -errno;
+      num_really_written = -errno;
       SSL_CLR_ERR_INCR_DYN_STAT(this, ssl_error_ssl, "SSL_write-SSL_ERROR_SSL errno=%d", errno);
     } break;
     }
-    return (r);
   }
+  return num_really_written;
 }
 
 SSLNetVConnection::SSLNetVConnection()
diff --git a/iocore/net/UnixNetVConnection.cc b/iocore/net/UnixNetVConnection.cc
index 2a903cf..b52985c 100644
--- a/iocore/net/UnixNetVConnection.cc
+++ b/iocore/net/UnixNetVConnection.cc
@@ -510,17 +510,15 @@ write_to_net_io(NetHandler *nh, UnixNetVConnection *vc, EThread *thread)
     return;
   }
 
-  int64_t total_written = 0, wattempted = 0;
   int needs = 0;
-  int64_t r = vc->load_buffer_and_write(towrite, wattempted, total_written, buf, needs);
+  int64_t total_written = 0;
+  int64_t r = vc->load_buffer_and_write(towrite, buf, total_written, needs);
 
-  // if we have already moved some bytes successfully, summarize in r
-  if (total_written != wattempted) {
-    if (r <= 0)
-      r = total_written - wattempted;
-    else
-      r = total_written - wattempted + r;
+  if (total_written > 0) {
+    NET_SUM_DYN_STAT(net_write_bytes_stat, total_written);
+    s->vio.ndone += total_written;
   }
+
   // check for errors
   if (r <= 0) { // if the socket was not ready,add to WaitList
     if (r == -EAGAIN || r == -ENOTCONN) {
@@ -543,19 +541,11 @@ write_to_net_io(NetHandler *nh, UnixNetVConnection *vc, EThread *thread)
       return;
     }
     vc->write.triggered = 0;
-    write_signal_error(nh, vc, (int)-r);
+    write_signal_error(nh, vc, (int)-total_written);
     return;
-  } else {
+  } else {                                        // Wrote data.  Finished without error
     int wbe_event = vc->write_buffer_empty_event; // save so we can clear if needed.
 
-    NET_SUM_DYN_STAT(net_write_bytes_stat, r);
-
-    // Remove data from the buffer and signal continuation.
-    ink_assert(buf.reader()->read_avail() >= r);
-    buf.reader()->consume(r);
-    ink_assert(buf.reader()->read_avail() >= 0);
-    s->vio.ndone += r;
-
     // If the empty write buffer trap is set, clear it.
     if (!(buf.reader()->is_read_avail_more_than(0)))
       vc->write_buffer_empty_event = 0;
@@ -946,28 +936,22 @@ UnixNetVConnection::net_read_io(NetHandler *nh, EThread *lthread)
 // (SSL read does not support overlapped i/o)
 // without duplicating all the code in write_to_net.
 int64_t
-UnixNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, int64_t &total_written, MIOBufferAccessor &buf,
-                                          int &needs)
+UnixNetVConnection::load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs)
 {
   int64_t r = 0;
-
-  // XXX Rather than dealing with the block directly, we should use the IOBufferReader API.
-  int64_t offset = buf.reader()->start_offset;
-  IOBufferBlock *b = buf.reader()->block.get();
+  int64_t try_to_write = 0;
+  IOBufferReader *tmp_reader = buf.reader()->clone();
 
   do {
     IOVec tiovec[NET_MAX_IOV];
     unsigned niov = 0;
-    int64_t total_written_last = total_written;
-    while (b && niov < NET_MAX_IOV) {
+    try_to_write = 0;
+    while (niov < NET_MAX_IOV) {
       // check if we have done this block
-      int64_t l = b->read_avail();
-      l -= offset;
-      if (l <= 0) {
-        offset = -l;
-        b = b->next.get();
-        continue;
-      }
+      int64_t l = tmp_reader->block_read_avail();
+      if (l <= 0)
+        break;
+      char *current_block = tmp_reader->start();
 
       // check if to amount to write exceeds that in this buffer
       int64_t wavail = towrite - total_written;
@@ -979,18 +963,14 @@ UnixNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted,
         break;
       }
 
-      total_written += l;
       // build an iov entry
       tiovec[niov].iov_len = l;
-      tiovec[niov].iov_base = b->start() + offset;
+      try_to_write += l;
+      tiovec[niov].iov_base = current_block;
       niov++;
-      // on to the next block
-      offset = 0;
-      b = b->next.get();
+      tmp_reader->consume(l);
     }
 
-    wattempted = total_written - total_written_last;
-
     ink_assert(niov > 0);
     ink_assert(niov <= countof(tiovec));
     r = socketManager.writev(con.fd, &tiovec[0], niov);
@@ -1011,14 +991,20 @@ UnixNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted,
                  strerror(errno));
       }
     }
+    if (r > 0) {
+      buf.reader()->consume(r);
+    }
+    total_written += r;
 
     ProxyMutex *mutex = thread->mutex.get();
     NET_INCREMENT_DYN_STAT(net_calls_to_write_stat);
-  } while (r == wattempted && total_written < towrite);
+  } while (r == try_to_write && total_written < towrite);
+
+  tmp_reader->dealloc();
 
   needs |= EVENTIO_WRITE;
 
-  return (r);
+  return r;
 }
 
 void

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].