]>
Commit | Line | Data |
---|---|---|
b9ae18aa | 1 | /* |
bbc27441 | 2 | * Copyright (C) 1996-2014 The Squid Software Foundation and contributors |
26ac0430 | 3 | * |
bbc27441 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
b9ae18aa | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 79 Squid-side Disk I/O functions. */ |
10 | ||
582c2af2 | 11 | #include "squid.h" |
b9ae18aa | 12 | #include "DiskThreadsDiskFile.h" |
8822ebee AR |
13 | #include "DiskThreadsIOStrategy.h" |
14 | #include "fde.h" | |
15 | #include "mgr/Registration.h" | |
4d5904f7 | 16 | #include "SquidConfig.h" |
e4f1fdae | 17 | #include "StatCounters.h" |
b9ae18aa | 18 | #include "Store.h" |
8822ebee | 19 | |
ed6e9fb9 AJ |
20 | /* squidaio_ctrl_t uses explicit alloc()/freeOne(). |
21 | * XXX: convert to MEMPROXY_CLASS() API | |
22 | */ | |
23 | #include "mem/Pool.h" | |
24 | ||
b9ae18aa | 25 | void |
26 | DiskThreadsIOStrategy::init(void) | |
27 | { | |
28 | if (initialised) | |
29 | return; | |
30 | ||
04eb0689 | 31 | squidaio_ctrl_pool = memPoolCreate("aio_ctrl", sizeof(squidaio_ctrl_t)); |
b9ae18aa | 32 | |
b9ae18aa | 33 | initialised = true; |
e65c313f | 34 | |
35 | /* | |
36 | * We'd like to call squidaio_init() here, but the configuration | |
37 | * hasn't been parsed yet and we don't know how many cache_dirs | |
38 | * there are, which means we don't know how many threads to start. | |
39 | */ | |
6fdc2d18 | 40 | |
26ac0430 | 41 | registerWithCacheManager(); |
b9ae18aa | 42 | } |
43 | ||
62ee09ca | 44 | void |
15fab853 | 45 | DiskThreadsIOStrategy::registerWithCacheManager(void) |
62ee09ca | 46 | { |
8822ebee | 47 | Mgr::RegisterAction("squidaio_counts", "Async IO Function Counters", |
d9fc6862 | 48 | aioStats, 0, 1); |
62ee09ca | 49 | } |
50 | ||
b9ae18aa | 51 | void |
52 | DiskThreadsIOStrategy::done(void) | |
53 | { | |
54 | if (!initialised) | |
55 | return; | |
56 | ||
d06925a4 | 57 | squidaio_shutdown(); |
58 | ||
b9ae18aa | 59 | delete squidaio_ctrl_pool; |
60 | ||
61 | squidaio_ctrl_pool = NULL; | |
62 | ||
63 | initialised = false; | |
64 | } | |
65 | ||
66 | int | |
67 | DiskThreadsIOStrategy::callback() | |
68 | { | |
69 | squidaio_result_t *resultp; | |
70 | squidaio_ctrl_t *ctrlp; | |
71 | int retval = 0; | |
72 | ||
73 | assert(initialised); | |
cb4185f1 | 74 | ++squidaio_counts.check_callback; |
b9ae18aa | 75 | |
76 | for (;;) { | |
77 | if ((resultp = squidaio_poll_done()) == NULL) | |
78 | break; | |
79 | ||
80 | ctrlp = (squidaio_ctrl_t *) resultp->data; | |
81 | ||
82 | switch (resultp->result_type) { | |
83 | ||
84 | case _AIO_OP_NONE: | |
85 | ||
b9ae18aa | 86 | case _AIO_OP_OPENDIR: |
87 | break; | |
88 | ||
89 | case _AIO_OP_OPEN: | |
90 | ++squidaio_counts.open_finish; | |
91 | break; | |
92 | ||
93 | case _AIO_OP_READ: | |
94 | ++squidaio_counts.read_finish; | |
95 | break; | |
96 | ||
97 | case _AIO_OP_WRITE: | |
98 | ++squidaio_counts.write_finish; | |
99 | break; | |
100 | ||
101 | case _AIO_OP_CLOSE: | |
102 | ++squidaio_counts.close_finish; | |
103 | break; | |
104 | ||
105 | case _AIO_OP_UNLINK: | |
106 | ++squidaio_counts.unlink_finish; | |
107 | break; | |
108 | ||
109 | case _AIO_OP_STAT: | |
110 | ++squidaio_counts.stat_finish; | |
111 | break; | |
112 | } | |
113 | ||
114 | if (ctrlp == NULL) | |
f53969cc | 115 | continue; /* XXX Should not happen */ |
b9ae18aa | 116 | |
117 | dlinkDelete(&ctrlp->node, &used_list); | |
118 | ||
119 | if (ctrlp->done_handler) { | |
350e2aec | 120 | AIOCB *done_callback = ctrlp->done_handler; |
b9ae18aa | 121 | void *cbdata; |
122 | ctrlp->done_handler = NULL; | |
123 | ||
124 | if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) { | |
f53969cc | 125 | retval = 1; /* Return that we've actually done some work */ |
350e2aec | 126 | done_callback(ctrlp->fd, cbdata, ctrlp->bufp, |
0cc4a8bc | 127 | ctrlp->result.aio_return, ctrlp->result.aio_errno); |
b9ae18aa | 128 | } else { |
129 | if (ctrlp->operation == _AIO_OPEN) { | |
130 | /* The open operation was aborted.. */ | |
131 | int fd = ctrlp->result.aio_return; | |
132 | ||
133 | if (fd >= 0) | |
134 | aioClose(fd); | |
135 | } | |
136 | } | |
137 | } | |
138 | ||
139 | /* free data if requested to aioWrite() */ | |
140 | if (ctrlp->free_func) | |
141 | ctrlp->free_func(ctrlp->bufp); | |
142 | ||
143 | /* free temporary read buffer */ | |
144 | if (ctrlp->operation == _AIO_READ) | |
145 | squidaio_xfree(ctrlp->bufp, ctrlp->len); | |
146 | ||
dc47f531 | 147 | squidaio_ctrl_pool->freeOne(ctrlp); |
b9ae18aa | 148 | } |
149 | ||
150 | return retval; | |
151 | } | |
152 | ||
153 | /* Flush all pending I/O */ | |
154 | void | |
155 | DiskThreadsIOStrategy::sync() | |
156 | { | |
157 | if (!initialised) | |
f53969cc | 158 | return; /* nothing to do then */ |
b9ae18aa | 159 | |
160 | /* Flush all pending operations */ | |
709873c3 | 161 | debugs(32, 2, "aioSync: flushing pending I/O operations"); |
b9ae18aa | 162 | |
163 | do { | |
164 | callback(); | |
165 | } while (squidaio_sync()); | |
166 | ||
709873c3 | 167 | debugs(32, 2, "aioSync: done"); |
b9ae18aa | 168 | } |
169 | ||
e19994df | 170 | DiskThreadsIOStrategy::DiskThreadsIOStrategy() : |
f53969cc SM |
171 | initialised(false), |
172 | squidaio_ctrl_pool(NULL) | |
e19994df | 173 | {} |
b9ae18aa | 174 | |
175 | void | |
176 | DiskThreadsIOStrategy::aioStats(StoreEntry * sentry) | |
177 | { | |
178 | storeAppendPrintf(sentry, "ASYNC IO Counters:\n"); | |
22cec59e AJ |
179 | storeAppendPrintf(sentry, " Operation\t# Requests\tNumber serviced\n"); |
180 | storeAppendPrintf(sentry, " open\t%" PRIu64 "\t%" PRIu64 "\n", squidaio_counts.open_start, squidaio_counts.open_finish); | |
181 | storeAppendPrintf(sentry, " close\t%" PRIu64 "\t%" PRIu64 "\n", squidaio_counts.close_start, squidaio_counts.close_finish); | |
182 | storeAppendPrintf(sentry, " cancel\t%" PRIu64 "\t-\n", squidaio_counts.cancel); | |
183 | storeAppendPrintf(sentry, " write\t%" PRIu64 "\t%" PRIu64 "\n", squidaio_counts.write_start, squidaio_counts.write_finish); | |
184 | storeAppendPrintf(sentry, " read\t%" PRIu64 "\t%" PRIu64 "\n", squidaio_counts.read_start, squidaio_counts.read_finish); | |
185 | storeAppendPrintf(sentry, " stat\t%" PRIu64 "\t%" PRIu64 "\n", squidaio_counts.stat_start, squidaio_counts.stat_finish); | |
186 | storeAppendPrintf(sentry, " unlink\t%" PRIu64 "\t%" PRIu64 "\n", squidaio_counts.unlink_start, squidaio_counts.unlink_finish); | |
187 | storeAppendPrintf(sentry, " check_callback\t%" PRIu64 "\t-\n", squidaio_counts.check_callback); | |
188 | storeAppendPrintf(sentry, " queue\t%d\t-\n", squidaio_get_queue_len()); | |
b0465494 | 189 | squidaio_stats(sentry); |
b9ae18aa | 190 | } |
191 | ||
b9ae18aa | 192 | DiskThreadsIOStrategy DiskThreadsIOStrategy::Instance; |
193 | bool | |
194 | DiskThreadsIOStrategy::shedLoad() | |
195 | { | |
196 | /* | |
197 | * we should detect some 'too many files open' condition and return | |
198 | * NULL here. | |
199 | */ | |
200 | #ifdef MAGIC2 | |
201 | ||
202 | if (aioQueueSize() > MAGIC2) | |
203 | return true; | |
204 | ||
205 | #endif | |
206 | ||
207 | return false; | |
208 | } | |
209 | ||
210 | int | |
211 | DiskThreadsIOStrategy::load() | |
212 | { | |
213 | int loadav; | |
214 | int ql; | |
215 | ||
216 | ql = aioQueueSize(); | |
217 | ||
218 | if (ql == 0) | |
219 | loadav = 0; | |
220 | ||
221 | loadav = ql * 1000 / MAGIC1; | |
222 | ||
bf8fe701 | 223 | debugs(47, 9, "DiskThreadsIOStrategy::load: load=" << loadav); |
b9ae18aa | 224 | |
225 | return loadav; | |
226 | } | |
227 | ||
228 | DiskFile::Pointer | |
229 | DiskThreadsIOStrategy::newFile (char const *path) | |
230 | { | |
231 | if (shedLoad()) { | |
232 | return NULL; | |
233 | } | |
234 | ||
235 | return new DiskThreadsDiskFile (path, this); | |
236 | } | |
237 | ||
c521ad17 DK |
238 | bool |
239 | DiskThreadsIOStrategy::unlinkdUseful() const | |
240 | { | |
241 | return false; | |
242 | } | |
243 | ||
b9ae18aa | 244 | void |
245 | DiskThreadsIOStrategy::unlinkFile(char const *path) | |
246 | { | |
e4f1fdae | 247 | ++statCounter.syscalls.disk.unlinks; |
b9ae18aa | 248 | aioUnlink(path, NULL, NULL); |
b9ae18aa | 249 | } |
f53969cc | 250 |