Read.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 "StatCounters.h"
23 
24 // Does comm check this fd for read readiness?
25 // Note that when comm is not monitoring, there can be a pending callback
26 // call, which may resume comm monitoring once fired.
27 bool
29 {
30  assert(isOpen(fd) && COMMIO_FD_READCB(fd) != NULL);
31  // Being active is usually the same as monitoring because we always
32  // start monitoring the FD when we configure Comm::IoCallback for I/O
33  // and we usually configure Comm::IoCallback for I/O when we starting
34  // monitoring a FD for reading.
35  return COMMIO_FD_READCB(fd)->active();
36 }
37 
38 void
40 {
41  // TODO: move comm_read_base() internals into here
42  // when comm_read() char* API is no longer needed
43  comm_read_base(conn, NULL, 0, callback);
44 }
45 
54 void
56 {
57  debugs(5, 5, "comm_read, queueing read for " << conn << "; asynCall " << callback);
58 
59  /* Make sure we are open and not closing */
60  assert(Comm::IsConnOpen(conn));
61  assert(!fd_table[conn->fd].closing());
62  Comm::IoCallback *ccb = COMMIO_FD_READCB(conn->fd);
63 
64  // Make sure we are either not reading or just passively monitoring.
65  // Active/passive conflicts are OK and simply cancel passive monitoring.
66  if (ccb->active()) {
67  // if the assertion below fails, we have an active comm_read conflict
68  assert(fd_table[conn->fd].halfClosedReader != NULL);
70  assert(!ccb->active());
71  }
72  ccb->conn = conn;
73 
74  /* Queue the read */
75  ccb->setCallback(Comm::IOCB_READ, callback, (char *)buf, NULL, size);
77 }
78 
81 {
82  /* Attempt a read */
83  ++ statCounter.syscalls.sock.reads;
84  SBuf::size_type sz = buf.spaceSize();
85  if (params.size > 0 && params.size < sz)
86  sz = params.size;
87  char *inbuf = buf.rawAppendStart(sz);
88  errno = 0;
89  const int retval = FD_READ_METHOD(params.conn->fd, inbuf, sz);
90  params.xerrno = errno;
91 
92  debugs(5, 3, params.conn << ", size " << sz << ", retval " << retval << ", errno " << params.xerrno);
93 
94  if (retval > 0) { // data read most common case
95  buf.rawAppendFinish(inbuf, retval);
96  fd_bytes(params.conn->fd, retval, FD_READ);
97  params.flag = Comm::OK;
98  params.size = retval;
99 
100  } else if (retval == 0) { // remote closure (somewhat less) common
101  // Note - read 0 == socket EOF, which is a valid read.
102  params.flag = Comm::ENDFILE;
103 
104  } else if (retval < 0) { // connection errors are worst-case
105  debugs(5, 3, params.conn << " Comm::COMM_ERROR: " << xstrerr(params.xerrno));
106  if (ignoreErrno(params.xerrno))
107  params.flag = Comm::INPROGRESS;
108  else
109  params.flag = Comm::COMM_ERROR;
110  }
111 
112  return params.flag;
113 }
114 
124 void
125 Comm::HandleRead(int fd, void *data)
126 {
127  Comm::IoCallback *ccb = (Comm::IoCallback *) data;
128 
129  assert(data == COMMIO_FD_READCB(fd));
130  assert(ccb->active());
131 
132  // Without a buffer, just call back.
133  // The callee may ReadMore() to get the data.
134  if (!ccb->buf) {
135  ccb->finish(Comm::OK, 0);
136  return;
137  }
138 
139  /* For legacy callers : Attempt a read */
140  // Keep in sync with Comm::ReadNow()!
141  ++ statCounter.syscalls.sock.reads;
142  int xerrno = errno = 0;
143  int retval = FD_READ_METHOD(fd, ccb->buf, ccb->size);
144  xerrno = errno;
145  debugs(5, 3, "FD " << fd << ", size " << ccb->size << ", retval " << retval << ", errno " << xerrno);
146 
147  /* See if we read anything */
148  /* Note - read 0 == socket EOF, which is a valid read */
149  if (retval >= 0) {
150  fd_bytes(fd, retval, FD_READ);
151  ccb->offset = retval;
152  ccb->finish(Comm::OK, 0);
153  return;
154  } else if (retval < 0 && !ignoreErrno(xerrno)) {
155  debugs(5, 3, "comm_read_try: scheduling Comm::COMM_ERROR");
156  ccb->offset = 0;
157  ccb->finish(Comm::COMM_ERROR, xerrno);
158  return;
159  };
160 
161  /* Nope, register for some more IO */
163 }
164 
177 void
179 {
180  if (!isOpen(fd)) {
181  debugs(5, 4, "fails: FD " << fd << " closed");
182  return;
183  }
184 
186  // TODO: is "active" == "monitors FD"?
187  if (!cb->active()) {
188  debugs(5, 4, "fails: FD " << fd << " inactive");
189  return;
190  }
191 
193  Call *call = dynamic_cast<Call*>(cb->callback.getRaw());
194  if (!call) {
195  debugs(5, 4, "fails: FD " << fd << " lacks callback");
196  return;
197  }
198 
199  call->cancel("old comm_read_cancel");
200 
201  typedef CommIoCbParams Params;
202  const Params &params = GetCommParams<Params>(cb->callback);
203 
204  /* Ok, we can be reasonably sure we won't lose any data here! */
205  assert(call->dialer.handler == callback);
206  assert(params.data == data);
207 
208  /* Delete the callback */
209  cb->cancel("old comm_read_cancel");
210 
211  /* And the IO event */
213 }
214 
215 void
217 {
218  callback->cancel("comm_read_cancel");
219 
220  if (!isOpen(fd)) {
221  debugs(5, 4, "fails: FD " << fd << " closed");
222  return;
223  }
224 
226 
227  if (!cb->active()) {
228  debugs(5, 4, "fails: FD " << fd << " inactive");
229  return;
230  }
231 
232  AsyncCall::Pointer call = cb->callback;
233 
234  /* Ok, we can be reasonably sure we won't lose any data here! */
235  assert(call == callback);
236 
237  /* Delete the callback */
238  cb->cancel("comm_read_cancel");
239 
240  /* And the IO event */
242 }
243 
#define fd_table
Definition: fde.h:157
#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:125
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:80
struct StatCounters::@136::@140 sock
Definition: SBuf.h:87
Definition: Flag.h:16
AsyncCall::Pointer callback
Definition: IoCallback.h:34
bool cancel(const char *reason)
Definition: AsyncCall.cc:52
bool active() const
Definition: IoCallback.h:45
int conn
the current server connection FD
Definition: Transport.cc:26
Definition: enums.h:23
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:39
void rawAppendFinish(const char *start, size_type actualSize)
Definition: SBuf.cc:155
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:261
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:147
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
struct StatCounters::@136 syscalls
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
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:28
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:178
int ignoreErrno(int ierrno)
Definition: comm.cc:1477
#define FD_READ_METHOD(fd, buf, len)
Definition: fde.h:161
Comm::Flag flag
comm layer result status.
Definition: CommCalls.h:87
void comm_read_base(const Comm::ConnectionPointer &conn, char *buf, int size, AsyncCall::Pointer &callback)
Definition: Read.cc:55
void ReadCancel(int fd, AsyncCall::Pointer &callback)
Cancel the read pending on FD. No action if none pending.
Definition: Read.cc:216
MemBlob::size_type size_type
Definition: SBuf.h:90
C * getRaw() const
Definition: RefCount.h:74
#define NULL
Definition: types.h:166
Details about a particular Comm IO callback event.
Definition: IoCallback.h:29
int size
Definition: ModDevPoll.cc:77
size_type spaceSize() const
Definition: SBuf.h:383

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors