]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskDaemon/DiskdFile.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / DiskIO / DiskDaemon / DiskdFile.cc
1 /*
2 * Copyright (C) 1996-2015 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 79 Squid-side DISKD I/O functions. */
10
11 #include "squid.h"
12 #include "ConfigOption.h"
13 #include "diomsg.h"
14 #include "DiskdFile.h"
15 #include "DiskdIOStrategy.h"
16 #include "DiskIO/IORequestor.h"
17 #include "DiskIO/ReadRequest.h"
18 #include "DiskIO/WriteRequest.h"
19 #include "StatCounters.h"
20
21 #if HAVE_SYS_IPC_H
22 #include <sys/ipc.h>
23 #endif
24 #if HAVE_SYS_MSG_H
25 #include <sys/msg.h>
26 #endif
27 #if HAVE_SYS_SHM_H
28 #include <sys/shm.h>
29 #endif
30
31 CBDATA_CLASS_INIT(DiskdFile);
32
33 DiskdFile::DiskdFile(char const *aPath, DiskdIOStrategy *anIO) :
34 errorOccured(false),
35 IO(anIO),
36 mode(0),
37 inProgressIOs(0)
38 {
39 assert(aPath);
40 debugs(79, 3, "DiskdFile::DiskdFile: " << aPath);
41 path_ = xstrdup(aPath);
42 id = diskd_stats.sio_id;
43 ++diskd_stats.sio_id;
44 }
45
46 DiskdFile::~DiskdFile()
47 {
48 assert(inProgressIOs == 0);
49 safe_free (path_);
50 }
51
52 void
53 DiskdFile::open(int flags, mode_t, RefCount<IORequestor> callback)
54 {
55 debugs(79, 3, "DiskdFile::open: " << this << " opening for " << callback.getRaw());
56 assert(ioRequestor.getRaw() == NULL);
57 ioRequestor = callback;
58 assert(callback.getRaw());
59 mode = flags;
60 ssize_t shm_offset;
61 char *buf = (char *)IO->shm.get(&shm_offset);
62 xstrncpy(buf, path_, SHMBUF_BLKSZ);
63 ioAway();
64 int x = IO->send(_MQD_OPEN,
65 id,
66 this,
67 strlen(buf) + 1,
68 mode,
69 shm_offset,
70 NULL);
71
72 if (x < 0) {
73 ioCompleted();
74 errorOccured = true;
75 // IO->shm.put (shm_offset);
76 ioRequestor->ioCompletedNotification();
77 ioRequestor = NULL;
78 }
79
80 ++diskd_stats.open.ops;
81 }
82
83 void
84 DiskdFile::create(int flags, mode_t, RefCount<IORequestor> callback)
85 {
86 debugs(79, 3, "DiskdFile::create: " << this << " creating for " << callback.getRaw());
87 assert (ioRequestor.getRaw() == NULL);
88 ioRequestor = callback;
89 assert (callback.getRaw());
90 mode = flags;
91 ssize_t shm_offset;
92 char *buf = (char *)IO->shm.get(&shm_offset);
93 xstrncpy(buf, path_, SHMBUF_BLKSZ);
94 ioAway();
95 int x = IO->send(_MQD_CREATE,
96 id,
97 this,
98 strlen(buf) + 1,
99 mode,
100 shm_offset,
101 NULL);
102
103 if (x < 0) {
104 ioCompleted();
105 errorOccured = true;
106 // IO->shm.put (shm_offset);
107 debugs(79, DBG_IMPORTANT, "storeDiskdSend CREATE: " << xstrerror());
108 notifyClient();
109 ioRequestor = NULL;
110 return;
111 }
112
113 ++diskd_stats.create.ops;
114 }
115
116 void
117 DiskdFile::read(ReadRequest *aRead)
118 {
119 assert (ioRequestor.getRaw() != NULL);
120 ssize_t shm_offset;
121 char *rbuf = (char *)IO->shm.get(&shm_offset);
122 assert(rbuf);
123 ioAway();
124 int x = IO->send(_MQD_READ,
125 id,
126 this,
127 aRead->len,
128 aRead->offset,
129 shm_offset,
130 aRead);
131
132 if (x < 0) {
133 ioCompleted();
134 errorOccured = true;
135 // IO->shm.put (shm_offset);
136 debugs(79, DBG_IMPORTANT, "storeDiskdSend READ: " << xstrerror());
137 notifyClient();
138 ioRequestor = NULL;
139 return;
140 }
141
142 ++diskd_stats.read.ops;
143 }
144
145 void
146 DiskdFile::close()
147 {
148 debugs(79, 3, "DiskdFile::close: " << this << " closing for " << ioRequestor.getRaw());
149 assert (ioRequestor.getRaw());
150 ioAway();
151 int x = IO->send(_MQD_CLOSE,
152 id,
153 this,
154 0,
155 0,
156 -1,
157 NULL);
158
159 if (x < 0) {
160 ioCompleted();
161 errorOccured = true;
162 debugs(79, DBG_IMPORTANT, "storeDiskdSend CLOSE: " << xstrerror());
163 notifyClient();
164 ioRequestor = NULL;
165 return;
166 }
167
168 ++diskd_stats.close.ops;
169 }
170
171 bool
172 DiskdFile::error() const
173 {
174 return errorOccured;
175 }
176
177 bool
178 DiskdFile::canRead() const
179 {
180 return !error();
181 }
182
183 bool
184 DiskdFile::canNotifyClient() const
185 {
186 if (!ioRequestor.getRaw()) {
187 debugs(79, 3, "DiskdFile::canNotifyClient: No ioRequestor to notify");
188 return false;
189 }
190
191 return true;
192 }
193
194 void
195 DiskdFile::notifyClient()
196 {
197 if (!canNotifyClient()) {
198 return;
199 }
200
201 ioRequestor->ioCompletedNotification();
202 }
203
204 void
205 DiskdFile::completed(diomsg *M)
206 {
207 assert (M->newstyle);
208
209 switch (M->mtype) {
210
211 case _MQD_OPEN:
212 openDone(M);
213 break;
214
215 case _MQD_CREATE:
216 createDone(M);
217 break;
218
219 case _MQD_CLOSE:
220 closeDone(M);
221 break;
222
223 case _MQD_READ:
224 readDone(M);
225 break;
226
227 case _MQD_WRITE:
228 writeDone(M);
229 break;
230
231 case _MQD_UNLINK:
232 assert (0);
233 break;
234
235 default:
236 assert(0);
237 break;
238 }
239 }
240
241 void
242 DiskdFile::openDone(diomsg *M)
243 {
244 ++statCounter.syscalls.disk.opens;
245 debugs(79, 3, "storeDiskdOpenDone: status " << M->status);
246
247 if (M->status < 0) {
248 ++diskd_stats.open.fail;
249 errorOccured = true;
250 } else {
251 ++diskd_stats.open.success;
252 }
253
254 ioCompleted();
255 notifyClient();
256 }
257
258 void
259 DiskdFile::createDone(diomsg *M)
260 {
261 ++statCounter.syscalls.disk.opens;
262 debugs(79, 3, "storeDiskdCreateDone: status " << M->status);
263
264 if (M->status < 0) {
265 ++diskd_stats.create.fail;
266 errorOccured = true;
267 } else {
268 ++diskd_stats.create.success;
269 }
270
271 ioCompleted();
272 notifyClient();
273 }
274
275 void
276 DiskdFile::write(WriteRequest *aRequest)
277 {
278 debugs(79, 3, "DiskdFile::write: this " << (void *)this << ", buf " << (void *)aRequest->buf << ", off " << aRequest->offset << ", len " << aRequest->len);
279 ssize_t shm_offset;
280 char *sbuf = (char *)IO->shm.get(&shm_offset);
281 memcpy(sbuf, aRequest->buf, aRequest->len);
282
283 if (aRequest->free_func)
284 aRequest->free_func(const_cast<char *>(aRequest->buf));
285
286 ioAway();
287
288 int x = IO->send(_MQD_WRITE,
289 id,
290 this,
291 aRequest->len,
292 aRequest->offset,
293 shm_offset,
294 aRequest);
295
296 if (x < 0) {
297 ioCompleted();
298 errorOccured = true;
299 debugs(79, DBG_IMPORTANT, "storeDiskdSend WRITE: " << xstrerror());
300 // IO->shm.put (shm_offset);
301 notifyClient();
302 ioRequestor = NULL;
303 return;
304 }
305
306 ++diskd_stats.write.ops;
307 }
308
309 void
310 DiskdFile::ioAway()
311 {
312 ++inProgressIOs;
313 }
314
315 void
316 DiskdFile::ioCompleted()
317 {
318 --inProgressIOs;
319 }
320
321 void
322 DiskdFile::closeDone(diomsg * M)
323 {
324 ++statCounter.syscalls.disk.closes;
325 debugs(79, 3, "DiskdFile::closeDone: status " << M->status);
326
327 if (M->status < 0) {
328 ++diskd_stats.close.fail;
329 errorOccured = true;
330 } else {
331 ++diskd_stats.close.success;
332 }
333
334 ioCompleted();
335
336 if (canNotifyClient())
337 ioRequestor->closeCompleted();
338
339 ioRequestor = NULL;
340 }
341
342 void
343 DiskdFile::readDone(diomsg * M)
344 {
345 ++statCounter.syscalls.disk.reads;
346 debugs(79, 3, "DiskdFile::readDone: status " << M->status);
347 assert (M->requestor);
348 ReadRequest::Pointer readRequest = dynamic_cast<ReadRequest *>(M->requestor);
349
350 /* remove the free protection */
351 if (readRequest != NULL)
352 readRequest->unlock();
353
354 if (M->status < 0) {
355 ++diskd_stats.read.fail;
356 ioCompleted();
357 errorOccured = true;
358 ioRequestor->readCompleted(NULL, -1, DISK_ERROR, readRequest);
359 return;
360 }
361
362 ++diskd_stats.read.success;
363
364 ioCompleted();
365 ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK, readRequest);
366 }
367
368 void
369 DiskdFile::writeDone(diomsg *M)
370 {
371 ++statCounter.syscalls.disk.writes;
372 debugs(79, 3, "storeDiskdWriteDone: status " << M->status);
373 assert (M->requestor);
374 WriteRequest::Pointer writeRequest = dynamic_cast<WriteRequest *>(M->requestor);
375 /* remove the free protection */
376 if (writeRequest != NULL)
377 writeRequest->unlock();
378
379 if (M->status < 0) {
380 errorOccured = true;
381 ++diskd_stats.write.fail;
382 ioCompleted();
383 ioRequestor->writeCompleted (DISK_ERROR,0, writeRequest);
384 return;
385 }
386
387 ++diskd_stats.write.success;
388 ioCompleted();
389 ioRequestor->writeCompleted (DISK_OK,M->status, writeRequest);
390 }
391
392 bool
393 DiskdFile::ioInProgress()const
394 {
395 return inProgressIOs != 0;
396 }
397