]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskThreads/DiskThreadsIOStrategy.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / DiskIO / DiskThreads / DiskThreadsIOStrategy.cc
1
2 /*
3 * $Id$
4 *
5 * DEBUG: section 79 Squid-side Disk I/O functions.
6 * AUTHOR: Robert Collins
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
35 */
36
37 #include "squid.h"
38
39 #include "DiskThreadsDiskFile.h"
40 #include "DiskThreadsIOStrategy.h"
41 #include "fde.h"
42 #include "mgr/Registration.h"
43 #include "StatCounters.h"
44 /* for statfs */
45 #include "Store.h"
46
47 void
48 DiskThreadsIOStrategy::init(void)
49 {
50 if (initialised)
51 return;
52
53 squidaio_ctrl_pool = memPoolCreate("aio_ctrl", sizeof(squidaio_ctrl_t));
54
55 initialised = true;
56
57 /*
58 * We'd like to call squidaio_init() here, but the configuration
59 * hasn't been parsed yet and we don't know how many cache_dirs
60 * there are, which means we don't know how many threads to start.
61 */
62
63 registerWithCacheManager();
64 }
65
66 void
67 DiskThreadsIOStrategy::registerWithCacheManager(void)
68 {
69 Mgr::RegisterAction("squidaio_counts", "Async IO Function Counters",
70 aioStats, 0, 1);
71 }
72
73 void
74 DiskThreadsIOStrategy::done(void)
75 {
76 if (!initialised)
77 return;
78
79 squidaio_shutdown();
80
81 delete squidaio_ctrl_pool;
82
83 squidaio_ctrl_pool = NULL;
84
85 initialised = false;
86 }
87
88 int
89 DiskThreadsIOStrategy::callback()
90 {
91 squidaio_result_t *resultp;
92 squidaio_ctrl_t *ctrlp;
93 int retval = 0;
94
95 assert(initialised);
96 ++squidaio_counts.check_callback;
97
98 for (;;) {
99 if ((resultp = squidaio_poll_done()) == NULL)
100 break;
101
102 ctrlp = (squidaio_ctrl_t *) resultp->data;
103
104 switch (resultp->result_type) {
105
106 case _AIO_OP_NONE:
107
108 case _AIO_OP_OPENDIR:
109 break;
110
111 case _AIO_OP_OPEN:
112 ++squidaio_counts.open_finish;
113 break;
114
115 case _AIO_OP_READ:
116 ++squidaio_counts.read_finish;
117 break;
118
119 case _AIO_OP_WRITE:
120 ++squidaio_counts.write_finish;
121 break;
122
123 case _AIO_OP_CLOSE:
124 ++squidaio_counts.close_finish;
125 break;
126
127 case _AIO_OP_UNLINK:
128 ++squidaio_counts.unlink_finish;
129 break;
130
131 case _AIO_OP_STAT:
132 ++squidaio_counts.stat_finish;
133 break;
134 }
135
136 if (ctrlp == NULL)
137 continue; /* XXX Should not happen */
138
139 dlinkDelete(&ctrlp->node, &used_list);
140
141 if (ctrlp->done_handler) {
142 AIOCB *done_callback = ctrlp->done_handler;
143 void *cbdata;
144 ctrlp->done_handler = NULL;
145
146 if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) {
147 retval = 1; /* Return that we've actually done some work */
148 done_callback(ctrlp->fd, cbdata, ctrlp->bufp,
149 ctrlp->result.aio_return, ctrlp->result.aio_errno);
150 } else {
151 if (ctrlp->operation == _AIO_OPEN) {
152 /* The open operation was aborted.. */
153 int fd = ctrlp->result.aio_return;
154
155 if (fd >= 0)
156 aioClose(fd);
157 }
158 }
159 }
160
161 /* free data if requested to aioWrite() */
162 if (ctrlp->free_func)
163 ctrlp->free_func(ctrlp->bufp);
164
165 /* free temporary read buffer */
166 if (ctrlp->operation == _AIO_READ)
167 squidaio_xfree(ctrlp->bufp, ctrlp->len);
168
169 squidaio_ctrl_pool->freeOne(ctrlp);
170 }
171
172 return retval;
173 }
174
175 /* Flush all pending I/O */
176 void
177 DiskThreadsIOStrategy::sync()
178 {
179 if (!initialised)
180 return; /* nothing to do then */
181
182 /* Flush all pending operations */
183 debugs(32, 2, "aioSync: flushing pending I/O operations");
184
185 do {
186 callback();
187 } while (squidaio_sync());
188
189 debugs(32, 2, "aioSync: done");
190 }
191
192 DiskThreadsIOStrategy::DiskThreadsIOStrategy() : initialised (false) {}
193
194 void
195 DiskThreadsIOStrategy::aioStats(StoreEntry * sentry)
196 {
197 storeAppendPrintf(sentry, "ASYNC IO Counters:\n");
198 storeAppendPrintf(sentry, "Operation\t# Requests\tNumber serviced\n");
199 storeAppendPrintf(sentry, "open\t%d\t%d\n", squidaio_counts.open_start, squidaio_counts.open_finish);
200 storeAppendPrintf(sentry, "close\t%d\t%d\n", squidaio_counts.close_start, squidaio_counts.close_finish);
201 storeAppendPrintf(sentry, "cancel\t%d\t-\n", squidaio_counts.cancel);
202 storeAppendPrintf(sentry, "write\t%d\t%d\n", squidaio_counts.write_start, squidaio_counts.write_finish);
203 storeAppendPrintf(sentry, "read\t%d\t%d\n", squidaio_counts.read_start, squidaio_counts.read_finish);
204 storeAppendPrintf(sentry, "stat\t%d\t%d\n", squidaio_counts.stat_start, squidaio_counts.stat_finish);
205 storeAppendPrintf(sentry, "unlink\t%d\t%d\n", squidaio_counts.unlink_start, squidaio_counts.unlink_finish);
206 storeAppendPrintf(sentry, "check_callback\t%d\t-\n", squidaio_counts.check_callback);
207 storeAppendPrintf(sentry, "queue\t%d\t-\n", squidaio_get_queue_len());
208 squidaio_stats(sentry);
209 }
210
211 DiskThreadsIOStrategy DiskThreadsIOStrategy::Instance;
212 bool
213 DiskThreadsIOStrategy::shedLoad()
214 {
215 /*
216 * we should detect some 'too many files open' condition and return
217 * NULL here.
218 */
219 #ifdef MAGIC2
220
221 if (aioQueueSize() > MAGIC2)
222 return true;
223
224 #endif
225
226 return false;
227 }
228
229 int
230 DiskThreadsIOStrategy::load()
231 {
232 int loadav;
233 int ql;
234
235 ql = aioQueueSize();
236
237 if (ql == 0)
238 loadav = 0;
239
240 loadav = ql * 1000 / MAGIC1;
241
242 debugs(47, 9, "DiskThreadsIOStrategy::load: load=" << loadav);
243
244 return loadav;
245 }
246
247 DiskFile::Pointer
248 DiskThreadsIOStrategy::newFile (char const *path)
249 {
250 if (shedLoad()) {
251 return NULL;
252 }
253
254 return new DiskThreadsDiskFile (path, this);
255 }
256
257 bool
258 DiskThreadsIOStrategy::unlinkdUseful() const
259 {
260 return false;
261 }
262
263 void
264 DiskThreadsIOStrategy::unlinkFile(char const *path)
265 {
266 ++statCounter.syscalls.disk.unlinks;
267 aioUnlink(path, NULL, NULL);
268 }