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