]>
Commit | Line | Data |
---|---|---|
b9ae18aa | 1 | |
2 | /* | |
b9ae18aa | 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. | |
26ac0430 | 19 | * |
b9ae18aa | 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. | |
26ac0430 | 24 | * |
b9ae18aa | 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 | ||
582c2af2 | 43 | #include "squid.h" |
b9ae18aa | 44 | #include "AIODiskFile.h" |
602d9612 | 45 | #include "AIODiskIOStrategy.h" |
b9ae18aa | 46 | #include "DiskIO/IORequestor.h" |
47 | #include "DiskIO/ReadRequest.h" | |
48 | #include "DiskIO/WriteRequest.h" | |
49 | ||
e19994df TH |
50 | AIODiskIOStrategy::AIODiskIOStrategy() : |
51 | fd(-1) | |
b9ae18aa | 52 | { |
e19994df | 53 | aq.aq_state = AQ_STATE_NONE; |
b9ae18aa | 54 | aq.aq_numpending = 0; |
e19994df | 55 | memset(&aq.aq_queue, 0, sizeof(aq.aq_queue)); |
b9ae18aa | 56 | } |
57 | ||
58 | AIODiskIOStrategy::~AIODiskIOStrategy() | |
59 | { | |
60 | assert(aq.aq_state == AQ_STATE_SETUP || | |
61 | aq.aq_numpending == 0); | |
62 | ||
63 | sync(); | |
64 | aq.aq_state = AQ_STATE_NONE; | |
65 | } | |
66 | ||
67 | bool | |
68 | AIODiskIOStrategy::shedLoad() | |
69 | { | |
70 | return false; | |
71 | } | |
72 | ||
73 | int | |
74 | AIODiskIOStrategy::load() | |
75 | { | |
76 | return aq.aq_numpending * 1000 / MAX_ASYNCOP; | |
77 | } | |
78 | ||
79 | RefCount<DiskFile> | |
80 | AIODiskIOStrategy::newFile (char const *path) | |
81 | { | |
82 | if (shedLoad()) { | |
83 | return NULL; | |
84 | } | |
85 | ||
86 | return new AIODiskFile (path, this); | |
87 | } | |
88 | ||
89 | void | |
90 | AIODiskIOStrategy::sync() | |
91 | { | |
92 | assert(aq.aq_state == AQ_STATE_SETUP); | |
93 | ||
94 | /* | |
95 | * Keep calling callback to complete ops until the queue is empty | |
96 | * We can't quit when callback returns 0 - some calls may not | |
97 | * return any completed pending events, but they're still pending! | |
98 | */ | |
99 | ||
100 | while (aq.aq_numpending) | |
101 | callback(); | |
102 | } | |
103 | ||
c521ad17 DK |
104 | bool |
105 | AIODiskIOStrategy::unlinkdUseful() const | |
106 | { | |
107 | return false; | |
108 | } | |
109 | ||
b9ae18aa | 110 | void |
111 | AIODiskIOStrategy::unlinkFile (char const *) | |
112 | {} | |
113 | ||
114 | /* | |
115 | * Note: we grab the state and free the state before calling the callback | |
116 | * because this allows us to cut down the amount of time it'll take | |
117 | * to find a free slot (since if we call the callback first, we're going | |
118 | * to probably be allocated the slot _after_ this one..) | |
119 | * | |
120 | * I'll make it much more optimal later. | |
121 | */ | |
122 | int | |
123 | AIODiskIOStrategy::callback() | |
124 | { | |
125 | return 0; | |
126 | int i; | |
127 | int completed = 0; | |
128 | int retval, reterr; | |
129 | FREE *freefunc; | |
130 | void *cbdata; | |
131 | int callback_valid; | |
132 | void *buf; | |
b9ae18aa | 133 | async_queue_entry_t *aqe; |
134 | async_queue_entry_type_t type; | |
135 | ||
136 | assert(aq.aq_state == AQ_STATE_SETUP); | |
137 | ||
138 | /* Loop through all slots */ | |
139 | ||
cb4185f1 | 140 | for (i = 0; i < MAX_ASYNCOP; ++i) { |
b9ae18aa | 141 | if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_USED) { |
142 | aqe = &aq.aq_queue[i]; | |
143 | /* Active, get status */ | |
144 | reterr = aio_error(&aqe->aq_e_aiocb); | |
145 | ||
146 | if (reterr < 0) { | |
147 | fatal("aio_error returned an error!\n"); | |
148 | } | |
149 | ||
150 | if (reterr != EINPROGRESS) { | |
151 | /* Get the return code */ | |
152 | retval = aio_return(&aqe->aq_e_aiocb); | |
153 | ||
154 | /* Get the callback parameters */ | |
155 | freefunc = aqe->aq_e_free; | |
156 | buf = aqe->aq_e_buf; | |
b9ae18aa | 157 | type = aqe->aq_e_type; |
158 | callback_valid = cbdataReferenceValidDone(aqe->aq_e_callback_data, &cbdata); | |
159 | AIODiskFile * theFile = NULL; | |
160 | void *theFileVoid = NULL; | |
8abf232c | 161 | void *theTmpFile = aqe->theFile; |
162 | bool fileOk = cbdataReferenceValidDone(theTmpFile, &theFileVoid); | |
b9ae18aa | 163 | |
164 | if (fileOk) { | |
165 | theFile = static_cast<AIODiskFile *>(theFileVoid); | |
166 | } | |
167 | ||
168 | /* Free slot */ | |
04830959 | 169 | memset(aqe, 0, sizeof(async_queue_entry_t)); |
b9ae18aa | 170 | |
171 | aqe->aq_e_state = AQ_ENTRY_FREE; | |
172 | ||
173 | --aq.aq_numpending; | |
174 | ||
175 | /* Callback */ | |
176 | ||
177 | if (callback_valid) { | |
178 | assert (fileOk); | |
179 | ||
180 | if (type == AQ_ENTRY_READ) | |
181 | theFile->ioRequestor->readCompleted((const char *)buf, retval, reterr, static_cast<ReadRequest *>(cbdata)); | |
182 | ||
183 | if (type == AQ_ENTRY_WRITE) | |
184 | theFile->ioRequestor->writeCompleted(reterr,retval, static_cast<WriteRequest *>(cbdata)); | |
185 | } | |
186 | ||
187 | if (type == AQ_ENTRY_WRITE && freefunc) | |
188 | freefunc(buf); | |
189 | } | |
190 | } | |
191 | } | |
192 | ||
193 | return completed; | |
194 | } | |
195 | ||
196 | void | |
197 | AIODiskIOStrategy::init() | |
198 | { | |
199 | /* Make sure the queue isn't setup */ | |
200 | assert(aq.aq_state == AQ_STATE_NONE); | |
201 | ||
202 | /* Loop through, blanking the queue entries */ | |
203 | ||
204 | /* Done */ | |
205 | aq.aq_state = AQ_STATE_SETUP; | |
206 | } | |
207 | ||
208 | void | |
209 | AIODiskIOStrategy::statfs(StoreEntry & sentry)const | |
26ac0430 | 210 | {} |
b9ae18aa | 211 | |
212 | ConfigOption * | |
213 | AIODiskIOStrategy::getOptionTree() const | |
214 | { | |
215 | return NULL; | |
216 | } | |
217 | ||
218 | /* | |
219 | * find a free aio slot. | |
220 | * Return the index, or -1 if we can't find one. | |
221 | */ | |
222 | int | |
223 | AIODiskIOStrategy::findSlot() | |
224 | { | |
225 | /* Later we should use something a little more .. efficient :) */ | |
226 | ||
cb4185f1 | 227 | for (int i = 0; i < MAX_ASYNCOP; ++i) { |
b9ae18aa | 228 | if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_FREE) |
229 | /* Found! */ | |
230 | return i; | |
231 | } | |
232 | ||
233 | /* found nothing */ | |
234 | return -1; | |
235 | } |