]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/AIO/AIODiskFile.cc
Boilerplate: update copyright blurbs on src/
[thirdparty/squid.git] / src / DiskIO / AIO / AIODiskFile.cc
1 /*
2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
3 *
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.
7 */
8
9 /* DEBUG: section 79 Disk IO Routines */
10
11 /**
12 * \par
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 *
17 * \par
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
23 #include "squid.h"
24 #include "AIODiskFile.h"
25 #include "AIODiskIOStrategy.h"
26 #include "disk.h"
27 #include "DiskIO/IORequestor.h"
28 #include "DiskIO/ReadRequest.h"
29 #include "DiskIO/WriteRequest.h"
30 #include "globals.h"
31
32 #include <cerrno>
33
34 CBDATA_CLASS_INIT(AIODiskFile);
35
36 AIODiskFile::AIODiskFile(char const *aPath, AIODiskIOStrategy *aStrategy) : fd(-1), closed(true), error_(false)
37 {
38 assert (aPath);
39 path = aPath;
40 strategy = aStrategy;
41 debugs(79, 3, "AIODiskFile::AIODiskFile: " << aPath);
42 }
43
44 AIODiskFile::~AIODiskFile()
45 {}
46
47 void
48 AIODiskFile::error(bool const &aBool)
49 {
50 error_ = aBool;
51 }
52
53 void
54 AIODiskFile::open(int flags, mode_t mode, RefCount<IORequestor> callback)
55 {
56 /* Simulate async calls */
57 #if _SQUID_WINDOWS_
58 fd = aio_open(path.termedBuf(), flags);
59 #else
60 fd = file_open(path.termedBuf() , flags);
61 #endif
62
63 ioRequestor = callback;
64
65 if (fd < 0) {
66 debugs(79, 3, HERE << ": got failure (" << errno << ")");
67 error(true);
68 } else {
69 closed = false;
70 ++store_open_disk_fd;
71 debugs(79, 3, HERE << ": opened FD " << fd);
72 }
73
74 callback->ioCompletedNotification();
75 }
76
77 void
78 AIODiskFile::create(int flags, mode_t mode, RefCount<IORequestor> callback)
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");
98 debugs(79, DBG_IMPORTANT, "WARNING: out of aiocb slots!");
99 /* fall back to blocking method */
100 // file_read(fd, request->buf, request->len, request->offset, callback, data);
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 */
130 ++ strategy->aq.aq_numpending;
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);
135 debugs(79, DBG_IMPORTANT, "WARNING: aio_read() returned error: " << xstrerror());
136 /* fall back to blocking method */
137 // file_read(fd, request->buf, request->len, request->offset, callback, data);
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");
156 debugs(79, DBG_IMPORTANT, "WARNING: out of aiocb slots!");
157 /* fall back to blocking method */
158 // file_write(fd, offset, buf, len, callback, data, freefunc);
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) {
192 fatalf("Aiee! aio_write() returned error (%d) FIXME and wrap file_write !\n", errno);
193 debugs(79, DBG_IMPORTANT, "WARNING: aio_write() returned error: " << xstrerror());
194 /* fall back to blocking method */
195 // file_write(fd, offset, buf, len, callback, data, freefunc);
196 }
197 }
198
199 void
200 AIODiskFile::close ()
201 {
202 assert (!closed);
203 #if _SQUID_WINDOWS_
204 aio_close(fd);
205 #else
206 file_close(fd);
207 #endif
208
209 fd = -1;
210 closed = true;
211 assert (ioRequestor != NULL);
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 }