]>
Commit | Line | Data |
---|---|---|
b9ae18aa | 1 | |
2 | /* | |
262a0e14 | 3 | * $Id$ |
b9ae18aa | 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. | |
26ac0430 | 21 | * |
b9ae18aa | 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. | |
26ac0430 | 26 | * |
b9ae18aa | 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.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 | void | |
104 | AIODiskIOStrategy::unlinkFile (char const *) | |
105 | {} | |
106 | ||
107 | /* | |
108 | * Note: we grab the state and free the state before calling the callback | |
109 | * because this allows us to cut down the amount of time it'll take | |
110 | * to find a free slot (since if we call the callback first, we're going | |
111 | * to probably be allocated the slot _after_ this one..) | |
112 | * | |
113 | * I'll make it much more optimal later. | |
114 | */ | |
115 | int | |
116 | AIODiskIOStrategy::callback() | |
117 | { | |
118 | return 0; | |
119 | int i; | |
120 | int completed = 0; | |
121 | int retval, reterr; | |
122 | FREE *freefunc; | |
123 | void *cbdata; | |
124 | int callback_valid; | |
125 | void *buf; | |
b9ae18aa | 126 | async_queue_entry_t *aqe; |
127 | async_queue_entry_type_t type; | |
128 | ||
129 | assert(aq.aq_state == AQ_STATE_SETUP); | |
130 | ||
131 | /* Loop through all slots */ | |
132 | ||
133 | for (i = 0; i < MAX_ASYNCOP; i++) { | |
134 | if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_USED) { | |
135 | aqe = &aq.aq_queue[i]; | |
136 | /* Active, get status */ | |
137 | reterr = aio_error(&aqe->aq_e_aiocb); | |
138 | ||
139 | if (reterr < 0) { | |
140 | fatal("aio_error returned an error!\n"); | |
141 | } | |
142 | ||
143 | if (reterr != EINPROGRESS) { | |
144 | /* Get the return code */ | |
145 | retval = aio_return(&aqe->aq_e_aiocb); | |
146 | ||
147 | /* Get the callback parameters */ | |
148 | freefunc = aqe->aq_e_free; | |
149 | buf = aqe->aq_e_buf; | |
b9ae18aa | 150 | type = aqe->aq_e_type; |
151 | callback_valid = cbdataReferenceValidDone(aqe->aq_e_callback_data, &cbdata); | |
152 | AIODiskFile * theFile = NULL; | |
153 | void *theFileVoid = NULL; | |
8abf232c | 154 | void *theTmpFile = aqe->theFile; |
155 | bool fileOk = cbdataReferenceValidDone(theTmpFile, &theFileVoid); | |
b9ae18aa | 156 | |
157 | if (fileOk) { | |
158 | theFile = static_cast<AIODiskFile *>(theFileVoid); | |
159 | } | |
160 | ||
161 | /* Free slot */ | |
04830959 | 162 | memset(aqe, 0, sizeof(async_queue_entry_t)); |
b9ae18aa | 163 | |
164 | aqe->aq_e_state = AQ_ENTRY_FREE; | |
165 | ||
166 | --aq.aq_numpending; | |
167 | ||
168 | /* Callback */ | |
169 | ||
170 | if (callback_valid) { | |
171 | assert (fileOk); | |
172 | ||
173 | if (type == AQ_ENTRY_READ) | |
174 | theFile->ioRequestor->readCompleted((const char *)buf, retval, reterr, static_cast<ReadRequest *>(cbdata)); | |
175 | ||
176 | if (type == AQ_ENTRY_WRITE) | |
177 | theFile->ioRequestor->writeCompleted(reterr,retval, static_cast<WriteRequest *>(cbdata)); | |
178 | } | |
179 | ||
180 | if (type == AQ_ENTRY_WRITE && freefunc) | |
181 | freefunc(buf); | |
182 | } | |
183 | } | |
184 | } | |
185 | ||
186 | return completed; | |
187 | } | |
188 | ||
189 | void | |
190 | AIODiskIOStrategy::init() | |
191 | { | |
192 | /* Make sure the queue isn't setup */ | |
193 | assert(aq.aq_state == AQ_STATE_NONE); | |
194 | ||
195 | /* Loop through, blanking the queue entries */ | |
196 | ||
197 | /* Done */ | |
198 | aq.aq_state = AQ_STATE_SETUP; | |
199 | } | |
200 | ||
201 | void | |
202 | AIODiskIOStrategy::statfs(StoreEntry & sentry)const | |
26ac0430 | 203 | {} |
b9ae18aa | 204 | |
205 | ConfigOption * | |
206 | AIODiskIOStrategy::getOptionTree() const | |
207 | { | |
208 | return NULL; | |
209 | } | |
210 | ||
211 | /* | |
212 | * find a free aio slot. | |
213 | * Return the index, or -1 if we can't find one. | |
214 | */ | |
215 | int | |
216 | AIODiskIOStrategy::findSlot() | |
217 | { | |
218 | /* Later we should use something a little more .. efficient :) */ | |
219 | ||
220 | for (int i = 0; i < MAX_ASYNCOP; i++) { | |
221 | if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_FREE) | |
222 | /* Found! */ | |
223 | return i; | |
224 | } | |
225 | ||
226 | /* found nothing */ | |
227 | return -1; | |
228 | } |