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