]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskDaemon/DiskdFile.cc
Merged from parent (large-rock r12530 including trunk r12732; v3.3.3+).
[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 "DiskdFile.h"
36 #include "ConfigOption.h"
37 #include "diomsg.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 void *
57 DiskdFile::operator new(size_t unused)
58 {
59 CBDATA_INIT_TYPE(DiskdFile);
60 DiskdFile *result = cbdataAlloc(DiskdFile);
61 /* Mark result as being owned - we want the refcounter to do the delete
62 * call */
63 debugs(79, 3, "diskdFile with base " << result << " allocating");
64 return result;
65 }
66
67 void
68 DiskdFile::operator delete(void *address)
69 {
70 DiskdFile *t = static_cast<DiskdFile *>(address);
71 debugs(79, 3, "diskdFile with base " << t << " deleting");
72 cbdataFree(t);
73 }
74
75 DiskdFile::DiskdFile(char const *aPath, DiskdIOStrategy *anIO) :
76 errorOccured(false),
77 IO(anIO),
78 mode(0),
79 inProgressIOs(0)
80 {
81 assert (aPath);
82 debugs(79, 3, "DiskdFile::DiskdFile: " << aPath);
83 path_ = xstrdup (aPath);
84 id = diskd_stats.sio_id;
85 ++diskd_stats.sio_id;
86 }
87
88 DiskdFile::~DiskdFile()
89 {
90 assert (inProgressIOs == 0);
91 safe_free (path_);
92 }
93
94 void
95 DiskdFile::open(int flags, mode_t aMode, RefCount< IORequestor > callback)
96 {
97 debugs(79, 3, "DiskdFile::open: " << this << " opening for " << callback.getRaw());
98 assert (ioRequestor.getRaw() == NULL);
99 ioRequestor = callback;
100 assert (callback.getRaw());
101 mode = flags;
102 ssize_t shm_offset;
103 char *buf = (char *)IO->shm.get(&shm_offset);
104 xstrncpy(buf, path_, SHMBUF_BLKSZ);
105 ioAway();
106 int x = IO->send(_MQD_OPEN,
107 id,
108 this,
109 strlen(buf) + 1,
110 mode,
111 shm_offset,
112 NULL);
113
114 if (x < 0) {
115 ioCompleted();
116 errorOccured = true;
117 // IO->shm.put (shm_offset);
118 ioRequestor->ioCompletedNotification();
119 ioRequestor = NULL;
120 }
121
122 ++diskd_stats.open.ops;
123 }
124
125 void
126 DiskdFile::create(int flags, mode_t aMode, RefCount< IORequestor > callback)
127 {
128 debugs(79, 3, "DiskdFile::create: " << this << " creating for " << callback.getRaw());
129 assert (ioRequestor.getRaw() == NULL);
130 ioRequestor = callback;
131 assert (callback.getRaw());
132 mode = flags;
133 ssize_t shm_offset;
134 char *buf = (char *)IO->shm.get(&shm_offset);
135 xstrncpy(buf, path_, SHMBUF_BLKSZ);
136 ioAway();
137 int x = IO->send(_MQD_CREATE,
138 id,
139 this,
140 strlen(buf) + 1,
141 mode,
142 shm_offset,
143 NULL);
144
145 if (x < 0) {
146 ioCompleted();
147 errorOccured = true;
148 // IO->shm.put (shm_offset);
149 debugs(79, DBG_IMPORTANT, "storeDiskdSend CREATE: " << xstrerror());
150 notifyClient();
151 ioRequestor = NULL;
152 return;
153 }
154
155 ++diskd_stats.create.ops;
156 }
157
158 void
159 DiskdFile::read(ReadRequest *aRead)
160 {
161 assert (ioRequestor.getRaw() != NULL);
162 ssize_t shm_offset;
163 char *rbuf = (char *)IO->shm.get(&shm_offset);
164 assert(rbuf);
165 ioAway();
166 int x = IO->send(_MQD_READ,
167 id,
168 this,
169 aRead->len,
170 aRead->offset,
171 shm_offset,
172 aRead);
173
174 if (x < 0) {
175 ioCompleted();
176 errorOccured = true;
177 // IO->shm.put (shm_offset);
178 debugs(79, DBG_IMPORTANT, "storeDiskdSend READ: " << xstrerror());
179 notifyClient();
180 ioRequestor = NULL;
181 return;
182 }
183
184 ++diskd_stats.read.ops;
185 }
186
187 void
188 DiskdFile::close()
189 {
190 debugs(79, 3, "DiskdFile::close: " << this << " closing for " << ioRequestor.getRaw());
191 assert (ioRequestor.getRaw());
192 ioAway();
193 int x = IO->send(_MQD_CLOSE,
194 id,
195 this,
196 0,
197 0,
198 -1,
199 NULL);
200
201 if (x < 0) {
202 ioCompleted();
203 errorOccured = true;
204 debugs(79, DBG_IMPORTANT, "storeDiskdSend CLOSE: " << xstrerror());
205 notifyClient();
206 ioRequestor = NULL;
207 return;
208 }
209
210 ++diskd_stats.close.ops;
211 }
212
213 bool
214 DiskdFile::error() const
215 {
216 return errorOccured;
217 }
218
219 bool
220 DiskdFile::canRead() const
221 {
222 return !error();
223 }
224
225 bool
226 DiskdFile::canNotifyClient() const
227 {
228 if (!ioRequestor.getRaw()) {
229 debugs(79, 3, "DiskdFile::canNotifyClient: No ioRequestor to notify");
230 return false;
231 }
232
233 return true;
234 }
235
236 void
237 DiskdFile::notifyClient()
238 {
239 if (!canNotifyClient()) {
240 return;
241 }
242
243 ioRequestor->ioCompletedNotification();
244 }
245
246 void
247 DiskdFile::completed(diomsg *M)
248 {
249 assert (M->newstyle);
250
251 switch (M->mtype) {
252
253 case _MQD_OPEN:
254 openDone(M);
255 break;
256
257 case _MQD_CREATE:
258 createDone(M);
259 break;
260
261 case _MQD_CLOSE:
262 closeDone(M);
263 break;
264
265 case _MQD_READ:
266 readDone(M);
267 break;
268
269 case _MQD_WRITE:
270 writeDone(M);
271 break;
272
273 case _MQD_UNLINK:
274 assert (0);
275 break;
276
277 default:
278 assert(0);
279 break;
280 }
281 }
282
283 void
284 DiskdFile::openDone(diomsg *M)
285 {
286 ++statCounter.syscalls.disk.opens;
287 debugs(79, 3, "storeDiskdOpenDone: status " << M->status);
288
289 if (M->status < 0) {
290 ++diskd_stats.open.fail;
291 errorOccured = true;
292 } else {
293 ++diskd_stats.open.success;
294 }
295
296 ioCompleted();
297 notifyClient();
298 }
299
300 void
301 DiskdFile::createDone(diomsg *M)
302 {
303 ++statCounter.syscalls.disk.opens;
304 debugs(79, 3, "storeDiskdCreateDone: status " << M->status);
305
306 if (M->status < 0) {
307 ++diskd_stats.create.fail;
308 errorOccured = true;
309 } else {
310 ++diskd_stats.create.success;
311 }
312
313 ioCompleted();
314 notifyClient();
315 }
316
317 void
318 DiskdFile::write(WriteRequest *aRequest)
319 {
320 debugs(79, 3, "DiskdFile::write: this " << (void *)this << ", buf " << (void *)aRequest->buf << ", off " << aRequest->offset << ", len " << aRequest->len);
321 ssize_t shm_offset;
322 char *sbuf = (char *)IO->shm.get(&shm_offset);
323 memcpy(sbuf, aRequest->buf, aRequest->len);
324
325 if (aRequest->free_func)
326 aRequest->free_func(const_cast<char *>(aRequest->buf));
327
328 ioAway();
329
330 int x = IO->send(_MQD_WRITE,
331 id,
332 this,
333 aRequest->len,
334 aRequest->offset,
335 shm_offset,
336 aRequest);
337
338 if (x < 0) {
339 ioCompleted();
340 errorOccured = true;
341 debugs(79, DBG_IMPORTANT, "storeDiskdSend WRITE: " << xstrerror());
342 // IO->shm.put (shm_offset);
343 notifyClient();
344 ioRequestor = NULL;
345 return;
346 }
347
348 ++diskd_stats.write.ops;
349 }
350
351 void
352 DiskdFile::ioAway()
353 {
354 ++inProgressIOs;
355 }
356
357 void
358 DiskdFile::ioCompleted()
359 {
360 --inProgressIOs;
361 }
362
363 void
364 DiskdFile::closeDone(diomsg * M)
365 {
366 ++statCounter.syscalls.disk.closes;
367 debugs(79, 3, "DiskdFile::closeDone: status " << M->status);
368
369 if (M->status < 0) {
370 ++diskd_stats.close.fail;
371 errorOccured = true;
372 } else {
373 ++diskd_stats.close.success;
374 }
375
376 ioCompleted();
377
378 if (canNotifyClient())
379 ioRequestor->closeCompleted();
380
381 ioRequestor = NULL;
382 }
383
384 void
385 DiskdFile::readDone(diomsg * M)
386 {
387 ++statCounter.syscalls.disk.reads;
388 debugs(79, 3, "DiskdFile::readDone: status " << M->status);
389 assert (M->requestor);
390 ReadRequest::Pointer readRequest = dynamic_cast<ReadRequest *>(M->requestor);
391
392 /* remove the free protection */
393 if (readRequest != NULL)
394 readRequest->unlock();
395
396 if (M->status < 0) {
397 ++diskd_stats.read.fail;
398 ioCompleted();
399 errorOccured = true;
400 ioRequestor->readCompleted(NULL, -1, DISK_ERROR, readRequest);
401 return;
402 }
403
404 ++diskd_stats.read.success;
405
406 ioCompleted();
407 ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK, readRequest);
408 }
409
410 void
411 DiskdFile::writeDone(diomsg *M)
412 {
413 ++statCounter.syscalls.disk.writes;
414 debugs(79, 3, "storeDiskdWriteDone: status " << M->status);
415 assert (M->requestor);
416 WriteRequest::Pointer writeRequest = dynamic_cast<WriteRequest *>(M->requestor);
417 /* remove the free protection */
418 if (writeRequest != NULL)
419 writeRequest->unlock();
420
421 if (M->status < 0) {
422 errorOccured = true;
423 ++diskd_stats.write.fail;
424 ioCompleted();
425 ioRequestor->writeCompleted (DISK_ERROR,0, writeRequest);
426 return;
427 }
428
429 ++diskd_stats.write.success;
430 ioCompleted();
431 ioRequestor->writeCompleted (DISK_OK,M->status, writeRequest);
432 }
433
434 bool
435 DiskdFile::ioInProgress()const
436 {
437 return inProgressIOs != 0;
438 }