]>
Commit | Line | Data |
---|---|---|
b9ae18aa | 1 | /* |
bbc27441 | 2 | * Copyright (C) 1996-2014 The Squid Software Foundation and contributors |
b9ae18aa | 3 | * |
bbc27441 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
b9ae18aa | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 79 Squid-side DISKD I/O functions. */ |
10 | ||
582c2af2 | 11 | #include "squid.h" |
b9ae18aa | 12 | #include "ConfigOption.h" |
13 | #include "diomsg.h" | |
602d9612 | 14 | #include "DiskdFile.h" |
b9ae18aa | 15 | #include "DiskdIOStrategy.h" |
16 | #include "DiskIO/IORequestor.h" | |
17 | #include "DiskIO/ReadRequest.h" | |
18 | #include "DiskIO/WriteRequest.h" | |
e4f1fdae | 19 | #include "StatCounters.h" |
3d41e53a | 20 | |
d440d5a4 | 21 | #if HAVE_SYS_IPC_H |
3d41e53a | 22 | #include <sys/ipc.h> |
d440d5a4 AJ |
23 | #endif |
24 | #if HAVE_SYS_MSG_H | |
3d41e53a | 25 | #include <sys/msg.h> |
d440d5a4 AJ |
26 | #endif |
27 | #if HAVE_SYS_SHM_H | |
3d41e53a | 28 | #include <sys/shm.h> |
d440d5a4 | 29 | #endif |
3d41e53a | 30 | |
b9ae18aa | 31 | CBDATA_CLASS_INIT(DiskdFile); |
32 | ||
e19994df TH |
33 | DiskdFile::DiskdFile(char const *aPath, DiskdIOStrategy *anIO) : |
34 | errorOccured(false), | |
35 | IO(anIO), | |
36 | mode(0), | |
37 | inProgressIOs(0) | |
b9ae18aa | 38 | { |
86c63190 | 39 | assert(aPath); |
bf8fe701 | 40 | debugs(79, 3, "DiskdFile::DiskdFile: " << aPath); |
86c63190 | 41 | path_ = xstrdup(aPath); |
f207fe64 FC |
42 | id = diskd_stats.sio_id; |
43 | ++diskd_stats.sio_id; | |
b9ae18aa | 44 | } |
45 | ||
46 | DiskdFile::~DiskdFile() | |
47 | { | |
86c63190 | 48 | assert(inProgressIOs == 0); |
b9ae18aa | 49 | safe_free (path_); |
50 | } | |
51 | ||
52 | void | |
63be0a78 | 53 | DiskdFile::open(int flags, mode_t aMode, RefCount< IORequestor > callback) |
b9ae18aa | 54 | { |
bf8fe701 | 55 | debugs(79, 3, "DiskdFile::open: " << this << " opening for " << callback.getRaw()); |
86c63190 | 56 | assert(ioRequestor.getRaw() == NULL); |
b9ae18aa | 57 | ioRequestor = callback; |
86c63190 | 58 | assert(callback.getRaw()); |
b9ae18aa | 59 | mode = flags; |
ee139403 | 60 | ssize_t shm_offset; |
b9ae18aa | 61 | char *buf = (char *)IO->shm.get(&shm_offset); |
62 | xstrncpy(buf, path_, SHMBUF_BLKSZ); | |
63 | ioAway(); | |
64 | int x = IO->send(_MQD_OPEN, | |
65 | id, | |
66 | this, | |
67 | strlen(buf) + 1, | |
68 | mode, | |
69 | shm_offset, | |
70 | NULL); | |
71 | ||
72 | if (x < 0) { | |
73 | ioCompleted(); | |
74 | errorOccured = true; | |
75 | // IO->shm.put (shm_offset); | |
76 | ioRequestor->ioCompletedNotification(); | |
77 | ioRequestor = NULL; | |
78 | } | |
79 | ||
cb4185f1 | 80 | ++diskd_stats.open.ops; |
b9ae18aa | 81 | } |
82 | ||
83 | void | |
63be0a78 | 84 | DiskdFile::create(int flags, mode_t aMode, RefCount< IORequestor > callback) |
b9ae18aa | 85 | { |
bf8fe701 | 86 | debugs(79, 3, "DiskdFile::create: " << this << " creating for " << callback.getRaw()); |
b9ae18aa | 87 | assert (ioRequestor.getRaw() == NULL); |
88 | ioRequestor = callback; | |
89 | assert (callback.getRaw()); | |
90 | mode = flags; | |
ee139403 | 91 | ssize_t shm_offset; |
b9ae18aa | 92 | char *buf = (char *)IO->shm.get(&shm_offset); |
93 | xstrncpy(buf, path_, SHMBUF_BLKSZ); | |
94 | ioAway(); | |
95 | int x = IO->send(_MQD_CREATE, | |
96 | id, | |
97 | this, | |
98 | strlen(buf) + 1, | |
99 | mode, | |
100 | shm_offset, | |
101 | NULL); | |
102 | ||
103 | if (x < 0) { | |
104 | ioCompleted(); | |
105 | errorOccured = true; | |
106 | // IO->shm.put (shm_offset); | |
e0236918 | 107 | debugs(79, DBG_IMPORTANT, "storeDiskdSend CREATE: " << xstrerror()); |
b9ae18aa | 108 | notifyClient(); |
109 | ioRequestor = NULL; | |
110 | return; | |
111 | } | |
112 | ||
cb4185f1 | 113 | ++diskd_stats.create.ops; |
b9ae18aa | 114 | } |
115 | ||
116 | void | |
117 | DiskdFile::read(ReadRequest *aRead) | |
118 | { | |
119 | assert (ioRequestor.getRaw() != NULL); | |
ee139403 | 120 | ssize_t shm_offset; |
b9ae18aa | 121 | char *rbuf = (char *)IO->shm.get(&shm_offset); |
122 | assert(rbuf); | |
123 | ioAway(); | |
124 | int x = IO->send(_MQD_READ, | |
125 | id, | |
126 | this, | |
ee139403 | 127 | aRead->len, |
128 | aRead->offset, | |
b9ae18aa | 129 | shm_offset, |
130 | aRead); | |
131 | ||
132 | if (x < 0) { | |
133 | ioCompleted(); | |
134 | errorOccured = true; | |
135 | // IO->shm.put (shm_offset); | |
e0236918 | 136 | debugs(79, DBG_IMPORTANT, "storeDiskdSend READ: " << xstrerror()); |
b9ae18aa | 137 | notifyClient(); |
138 | ioRequestor = NULL; | |
139 | return; | |
140 | } | |
141 | ||
cb4185f1 | 142 | ++diskd_stats.read.ops; |
b9ae18aa | 143 | } |
144 | ||
145 | void | |
146 | DiskdFile::close() | |
147 | { | |
bf8fe701 | 148 | debugs(79, 3, "DiskdFile::close: " << this << " closing for " << ioRequestor.getRaw()); |
b9ae18aa | 149 | assert (ioRequestor.getRaw()); |
150 | ioAway(); | |
151 | int x = IO->send(_MQD_CLOSE, | |
152 | id, | |
153 | this, | |
154 | 0, | |
155 | 0, | |
156 | -1, | |
157 | NULL); | |
158 | ||
159 | if (x < 0) { | |
160 | ioCompleted(); | |
161 | errorOccured = true; | |
e0236918 | 162 | debugs(79, DBG_IMPORTANT, "storeDiskdSend CLOSE: " << xstrerror()); |
b9ae18aa | 163 | notifyClient(); |
164 | ioRequestor = NULL; | |
165 | return; | |
166 | } | |
167 | ||
cb4185f1 | 168 | ++diskd_stats.close.ops; |
b9ae18aa | 169 | } |
170 | ||
171 | bool | |
172 | DiskdFile::error() const | |
173 | { | |
174 | return errorOccured; | |
175 | } | |
176 | ||
177 | bool | |
178 | DiskdFile::canRead() const | |
179 | { | |
180 | return !error(); | |
181 | } | |
182 | ||
183 | bool | |
184 | DiskdFile::canNotifyClient() const | |
185 | { | |
186 | if (!ioRequestor.getRaw()) { | |
bf8fe701 | 187 | debugs(79, 3, "DiskdFile::canNotifyClient: No ioRequestor to notify"); |
b9ae18aa | 188 | return false; |
189 | } | |
190 | ||
191 | return true; | |
192 | } | |
193 | ||
194 | void | |
195 | DiskdFile::notifyClient() | |
196 | { | |
197 | if (!canNotifyClient()) { | |
198 | return; | |
199 | } | |
200 | ||
201 | ioRequestor->ioCompletedNotification(); | |
202 | } | |
203 | ||
204 | void | |
205 | DiskdFile::completed(diomsg *M) | |
206 | { | |
207 | assert (M->newstyle); | |
208 | ||
209 | switch (M->mtype) { | |
210 | ||
211 | case _MQD_OPEN: | |
212 | openDone(M); | |
213 | break; | |
214 | ||
215 | case _MQD_CREATE: | |
216 | createDone(M); | |
217 | break; | |
218 | ||
219 | case _MQD_CLOSE: | |
220 | closeDone(M); | |
221 | break; | |
222 | ||
223 | case _MQD_READ: | |
224 | readDone(M); | |
225 | break; | |
226 | ||
227 | case _MQD_WRITE: | |
228 | writeDone(M); | |
229 | break; | |
230 | ||
231 | case _MQD_UNLINK: | |
232 | assert (0); | |
233 | break; | |
234 | ||
235 | default: | |
236 | assert(0); | |
237 | break; | |
238 | } | |
239 | } | |
240 | ||
241 | void | |
242 | DiskdFile::openDone(diomsg *M) | |
243 | { | |
e4f1fdae | 244 | ++statCounter.syscalls.disk.opens; |
bf8fe701 | 245 | debugs(79, 3, "storeDiskdOpenDone: status " << M->status); |
b9ae18aa | 246 | |
247 | if (M->status < 0) { | |
cb4185f1 | 248 | ++diskd_stats.open.fail; |
b9ae18aa | 249 | errorOccured = true; |
250 | } else { | |
cb4185f1 | 251 | ++diskd_stats.open.success; |
b9ae18aa | 252 | } |
253 | ||
254 | ioCompleted(); | |
255 | notifyClient(); | |
256 | } | |
257 | ||
258 | void | |
259 | DiskdFile::createDone(diomsg *M) | |
260 | { | |
e4f1fdae | 261 | ++statCounter.syscalls.disk.opens; |
bf8fe701 | 262 | debugs(79, 3, "storeDiskdCreateDone: status " << M->status); |
b9ae18aa | 263 | |
264 | if (M->status < 0) { | |
cb4185f1 | 265 | ++diskd_stats.create.fail; |
b9ae18aa | 266 | errorOccured = true; |
267 | } else { | |
cb4185f1 | 268 | ++diskd_stats.create.success; |
b9ae18aa | 269 | } |
270 | ||
271 | ioCompleted(); | |
272 | notifyClient(); | |
273 | } | |
274 | ||
275 | void | |
276 | DiskdFile::write(WriteRequest *aRequest) | |
277 | { | |
278 | debugs(79, 3, "DiskdFile::write: this " << (void *)this << ", buf " << (void *)aRequest->buf << ", off " << aRequest->offset << ", len " << aRequest->len); | |
ee139403 | 279 | ssize_t shm_offset; |
b9ae18aa | 280 | char *sbuf = (char *)IO->shm.get(&shm_offset); |
41d00cd3 | 281 | memcpy(sbuf, aRequest->buf, aRequest->len); |
b9ae18aa | 282 | |
283 | if (aRequest->free_func) | |
284 | aRequest->free_func(const_cast<char *>(aRequest->buf)); | |
285 | ||
286 | ioAway(); | |
287 | ||
288 | int x = IO->send(_MQD_WRITE, | |
289 | id, | |
290 | this, | |
ee139403 | 291 | aRequest->len, |
292 | aRequest->offset, | |
b9ae18aa | 293 | shm_offset, |
294 | aRequest); | |
295 | ||
296 | if (x < 0) { | |
3d0ac046 | 297 | ioCompleted(); |
b9ae18aa | 298 | errorOccured = true; |
e0236918 | 299 | debugs(79, DBG_IMPORTANT, "storeDiskdSend WRITE: " << xstrerror()); |
b9ae18aa | 300 | // IO->shm.put (shm_offset); |
301 | notifyClient(); | |
302 | ioRequestor = NULL; | |
303 | return; | |
304 | } | |
305 | ||
cb4185f1 | 306 | ++diskd_stats.write.ops; |
b9ae18aa | 307 | } |
308 | ||
309 | void | |
310 | DiskdFile::ioAway() | |
311 | { | |
312 | ++inProgressIOs; | |
313 | } | |
314 | ||
315 | void | |
316 | DiskdFile::ioCompleted() | |
317 | { | |
318 | --inProgressIOs; | |
319 | } | |
320 | ||
321 | void | |
322 | DiskdFile::closeDone(diomsg * M) | |
323 | { | |
e4f1fdae | 324 | ++statCounter.syscalls.disk.closes; |
bf8fe701 | 325 | debugs(79, 3, "DiskdFile::closeDone: status " << M->status); |
b9ae18aa | 326 | |
327 | if (M->status < 0) { | |
cb4185f1 | 328 | ++diskd_stats.close.fail; |
b9ae18aa | 329 | errorOccured = true; |
330 | } else { | |
cb4185f1 | 331 | ++diskd_stats.close.success; |
b9ae18aa | 332 | } |
333 | ||
334 | ioCompleted(); | |
335 | ||
336 | if (canNotifyClient()) | |
337 | ioRequestor->closeCompleted(); | |
338 | ||
339 | ioRequestor = NULL; | |
340 | } | |
341 | ||
342 | void | |
343 | DiskdFile::readDone(diomsg * M) | |
344 | { | |
e4f1fdae | 345 | ++statCounter.syscalls.disk.reads; |
bf8fe701 | 346 | debugs(79, 3, "DiskdFile::readDone: status " << M->status); |
b9ae18aa | 347 | assert (M->requestor); |
348 | ReadRequest::Pointer readRequest = dynamic_cast<ReadRequest *>(M->requestor); | |
e19994df | 349 | |
b9ae18aa | 350 | /* remove the free protection */ |
e19994df TH |
351 | if (readRequest != NULL) |
352 | readRequest->unlock(); | |
b9ae18aa | 353 | |
354 | if (M->status < 0) { | |
cb4185f1 | 355 | ++diskd_stats.read.fail; |
b9ae18aa | 356 | ioCompleted(); |
357 | errorOccured = true; | |
358 | ioRequestor->readCompleted(NULL, -1, DISK_ERROR, readRequest); | |
359 | return; | |
360 | } | |
361 | ||
cb4185f1 | 362 | ++diskd_stats.read.success; |
b9ae18aa | 363 | |
364 | ioCompleted(); | |
365 | ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK, readRequest); | |
366 | } | |
367 | ||
368 | void | |
369 | DiskdFile::writeDone(diomsg *M) | |
370 | { | |
e4f1fdae | 371 | ++statCounter.syscalls.disk.writes; |
bf8fe701 | 372 | debugs(79, 3, "storeDiskdWriteDone: status " << M->status); |
b9ae18aa | 373 | assert (M->requestor); |
374 | WriteRequest::Pointer writeRequest = dynamic_cast<WriteRequest *>(M->requestor); | |
375 | /* remove the free protection */ | |
e19994df TH |
376 | if (writeRequest != NULL) |
377 | writeRequest->unlock(); | |
b9ae18aa | 378 | |
379 | if (M->status < 0) { | |
380 | errorOccured = true; | |
cb4185f1 | 381 | ++diskd_stats.write.fail; |
b9ae18aa | 382 | ioCompleted(); |
383 | ioRequestor->writeCompleted (DISK_ERROR,0, writeRequest); | |
384 | return; | |
385 | } | |
386 | ||
cb4185f1 | 387 | ++diskd_stats.write.success; |
b9ae18aa | 388 | ioCompleted(); |
389 | ioRequestor->writeCompleted (DISK_OK,M->status, writeRequest); | |
390 | } | |
391 | ||
392 | bool | |
393 | DiskdFile::ioInProgress()const | |
394 | { | |
395 | return inProgressIOs != 0; | |
396 | } |