| 1780 | static const size_t DATA_LIST_MAX = 256; |
| 1781 | |
| 1782 | void* Socket::KeepWrite(void* void_arg) { |
| 1783 | g_vars->nkeepwrite << 1; |
| 1784 | WriteRequest* req = static_cast<WriteRequest*>(void_arg); |
| 1785 | SocketUniquePtr s(req->get_socket()); |
| 1786 | |
| 1787 | // When error occurs, spin until there's no more requests instead of |
| 1788 | // returning directly otherwise _write_head is permantly non-NULL which |
| 1789 | // makes later Write() abnormal. |
| 1790 | WriteRequest* cur_tail = NULL; |
| 1791 | do { |
| 1792 | // req was written, skip it. |
| 1793 | bool need_shutdown = false; |
| 1794 | if (req->next != NULL && req->data.empty()) { |
| 1795 | WriteRequest* const saved_req = req; |
| 1796 | need_shutdown = req->need_shutdown_write(); |
| 1797 | req = req->next; |
| 1798 | s->ReturnSuccessfulWriteRequest(saved_req); |
| 1799 | } |
| 1800 | if (need_shutdown) { |
| 1801 | LOG(WARNING) << "Shutdown write of " << *s; |
| 1802 | break; |
| 1803 | } |
| 1804 | |
| 1805 | const ssize_t nw = s->DoWrite(req); |
| 1806 | if (nw < 0) { |
| 1807 | if (errno != EAGAIN && errno != EOVERCROWDED) { |
| 1808 | const int saved_errno = errno; |
| 1809 | PLOG(WARNING) << "Fail to keep-write into " << *s; |
| 1810 | s->SetFailed(saved_errno, "Fail to keep-write into %s: %s", |
| 1811 | s->description().c_str(), berror(saved_errno)); |
| 1812 | break; |
| 1813 | } |
| 1814 | } else { |
| 1815 | s->AddOutputBytes(nw); |
| 1816 | } |
| 1817 | // Release WriteRequest until non-empty data, last request or shutdown write. |
| 1818 | while (req->next != NULL && req->data.empty()) { |
| 1819 | WriteRequest* const saved_req = req; |
| 1820 | need_shutdown = req->need_shutdown_write(); |
| 1821 | req = req->next; |
| 1822 | s->ReturnSuccessfulWriteRequest(saved_req); |
| 1823 | if (need_shutdown) { |
| 1824 | break; |
| 1825 | } |
| 1826 | } |
| 1827 | if (need_shutdown) { |
| 1828 | LOG(WARNING) << "Shutdown write of " << *s; |
| 1829 | break; |
| 1830 | } |
| 1831 | // TODO(gejun): wait for epollout when we actually have written |
| 1832 | // all the data. This weird heuristic reduces 30us delay... |
| 1833 | // Update(12/22/2015): seem not working. better switch to correct code. |
| 1834 | // Update(1/8/2016, r31823): Still working. |
| 1835 | // Update(8/15/2017): Not working, performance downgraded. |
| 1836 | //if (nw <= 0 || req->data.empty()/*note*/) { |
| 1837 | if (nw <= 0) { |
| 1838 | // NOTE: Waiting epollout within timeout is a must to force |
| 1839 | // KeepWrite to check and setup pending WriteRequests periodically, |
nothing calls this directly
no test coverage detected