]> git.ipfire.org Git - thirdparty/squid.git/blame - src/mgr/StoreToCommWriter.cc
Preserve caller context across (and improve) deferred reads (#1025)
[thirdparty/squid.git] / src / mgr / StoreToCommWriter.cc
CommitLineData
8822ebee 1/*
bf95c10a 2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
8822ebee 3 *
bbc27441
AJ
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.
8822ebee
AR
7 */
8
bbc27441
AJ
9/* DEBUG: section 16 Cache Manager API */
10
f7f3304a 11#include "squid.h"
7e9f330d 12#include "base/AsyncCbdataCalls.h"
8822ebee 13#include "base/TextException.h"
a928fdfd 14#include "comm.h"
c3e8e4e9 15#include "comm/Connection.h"
ec41b64c 16#include "comm/Write.h"
602d9612 17#include "CommCalls.h"
8822ebee
AR
18#include "ipc/FdNotes.h"
19#include "mgr/StoreToCommWriter.h"
8822ebee 20#include "Store.h"
602d9612 21#include "StoreClient.h"
8822ebee 22
8822ebee
AR
23CBDATA_NAMESPACED_CLASS_INIT(Mgr, StoreToCommWriter);
24
c3e8e4e9 25Mgr::StoreToCommWriter::StoreToCommWriter(const Comm::ConnectionPointer &conn, StoreEntry* anEntry):
f53969cc
SM
26 AsyncJob("Mgr::StoreToCommWriter"),
27 clientConnection(conn), entry(anEntry), sc(NULL), writeOffset(0), closer(NULL)
8822ebee 28{
bf95c10a 29 debugs(16, 6, clientConnection);
8822ebee 30 closer = asyncCall(16, 5, "Mgr::StoreToCommWriter::noteCommClosed",
d9fc6862 31 CommCbMemFunT<StoreToCommWriter, CommCloseCbParams>(this, &StoreToCommWriter::noteCommClosed));
c3e8e4e9 32 comm_add_close_handler(clientConnection->fd, closer);
8822ebee
AR
33}
34
35Mgr::StoreToCommWriter::~StoreToCommWriter()
36{
bf95c10a 37 debugs(16, 6, MYNAME);
8822ebee
AR
38 assert(!entry);
39 assert(!sc);
40 close();
41}
42
43/// closes our copy of the client HTTP connection socket
44void
45Mgr::StoreToCommWriter::close()
46{
c3e8e4e9 47 if (Comm::IsConnOpen(clientConnection)) {
8822ebee 48 if (closer != NULL) {
c3e8e4e9 49 comm_remove_close_handler(clientConnection->fd, closer);
8822ebee
AR
50 closer = NULL;
51 }
c3e8e4e9 52 clientConnection->close();
8822ebee
AR
53 }
54}
55
56void
57Mgr::StoreToCommWriter::start()
58{
bf95c10a 59 debugs(16, 6, MYNAME);
c3e8e4e9 60 Must(Comm::IsConnOpen(clientConnection));
8822ebee 61 Must(entry != NULL);
7e9f330d
EB
62 AsyncCall::Pointer call = asyncCall(16, 4, "StoreToCommWriter::Abort", cbdataDialer(&StoreToCommWriter::HandleStoreAbort, this));
63 entry->registerAbortCallback(call);
8822ebee
AR
64 sc = storeClientListAdd(entry, this);
65 Must(sc != NULL);
66
67 // initiate the receive-from-store, write-to-comm sequence
68 scheduleStoreCopy();
69}
70
71void
72Mgr::StoreToCommWriter::scheduleStoreCopy()
73{
bf95c10a 74 debugs(16, 6, MYNAME);
8822ebee
AR
75 Must(entry != NULL);
76 Must(sc != NULL);
77 StoreIOBuffer readBuf(sizeof(buffer), writeOffset, buffer);
78 storeClientCopy(sc, entry, readBuf, &NoteStoreCopied, this);
79}
80
81void
82Mgr::StoreToCommWriter::NoteStoreCopied(void* data, StoreIOBuffer ioBuf)
83{
84 Must(data != NULL);
85 // make sync Store call async to get async call protections and features
86 StoreToCommWriter* writer = static_cast<StoreToCommWriter*>(data);
87 typedef UnaryMemFunT<StoreToCommWriter, StoreIOBuffer> MyDialer;
88 AsyncCall::Pointer call =
89 asyncCall(16, 5, "Mgr::StoreToCommWriter::noteStoreCopied",
d9fc6862 90 MyDialer(writer, &StoreToCommWriter::noteStoreCopied, ioBuf));
8822ebee
AR
91 ScheduleCallHere(call);
92}
93
94void
95Mgr::StoreToCommWriter::noteStoreCopied(StoreIOBuffer ioBuf)
96{
bf95c10a 97 debugs(16, 6, MYNAME);
8822ebee
AR
98 Must(!ioBuf.flags.error);
99 if (ioBuf.length > 0)
100 scheduleCommWrite(ioBuf); // write received action results to client
101 else
102 Must(doneAll()); // otherwise, why would Store call us with no data?
103}
104
105void
106Mgr::StoreToCommWriter::scheduleCommWrite(const StoreIOBuffer& ioBuf)
107{
bf95c10a 108 debugs(16, 6, MYNAME);
c3e8e4e9 109 Must(Comm::IsConnOpen(clientConnection));
8822ebee
AR
110 Must(ioBuf.data != NULL);
111 // write filled buffer
112 typedef CommCbMemFunT<StoreToCommWriter, CommIoCbParams> MyDialer;
113 AsyncCall::Pointer writer =
114 asyncCall(16, 5, "Mgr::StoreToCommWriter::noteCommWrote",
d9fc6862 115 MyDialer(this, &StoreToCommWriter::noteCommWrote));
b0388924 116 Comm::Write(clientConnection, ioBuf.data, ioBuf.length, writer, NULL);
8822ebee
AR
117}
118
119void
120Mgr::StoreToCommWriter::noteCommWrote(const CommIoCbParams& params)
121{
bf95c10a 122 debugs(16, 6, MYNAME);
c8407295 123 Must(params.flag == Comm::OK);
c3e8e4e9 124 Must(clientConnection != NULL && params.fd == clientConnection->fd);
8822ebee
AR
125 Must(params.size != 0);
126 writeOffset += params.size;
127 if (!doneAll())
128 scheduleStoreCopy(); // retrieve the next data portion
129}
130
131void
ced8def3 132Mgr::StoreToCommWriter::noteCommClosed(const CommCloseCbParams &)
8822ebee 133{
bf95c10a 134 debugs(16, 6, MYNAME);
2b6b1bcb
AR
135 if (clientConnection) {
136 clientConnection->noteClosure();
137 clientConnection = nullptr;
138 }
139 closer = nullptr;
8822ebee
AR
140 mustStop("commClosed");
141}
142
143void
144Mgr::StoreToCommWriter::swanSong()
145{
bf95c10a 146 debugs(16, 6, MYNAME);
8822ebee
AR
147 if (entry != NULL) {
148 if (sc != NULL) {
149 storeUnregister(sc, entry, this);
150 sc = NULL;
151 }
7e9f330d 152 entry->unregisterAbortCallback("StoreToCommWriter done");
acc5dc4c 153 entry->unlock("Mgr::StoreToCommWriter::swanSong");
8822ebee
AR
154 entry = NULL;
155 }
156 close();
157}
158
159bool
160Mgr::StoreToCommWriter::doneAll() const
161{
162 return entry &&
d9fc6862
A
163 entry->store_status == STORE_OK && // the action is over
164 writeOffset >= entry->objectLen(); // we wrote all the results
8822ebee
AR
165}
166
167void
7e9f330d 168Mgr::StoreToCommWriter::HandleStoreAbort(StoreToCommWriter *mgrWriter)
8822ebee 169{
c3e8e4e9
AJ
170 if (Comm::IsConnOpen(mgrWriter->clientConnection))
171 mgrWriter->clientConnection->close();
8822ebee 172}
f53969cc 173