]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/fs/ufs/store_io_ufs.cc
3 * $Id: store_io_ufs.cc,v 1.18 2003/03/04 01:40:57 robertc Exp $
5 * DEBUG: section 79 Storage Manager UFS Interface
6 * AUTHOR: Duane Wessels
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
37 #include "store_ufs.h"
39 #include "ufscommon.h"
43 UfsIO
UfsIO::Instance
;
51 UfsIO::deleteSelf() const
53 /* Do nothing, we use a single instance */
57 UfsIO::createState(SwapDir
*SD
, StoreEntry
*e
, STIOCB
* callback
, void *callback_data
) const
59 return new ufsstate_t (SD
, e
, callback
, callback_data
);
63 UfsIO::newFile (char const *path
)
65 return new UFSFile (path
);
68 CBDATA_CLASS_INIT(ufsstate_t
);
71 ufsstate_t::operator new (size_t)
73 CBDATA_INIT_TYPE(ufsstate_t
);
74 ufsstate_t
*result
= cbdataAlloc(ufsstate_t
);
75 /* Mark result as being owned - we want the refcounter to do the delete
77 cbdataReference(result
);
82 ufsstate_t::operator delete (void *address
)
84 ufsstate_t
*t
= static_cast<ufsstate_t
*>(address
);
86 /* And allow the memory to be freed */
87 cbdataReferenceDone (t
);
90 ufsstate_t::ufsstate_t(SwapDir
* SD
, StoreEntry
* anEntry
, STIOCB
* callback_
, void *callback_data_
)
92 swap_filen
= anEntry
->swap_filen
;
93 swap_dirn
= SD
->index
;
96 callback_data
= cbdataReference(callback_data_
);
100 CBDATA_CLASS_INIT(UFSFile
);
102 UFSFile::operator new (size_t)
104 CBDATA_INIT_TYPE(UFSFile
);
105 UFSFile
*result
= cbdataAlloc(UFSFile
);
106 /* Mark result as being owned - we want the refcounter to do the delete
108 cbdataReference(result
);
113 UFSFile::operator delete (void *address
)
115 UFSFile
*t
= static_cast<UFSFile
*>(address
);
117 /* And allow the memory to be freed */
118 cbdataReferenceDone (t
);
122 UFSFile::deleteSelf() const {delete this;}
124 UFSFile::UFSFile (char const *aPath
) : fd (-1)
127 debug (79,3)("UFSFile::UFSFile: %s\n", aPath
);
128 path_
= xstrdup (aPath
);
138 UFSFile::open (int flags
, mode_t mode
, IORequestor::Pointer callback
)
140 /* Simulate async calls */
141 fd
= file_open(path_
, flags
);
142 ioRequestor
= callback
;
145 debug(79, 3) ("UFSFile::open: got failure (%d)\n", errno
);
147 store_open_disk_fd
++;
148 debug(79, 3) ("UFSFile::open: opened FD %d\n", fd
);
151 callback
->ioCompletedNotification();
155 UFSFile::create (int flags
, mode_t mode
, IORequestor::Pointer callback
)
157 /* We use the same logic path for open */
158 open(flags
, mode
, callback
);
162 void UFSFile::doClose()
166 store_open_disk_fd
--;
174 debug (79,3)("UFSFile::close: %p closing for %p\n", this, ioRequestor
.getRaw());
176 assert (ioRequestor
.getRaw());
177 ioRequestor
->closeCompleted();
181 UFSFile::canRead() const
187 UFSFile::error() const
196 ufsstate_t::ioCompletedNotification()
200 /* There is no 'opened' callback */
213 ufsstate_t::closeCompleted()
215 doCallback(theFile
->error() ? 0 : -1);
221 debug(79, 3) ("storeUfsClose: dirno %d, fileno %08X\n",
222 swap_dirn
, swap_filen
);
225 if (!(reading
|| writing
)) {
226 ((UFSFile
*)theFile
.getRaw())->close();
231 UFSStoreState::read_(char *buf
, size_t size
, off_t offset
, STRCB
* callback
, void *callback_data
)
233 assert(read
.callback
== NULL
);
234 assert(read
.callback_data
== NULL
);
239 if (!theFile
->canRead()) {
240 debug(79, 3) ("UFSStoreState::read_: queueing read because theFile can't read\n");
241 queueRead (buf
, size
, offset
, callback
, callback_data
);
245 read
.callback
= callback
;
246 read
.callback_data
= cbdataReference(callback_data
);
247 debug(79, 3) ("UFSStoreState::read_: dirno %d, fileno %08X\n",
248 swap_dirn
, swap_filen
);
252 theFile
->read(buf
, offset
, size
);
256 UFSFile::read(char *buf
, off_t offset
, size_t size
)
259 assert (ioRequestor
.getRaw());
260 file_read(fd
, buf
, size
, offset
, ReadDone
, this);
264 UFSFile::ReadDone(int fd
, const char *buf
, int len
, int errflag
, void *my_data
)
266 UFSFile
*myFile
= static_cast<UFSFile
*>(my_data
);
268 myFile
->readDone (fd
, buf
, len
, errflag
);
272 UFSFile::write(char const *buf
, size_t size
, off_t offset
, FREE
*free_func
)
274 debug(79, 3) ("storeUfsWrite: FD %d\n",fd
);
285 UFSStoreState::write(char const *buf
, size_t size
, off_t offset
, FREE
* free_func
)
287 debug(79, 3) ("UFSStoreState::write: dirn %d, fileno %08X\n", swap_dirn
, swap_filen
);
289 if (!theFile
->canWrite() || writing
) {
290 assert(creating
|| writing
);
291 queueWrite(buf
, size
, offset
, free_func
);
296 theFile
->write(buf
,size
,offset
,free_func
);
300 UfsSwapDir::unlink(StoreEntry
& e
)
302 debug(79, 3) ("storeUfsUnlink: fileno %08X\n", e
.swap_filen
);
303 replacementRemove(&e
);
304 mapBitReset(e
.swap_filen
);
305 UFSSwapDir::unlinkFile(e
.swap_filen
);
308 /* === STATIC =========================================================== */
311 UFSFile::readDone(int rvfd
, const char *buf
, int len
, int errflag
)
313 debug (79,3)("UFSFile::readDone: FD %d\n",rvfd
);
319 debug(79, 3) ("UFSFile::readDone: got failure (%d)\n", errflag
);
322 rlen
= (ssize_t
) len
;
325 if (errflag
== DISK_EOF
)
326 errflag
= DISK_OK
; /* EOF is signalled by len == 0, not errors... */
328 ioRequestor
->readCompleted(buf
, rlen
, errflag
);
332 ufsstate_t::readCompleted(const char *buf
, int len
, int errflag
)
336 debug(79, 3) ("storeUfsReadDone: dirno %d, fileno %08X, len %d\n",
337 swap_dirn
, swap_filen
, len
);
342 STRCB
*callback
= read
.callback
;
346 read
.callback
= NULL
;
350 if (!closing
&& cbdataReferenceValidDone(read
.callback_data
, &cbdata
)) {
351 if (len
> 0 && read_buf
!= buf
)
352 memcpy(read_buf
, buf
, len
);
354 callback(cbdata
, read_buf
, len
);
356 fatal("Sync ufs doesn't support overlapped close and read calls\n");
360 UFSFile::WriteDone (int fd
, int errflag
, size_t len
, void *me
)
362 UFSFile
*aFile
= static_cast<UFSFile
*>(me
);
363 aFile
->writeDone (fd
, errflag
, len
);
367 UFSFile::writeDone(int rvfd
, int errflag
, size_t len
)
370 debug(79, 3) ("storeUfsWriteDone: FD %d, len %ld\n",
374 debug(79, 0) ("storeUfsWriteDone: got failure (%d)\n", errflag
);
376 ioRequestor
->writeCompleted (DISK_ERROR
,0);
380 ioRequestor
->writeCompleted(DISK_OK
, len
);
384 ufsstate_t::writeCompleted(int errflag
, size_t len
)
386 debug(79, 3) ("storeUfsWriteDone: dirno %d, fileno %08X, len %ld\n",
387 swap_dirn
, swap_filen
, (long int) len
);
390 if (theFile
->error())
391 doCallback(DISK_ERROR
);
396 ((UFSFile
*)theFile
.getRaw())->close();
400 ufsstate_t::doCallback(int errflag
)
402 debug(79, 3) ("storeUfsIOCallback: errflag=%d\n", errflag
);
403 /* We are finished with the file */
407 if (cbdataReferenceValidDone(callback_data
, &cbdata
))
408 callback(cbdata
, errflag
, this);
415 * Clean up any references from the SIO before it get's released.
417 ufsstate_t::~ufsstate_t()
422 /* ============= THE REAL UFS CODE ================ */
424 UFSStoreState::UFSStoreState() : opening (false), creating (false), closing (false), reading(false), writing(false), pending_reads(NULL
), pending_writes (NULL
){}
426 UFSStoreState::~UFSStoreState()
430 while ((qr
= (_queued_read
*)linklistShift(&pending_reads
))) {
431 cbdataReferenceDone(qr
->callback_data
);
435 struct _queued_write
*qw
;
437 while ((qw
= (struct _queued_write
*)linklistShift(&pending_writes
))) {
439 qw
->free_func(const_cast<char *>(qw
->buf
));
445 UFSStoreState::kickReadQueue()
447 _queued_read
*q
= (_queued_read
*)linklistShift(&pending_reads
);
452 debug(79, 3) ("UFSStoreState::kickReadQueue: reading queued request of %ld bytes\n",
457 if (cbdataReferenceValidDone(q
->callback_data
, &cbdata
))
458 read_(q
->buf
, q
->size
, q
->offset
, q
->callback
, cbdata
);
465 MemPool
* UFSStoreState::_queued_read::Pool
= NULL
;
468 UFSStoreState::_queued_read::operator new(size_t size
)
471 Pool
= memPoolCreate("AUFS Queued read data",sizeof (_queued_read
));
473 return memPoolAlloc (Pool
);
477 UFSStoreState::_queued_read::operator delete (void *address
)
479 memPoolFree (Pool
, address
);
483 UFSStoreState::queueRead(char *buf
, size_t size
, off_t offset
, STRCB
*callback
, void *callback_data
)
485 debug(79, 3) ("UFSStoreState::queueRead: queueing read\n");
487 assert (pending_reads
== NULL
);
488 _queued_read
*q
= new _queued_read
;
492 q
->callback
= callback
;
493 q
->callback_data
= cbdataReference(callback_data
);
494 linklistPush(&pending_reads
, q
);
497 MemPool
* UFSStoreState::_queued_write::Pool
= NULL
;
500 UFSStoreState::_queued_write::operator new(size_t size
)
503 Pool
= memPoolCreate("AUFS Queued write data",sizeof (_queued_write
));
505 return memPoolAlloc (Pool
);
509 UFSStoreState::_queued_write::operator delete (void *address
)
511 memPoolFree (Pool
, address
);
515 UFSStoreState::kickWriteQueue()
517 _queued_write
*q
= (_queued_write
*)linklistShift(&pending_writes
);
522 debug(79, 3) ("storeAufsKickWriteQueue: writing queued chunk of %ld bytes\n",
525 write(const_cast<char *>(q
->buf
), q
->size
, q
->offset
, q
->free_func
);
531 UFSStoreState::queueWrite(char const *buf
, size_t size
, off_t offset
, FREE
* free_func
)
533 debug(79, 3) ("UFSStoreState::queueWrite: queuing write\n");
535 struct _queued_write
*q
;
536 q
= new _queued_write
;
540 q
->free_func
= free_func
;
541 linklistPush(&pending_writes
, q
);
544 StoreIOState::Pointer
545 UFSStrategy::open(SwapDir
* SD
, StoreEntry
* e
, STFNCB
* file_callback
,
546 STIOCB
* callback
, void *callback_data
)
548 assert (((UfsSwapDir
*)SD
)->IO
== this);
549 debug(79, 3) ("UFSStrategy::open: fileno %08X\n", e
->swap_filen
);
556 /* to consider: make createstate a private UFSStrategy call */
557 StoreIOState::Pointer sio
= createState (SD
, e
, callback
, callback_data
);
559 sio
->mode
|= O_RDONLY
;
561 UFSStoreState
*state
= dynamic_cast <UFSStoreState
*>(sio
.getRaw());
565 char *path
= ((UFSSwapDir
*)SD
)->fullPath(e
->swap_filen
, NULL
);
567 DiskFile::Pointer myFile
= newFile (path
);
569 state
->theFile
= myFile
;
571 state
->opening
= true;
573 myFile
->open (sio
->mode
, 0644, state
);
581 StoreIOState::Pointer
582 UFSStrategy::create(SwapDir
* SD
, StoreEntry
* e
, STFNCB
* file_callback
,
583 STIOCB
* callback
, void *callback_data
)
585 assert (((UfsSwapDir
*)SD
)->IO
== this);
586 /* Allocate a number */
587 sfileno filn
= ((UFSSwapDir
*)SD
)->mapBitAllocate();
588 debug(79, 3) ("UFSStrategy::create: fileno %08X\n", filn
);
592 ((UFSSwapDir
*)SD
)->mapBitReset (filn
);
596 /* Shouldn't we handle a 'bitmap full' error here? */
598 StoreIOState::Pointer sio
= createState (SD
, e
, callback
, callback_data
);
600 sio
->mode
|= O_WRONLY
| O_CREAT
| O_TRUNC
;
602 sio
->swap_filen
= filn
;
604 UFSStoreState
*state
= dynamic_cast <UFSStoreState
*>(sio
.getRaw());
608 char *path
= ((UFSSwapDir
*)SD
)->fullPath(filn
, NULL
);
610 DiskFile::Pointer myFile
= newFile (path
);
612 state
->theFile
= myFile
;
614 state
->creating
= true;
616 myFile
->create (state
->mode
, 0644, state
);
618 if (myFile
->error()) {
619 ((UFSSwapDir
*)SD
)->mapBitReset (filn
);
623 /* now insert into the replacement policy */
624 ((UFSSwapDir
*)SD
)->replacementAdd(e
);