]>
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 | */ |
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" |
b9ae18aa | 22 | #include "AIODiskFile.h" |
602d9612 | 23 | #include "AIODiskIOStrategy.h" |
b9ae18aa | 24 | #include "DiskIO/IORequestor.h" |
25 | #include "DiskIO/ReadRequest.h" | |
26 | #include "DiskIO/WriteRequest.h" | |
27 | ||
e19994df | 28 | AIODiskIOStrategy::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 | ||
36 | AIODiskIOStrategy::~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 | ||
45 | bool | |
46 | AIODiskIOStrategy::shedLoad() | |
47 | { | |
48 | return false; | |
49 | } | |
50 | ||
51 | int | |
52 | AIODiskIOStrategy::load() | |
53 | { | |
54 | return aq.aq_numpending * 1000 / MAX_ASYNCOP; | |
55 | } | |
56 | ||
57 | RefCount<DiskFile> | |
58 | AIODiskIOStrategy::newFile (char const *path) | |
59 | { | |
60 | if (shedLoad()) { | |
61 | return NULL; | |
62 | } | |
63 | ||
64 | return new AIODiskFile (path, this); | |
65 | } | |
66 | ||
67 | void | |
68 | AIODiskIOStrategy::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 |
82 | bool |
83 | AIODiskIOStrategy::unlinkdUseful() const | |
84 | { | |
85 | return false; | |
86 | } | |
87 | ||
b9ae18aa | 88 | void |
89 | AIODiskIOStrategy::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 | */ | |
100 | int | |
101 | AIODiskIOStrategy::callback() | |
102 | { | |
103 | return 0; | |
104 | int i; | |
105 | int completed = 0; | |
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 | ||
171 | return completed; | |
172 | } | |
173 | ||
174 | void | |
175 | AIODiskIOStrategy::init() | |
176 | { | |
177 | /* Make sure the queue isn't setup */ | |
178 | assert(aq.aq_state == AQ_STATE_NONE); | |
179 | ||
180 | /* Loop through, blanking the queue entries */ | |
181 | ||
182 | /* Done */ | |
183 | aq.aq_state = AQ_STATE_SETUP; | |
184 | } | |
185 | ||
186 | void | |
187 | AIODiskIOStrategy::statfs(StoreEntry & sentry)const | |
26ac0430 | 188 | {} |
b9ae18aa | 189 | |
190 | ConfigOption * | |
191 | AIODiskIOStrategy::getOptionTree() const | |
192 | { | |
193 | return NULL; | |
194 | } | |
195 | ||
196 | /* | |
197 | * find a free aio slot. | |
198 | * Return the index, or -1 if we can't find one. | |
199 | */ | |
200 | int | |
201 | AIODiskIOStrategy::findSlot() | |
202 | { | |
203 | /* Later we should use something a little more .. efficient :) */ | |
204 | ||
cb4185f1 | 205 | for (int i = 0; i < MAX_ASYNCOP; ++i) { |
b9ae18aa | 206 | if (aq.aq_queue[i].aq_e_state == AQ_ENTRY_FREE) |
207 | /* Found! */ | |
208 | return i; | |
209 | } | |
210 | ||
211 | /* found nothing */ | |
212 | return -1; | |
213 | } | |
f53969cc | 214 |