]> git.ipfire.org Git - thirdparty/squid.git/blame - src/DiskIO/AIO/AIODiskIOStrategy.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / DiskIO / AIO / AIODiskIOStrategy.cc
CommitLineData
b9ae18aa 1/*
ef57eb7b 2 * Copyright (C) 1996-2016 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 */
bbc27441 8
b9ae18aa 9/*
10 * Author: Adrian Chadd <adrian@squid-cache.org>
11 *
12 * These routines are simple plugin replacements for the file_* routines
13 * in disk.c . They back-end into the POSIX AIO routines to provide
14 * a nice and simple async IO framework for COSS.
15 *
16 * AIO is suitable for COSS - the only sync operations that the standard
17 * supports are read/write, and since COSS works on a single file
18 * per storedir it should work just fine.
19 */
20
582c2af2 21#include "squid.h"
d9691f09
AJ
22#include "DiskIO/AIO/AIODiskFile.h"
23#include "DiskIO/AIO/AIODiskIOStrategy.h"
b9ae18aa 24#include "DiskIO/IORequestor.h"
25#include "DiskIO/ReadRequest.h"
26#include "DiskIO/WriteRequest.h"
27
e19994df 28AIODiskIOStrategy::AIODiskIOStrategy() :
f53969cc 29 fd(-1)
b9ae18aa 30{
e19994df 31 aq.aq_state = AQ_STATE_NONE;
b9ae18aa 32 aq.aq_numpending = 0;
e19994df 33 memset(&aq.aq_queue, 0, sizeof(aq.aq_queue));
b9ae18aa 34}
35
36AIODiskIOStrategy::~AIODiskIOStrategy()
37{
38 assert(aq.aq_state == AQ_STATE_SETUP ||
39 aq.aq_numpending == 0);
40
41 sync();
42 aq.aq_state = AQ_STATE_NONE;
43}
44
45bool
46AIODiskIOStrategy::shedLoad()
47{
48 return false;
49}
50
51int
52AIODiskIOStrategy::load()
53{
54 return aq.aq_numpending * 1000 / MAX_ASYNCOP;
55}
56
57RefCount<DiskFile>
58AIODiskIOStrategy::newFile (char const *path)
59{
60 if (shedLoad()) {
61 return NULL;
62 }
63
64 return new AIODiskFile (path, this);
65}
66
67void
68AIODiskIOStrategy::sync()
69{
70 assert(aq.aq_state == AQ_STATE_SETUP);
71
72 /*
73 * Keep calling callback to complete ops until the queue is empty
74 * We can't quit when callback returns 0 - some calls may not
75 * return any completed pending events, but they're still pending!
76 */
77
78 while (aq.aq_numpending)
79 callback();
80}
81
c521ad17
DK
82bool
83AIODiskIOStrategy::unlinkdUseful() const
84{
85 return false;
86}
87
b9ae18aa 88void
89AIODiskIOStrategy::unlinkFile (char const *)
90{}
91
92/*
93 * Note: we grab the state and free the state before calling the callback
94 * because this allows us to cut down the amount of time it'll take
95 * to find a free slot (since if we call the callback first, we're going
96 * to probably be allocated the slot _after_ this one..)
97 *
98 * I'll make it much more optimal later.
99 */
100int
101AIODiskIOStrategy::callback()
102{
103 return 0;
ab9dc81d 104#if 0
b9ae18aa 105 int i;
b9ae18aa 106 int retval, reterr;
107 FREE *freefunc;
108 void *cbdata;
109 int callback_valid;
110 void *buf;
b9ae18aa 111 async_queue_entry_t *aqe;
112 async_queue_entry_type_t type;
113
114 assert(aq.aq_state == AQ_STATE_SETUP);
115
116 /* Loop through all slots */
117
cb4185f1 118 for (i = 0; i < MAX_ASYNCOP; ++i) {
b9ae18aa 119 if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_USED) {
120 aqe = &aq.aq_queue[i];
121 /* Active, get status */
122 reterr = aio_error(&aqe->aq_e_aiocb);
123
124 if (reterr < 0) {
125 fatal("aio_error returned an error!\n");
126 }
127
128 if (reterr != EINPROGRESS) {
129 /* Get the return code */
130 retval = aio_return(&aqe->aq_e_aiocb);
131
132 /* Get the callback parameters */
133 freefunc = aqe->aq_e_free;
134 buf = aqe->aq_e_buf;
b9ae18aa 135 type = aqe->aq_e_type;
136 callback_valid = cbdataReferenceValidDone(aqe->aq_e_callback_data, &cbdata);
137 AIODiskFile * theFile = NULL;
138 void *theFileVoid = NULL;
8abf232c 139 void *theTmpFile = aqe->theFile;
140 bool fileOk = cbdataReferenceValidDone(theTmpFile, &theFileVoid);
b9ae18aa 141
142 if (fileOk) {
143 theFile = static_cast<AIODiskFile *>(theFileVoid);
144 }
145
146 /* Free slot */
04830959 147 memset(aqe, 0, sizeof(async_queue_entry_t));
b9ae18aa 148
149 aqe->aq_e_state = AQ_ENTRY_FREE;
150
151 --aq.aq_numpending;
152
153 /* Callback */
154
155 if (callback_valid) {
156 assert (fileOk);
157
158 if (type == AQ_ENTRY_READ)
159 theFile->ioRequestor->readCompleted((const char *)buf, retval, reterr, static_cast<ReadRequest *>(cbdata));
160
161 if (type == AQ_ENTRY_WRITE)
162 theFile->ioRequestor->writeCompleted(reterr,retval, static_cast<WriteRequest *>(cbdata));
163 }
164
165 if (type == AQ_ENTRY_WRITE && freefunc)
166 freefunc(buf);
167 }
168 }
169 }
170
f373b7d9 171 return 0;
ab9dc81d 172#endif
b9ae18aa 173}
174
175void
176AIODiskIOStrategy::init()
177{
178 /* Make sure the queue isn't setup */
179 assert(aq.aq_state == AQ_STATE_NONE);
180
181 /* Loop through, blanking the queue entries */
182
183 /* Done */
184 aq.aq_state = AQ_STATE_SETUP;
185}
186
187void
ced8def3 188AIODiskIOStrategy::statfs(StoreEntry &) const
26ac0430 189{}
b9ae18aa 190
191ConfigOption *
192AIODiskIOStrategy::getOptionTree() const
193{
194 return NULL;
195}
196
197/*
198 * find a free aio slot.
199 * Return the index, or -1 if we can't find one.
200 */
201int
202AIODiskIOStrategy::findSlot()
203{
204 /* Later we should use something a little more .. efficient :) */
205
cb4185f1 206 for (int i = 0; i < MAX_ASYNCOP; ++i) {
b9ae18aa 207 if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_FREE)
208 /* Found! */
209 return i;
210 }
211
212 /* found nothing */
213 return -1;
214}
f53969cc 215