3 * $Id: AIODiskIOStrategy.cc,v 1.3 2005/12/26 11:35:22 serassio Exp $
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
31 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
34 * Author: Adrian Chadd <adrian@squid-cache.org>
36 * These routines are simple plugin replacements for the file_* routines
37 * in disk.c . They back-end into the POSIX AIO routines to provide
38 * a nice and simple async IO framework for COSS.
40 * AIO is suitable for COSS - the only sync operations that the standard
41 * supports are read/write, and since COSS works on a single file
42 * per storedir it should work just fine.
46 #include "AIODiskIOStrategy.h"
47 #include "AIODiskFile.h"
48 #include "DiskIO/IORequestor.h"
49 #include "DiskIO/ReadRequest.h"
50 #include "DiskIO/WriteRequest.h"
52 AIODiskIOStrategy::AIODiskIOStrategy()
57 AIODiskIOStrategy::~AIODiskIOStrategy()
59 assert(aq
.aq_state
== AQ_STATE_SETUP
||
60 aq
.aq_numpending
== 0);
63 aq
.aq_state
= AQ_STATE_NONE
;
67 AIODiskIOStrategy::shedLoad()
73 AIODiskIOStrategy::load()
75 return aq
.aq_numpending
* 1000 / MAX_ASYNCOP
;
79 AIODiskIOStrategy::newFile (char const *path
)
85 return new AIODiskFile (path
, this);
89 AIODiskIOStrategy::sync()
91 assert(aq
.aq_state
== AQ_STATE_SETUP
);
94 * Keep calling callback to complete ops until the queue is empty
95 * We can't quit when callback returns 0 - some calls may not
96 * return any completed pending events, but they're still pending!
99 while (aq
.aq_numpending
)
104 AIODiskIOStrategy::unlinkFile (char const *)
108 * Note: we grab the state and free the state before calling the callback
109 * because this allows us to cut down the amount of time it'll take
110 * to find a free slot (since if we call the callback first, we're going
111 * to probably be allocated the slot _after_ this one..)
113 * I'll make it much more optimal later.
116 AIODiskIOStrategy::callback()
127 async_queue_entry_t
*aqe
;
128 async_queue_entry_type_t type
;
130 assert(aq
.aq_state
== AQ_STATE_SETUP
);
132 /* Loop through all slots */
134 for (i
= 0; i
< MAX_ASYNCOP
; i
++) {
135 if (aq
.aq_queue
[i
].aq_e_state
== AQ_ENTRY_USED
) {
136 aqe
= &aq
.aq_queue
[i
];
137 /* Active, get status */
138 reterr
= aio_error(&aqe
->aq_e_aiocb
);
141 fatal("aio_error returned an error!\n");
144 if (reterr
!= EINPROGRESS
) {
145 /* Get the return code */
146 retval
= aio_return(&aqe
->aq_e_aiocb
);
148 /* Get the callback parameters */
149 freefunc
= aqe
->aq_e_free
;
152 type
= aqe
->aq_e_type
;
153 callback_valid
= cbdataReferenceValidDone(aqe
->aq_e_callback_data
, &cbdata
);
154 AIODiskFile
* theFile
= NULL
;
155 void *theFileVoid
= NULL
;
156 void *theTmpFile
= aqe
->theFile
;
157 bool fileOk
= cbdataReferenceValidDone(theTmpFile
, &theFileVoid
);
160 theFile
= static_cast<AIODiskFile
*>(theFileVoid
);
164 memset(aqe
, 0, sizeof(async_queue_entry_t
));
166 aqe
->aq_e_state
= AQ_ENTRY_FREE
;
172 if (callback_valid
) {
175 if (type
== AQ_ENTRY_READ
)
176 theFile
->ioRequestor
->readCompleted((const char *)buf
, retval
, reterr
, static_cast<ReadRequest
*>(cbdata
));
178 if (type
== AQ_ENTRY_WRITE
)
179 theFile
->ioRequestor
->writeCompleted(reterr
,retval
, static_cast<WriteRequest
*>(cbdata
));
182 if (type
== AQ_ENTRY_WRITE
&& freefunc
)
192 AIODiskIOStrategy::init()
194 /* Make sure the queue isn't setup */
195 assert(aq
.aq_state
== AQ_STATE_NONE
);
197 /* Loop through, blanking the queue entries */
200 aq
.aq_state
= AQ_STATE_SETUP
;
204 AIODiskIOStrategy::statfs(StoreEntry
& sentry
)const
208 AIODiskIOStrategy::getOptionTree() const
214 * find a free aio slot.
215 * Return the index, or -1 if we can't find one.
218 AIODiskIOStrategy::findSlot()
220 /* Later we should use something a little more .. efficient :) */
222 for (int i
= 0; i
< MAX_ASYNCOP
; i
++) {
223 if (aq
.aq_queue
[i
].aq_e_state
== AQ_ENTRY_FREE
)