]> git.ipfire.org Git - thirdparty/squid.git/blame - src/comm/Write.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / comm / Write.cc
CommitLineData
bbc27441 1/*
77b1029d 2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
bbc27441
AJ
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
f7f3304a 9#include "squid.h"
b27668ec 10#include "cbdata.h"
b0388924 11#include "comm/Connection.h"
ec41b64c 12#include "comm/IoCallback.h"
b27668ec 13#include "comm/Loops.h"
ec41b64c 14#include "comm/Write.h"
c4ad1349 15#include "fd.h"
ec41b64c 16#include "fde.h"
582c2af2 17#include "globals.h"
ec41b64c 18#include "MemBuf.h"
582c2af2 19#include "profiler/Profiler.h"
21d845b1
FC
20#include "SquidTime.h"
21#include "StatCounters.h"
21d845b1
FC
22#if USE_DELAY_POOLS
23#include "ClientInfo.h"
24#endif
074d6a40
AJ
25
26#include <cerrno>
ec41b64c
AJ
27
28void
b0388924 29Comm::Write(const Comm::ConnectionPointer &conn, MemBuf *mb, AsyncCall::Pointer &callback)
ec41b64c 30{
b0388924 31 Comm::Write(conn, mb->buf, mb->size, callback, mb->freeFunc());
ec41b64c
AJ
32}
33
34void
b0388924 35Comm::Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE * free_func)
ec41b64c 36{
b0388924 37 debugs(5, 5, HERE << conn << ": sz " << size << ": asynCall " << callback);
ec41b64c
AJ
38
39 /* Make sure we are open, not closing, and not writing */
b0388924
AJ
40 assert(fd_table[conn->fd].flags.open);
41 assert(!fd_table[conn->fd].closing());
42 Comm::IoCallback *ccb = COMMIO_FD_WRITECB(conn->fd);
ec41b64c
AJ
43 assert(!ccb->active());
44
b0388924
AJ
45 fd_table[conn->fd].writeStart = squid_curtime;
46 ccb->conn = conn;
ec41b64c
AJ
47 /* Queue the write */
48 ccb->setCallback(IOCB_WRITE, callback, (char *)buf, free_func, size);
49 ccb->selectOrQueueWrite();
50}
51
52/** Write to FD.
53 * This function is used by the lowest level of IO loop which only has access to FD numbers.
b0388924 54 * We have to use the comm iocb_table to map FD numbers to waiting data and Comm::Connections.
ec41b64c
AJ
55 * Once the write has been concluded we schedule the waiting call with success/fail results.
56 */
57void
58Comm::HandleWrite(int fd, void *data)
59{
60 Comm::IoCallback *state = static_cast<Comm::IoCallback *>(data);
61 int len = 0;
62 int nleft;
63
b27668ec
EB
64 assert(state->conn != NULL);
65 assert(state->conn->fd == fd);
ec41b64c
AJ
66
67 PROF_start(commHandleWrite);
b0388924 68 debugs(5, 5, HERE << state->conn << ": off " <<
ec41b64c
AJ
69 (long int) state->offset << ", sz " << (long int) state->size << ".");
70
71 nleft = state->size - state->offset;
72
9a0a18de 73#if USE_DELAY_POOLS
b27668ec
EB
74 BandwidthBucket *bucket = BandwidthBucket::SelectBucket(&fd_table[fd]);
75 if (bucket) {
76 assert(bucket->selectWaiting);
77 bucket->selectWaiting = false;
78 if (nleft > 0 && !bucket->applyQuota(nleft, state)) {
79 PROF_stop(commHandleWrite);
80 return;
ec41b64c
AJ
81 }
82 }
9a0a18de 83#endif /* USE_DELAY_POOLS */
ec41b64c
AJ
84
85 /* actually WRITE data */
5dc67d58 86 int xerrno = errno = 0;
ec41b64c 87 len = FD_WRITE_METHOD(fd, state->buf + state->offset, nleft);
5dc67d58 88 xerrno = errno;
ec41b64c
AJ
89 debugs(5, 5, HERE << "write() returns " << len);
90
9a0a18de 91#if USE_DELAY_POOLS
b27668ec
EB
92 if (bucket) {
93 /* we wrote data - drain them from bucket */
94 bucket->reduceBucket(len);
ec41b64c 95 }
9a0a18de 96#endif /* USE_DELAY_POOLS */
ec41b64c
AJ
97
98 fd_bytes(fd, len, FD_WRITE);
e4f1fdae 99 ++statCounter.syscalls.sock.writes;
ec41b64c
AJ
100 // After each successful partial write,
101 // reset fde::writeStart to the current time.
102 fd_table[fd].writeStart = squid_curtime;
103
104 if (len == 0) {
105 /* Note we even call write if nleft == 0 */
106 /* We're done */
107 if (nleft != 0)
108 debugs(5, DBG_IMPORTANT, "FD " << fd << " write failure: connection closed with " << nleft << " bytes remaining.");
109
5dc67d58 110 state->finish(nleft ? Comm::COMM_ERROR : Comm::OK, 0);
ec41b64c
AJ
111 } else if (len < 0) {
112 /* An error */
113 if (fd_table[fd].flags.socket_eof) {
5dc67d58
AD
114 debugs(50, 2, "FD " << fd << " write failure: " << xstrerr(xerrno) << ".");
115 state->finish(nleft ? Comm::COMM_ERROR : Comm::OK, xerrno);
116 } else if (ignoreErrno(xerrno)) {
117 debugs(50, 9, "FD " << fd << " write failure: " << xstrerr(xerrno) << ".");
ec41b64c
AJ
118 state->selectOrQueueWrite();
119 } else {
5dc67d58
AD
120 debugs(50, 2, "FD " << fd << " write failure: " << xstrerr(xerrno) << ".");
121 state->finish(nleft ? Comm::COMM_ERROR : Comm::OK, xerrno);
ec41b64c
AJ
122 }
123 } else {
124 /* A successful write, continue */
125 state->offset += len;
126
127 if (state->offset < state->size) {
128 /* Not done, reinstall the write handler and write some more */
129 state->selectOrQueueWrite();
130 } else {
5dc67d58 131 state->finish(nleft ? Comm::OK : Comm::COMM_ERROR, 0);
ec41b64c
AJ
132 }
133 }
134
135 PROF_stop(commHandleWrite);
136}
f53969cc 137