]> git.ipfire.org Git - thirdparty/squid.git/blame - src/DiskIO/DiskThreads/DiskThreadsIOStrategy.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / DiskIO / DiskThreads / DiskThreadsIOStrategy.cc
CommitLineData
b9ae18aa 1/*
bde978a6 2 * Copyright (C) 1996-2015 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 25void
26DiskThreadsIOStrategy::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 44void
15fab853 45DiskThreadsIOStrategy::registerWithCacheManager(void)
62ee09ca 46{
8822ebee 47 Mgr::RegisterAction("squidaio_counts", "Async IO Function Counters",
d9fc6862 48 aioStats, 0, 1);
62ee09ca 49}
50
b9ae18aa 51void
52DiskThreadsIOStrategy::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
66int
67DiskThreadsIOStrategy::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 */
154void
155DiskThreadsIOStrategy::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 170DiskThreadsIOStrategy::DiskThreadsIOStrategy() :
f53969cc
SM
171 initialised(false),
172 squidaio_ctrl_pool(NULL)
e19994df 173{}
b9ae18aa 174
175void
176DiskThreadsIOStrategy::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 192DiskThreadsIOStrategy DiskThreadsIOStrategy::Instance;
193bool
194DiskThreadsIOStrategy::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
210int
211DiskThreadsIOStrategy::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
228DiskFile::Pointer
229DiskThreadsIOStrategy::newFile (char const *path)
230{
231 if (shedLoad()) {
232 return NULL;
233 }
234
235 return new DiskThreadsDiskFile (path, this);
236}
237
c521ad17
DK
238bool
239DiskThreadsIOStrategy::unlinkdUseful() const
240{
241 return false;
242}
243
b9ae18aa 244void
245DiskThreadsIOStrategy::unlinkFile(char const *path)
246{
e4f1fdae 247 ++statCounter.syscalls.disk.unlinks;
b9ae18aa 248 aioUnlink(path, NULL, NULL);
b9ae18aa 249}
f53969cc 250