Write.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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 #include "squid.h"
10 #include "cbdata.h"
11 #include "comm/Connection.h"
12 #include "comm/IoCallback.h"
13 #include "comm/Loops.h"
14 #include "comm/Write.h"
15 #include "fd.h"
16 #include "fde.h"
17 #include "globals.h"
18 #include "MemBuf.h"
19 #include "StatCounters.h"
20 #if USE_DELAY_POOLS
21 #include "ClientInfo.h"
22 #endif
23 
24 #include <cerrno>
25 
26 void
28 {
29  Comm::Write(conn, mb->buf, mb->size, callback, mb->freeFunc());
30 }
31 
32 void
33 Comm::Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE * free_func)
34 {
35  debugs(5, 5, conn << ": sz " << size << ": asynCall " << callback);
36 
37  /* Make sure we are open, not closing, and not writing */
38  assert(fd_table[conn->fd].flags.open);
39  assert(!fd_table[conn->fd].closing());
41  assert(!ccb->active());
42 
43  fd_table[conn->fd].writeStart = squid_curtime;
44  ccb->conn = conn;
45  /* Queue the write */
46  ccb->setCallback(IOCB_WRITE, callback, (char *)buf, free_func, size);
47  ccb->selectOrQueueWrite();
48 }
49 
55 void
56 Comm::HandleWrite(int fd, void *data)
57 {
58  Comm::IoCallback *state = static_cast<Comm::IoCallback *>(data);
59  int len = 0;
60  int nleft;
61 
62  assert(state->conn != nullptr);
63  assert(state->conn->fd == fd);
64 
65  debugs(5, 5, state->conn << ": off " <<
66  (long int) state->offset << ", sz " << (long int) state->size << ".");
67 
68  nleft = state->size - state->offset;
69 
70 #if USE_DELAY_POOLS
72  if (bucket) {
73  assert(bucket->selectWaiting);
74  bucket->selectWaiting = false;
75  if (nleft > 0 && !bucket->applyQuota(nleft, state)) {
76  return;
77  }
78  }
79 #endif /* USE_DELAY_POOLS */
80 
81  /* actually WRITE data */
82  int xerrno = errno = 0;
83  len = FD_WRITE_METHOD(fd, state->buf + state->offset, nleft);
84  xerrno = errno;
85  debugs(5, 5, "write() returns " << len);
86 
87 #if USE_DELAY_POOLS
88  if (bucket) {
89  /* we wrote data - drain them from bucket */
90  bucket->reduceBucket(len);
91  }
92 #endif /* USE_DELAY_POOLS */
93 
94  fd_bytes(fd, len, IoDirection::Write);
95  ++statCounter.syscalls.sock.writes;
96  // After each successful partial write,
97  // reset fde::writeStart to the current time.
98  fd_table[fd].writeStart = squid_curtime;
99 
100  if (len == 0) {
101  /* Note we even call write if nleft == 0 */
102  /* We're done */
103  if (nleft != 0)
104  debugs(5, DBG_IMPORTANT, "FD " << fd << " write failure: connection closed with " << nleft << " bytes remaining.");
105 
106  state->finish(nleft ? Comm::COMM_ERROR : Comm::OK, 0);
107  } else if (len < 0) {
108  /* An error */
109  if (fd_table[fd].flags.socket_eof) {
110  debugs(50, 2, "FD " << fd << " write failure: " << xstrerr(xerrno) << ".");
111  state->finish(nleft ? Comm::COMM_ERROR : Comm::OK, xerrno);
112  } else if (ignoreErrno(xerrno)) {
113  debugs(50, 9, "FD " << fd << " write failure: " << xstrerr(xerrno) << ".");
114  state->selectOrQueueWrite();
115  } else {
116  debugs(50, 2, "FD " << fd << " write failure: " << xstrerr(xerrno) << ".");
117  state->finish(nleft ? Comm::COMM_ERROR : Comm::OK, xerrno);
118  }
119  } else {
120  /* A successful write, continue */
121  state->offset += len;
122 
123  if (state->offset < state->size) {
124  /* Not done, reinstall the write handler and write some more */
125  state->selectOrQueueWrite();
126  } else {
127  state->finish(nleft ? Comm::OK : Comm::COMM_ERROR, 0);
128  }
129  }
130 }
131 
const char * xstrerr(int error)
Definition: xstrerror.cc:83
char * buf
Definition: MemBuf.h:134
FREE * freeFunc()
Definition: MemBuf.cc:303
void fd_bytes(const int fd, const int len, const IoDirection direction)
Definition: fd.cc:226
void FREE(void *)
Definition: forward.h:37
mb_size_t size
Definition: MemBuf.h:135
bool active() const
Definition: IoCallback.h:45
void setCallback(iocb_type type, AsyncCall::Pointer &cb, char *buf, FREE *func, int sz)
Definition: IoCallback.cc:55
@ OK
Definition: Flag.h:16
#define COMMIO_FD_WRITECB(fd)
Definition: IoCallback.h:79
Comm::ConnectionPointer conn
Definition: IoCallback.h:33
struct StatCounters::@119 syscalls
int size
Definition: ModDevPoll.cc:69
Details about a particular Comm IO callback event.
Definition: IoCallback.h:29
virtual void reduceBucket(const int len)
Decreases the bucket level.
virtual bool applyQuota(int &nleft, Comm::IoCallback *state)
@ IOCB_WRITE
Definition: IoCallback.h:25
Definition: MemBuf.h:23
Base class for Squid-to-client bandwidth limiting.
#define assert(EX)
Definition: assert.h:17
struct StatCounters::@119::@124 sock
static BandwidthBucket * SelectBucket(fde *f)
@ COMM_ERROR
Definition: Flag.h:17
void selectOrQueueWrite()
called when fd needs to write but may need to wait in line for its quota
Definition: IoCallback.cc:69
int FD_WRITE_METHOD(int fd, const char *buf, int len)
Definition: fde.h:200
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
Definition: Write.cc:33
time_t squid_curtime
Definition: stub_libtime.cc:20
int ignoreErrno(int ierrno)
Definition: comm.cc:1422
#define fd_table
Definition: fde.h:189
void finish(Comm::Flag code, int xerrn)
finish the IO operation immediately and schedule the callback with the current state.
Definition: IoCallback.cc:110
#define DBG_IMPORTANT
Definition: Stream.h:38
PF HandleWrite
Definition: forward.h:33
bool selectWaiting
is between commSetSelect and commHandleWrite
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
StatCounters statCounter
Definition: StatCounters.cc:12

 

Introduction

Documentation

Support

Miscellaneous