Squid Web Cache master
Loading...
Searching...
No Matches
Write.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 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
26void
28{
29 Comm::Write(conn, mb->buf, mb->size, callback, mb->freeFunc());
30}
31
32void
33Comm::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
55void
56Comm::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
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
#define COMMIO_FD_WRITECB(fd)
Definition IoCallback.h:76
int size
Definition ModDevPoll.cc:70
time_t squid_curtime
StatCounters statCounter
#define assert(EX)
Definition assert.h:17
Base class for Squid-to-client bandwidth limiting.
virtual bool applyQuota(int &nleft, Comm::IoCallback *state)
static BandwidthBucket * SelectBucket(fde *f)
virtual void reduceBucket(const int len)
Decreases the bucket level.
bool selectWaiting
is between commSetSelect and commHandleWrite
Details about a particular Comm IO callback event.
Definition IoCallback.h:30
void setCallback(iocb_type type, AsyncCall::Pointer &cb, char *buf, FREE *func, int sz)
Definition IoCallback.cc:60
bool active() const
Definition IoCallback.h:45
void selectOrQueueWrite()
called when fd needs to write but may need to wait in line for its quota
Definition IoCallback.cc:74
void finish(Comm::Flag code, int xerrn)
finish the IO operation immediately and schedule the callback with the current state.
Comm::ConnectionPointer conn
Definition IoCallback.h:33
FREE * freeFunc()
Definition MemBuf.cc:303
mb_size_t size
Definition MemBuf.h:135
char * buf
Definition MemBuf.h:134
struct StatCounters::@112 syscalls
struct StatCounters::@112::@117 sock
int ignoreErrno(int ierrno)
Definition comm.cc:1407
#define DBG_IMPORTANT
Definition Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition Stream.h:192
void fd_bytes(const int fd, const int len, const IoDirection direction)
Definition fd.cc:221
#define fd_table
Definition fde.h:189
int FD_WRITE_METHOD(int fd, const char *buf, int len)
Definition fde.h:200
void FREE(void *)
Definition forward.h:37
Abstraction layer for TCP, UDP, TLS, UDS and filedescriptor sockets.
PF HandleWrite
Definition forward.h:33
@ IOCB_WRITE
Definition IoCallback.h:25
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
Definition Write.cc:33
@ OK
Definition Flag.h:16
@ COMM_ERROR
Definition Flag.h:17
const char * xstrerr(int error)
Definition xstrerror.cc:83