]> 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 * DEBUG: section 79 Squid-side DISKD I/O functions.
3 * AUTHOR: Duane Wessels
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 * CopyRight (c) 2003, Robert Collins <robertc@squid-cache.org>
32 */
33
34 #include "squid.h"
35 #include "ConfigOption.h"
36 #include "diomsg.h"
37 #include "DiskdFile.h"
38 #include "DiskdIOStrategy.h"
39 #include "DiskIO/IORequestor.h"
40 #include "DiskIO/ReadRequest.h"
41 #include "DiskIO/WriteRequest.h"
42 #include "StatCounters.h"
43
44 #if HAVE_SYS_IPC_H
45 #include <sys/ipc.h>
46 #endif
47 #if HAVE_SYS_MSG_H
48 #include <sys/msg.h>
49 #endif
50 #if HAVE_SYS_SHM_H
51 #include <sys/shm.h>
52 #endif
53
54 CBDATA_CLASS_INIT(DiskdFile);
55
56 DiskdFile::DiskdFile(char const *aPath, DiskdIOStrategy *anIO) :
57 errorOccured(false),
58 IO(anIO),
59 mode(0),
60 inProgressIOs(0)
61 {
62 assert (aPath);
63 debugs(79, 3, "DiskdFile::DiskdFile: " << aPath);
64 path_ = xstrdup (aPath);
65 id = diskd_stats.sio_id;
66 ++diskd_stats.sio_id;
67 }
68
69 DiskdFile::~DiskdFile()
70 {
71 assert (inProgressIOs == 0);
72 safe_free (path_);
73 }
74
75 void
76 DiskdFile::open(int flags, mode_t aMode, RefCount< IORequestor > callback)
77 {
78 debugs(79, 3, "DiskdFile::open: " << this << " opening for " << callback.getRaw());
79 assert (ioRequestor.getRaw() == NULL);
80 ioRequestor = callback;
81 assert (callback.getRaw());
82 mode = flags;
83 ssize_t shm_offset;
84 char *buf = (char *)IO->shm.get(&shm_offset);
85 xstrncpy(buf, path_, SHMBUF_BLKSZ);
86 ioAway();
87 int x = IO->send(_MQD_OPEN,
88 id,
89 this,
90 strlen(buf) + 1,
91 mode,
92 shm_offset,
93 NULL);
94
95 if (x < 0) {
96 ioCompleted();
97 errorOccured = true;
98 // IO->shm.put (shm_offset);
99 ioRequestor->ioCompletedNotification();
100 ioRequestor = NULL;
101 }
102
103 ++diskd_stats.open.ops;
104 }
105
106 void
107 DiskdFile::create(int flags, mode_t aMode, RefCount< IORequestor > callback)
108 {
109 debugs(79, 3, "DiskdFile::create: " << this << " creating for " << callback.getRaw());
110 assert (ioRequestor.getRaw() == NULL);
111 ioRequestor = callback;
112 assert (callback.getRaw());
113 mode = flags;
114 ssize_t shm_offset;
115 char *buf = (char *)IO->shm.get(&shm_offset);
116 xstrncpy(buf, path_, SHMBUF_BLKSZ);
117 ioAway();
118 int x = IO->send(_MQD_CREATE,
119 id,
120 this,
121 strlen(buf) + 1,
122 mode,
123 shm_offset,
124 NULL);
125
126 if (x < 0) {
127 ioCompleted();
128 errorOccured = true;
129 // IO->shm.put (shm_offset);
130 debugs(79, DBG_IMPORTANT, "storeDiskdSend CREATE: " << xstrerror());
131 notifyClient();
132 ioRequestor = NULL;
133 return;
134 }
135
136 ++diskd_stats.create.ops;
137 }
138
139 void
140 DiskdFile::read(ReadRequest *aRead)
141 {
142 assert (ioRequestor.getRaw() != NULL);
143 ssize_t shm_offset;
144 char *rbuf = (char *)IO->shm.get(&shm_offset);
145 assert(rbuf);
146 ioAway();
147 int x = IO->send(_MQD_READ,
148 id,
149 this,
150 aRead->len,
151 aRead->offset,
152 shm_offset,
153 aRead);
154
155 if (x < 0) {
156 ioCompleted();
157 errorOccured = true;
158 // IO->shm.put (shm_offset);
159 debugs(79, DBG_IMPORTANT, "storeDiskdSend READ: " << xstrerror());
160 notifyClient();
161 ioRequestor = NULL;
162 return;
163 }
164
165 ++diskd_stats.read.ops;
166 }
167
168 void
169 DiskdFile::close()
170 {
171 debugs(79, 3, "DiskdFile::close: " << this << " closing for " << ioRequestor.getRaw());
172 assert (ioRequestor.getRaw());
173 ioAway();
174 int x = IO->send(_MQD_CLOSE,
175 id,
176 this,
177 0,
178 0,
179 -1,
180 NULL);
181
182 if (x < 0) {
183 ioCompleted();
184 errorOccured = true;
185 debugs(79, DBG_IMPORTANT, "storeDiskdSend CLOSE: " << xstrerror());
186 notifyClient();
187 ioRequestor = NULL;
188 return;
189 }
190
191 ++diskd_stats.close.ops;
192 }
193
194 bool
195 DiskdFile::error() const
196 {
197 return errorOccured;
198 }
199
200 bool
201 DiskdFile::canRead() const
202 {
203 return !error();
204 }
205
206 bool
207 DiskdFile::canNotifyClient() const
208 {
209 if (!ioRequestor.getRaw()) {
210 debugs(79, 3, "DiskdFile::canNotifyClient: No ioRequestor to notify");
211 return false;
212 }
213
214 return true;
215 }
216
217 void
218 DiskdFile::notifyClient()
219 {
220 if (!canNotifyClient()) {
221 return;
222 }
223
224 ioRequestor->ioCompletedNotification();
225 }
226
227 void
228 DiskdFile::completed(diomsg *M)
229 {
230 assert (M->newstyle);
231
232 switch (M->mtype) {
233
234 case _MQD_OPEN:
235 openDone(M);
236 break;
237
238 case _MQD_CREATE:
239 createDone(M);
240 break;
241
242 case _MQD_CLOSE:
243 closeDone(M);
244 break;
245
246 case _MQD_READ:
247 readDone(M);
248 break;
249
250 case _MQD_WRITE:
251 writeDone(M);
252 break;
253
254 case _MQD_UNLINK:
255 assert (0);
256 break;
257
258 default:
259 assert(0);
260 break;
261 }
262 }
263
264 void
265 DiskdFile::openDone(diomsg *M)
266 {
267 ++statCounter.syscalls.disk.opens;
268 debugs(79, 3, "storeDiskdOpenDone: status " << M->status);
269
270 if (M->status < 0) {
271 ++diskd_stats.open.fail;
272 errorOccured = true;
273 } else {
274 ++diskd_stats.open.success;
275 }
276
277 ioCompleted();
278 notifyClient();
279 }
280
281 void
282 DiskdFile::createDone(diomsg *M)
283 {
284 ++statCounter.syscalls.disk.opens;
285 debugs(79, 3, "storeDiskdCreateDone: status " << M->status);
286
287 if (M->status < 0) {
288 ++diskd_stats.create.fail;
289 errorOccured = true;
290 } else {
291 ++diskd_stats.create.success;
292 }
293
294 ioCompleted();
295 notifyClient();
296 }
297
298 void
299 DiskdFile::write(WriteRequest *aRequest)
300 {
301 debugs(79, 3, "DiskdFile::write: this " << (void *)this << ", buf " << (void *)aRequest->buf << ", off " << aRequest->offset << ", len " << aRequest->len);
302 ssize_t shm_offset;
303 char *sbuf = (char *)IO->shm.get(&shm_offset);
304 memcpy(sbuf, aRequest->buf, aRequest->len);
305
306 if (aRequest->free_func)
307 aRequest->free_func(const_cast<char *>(aRequest->buf));
308
309 ioAway();
310
311 int x = IO->send(_MQD_WRITE,
312 id,
313 this,
314 aRequest->len,
315 aRequest->offset,
316 shm_offset,
317 aRequest);
318
319 if (x < 0) {
320 ioCompleted();
321 errorOccured = true;
322 debugs(79, DBG_IMPORTANT, "storeDiskdSend WRITE: " << xstrerror());
323 // IO->shm.put (shm_offset);
324 notifyClient();
325 ioRequestor = NULL;
326 return;
327 }
328
329 ++diskd_stats.write.ops;
330 }
331
332 void
333 DiskdFile::ioAway()
334 {
335 ++inProgressIOs;
336 }
337
338 void
339 DiskdFile::ioCompleted()
340 {
341 --inProgressIOs;
342 }
343
344 void
345 DiskdFile::closeDone(diomsg * M)
346 {
347 ++statCounter.syscalls.disk.closes;
348 debugs(79, 3, "DiskdFile::closeDone: status " << M->status);
349
350 if (M->status < 0) {
351 ++diskd_stats.close.fail;
352 errorOccured = true;
353 } else {
354 ++diskd_stats.close.success;
355 }
356
357 ioCompleted();
358
359 if (canNotifyClient())
360 ioRequestor->closeCompleted();
361
362 ioRequestor = NULL;
363 }
364
365 void
366 DiskdFile::readDone(diomsg * M)
367 {
368 ++statCounter.syscalls.disk.reads;
369 debugs(79, 3, "DiskdFile::readDone: status " << M->status);
370 assert (M->requestor);
371 ReadRequest::Pointer readRequest = dynamic_cast<ReadRequest *>(M->requestor);
372
373 /* remove the free protection */
374 if (readRequest != NULL)
375 readRequest->unlock();
376
377 if (M->status < 0) {
378 ++diskd_stats.read.fail;
379 ioCompleted();
380 errorOccured = true;
381 ioRequestor->readCompleted(NULL, -1, DISK_ERROR, readRequest);
382 return;
383 }
384
385 ++diskd_stats.read.success;
386
387 ioCompleted();
388 ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK, readRequest);
389 }
390
391 void
392 DiskdFile::writeDone(diomsg *M)
393 {
394 ++statCounter.syscalls.disk.writes;
395 debugs(79, 3, "storeDiskdWriteDone: status " << M->status);
396 assert (M->requestor);
397 WriteRequest::Pointer writeRequest = dynamic_cast<WriteRequest *>(M->requestor);
398 /* remove the free protection */
399 if (writeRequest != NULL)
400 writeRequest->unlock();
401
402 if (M->status < 0) {
403 errorOccured = true;
404 ++diskd_stats.write.fail;
405 ioCompleted();
406 ioRequestor->writeCompleted (DISK_ERROR,0, writeRequest);
407 return;
408 }
409
410 ++diskd_stats.write.success;
411 ioCompleted();
412 ioRequestor->writeCompleted (DISK_OK,M->status, writeRequest);
413 }
414
415 bool
416 DiskdFile::ioInProgress()const
417 {
418 return inProgressIOs != 0;
419 }