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