]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/AIO/AIODiskIOStrategy.cc
Renamed squid.h to squid-old.h and config.h to squid.h
[thirdparty/squid.git] / src / DiskIO / AIO / AIODiskIOStrategy.cc
1
2 /*
3 * $Id$
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
32 */
33 /*
34 * Author: Adrian Chadd <adrian@squid-cache.org>
35 *
36 * These routines are simple plugin replacements for the file_* routines
37 * in disk.c . They back-end into the POSIX AIO routines to provide
38 * a nice and simple async IO framework for COSS.
39 *
40 * AIO is suitable for COSS - the only sync operations that the standard
41 * supports are read/write, and since COSS works on a single file
42 * per storedir it should work just fine.
43 */
44
45 #include "squid-old.h"
46 #include "AIODiskIOStrategy.h"
47 #include "AIODiskFile.h"
48 #include "DiskIO/IORequestor.h"
49 #include "DiskIO/ReadRequest.h"
50 #include "DiskIO/WriteRequest.h"
51
52 AIODiskIOStrategy::AIODiskIOStrategy()
53 {
54 aq.aq_numpending = 0;
55 }
56
57 AIODiskIOStrategy::~AIODiskIOStrategy()
58 {
59 assert(aq.aq_state == AQ_STATE_SETUP ||
60 aq.aq_numpending == 0);
61
62 sync();
63 aq.aq_state = AQ_STATE_NONE;
64 }
65
66 bool
67 AIODiskIOStrategy::shedLoad()
68 {
69 return false;
70 }
71
72 int
73 AIODiskIOStrategy::load()
74 {
75 return aq.aq_numpending * 1000 / MAX_ASYNCOP;
76 }
77
78 RefCount<DiskFile>
79 AIODiskIOStrategy::newFile (char const *path)
80 {
81 if (shedLoad()) {
82 return NULL;
83 }
84
85 return new AIODiskFile (path, this);
86 }
87
88 void
89 AIODiskIOStrategy::sync()
90 {
91 assert(aq.aq_state == AQ_STATE_SETUP);
92
93 /*
94 * Keep calling callback to complete ops until the queue is empty
95 * We can't quit when callback returns 0 - some calls may not
96 * return any completed pending events, but they're still pending!
97 */
98
99 while (aq.aq_numpending)
100 callback();
101 }
102
103 bool
104 AIODiskIOStrategy::unlinkdUseful() const
105 {
106 return false;
107 }
108
109 void
110 AIODiskIOStrategy::unlinkFile (char const *)
111 {}
112
113 /*
114 * Note: we grab the state and free the state before calling the callback
115 * because this allows us to cut down the amount of time it'll take
116 * to find a free slot (since if we call the callback first, we're going
117 * to probably be allocated the slot _after_ this one..)
118 *
119 * I'll make it much more optimal later.
120 */
121 int
122 AIODiskIOStrategy::callback()
123 {
124 return 0;
125 int i;
126 int completed = 0;
127 int retval, reterr;
128 FREE *freefunc;
129 void *cbdata;
130 int callback_valid;
131 void *buf;
132 async_queue_entry_t *aqe;
133 async_queue_entry_type_t type;
134
135 assert(aq.aq_state == AQ_STATE_SETUP);
136
137 /* Loop through all slots */
138
139 for (i = 0; i < MAX_ASYNCOP; i++) {
140 if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_USED) {
141 aqe = &aq.aq_queue[i];
142 /* Active, get status */
143 reterr = aio_error(&aqe->aq_e_aiocb);
144
145 if (reterr < 0) {
146 fatal("aio_error returned an error!\n");
147 }
148
149 if (reterr != EINPROGRESS) {
150 /* Get the return code */
151 retval = aio_return(&aqe->aq_e_aiocb);
152
153 /* Get the callback parameters */
154 freefunc = aqe->aq_e_free;
155 buf = aqe->aq_e_buf;
156 type = aqe->aq_e_type;
157 callback_valid = cbdataReferenceValidDone(aqe->aq_e_callback_data, &cbdata);
158 AIODiskFile * theFile = NULL;
159 void *theFileVoid = NULL;
160 void *theTmpFile = aqe->theFile;
161 bool fileOk = cbdataReferenceValidDone(theTmpFile, &theFileVoid);
162
163 if (fileOk) {
164 theFile = static_cast<AIODiskFile *>(theFileVoid);
165 }
166
167 /* Free slot */
168 memset(aqe, 0, sizeof(async_queue_entry_t));
169
170 aqe->aq_e_state = AQ_ENTRY_FREE;
171
172 --aq.aq_numpending;
173
174 /* Callback */
175
176 if (callback_valid) {
177 assert (fileOk);
178
179 if (type == AQ_ENTRY_READ)
180 theFile->ioRequestor->readCompleted((const char *)buf, retval, reterr, static_cast<ReadRequest *>(cbdata));
181
182 if (type == AQ_ENTRY_WRITE)
183 theFile->ioRequestor->writeCompleted(reterr,retval, static_cast<WriteRequest *>(cbdata));
184 }
185
186 if (type == AQ_ENTRY_WRITE && freefunc)
187 freefunc(buf);
188 }
189 }
190 }
191
192 return completed;
193 }
194
195 void
196 AIODiskIOStrategy::init()
197 {
198 /* Make sure the queue isn't setup */
199 assert(aq.aq_state == AQ_STATE_NONE);
200
201 /* Loop through, blanking the queue entries */
202
203 /* Done */
204 aq.aq_state = AQ_STATE_SETUP;
205 }
206
207 void
208 AIODiskIOStrategy::statfs(StoreEntry & sentry)const
209 {}
210
211 ConfigOption *
212 AIODiskIOStrategy::getOptionTree() const
213 {
214 return NULL;
215 }
216
217 /*
218 * find a free aio slot.
219 * Return the index, or -1 if we can't find one.
220 */
221 int
222 AIODiskIOStrategy::findSlot()
223 {
224 /* Later we should use something a little more .. efficient :) */
225
226 for (int i = 0; i < MAX_ASYNCOP; i++) {
227 if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_FREE)
228 /* Found! */
229 return i;
230 }
231
232 /* found nothing */
233 return -1;
234 }