Advertisement
Guest User

Untitled

a guest
May 30th, 2015
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.99 KB | None | 0 0
  1.  
  2. bool TrySend(connection *const c)
  3. {
  4. iovec iov[128];
  5. int fd = c->fd;
  6.  
  7. sendv:
  8. auto it = c->respTail;
  9. int32_t r;
  10. bool haveCork;
  11.  
  12. // If we have multiple requests(therefore multiple writev() calls are likely required)
  13. // and/or have say data to stream using sendfile(), then we need a cork
  14. // We don't use sendfile(), but that's how it'd work. Also, if we did need sendfile()
  15. // c could have been == nullptr.
  16.  
  17. if (!it->next) // Fast path: single request(no pipelining)
  18. {
  19. r = writev(fd, it->iov + it->iovCur, it->iovCnt - it->iovCur);
  20. haveCork = false;
  21. }
  22. else
  23. {
  24. // Need to reduce writev() calls to absolute minimum
  25. uint8_t i{0};
  26. auto cur= it->iovCur;
  27.  
  28.  
  29. if (!SwitchNetwork::SetTCPCork(fd, 1))
  30. haveCork = true;
  31.  
  32. do
  33. {
  34. if (cur >= 127)
  35. {
  36. // Patch, starting from it->iovCnt - 127. Reset it afterwards
  37. const auto cnt = it->iovCnt;
  38.  
  39. for (decltype(it->iovCnt) i = it->iovCur - 127; i != cnt; ++i)
  40. {
  41. auto &v = it->iov[i];
  42.  
  43. if (v.iov_len >= (1U<<30))
  44. {
  45. v.iov_len -= 1U<<30;
  46. v.iov_base = it->content->At((uint32_t)(uintptr_t)v.iov_base);
  47. }
  48. }
  49. cur = it->iovCur = 0;
  50. }
  51.  
  52. const auto n = Min<uint8_t>(sizeof_array(iov) - i, it->iovCnt - cur);
  53.  
  54. (void)memcpy(iov + i, it->iov + it->iovCur, n * sizeof(iovec));
  55. i+=n;
  56. cur = 0;
  57. } while (i != sizeof_array(iov) && (it = it->next));
  58.  
  59.  
  60. // Timings:
  61. // 5%: 4
  62. // 10%: 5
  63. // 25%: 5
  64. // 50%: 7
  65. // 75%: 8
  66. // 90%: 13
  67. // 95%: 19
  68. // 99%: 31
  69. r = writev(c->fd, iov, i);
  70. }
  71.  
  72. if (unlikely(r == -1))
  73. {
  74. const auto err = errno;
  75.  
  76. if (unlikely(haveCork))
  77. SwitchNetwork::SetTCPCork(fd, 0);
  78.  
  79. if (err == EAGAIN)
  80. {
  81. if (!c->needIoAvail)
  82. {
  83. c->needIoAvail = true;
  84. (void)poller.SetDataAndEvents(c->fd, c, POLLIN|POLLOUT);
  85. }
  86. }
  87. else if (err != EINTR)
  88. {
  89. Shutdown(c, __LINE__);
  90. return false;
  91. }
  92.  
  93. return true;
  94. }
  95.  
  96. for (it = c->respTail; r >= it->iov[it->iovCur].iov_len; )
  97. {
  98. r-=it->iov[it->iovCur].iov_len;
  99. if (++(it->iovCur) == it->iovCnt)
  100. {
  101. auto *const n = it->next;
  102.  
  103. PutResponse(it);
  104. it = c->respTail = n;
  105. if (!it)
  106. {
  107. if (unlikely(haveCork))
  108. SwitchNetwork::SetTCPCork(fd, 0);
  109.  
  110. if (!c->keepAlive)
  111. {
  112. Shutdown(c, __LINE__);
  113. return false;
  114. }
  115. else
  116. {
  117. c->respHead = nullptr;
  118. if (c->needIoAvail)
  119. {
  120. (void)poller.SetDataAndEvents(c->fd, c, POLLIN);
  121. c->needIoAvail = false;
  122. }
  123. return true;
  124. }
  125. }
  126. }
  127. }
  128.  
  129. auto &v = it->iov[it->iovCur];
  130.  
  131. v.iov_len-=r;
  132. v.iov_base = (char *)v.iov_base + r;
  133.  
  134. // We didn't get to send all the content out - because we are limited in terms of sizeof_array(iov)
  135. // so we need another short at it
  136. // Ideally, we 'd have a large enough iov[] anyway.
  137. //
  138. // However, this could have been because there is no more space left in the socket send buf
  139. // so it only accepted as much as it could. In this case, another call to writev() will
  140. // return EAGAIN.
  141. //
  142. // We could probably better deal with this (enter needIoAvail mode if not all scheduled
  143. // content was dispatched, instead of retrying).
  144. goto sendv;
  145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement