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