3 * SQUID Web Proxy Cache http://www.squid-cache.org/
4 * ----------------------------------------------------------
6 * Squid is the result of efforts by numerous individuals from
7 * the Internet community; see the CONTRIBUTORS file for full
8 * details. Many organizations have provided support for Squid's
9 * development; see the SPONSORS file for full details. Squid is
10 * Copyrighted (C) 2001 by the Regents of the University of
11 * California; see the COPYRIGHT file for full details. Squid
12 * incorporates software developed and/or copyrighted by other
13 * sources; see the CREDITS file for full details.
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
32 * Author: Adrian Chadd <adrian@squid-cache.org>
34 * These routines are simple plugin replacements for the file_* routines
35 * in disk.c . They back-end into the POSIX AIO routines to provide
36 * a nice and simple async IO framework for COSS.
38 * AIO is suitable for COSS - the only sync operations that the standard
39 * supports are read/write, and since COSS works on a single file
40 * per storedir it should work just fine.
44 #include "AIODiskIOStrategy.h"
45 #include "AIODiskFile.h"
46 #include "DiskIO/IORequestor.h"
47 #include "DiskIO/ReadRequest.h"
48 #include "DiskIO/WriteRequest.h"
50 AIODiskIOStrategy::AIODiskIOStrategy()
55 AIODiskIOStrategy::~AIODiskIOStrategy()
57 assert(aq
.aq_state
== AQ_STATE_SETUP
||
58 aq
.aq_numpending
== 0);
61 aq
.aq_state
= AQ_STATE_NONE
;
65 AIODiskIOStrategy::shedLoad()
71 AIODiskIOStrategy::load()
73 return aq
.aq_numpending
* 1000 / MAX_ASYNCOP
;
77 AIODiskIOStrategy::newFile (char const *path
)
83 return new AIODiskFile (path
, this);
87 AIODiskIOStrategy::sync()
89 assert(aq
.aq_state
== AQ_STATE_SETUP
);
92 * Keep calling callback to complete ops until the queue is empty
93 * We can't quit when callback returns 0 - some calls may not
94 * return any completed pending events, but they're still pending!
97 while (aq
.aq_numpending
)
102 AIODiskIOStrategy::unlinkdUseful() const
108 AIODiskIOStrategy::unlinkFile (char const *)
112 * Note: we grab the state and free the state before calling the callback
113 * because this allows us to cut down the amount of time it'll take
114 * to find a free slot (since if we call the callback first, we're going
115 * to probably be allocated the slot _after_ this one..)
117 * I'll make it much more optimal later.
120 AIODiskIOStrategy::callback()
130 async_queue_entry_t
*aqe
;
131 async_queue_entry_type_t type
;
133 assert(aq
.aq_state
== AQ_STATE_SETUP
);
135 /* Loop through all slots */
137 for (i
= 0; i
< MAX_ASYNCOP
; ++i
) {
138 if (aq
.aq_queue
[i
].aq_e_state
== AQ_ENTRY_USED
) {
139 aqe
= &aq
.aq_queue
[i
];
140 /* Active, get status */
141 reterr
= aio_error(&aqe
->aq_e_aiocb
);
144 fatal("aio_error returned an error!\n");
147 if (reterr
!= EINPROGRESS
) {
148 /* Get the return code */
149 retval
= aio_return(&aqe
->aq_e_aiocb
);
151 /* Get the callback parameters */
152 freefunc
= aqe
->aq_e_free
;
154 type
= aqe
->aq_e_type
;
155 callback_valid
= cbdataReferenceValidDone(aqe
->aq_e_callback_data
, &cbdata
);
156 AIODiskFile
* theFile
= NULL
;
157 void *theFileVoid
= NULL
;
158 void *theTmpFile
= aqe
->theFile
;
159 bool fileOk
= cbdataReferenceValidDone(theTmpFile
, &theFileVoid
);
162 theFile
= static_cast<AIODiskFile
*>(theFileVoid
);
166 memset(aqe
, 0, sizeof(async_queue_entry_t
));
168 aqe
->aq_e_state
= AQ_ENTRY_FREE
;
174 if (callback_valid
) {
177 if (type
== AQ_ENTRY_READ
)
178 theFile
->ioRequestor
->readCompleted((const char *)buf
, retval
, reterr
, static_cast<ReadRequest
*>(cbdata
));
180 if (type
== AQ_ENTRY_WRITE
)
181 theFile
->ioRequestor
->writeCompleted(reterr
,retval
, static_cast<WriteRequest
*>(cbdata
));
184 if (type
== AQ_ENTRY_WRITE
&& freefunc
)
194 AIODiskIOStrategy::init()
196 /* Make sure the queue isn't setup */
197 assert(aq
.aq_state
== AQ_STATE_NONE
);
199 /* Loop through, blanking the queue entries */
202 aq
.aq_state
= AQ_STATE_SETUP
;
206 AIODiskIOStrategy::statfs(StoreEntry
& sentry
)const
210 AIODiskIOStrategy::getOptionTree() const
216 * find a free aio slot.
217 * Return the index, or -1 if we can't find one.
220 AIODiskIOStrategy::findSlot()
222 /* Later we should use something a little more .. efficient :) */
224 for (int i
= 0; i
< MAX_ASYNCOP
; ++i
) {
225 if (aq
.aq_queue
[i
].aq_e_state
== AQ_ENTRY_FREE
)