]>
Commit | Line | Data |
---|---|---|
b9ae18aa | 1 | |
2 | /* | |
04830959 | 3 | * $Id: AIODiskIOStrategy.cc,v 1.2 2005/03/10 21:49:20 serassio Exp $ |
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. | |
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.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; | |
126 | int fd; | |
127 | async_queue_entry_t *aqe; | |
128 | async_queue_entry_type_t type; | |
129 | ||
130 | assert(aq.aq_state == AQ_STATE_SETUP); | |
131 | ||
132 | /* Loop through all slots */ | |
133 | ||
134 | for (i = 0; i < MAX_ASYNCOP; i++) { | |
135 | if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_USED) { | |
136 | aqe = &aq.aq_queue[i]; | |
137 | /* Active, get status */ | |
138 | reterr = aio_error(&aqe->aq_e_aiocb); | |
139 | ||
140 | if (reterr < 0) { | |
141 | fatal("aio_error returned an error!\n"); | |
142 | } | |
143 | ||
144 | if (reterr != EINPROGRESS) { | |
145 | /* Get the return code */ | |
146 | retval = aio_return(&aqe->aq_e_aiocb); | |
147 | ||
148 | /* Get the callback parameters */ | |
149 | freefunc = aqe->aq_e_free; | |
150 | buf = aqe->aq_e_buf; | |
151 | fd = aqe->aq_e_fd; | |
152 | type = aqe->aq_e_type; | |
153 | callback_valid = cbdataReferenceValidDone(aqe->aq_e_callback_data, &cbdata); | |
154 | AIODiskFile * theFile = NULL; | |
155 | void *theFileVoid = NULL; | |
156 | bool fileOk = cbdataReferenceValidDone(aqe->theFile, &theFileVoid); | |
157 | ||
158 | if (fileOk) { | |
159 | theFile = static_cast<AIODiskFile *>(theFileVoid); | |
160 | } | |
161 | ||
162 | /* Free slot */ | |
04830959 | 163 | memset(aqe, 0, sizeof(async_queue_entry_t)); |
b9ae18aa | 164 | |
165 | aqe->aq_e_state = AQ_ENTRY_FREE; | |
166 | ||
167 | --aq.aq_numpending; | |
168 | ||
169 | /* Callback */ | |
170 | ||
171 | if (callback_valid) { | |
172 | assert (fileOk); | |
173 | ||
174 | if (type == AQ_ENTRY_READ) | |
175 | theFile->ioRequestor->readCompleted((const char *)buf, retval, reterr, static_cast<ReadRequest *>(cbdata)); | |
176 | ||
177 | if (type == AQ_ENTRY_WRITE) | |
178 | theFile->ioRequestor->writeCompleted(reterr,retval, static_cast<WriteRequest *>(cbdata)); | |
179 | } | |
180 | ||
181 | if (type == AQ_ENTRY_WRITE && freefunc) | |
182 | freefunc(buf); | |
183 | } | |
184 | } | |
185 | } | |
186 | ||
187 | return completed; | |
188 | } | |
189 | ||
190 | void | |
191 | AIODiskIOStrategy::init() | |
192 | { | |
193 | /* Make sure the queue isn't setup */ | |
194 | assert(aq.aq_state == AQ_STATE_NONE); | |
195 | ||
196 | /* Loop through, blanking the queue entries */ | |
197 | ||
198 | /* Done */ | |
199 | aq.aq_state = AQ_STATE_SETUP; | |
200 | } | |
201 | ||
202 | void | |
203 | AIODiskIOStrategy::statfs(StoreEntry & sentry)const | |
204 | {} | |
205 | ||
206 | ConfigOption * | |
207 | AIODiskIOStrategy::getOptionTree() const | |
208 | { | |
209 | return NULL; | |
210 | } | |
211 | ||
212 | /* | |
213 | * find a free aio slot. | |
214 | * Return the index, or -1 if we can't find one. | |
215 | */ | |
216 | int | |
217 | AIODiskIOStrategy::findSlot() | |
218 | { | |
219 | /* Later we should use something a little more .. efficient :) */ | |
220 | ||
221 | for (int i = 0; i < MAX_ASYNCOP; i++) { | |
222 | if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_FREE) | |
223 | /* Found! */ | |
224 | return i; | |
225 | } | |
226 | ||
227 | /* found nothing */ | |
228 | return -1; | |
229 | } |