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