]>
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 "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 | ||
c521ad17 DK |
101 | bool |
102 | AIODiskIOStrategy::unlinkdUseful() const | |
103 | { | |
104 | return false; | |
105 | } | |
106 | ||
b9ae18aa | 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; | |
b9ae18aa | 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 | ||
cb4185f1 | 137 | for (i = 0; i < MAX_ASYNCOP; ++i) { |
b9ae18aa | 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; | |
b9ae18aa | 154 | type = aqe->aq_e_type; |
155 | callback_valid = cbdataReferenceValidDone(aqe->aq_e_callback_data, &cbdata); | |
156 | AIODiskFile * theFile = NULL; | |
157 | void *theFileVoid = NULL; | |
8abf232c | 158 | void *theTmpFile = aqe->theFile; |
159 | bool fileOk = cbdataReferenceValidDone(theTmpFile, &theFileVoid); | |
b9ae18aa | 160 | |
161 | if (fileOk) { | |
162 | theFile = static_cast<AIODiskFile *>(theFileVoid); | |
163 | } | |
164 | ||
165 | /* Free slot */ | |
04830959 | 166 | memset(aqe, 0, sizeof(async_queue_entry_t)); |
b9ae18aa | 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 | |
26ac0430 | 207 | {} |
b9ae18aa | 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 | ||
cb4185f1 | 224 | for (int i = 0; i < MAX_ASYNCOP; ++i) { |
b9ae18aa | 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 | } |