]>
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 | */ |
63be0a78 | 8 | |
a151895d | 9 | /* DEBUG: section 79 Disk IO Routines */ |
bbc27441 | 10 | |
63be0a78 | 11 | /** |
bbc27441 | 12 | * \par |
b9ae18aa | 13 | * These routines are simple plugin replacements for the file_* routines |
14 | * in disk.c . They back-end into the POSIX AIO routines to provide | |
15 | * a nice and simple async IO framework for COSS. | |
16 | * | |
bbc27441 | 17 | * \par |
b9ae18aa | 18 | * AIO is suitable for COSS - the only sync operations that the standard |
19 | * supports are read/write, and since COSS works on a single file | |
20 | * per storedir it should work just fine. | |
21 | */ | |
22 | ||
582c2af2 | 23 | #include "squid.h" |
b9ae18aa | 24 | #include "AIODiskFile.h" |
25 | #include "AIODiskIOStrategy.h" | |
602d9612 | 26 | #include "disk.h" |
b9ae18aa | 27 | #include "DiskIO/IORequestor.h" |
28 | #include "DiskIO/ReadRequest.h" | |
29 | #include "DiskIO/WriteRequest.h" | |
67679543 | 30 | #include "globals.h" |
b9ae18aa | 31 | |
1a30fdf5 | 32 | #include <cerrno> |
21d845b1 | 33 | |
b9ae18aa | 34 | CBDATA_CLASS_INIT(AIODiskFile); |
b9ae18aa | 35 | |
63be0a78 | 36 | AIODiskFile::AIODiskFile(char const *aPath, AIODiskIOStrategy *aStrategy) : fd(-1), closed(true), error_(false) |
b9ae18aa | 37 | { |
38 | assert (aPath); | |
39 | path = aPath; | |
40 | strategy = aStrategy; | |
bf8fe701 | 41 | debugs(79, 3, "AIODiskFile::AIODiskFile: " << aPath); |
b9ae18aa | 42 | } |
43 | ||
44 | AIODiskFile::~AIODiskFile() | |
45 | {} | |
46 | ||
47 | void | |
48 | AIODiskFile::error(bool const &aBool) | |
49 | { | |
50 | error_ = aBool; | |
51 | } | |
52 | ||
53 | void | |
63be0a78 | 54 | AIODiskFile::open(int flags, mode_t mode, RefCount<IORequestor> callback) |
b9ae18aa | 55 | { |
56 | /* Simulate async calls */ | |
be266cb2 | 57 | #if _SQUID_WINDOWS_ |
a7a42b14 | 58 | fd = aio_open(path.termedBuf(), flags); |
abb2a3d9 | 59 | #else |
a7a42b14 | 60 | fd = file_open(path.termedBuf() , flags); |
abb2a3d9 | 61 | #endif |
62 | ||
b9ae18aa | 63 | ioRequestor = callback; |
64 | ||
65 | if (fd < 0) { | |
63be0a78 | 66 | debugs(79, 3, HERE << ": got failure (" << errno << ")"); |
b9ae18aa | 67 | error(true); |
68 | } else { | |
69 | closed = false; | |
cb4185f1 | 70 | ++store_open_disk_fd; |
63be0a78 | 71 | debugs(79, 3, HERE << ": opened FD " << fd); |
b9ae18aa | 72 | } |
73 | ||
74 | callback->ioCompletedNotification(); | |
75 | } | |
76 | ||
77 | void | |
63be0a78 | 78 | AIODiskFile::create(int flags, mode_t mode, RefCount<IORequestor> callback) |
b9ae18aa | 79 | { |
80 | /* We use the same logic path for open */ | |
81 | open(flags, mode, callback); | |
82 | } | |
83 | ||
84 | void | |
85 | AIODiskFile::read(ReadRequest *request) | |
86 | { | |
87 | int slot; | |
88 | async_queue_entry_t *qe; | |
89 | ||
90 | assert(strategy->aq.aq_state == AQ_STATE_SETUP); | |
91 | ||
92 | /* Find a free slot */ | |
93 | slot = strategy->findSlot(); | |
94 | ||
95 | if (slot < 0) { | |
96 | /* No free slot? Callback error, and return */ | |
97 | fatal("Aiee! out of aiocb slots! - FIXME and wrap file_read\n"); | |
e0236918 | 98 | debugs(79, DBG_IMPORTANT, "WARNING: out of aiocb slots!"); |
b9ae18aa | 99 | /* fall back to blocking method */ |
bb790702 | 100 | // file_read(fd, request->buf, request->len, request->offset, callback, data); |
b9ae18aa | 101 | return; |
102 | } | |
103 | ||
104 | /* Mark slot as ours */ | |
105 | qe = &strategy->aq.aq_queue[slot]; | |
106 | ||
107 | qe->aq_e_state = AQ_ENTRY_USED; | |
108 | ||
109 | qe->aq_e_callback_data = cbdataReference(request); | |
110 | ||
111 | qe->theFile = cbdataReference(this); | |
112 | ||
113 | qe->aq_e_type = AQ_ENTRY_READ; | |
114 | ||
115 | qe->aq_e_free = NULL; | |
116 | ||
117 | qe->aq_e_buf = request->buf; | |
118 | ||
119 | qe->aq_e_fd = getFD(); | |
120 | ||
121 | qe->aq_e_aiocb.aio_fildes = getFD(); | |
122 | ||
123 | qe->aq_e_aiocb.aio_nbytes = request->len; | |
124 | ||
125 | qe->aq_e_aiocb.aio_offset = request->offset; | |
126 | ||
127 | qe->aq_e_aiocb.aio_buf = request->buf; | |
128 | ||
129 | /* Account */ | |
cb4185f1 | 130 | ++ strategy->aq.aq_numpending; |
b9ae18aa | 131 | |
132 | /* Initiate aio */ | |
133 | if (aio_read(&qe->aq_e_aiocb) < 0) { | |
134 | fatalf("Aiee! aio_read() returned error (%d) FIXME and wrap file_read !\n", errno); | |
e0236918 | 135 | debugs(79, DBG_IMPORTANT, "WARNING: aio_read() returned error: " << xstrerror()); |
b9ae18aa | 136 | /* fall back to blocking method */ |
bb790702 | 137 | // file_read(fd, request->buf, request->len, request->offset, callback, data); |
b9ae18aa | 138 | } |
139 | ||
140 | } | |
141 | ||
142 | void | |
143 | AIODiskFile::write(WriteRequest *request) | |
144 | { | |
145 | int slot; | |
146 | async_queue_entry_t *qe; | |
147 | ||
148 | assert(strategy->aq.aq_state == AQ_STATE_SETUP); | |
149 | ||
150 | /* Find a free slot */ | |
151 | slot = strategy->findSlot(); | |
152 | ||
153 | if (slot < 0) { | |
154 | /* No free slot? Callback error, and return */ | |
155 | fatal("Aiee! out of aiocb slots FIXME and wrap file_write !\n"); | |
e0236918 | 156 | debugs(79, DBG_IMPORTANT, "WARNING: out of aiocb slots!"); |
b9ae18aa | 157 | /* fall back to blocking method */ |
bb790702 | 158 | // file_write(fd, offset, buf, len, callback, data, freefunc); |
b9ae18aa | 159 | return; |
160 | } | |
161 | ||
162 | /* Mark slot as ours */ | |
163 | qe = &strategy->aq.aq_queue[slot]; | |
164 | ||
165 | qe->aq_e_state = AQ_ENTRY_USED; | |
166 | ||
167 | qe->aq_e_callback_data = cbdataReference(request); | |
168 | ||
169 | qe->theFile = cbdataReference(this); | |
170 | ||
171 | qe->aq_e_type = AQ_ENTRY_WRITE; | |
172 | ||
173 | qe->aq_e_free = request->free_func; | |
174 | ||
175 | qe->aq_e_buf = (void *)request->buf; | |
176 | ||
177 | qe->aq_e_fd = fd; | |
178 | ||
179 | qe->aq_e_aiocb.aio_fildes = fd; | |
180 | ||
181 | qe->aq_e_aiocb.aio_nbytes = request->len; | |
182 | ||
183 | qe->aq_e_aiocb.aio_offset = request->offset; | |
184 | ||
185 | qe->aq_e_aiocb.aio_buf = (void *)request->buf; | |
186 | ||
187 | /* Account */ | |
188 | ++strategy->aq.aq_numpending; | |
189 | ||
190 | /* Initiate aio */ | |
191 | if (aio_write(&qe->aq_e_aiocb) < 0) { | |
abb2a3d9 | 192 | fatalf("Aiee! aio_write() returned error (%d) FIXME and wrap file_write !\n", errno); |
e0236918 | 193 | debugs(79, DBG_IMPORTANT, "WARNING: aio_write() returned error: " << xstrerror()); |
b9ae18aa | 194 | /* fall back to blocking method */ |
bb790702 | 195 | // file_write(fd, offset, buf, len, callback, data, freefunc); |
b9ae18aa | 196 | } |
197 | } | |
198 | ||
199 | void | |
200 | AIODiskFile::close () | |
201 | { | |
202 | assert (!closed); | |
be266cb2 | 203 | #if _SQUID_WINDOWS_ |
abb2a3d9 | 204 | aio_close(fd); |
205 | #else | |
b9ae18aa | 206 | file_close(fd); |
abb2a3d9 | 207 | #endif |
208 | ||
b9ae18aa | 209 | fd = -1; |
210 | closed = true; | |
c6062184 | 211 | assert (ioRequestor != NULL); |
b9ae18aa | 212 | ioRequestor->closeCompleted(); |
213 | } | |
214 | ||
215 | bool | |
216 | AIODiskFile::canRead() const | |
217 | { | |
218 | return true; | |
219 | } | |
220 | ||
221 | bool | |
222 | AIODiskFile::canWrite() const | |
223 | { | |
224 | return true; | |
225 | } | |
226 | ||
227 | int | |
228 | AIODiskFile::getFD() const | |
229 | { | |
230 | return fd; | |
231 | } | |
232 | ||
233 | bool | |
234 | AIODiskFile::error() const | |
235 | { | |
236 | return error_; | |
237 | } | |
238 | ||
239 | bool | |
240 | AIODiskFile::ioInProgress() const | |
241 | { | |
242 | return false; | |
243 | } | |
f53969cc | 244 |