Read.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 The Squid Software Foundation and contributors
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 
9 /* DEBUG: section 05 Socket Functions */
10 
11 #include "squid.h"
12 #include "comm.h"
13 #include "comm/IoCallback.h"
14 #include "comm/Loops.h"
15 #include "comm/Read.h"
16 #include "comm_internal.h"
17 #include "CommCalls.h"
18 #include "Debug.h"
19 #include "fd.h"
20 #include "fde.h"
21 #include "sbuf/SBuf.h"
22 #include "SquidConfig.h"
23 #include "StatCounters.h"
24 
25 // Does comm check this fd for read readiness?
26 // Note that when comm is not monitoring, there can be a pending callback
27 // call, which may resume comm monitoring once fired.
28 bool
30 {
31  assert(isOpen(fd) && COMMIO_FD_READCB(fd) != NULL);
32  // Being active is usually the same as monitoring because we always
33  // start monitoring the FD when we configure Comm::IoCallback for I/O
34  // and we usually configure Comm::IoCallback for I/O when we starting
35  // monitoring a FD for reading.
36  return COMMIO_FD_READCB(fd)->active();
37 }
38 
39 void
41 {
42  // TODO: move comm_read_base() internals into here
43  // when comm_read() char* API is no longer needed
44  comm_read_base(conn, NULL, 0, callback);
45 }
46 
55 void
57 {
58  debugs(5, 5, "comm_read, queueing read for " << conn << "; asynCall " << callback);
59 
60  /* Make sure we are open and not closing */
61  assert(Comm::IsConnOpen(conn));
62  assert(!fd_table[conn->fd].closing());
63  Comm::IoCallback *ccb = COMMIO_FD_READCB(conn->fd);
64 
65  // Make sure we are either not reading or just passively monitoring.
66  // Active/passive conflicts are OK and simply cancel passive monitoring.
67  if (ccb->active()) {
68  // if the assertion below fails, we have an active comm_read conflict
69  assert(fd_table[conn->fd].halfClosedReader != NULL);
71  assert(!ccb->active());
72  }
73  ccb->conn = conn;
74 
75  /* Queue the read */
76  ccb->setCallback(Comm::IOCB_READ, callback, (char *)buf, NULL, size);
78 }
79 
82 {
83  /* Attempt a read */
84  ++ statCounter.syscalls.sock.reads;
86  if (params.size > 0 && params.size < sz)
87  sz = params.size;
88  char *inbuf = buf.rawAppendStart(sz);
89  errno = 0;
90  const int retval = FD_READ_METHOD(params.conn->fd, inbuf, sz);
91  params.xerrno = errno;
92 
93  debugs(5, 3, params.conn << ", size " << sz << ", retval " << retval << ", errno " << params.xerrno);
94 
95  if (retval > 0) { // data read most common case
96  buf.rawAppendFinish(inbuf, retval);
97  fd_bytes(params.conn->fd, retval, FD_READ);
98  params.flag = Comm::OK;
99  params.size = retval;
100 
101  } else if (retval == 0) { // remote closure (somewhat less) common
102  // Note - read 0 == socket EOF, which is a valid read.
103  params.flag = Comm::ENDFILE;
104 
105  } else if (retval < 0) { // connection errors are worst-case
106  debugs(5, 3, params.conn << " Comm::COMM_ERROR: " << xstrerr(params.xerrno));
107  if (ignoreErrno(params.xerrno))
108  params.flag = Comm::INPROGRESS;
109  else
110  params.flag = Comm::COMM_ERROR;
111  }
112 
113  return params.flag;
114 }
115 
125 void
126 Comm::HandleRead(int fd, void *data)
127 {
128  Comm::IoCallback *ccb = (Comm::IoCallback *) data;
129 
130  assert(data == COMMIO_FD_READCB(fd));
131  assert(ccb->active());
132 
133  // Without a buffer, just call back.
134  // The callee may ReadMore() to get the data.
135  if (!ccb->buf) {
136  ccb->finish(Comm::OK, 0);
137  return;
138  }
139 
140  /* For legacy callers : Attempt a read */
141  // Keep in sync with Comm::ReadNow()!
142  ++ statCounter.syscalls.sock.reads;
143  int xerrno = errno = 0;
144  int retval = FD_READ_METHOD(fd, ccb->buf, ccb->size);
145  xerrno = errno;
146  debugs(5, 3, "FD " << fd << ", size " << ccb->size << ", retval " << retval << ", errno " << xerrno);
147 
148  /* See if we read anything */
149  /* Note - read 0 == socket EOF, which is a valid read */
150  if (retval >= 0) {
151  fd_bytes(fd, retval, FD_READ);
152  ccb->offset = retval;
153  ccb->finish(Comm::OK, 0);
154  return;
155  } else if (retval < 0 && !ignoreErrno(xerrno)) {
156  debugs(5, 3, "comm_read_try: scheduling Comm::COMM_ERROR");
157  ccb->offset = 0;
158  ccb->finish(Comm::COMM_ERROR, xerrno);
159  return;
160  };
161 
162  /* Nope, register for some more IO */
164 }
165 
178 void
180 {
181  if (!isOpen(fd)) {
182  debugs(5, 4, "fails: FD " << fd << " closed");
183  return;
184  }
185 
187  // TODO: is "active" == "monitors FD"?
188  if (!cb->active()) {
189  debugs(5, 4, "fails: FD " << fd << " inactive");
190  return;
191  }
192 
194  Call *call = dynamic_cast<Call*>(cb->callback.getRaw());
195  if (!call) {
196  debugs(5, 4, "fails: FD " << fd << " lacks callback");
197  return;
198  }
199 
200  call->cancel("old comm_read_cancel");
201 
202  typedef CommIoCbParams Params;
203  const Params &params = GetCommParams<Params>(cb->callback);
204 
205  /* Ok, we can be reasonably sure we won't lose any data here! */
206  assert(call->dialer.handler == callback);
207  assert(params.data == data);
208 
209  /* Delete the callback */
210  cb->cancel("old comm_read_cancel");
211 
212  /* And the IO event */
214 }
215 
216 void
218 {
219  callback->cancel("comm_read_cancel");
220 
221  if (!isOpen(fd)) {
222  debugs(5, 4, "fails: FD " << fd << " closed");
223  return;
224  }
225 
227 
228  if (!cb->active()) {
229  debugs(5, 4, "fails: FD " << fd << " inactive");
230  return;
231  }
232 
233  AsyncCall::Pointer call = cb->callback;
234 
235  /* Ok, we can be reasonably sure we won't lose any data here! */
236  assert(call == callback);
237 
238  /* Delete the callback */
239  cb->cancel("comm_read_cancel");
240 
241  /* And the IO event */
243 }
244 
245 time_t
246 Comm::MortalReadTimeout(const time_t startTime, const time_t lifetimeLimit)
247 {
248  if (lifetimeLimit > 0) {
249  const time_t timeUsed = (squid_curtime > startTime) ? (squid_curtime - startTime) : 0;
250  const time_t timeLeft = (lifetimeLimit > timeUsed) ? (lifetimeLimit - timeUsed) : 0;
251  return min(::Config.Timeout.read, timeLeft);
252  } else
254 }
255 
#define fd_table
Definition: fde.h:174
#define COMMIO_FD_READCB(fd)
Definition: IoCallback.h:78
#define COMM_SELECT_READ
Definition: defines.h:36
StatCounters statCounter
Definition: StatCounters.cc:12
#define assert(EX)
Definition: assert.h:17
bool isOpen(const int fd)
Definition: comm.cc:86
void const char HLPCB * callback
Definition: stub_helper.cc:16
PF HandleRead
callback handler to process an FD which is available for reading
Definition: Read.cc:126
void finish(Comm::Flag code, int xerrn)
finish the IO operation imediately and schedule the callback with the current state.
Definition: IoCallback.cc:110
Comm::Flag ReadNow(CommIoCbParams &params, SBuf &buf)
Definition: Read.cc:81
int FD_READ_METHOD(int fd, char *buf, int len)
Definition: fde.h:179
Definition: SBuf.h:86
struct StatCounters::@137::@141 sock
Definition: Flag.h:16
AsyncCall::Pointer callback
Definition: IoCallback.h:34
bool cancel(const char *reason)
Definition: AsyncCall.cc:52
int conn
the current server connection FD
Definition: Transport.cc:26
Definition: enums.h:23
time_t squid_curtime
Definition: stub_time.cc:17
void commStopHalfClosedMonitor(int fd)
stop waiting for possibly half-closed connection to close
Definition: comm.cc:1662
void Read(const Comm::ConnectionPointer &conn, AsyncCall::Pointer &callback)
Definition: Read.cc:40
void rawAppendFinish(const char *start, size_type actualSize)
Definition: SBuf.cc:144
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:256
Comm::ConnectionPointer conn
Definition: CommCalls.h:85
const char * xstrerr(int error)
Definition: xstrerror.cc:83
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:24
void const char HLPCB void * data
Definition: stub_helper.cc:16
char * rawAppendStart(size_type anticipatedSize)
Definition: SBuf.cc:136
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
void cancel(const char *reason)
Actively cancel the given callback.
Definition: IoCallback.cc:82
void SetSelect(int, unsigned int, PF *, void *, time_t)
Mark an FD to be watched for its IO status.
Definition: ModDevPoll.cc:225
void const char int sz
Definition: stub_cbdata.cc:16
int xerrno
The last errno to occur. non-zero if flag is Comm::COMM_ERROR.
Definition: CommCalls.h:88
bool MonitorsRead(int fd)
whether the FD socket is being monitored for read
Definition: Read.cc:29
void const char * buf
Definition: stub_helper.cc:16
void IOCB(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int xerrno, void *data)
Definition: CommCalls.h:36
Flag
Definition: Flag.h:15
void comm_read_cancel(int fd, IOCB *callback, void *data)
Definition: Read.cc:179
int ignoreErrno(int ierrno)
Definition: comm.cc:1477
time_t MortalReadTimeout(const time_t startTime, const time_t lifetimeLimit)
maximum read delay for readers with limited lifetime
Definition: Read.cc:246
Comm::Flag flag
comm layer result status.
Definition: CommCalls.h:87
C * getRaw() const
Definition: RefCount.h:74
struct SquidConfig::@98 Timeout
void comm_read_base(const Comm::ConnectionPointer &conn, char *buf, int size, AsyncCall::Pointer &callback)
Definition: Read.cc:56
void ReadCancel(int fd, AsyncCall::Pointer &callback)
Cancel the read pending on FD. No action if none pending.
Definition: Read.cc:217
bool active() const
Definition: IoCallback.h:45
MemBlob::size_type size_type
Definition: SBuf.h:89
class SquidConfig Config
Definition: SquidConfig.cc:12
#define NULL
Definition: types.h:166
Details about a particular Comm IO callback event.
Definition: IoCallback.h:29
int size
Definition: ModDevPoll.cc:77
A const & min(A const &lhs, A const &rhs)
time_t read
Definition: SquidConfig.h:106
struct StatCounters::@137 syscalls
size_type spaceSize() const
Definition: SBuf.h:382

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors