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