/*
- * $Id: store_io_ufs.cc,v 1.22 2003/08/04 22:14:53 robertc Exp $
+ * $Id$
*
* DEBUG: section 79 Storage Manager UFS Interface
* AUTHOR: Duane Wessels
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
-#include "squid.h"
-#include "store_ufs.h"
+#include "squid-old.h"
#include "Store.h"
#include "ufscommon.h"
+#include "Generic.h"
+#include "DiskIO/DiskFile.h"
+#include "DiskIO/DiskIOStrategy.h"
+#include "DiskIO/ReadRequest.h"
+#include "DiskIO/WriteRequest.h"
#include "SwapDir.h"
-UfsIO UfsIO::Instance;
bool
-UfsIO::shedLoad()
+UFSStrategy::shedLoad()
{
- return false;
+ return io->shedLoad();
}
int
-UfsIO::load()
+UFSStrategy::load()
+{
+ return io->load();
+}
+
+UFSStrategy::UFSStrategy (DiskIOStrategy *anIO) : io(anIO)
+{}
+
+UFSStrategy::~UFSStrategy ()
{
- /* Return 999 (99.9%) constant load */
- return 999;
+ delete io;
}
StoreIOState::Pointer
-UfsIO::createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const
+UFSStrategy::createState(SwapDir *SD, StoreEntry *e, StoreIOState::STIOCB * aCallback, void *callback_data) const
{
- return new UFSStoreState (SD, e, callback, callback_data);
+ return new UFSStoreState (SD, e, aCallback, callback_data);
}
DiskFile::Pointer
-UfsIO::newFile (char const *path)
+UFSStrategy::newFile (char const *path)
{
- return new UFSFile (path);
+ return io->newFile(path);
}
+
void
-UfsIO::unlinkFile(char const *path)
+UFSStrategy::unlinkFile(char const *path)
{
-#if USE_UNLINKD
- unlinkdUnlink(path);
-#elif USE_TRUNCATE
-
- truncate(path, 0);
-#else
-
- ::unlink(path);
-#endif
+ io->unlinkFile(path);
}
CBDATA_CLASS_INIT(UFSStoreState);
cbdataFree(address);
}
-CBDATA_CLASS_INIT(UFSFile);
-void *
-UFSFile::operator new (size_t)
-{
- CBDATA_INIT_TYPE(UFSFile);
- UFSFile *result = cbdataAlloc(UFSFile);
- /* Mark result as being owned - we want the refcounter to do the delete
- * call */
- cbdataReference(result);
- return result;
-}
-
-void
-UFSFile::operator delete (void *address)
-{
- UFSFile *t = static_cast<UFSFile *>(address);
- cbdataFree(address);
- /* And allow the memory to be freed */
- cbdataReferenceDone (t);
-}
-
-UFSFile::UFSFile (char const *aPath) : fd (-1), closed (true), error_(false)
-{
- assert (aPath);
- debug (79,3)("UFSFile::UFSFile: %s\n", aPath);
- path_ = xstrdup (aPath);
-}
-
-UFSFile::~UFSFile()
-{
- safe_free (path_);
- doClose();
-}
-
-void
-UFSFile::open (int flags, mode_t mode, IORequestor::Pointer callback)
-{
- /* Simulate async calls */
- fd = file_open(path_ , flags);
- ioRequestor = callback;
-
- if (fd < 0) {
- debug(79, 3) ("UFSFile::open: got failure (%d)\n", errno);
- error(true);
- } else {
- closed = false;
- store_open_disk_fd++;
- debug(79, 3) ("UFSFile::open: opened FD %d\n", fd);
- }
-
- callback->ioCompletedNotification();
-}
-
-void
-UFSFile::create (int flags, mode_t mode, IORequestor::Pointer callback)
-{
- /* We use the same logic path for open */
- open(flags, mode, callback);
-}
-
-
-void UFSFile::doClose()
-{
- if (fd > -1) {
- closed = true;
- file_close(fd);
- store_open_disk_fd--;
- fd = -1;
- }
-}
-
-void
-UFSFile::close ()
-{
- debug (79,3)("UFSFile::close: %p closing for %p\n", this, ioRequestor.getRaw());
- doClose();
- assert (ioRequestor.getRaw());
- ioRequestor->closeCompleted();
-}
-
-bool
-UFSFile::canRead() const
-{
- return fd > -1;
-}
-
-bool
-UFSFile::error() const
-{
- if ((fd < 0 && !closed) || error_)
- return true;
-
- return false;
-}
-
-void UFSFile::error(bool const &aBool)
-{
- error_ = aBool;
-}
-
void
UFSStoreState::ioCompletedNotification()
{
if (opening) {
opening = false;
- debug(79, 3) ("storeDiskdOpenDone: dirno %d, fileno %08x status %d\n",
- swap_dirn, swap_filen, theFile->error());
+ debugs(79, 3, "UFSStoreState::ioCompletedNotification: dirno " <<
+ swap_dirn << ", fileno "<< std::setfill('0') << std::hex <<
+ std::setw(8) << swap_filen << " status "<< std::setfill(' ') <<
+ std::dec << theFile->error());
+
assert (FILE_MODE(mode) == O_RDONLY);
openDone();
if (creating) {
creating = false;
- debug(79, 3) ("storeDiskdCreateDone: dirno %d, fileno %08x status %d\n",
- swap_dirn, swap_filen, theFile->error());
+ debugs(79, 3, "UFSStoreState::ioCompletedNotification: dirno " <<
+ swap_dirn << ", fileno "<< std::setfill('0') << std::hex <<
+ std::setw(8) << swap_filen << " status "<< std::setfill(' ') <<
+ std::dec << theFile->error());
+
openDone();
return;
}
assert (!(closing ||opening));
- debug(79, 3) ("diskd::ioCompleted: dirno %d, fileno %08x status %d\n", swap_dirn, swap_filen, theFile->error());
+ debugs(79, 3, "diskd::ioCompleted: dirno " << swap_dirn << ", fileno "<<
+ std::setfill('0') << std::hex << std::setw(8) << swap_filen <<
+ " status "<< std::setfill(' ') << std::dec << theFile->error());
+
/* Ok, notification past open means an error has occured */
assert (theFile->error());
- doCallback(DISK_ERROR);
+ tryClosing();
}
void
UFSStoreState::openDone()
{
+ if (closing)
+ debugs(0,0,HERE << "already closing in openDone()!?");
+
if (theFile->error()) {
- doCallback(DISK_ERROR);
+ tryClosing();
return;
}
if (FILE_MODE(mode) == O_WRONLY) {
- if (kickWriteQueue())
- return;
+ drainWriteQueue();
+
} else if ((FILE_MODE(mode) == O_RDONLY) && !closing) {
if (kickReadQueue())
return;
}
- if (closing && !theFile->ioInProgress())
- doCallback(theFile->error() ? -1 : 0);
+ if (flags.try_closing)
+ tryClosing();
- debug(79, 3) ("squidaiostate_t::openDone: exiting\n");
+ debugs(79, 3, "UFSStoreState::openDone: exiting");
}
void
UFSStoreState::closeCompleted()
{
assert (closing);
- debug(79, 3) ("UFSStoreState::closeCompleted: dirno %d, fileno %08x status %d\n",
- swap_dirn, swap_filen, theFile->error());
+ debugs(79, 3, "UFSStoreState::closeCompleted: dirno " << swap_dirn <<
+ ", fileno "<< std::setfill('0') << std::hex << std::setw(8) <<
+ swap_filen << " status "<< std::setfill(' ') << std::dec <<
+ theFile->error());
- if (theFile->error())
- doCallback(DISK_ERROR);
- else
- doCallback(DISK_OK);
+ if (theFile->error()) {
+ debugs(79,3,HERE<< "theFile->error() ret " << theFile->error());
+ doCloseCallback(DISK_ERROR);
+ } else {
+ doCloseCallback(DISK_OK);
+ }
closing = false;
}
-/* Close */
+/*
+ * DPW 2006-05-24
+ * This close function is called by the higher layer when it has finished
+ * reading/writing everything, or otherwise wants to close the swap
+ * file. In the case of writing and using aufs storage, close() might
+ * be called before any/all data is written, and even before the open
+ * callback occurs. Thus, we use our tryClosing() method, which knows
+ * when it is safe to actually signal the lower layer for closing.
+ */
void
-UFSStoreState::close()
+UFSStoreState::close(int)
{
- debug(79, 3) ("UFSStoreState::close: dirno %d, fileno %08X\n", swap_dirn,
- swap_filen);
- /* mark the object to be closed on the next io that completes */
- closing = true;
- theFile->close();
+ debugs(79, 3, "UFSStoreState::close: dirno " << swap_dirn << ", fileno "<<
+ std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen);
+ tryClosing(); // UFS does not distinguish different closure types
}
void
-UFSStoreState::read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
+UFSStoreState::read_(char *buf, size_t size, off_t aOffset, STRCB * aCallback, void *aCallbackData)
{
assert(read.callback == NULL);
assert(read.callback_data == NULL);
assert(!reading);
assert(!closing);
- assert (callback);
+ assert (aCallback);
if (!theFile->canRead()) {
- debug(79, 3) ("UFSStoreState::read_: queueing read because theFile can't read\n");
- queueRead (buf, size, offset, callback, callback_data);
+ debugs(79, 3, "UFSStoreState::read_: queueing read because theFile can't read");
+ queueRead (buf, size, aOffset, aCallback, aCallbackData);
return;
}
- read.callback = callback;
- read.callback_data = cbdataReference(callback_data);
- debug(79, 3) ("UFSStoreState::read_: dirno %d, fileno %08X\n",
- swap_dirn, swap_filen);
- offset_ = offset;
+ read.callback = aCallback;
+ read.callback_data = cbdataReference(aCallbackData);
+ debugs(79, 3, "UFSStoreState::read_: dirno " << swap_dirn << ", fileno "<<
+ std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen);
+ offset_ = aOffset;
read_buf = buf;
reading = true;
- theFile->read(buf, offset, size);
+ theFile->read(new ReadRequest(buf,aOffset,size));
}
-void
-UFSFile::read(char *buf, off_t offset, size_t size)
-{
- assert (fd > -1);
- assert (ioRequestor.getRaw());
- file_read(fd, buf, size, offset, ReadDone, this);
-}
-
-void
-UFSFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data)
-{
- UFSFile *myFile = static_cast<UFSFile *>(my_data);
- assert (myFile);
- myFile->readDone (fd, buf, len, errflag);
-}
-
-void
-UFSFile::write(char const *buf, size_t size, off_t offset, FREE *free_func)
-{
- debug(79, 3) ("storeUfsWrite: FD %d\n",fd);
- file_write(fd,
- offset,
- (char *)buf,
- size,
- WriteDone,
- this,
- free_func);
-}
+/*
+ * DPW 2006-05-24
+ * This, the public write interface, places the write request at the end
+ * of the pending_writes queue to ensure correct ordering of writes.
+ * We could optimize things a little if there are no other pending
+ * writes and just do the write directly. But for now we'll keep the
+ * code simpler and always go through the pending_writes queue.
+ */
void
-UFSStoreState::write(char const *buf, size_t size, off_t offset, FREE * free_func)
+UFSStoreState::write(char const *buf, size_t size, off_t aOffset, FREE * free_func)
{
- debug(79, 3) ("UFSStoreState::write: dirn %d, fileno %08X\n", swap_dirn, swap_filen);
+ debugs(79, 3, "UFSStoreState::write: dirn " << swap_dirn << ", fileno "<<
+ std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen);
- if (!theFile->canWrite()) {
- assert(creating || writing);
- queueWrite(buf, size, offset, free_func);
+ if (theFile->error()) {
+ debugs(79,1,HERE << "avoid write on theFile with error");
+ debugs(79,1,HERE << "calling free_func for " << (void*) buf);
+ free_func((void*)buf);
return;
}
- writing = true;
- theFile->write(buf,size,offset,free_func);
-}
-
-bool
-UFSFile::ioInProgress()const
-{
- /* IO is never pending with UFS */
- return false;
+ queueWrite(buf, size, aOffset, free_func);
+ drainWriteQueue();
}
-/* === STATIC =========================================================== */
+/*
+ * DPW 2006-05-24
+ * This, the private write method, calls the lower level write for the
+ * first write request in the pending_writes queue. doWrite() is only
+ * called by drainWriteQueue().
+ */
void
-UFSFile::readDone(int rvfd, const char *buf, int len, int errflag)
+UFSStoreState::doWrite()
{
- debug (79,3)("UFSFile::readDone: FD %d\n",rvfd);
- assert (fd == rvfd);
+ debugs(79, 3, HERE << this << " UFSStoreState::doWrite");
- ssize_t rlen;
+ assert(theFile->canWrite());
- if (errflag) {
- debug(79, 3) ("UFSFile::readDone: got failure (%d)\n", errflag);
- rlen = -1;
- } else {
- rlen = (ssize_t) len;
+ _queued_write *q = (_queued_write *)linklistShift(&pending_writes);
+
+ if (q == NULL) {
+ debugs(79, 3, HERE << this << " UFSStoreState::doWrite queue is empty");
+ return;
+ }
+
+ if (theFile->error()) {
+ debugs(79,1,HERE << "avoid write on theFile with error");
+ debugs(79,3,HERE << "calling free_func for " << (void*) q->buf);
+ /*
+ * DPW 2006-05-24
+ * Note "free_func" is memNodeWriteComplete(), which doesn't
+ * really free the memory. Instead it clears the node's
+ * write_pending flag.
+ */
+ q->free_func((void*)q->buf);
+ delete q;
+ return;
}
- if (errflag == DISK_EOF)
- errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */
+ /*
+ * DPW 2006-05-24
+ * UFSStoreState has a 'writing' flag that we used to set here,
+ * but it wasn't really used anywhere. In fact, some lower
+ * layers such as DISKD allow multiple outstanding writes, which
+ * makes the boolean writing flag meaningless. We would need
+ * a counter to keep track of writes going out and write callbacks
+ * coming in. For now let's just not use the writing flag at
+ * all.
+ */
+ debugs(79, 3, HERE << this << " calling theFile->write(" << q->size << ")");
- ioRequestor->readCompleted(buf, rlen, errflag);
+ theFile->write(new WriteRequest(q->buf, q->offset, q->size, q->free_func));
+ delete q;
}
void
-UFSStoreState::readCompleted(const char *buf, int len, int errflag)
+UFSStoreState::readCompleted(const char *buf, int len, int errflag, RefCount<ReadRequest> result)
{
+ assert (result.getRaw());
reading = false;
- debug(79, 3) ("storeDiskdReadDone: dirno %d, fileno %08x len %d\n",
- swap_dirn, swap_filen, len);
+ debugs(79, 3, "UFSStoreState::readCompleted: dirno " << swap_dirn <<
+ ", fileno "<< std::setfill('0') << std::hex << std::setw(8) <<
+ swap_filen << " len "<< std::setfill(' ') << std::dec << len);
if (len > 0)
offset_ += len;
- STRCB *callback = read.callback;
+ STRCB *callback_ = read.callback;
- assert(callback);
+ assert(callback_);
read.callback = NULL;
* aufs performs closes syncronously, so close events must be managed
* to force strict ordering.
* The below does this:
- * closing is set when close() is called, and close only triggers
+ * closing is set when theFile->close() has been called, and close only triggers
* when no io's are pending.
* writeCompleted likewise.
*/
if (len > 0 && read_buf != buf)
memcpy(read_buf, buf, len);
- callback(cbdata, read_buf, len);
- } else if (closing && theFile.getRaw()!= NULL && !theFile->ioInProgress())
- doCallback(errflag);
-}
-
-void
-UFSFile::WriteDone (int fd, int errflag, size_t len, void *me)
-{
- UFSFile *aFile = static_cast<UFSFile *>(me);
- aFile->writeDone (fd, errflag, len);
-}
-
-void
-UFSFile::writeDone(int rvfd, int errflag, size_t len)
-{
- assert (rvfd == fd);
- debug(79, 3) ("storeUfsWriteDone: FD %d, len %ld\n",
- fd, (long int) len);
-
- if (errflag) {
- debug(79, 0) ("storeUfsWriteDone: got failure (%d)\n", errflag);
- doClose();
- ioRequestor->writeCompleted (DISK_ERROR,0);
- return;
+ callback_(cbdata, read_buf, len, this);
}
- ioRequestor->writeCompleted(DISK_OK, len);
+ if (flags.try_closing || (theFile != NULL && theFile->error()) )
+ tryClosing();
}
void
-UFSStoreState::writeCompleted(int errflag, size_t len)
-{
- debug(79, 3) ("storeUfsWriteDone: dirno %d, fileno %08X, len %ld\n",
- swap_dirn, swap_filen, (long int) len);
- writing = false;
+UFSStoreState::writeCompleted(int errflag, size_t len, RefCount<WriteRequest> writeRequest)
+{
+ debugs(79, 3, HERE << "dirno " << swap_dirn << ", fileno " <<
+ std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen <<
+ ", len " << len);
+ /*
+ * DPW 2006-05-24
+ * See doWrites() for why we don't update UFSStoreState::writing
+ * here anymore.
+ */
offset_ += len;
if (theFile->error()) {
- doCallback(DISK_ERROR);
- return;
- }
-
- if (closing && !theFile->ioInProgress()) {
- theFile->close();
- return;
+ debugs(79,2,HERE << " detected an error, will try to close");
+ tryClosing();
}
- if (!flags.write_kicking) {
- flags.write_kicking = true;
- /* While we start and complete syncronously io's. */
-
- while (kickWriteQueue() && !theFile->ioInProgress())
-
- ;
- flags.write_kicking = false;
-
- if (!theFile->ioInProgress() && closing)
- doCallback(errflag);
- }
+ /*
+ * HNO 2009-07-24
+ * Kick any pending write/close operations alive
+ */
+ drainWriteQueue();
}
void
-UFSStoreState::doCallback(int errflag)
-{
- debug(79, 3) ("storeUfsIOCallback: errflag=%d\n", errflag);
- /* We are finished with the file as this is on close or error only.*/
- theFile = NULL;
-
+UFSStoreState::doCloseCallback(int errflag)
+{
+ debugs(79, 3, "storeUfsIOCallback: errflag=" << errflag);
+ /*
+ * DPW 2006-05-24
+ * When we signal the higher layer with this callback, it might unlock
+ * the StoreEntry and its associated data. We must "free" any queued
+ * I/Os (especially writes) now, otherwise the StoreEntry's mem_node's
+ * will have their write_pending flag set, and we'll get an assertion.
+ */
+ freePending();
STIOCB *theCallback = callback;
callback = NULL;
if (cbdataReferenceValidDone(callback_data, &cbdata) && theCallback)
theCallback(cbdata, errflag, this);
+
+ /*
+ * We are finished with theFile since the lower layer signalled
+ * us that the file has been closed. This must be the last line,
+ * as theFile may be the only object holding us in memory.
+ */
+ theFile = NULL; // refcounted
}
/* ============= THE REAL UFS CODE ================ */
callback = callback_;
callback_data = cbdataReference(callback_data_);
e = anEntry;
- flags.write_kicking = false;
+ flags.write_draining = false;
+ flags.try_closing = false;
}
UFSStoreState::~UFSStoreState()
+{
+ assert(pending_reads == NULL);
+ assert(pending_writes == NULL);
+}
+
+void
+UFSStoreState::freePending()
{
_queued_read *qr;
delete qr;
}
+ debugs(79,3,HERE << "UFSStoreState::freePending: freed pending reads");
+
_queued_write *qw;
while ((qw = (_queued_write *)linklistShift(&pending_writes))) {
qw->free_func(const_cast<char *>(qw->buf));
delete qw;
}
+
+ debugs(79,3,HERE << "UFSStoreState::freePending: freed pending writes");
}
bool
if (NULL == q)
return false;
- debug(79, 3) ("UFSStoreState::kickReadQueue: reading queued request of %ld bytes\n",
- (long int) q->size);
+ debugs(79, 3, "UFSStoreState::kickReadQueue: reading queued request of " << q->size << " bytes");
void *cbdata;
- if (cbdataReferenceValidDone(q->callback_data, &cbdata))
+ if (cbdataReferenceValidDone(q->callback_data, &cbdata)) {
read_(q->buf, q->size, q->offset, q->callback, cbdata);
+ } else {
+ debugs(79, 2, "UFSStoreState::kickReadQueue: this: " << this << " cbdataReferenceValidDone returned false." << " closing: " << closing << " flags.try_closing: " << flags.try_closing);
+ delete q;
+ return false;
+ }
delete q;
return true;
}
-MemPool * UFSStoreState::_queued_read::Pool = NULL;
-
-void *
-UFSStoreState::_queued_read::operator new(size_t size)
-{
- if (!Pool)
- Pool = memPoolCreate("AUFS Queued read data",sizeof (_queued_read));
-
- return memPoolAlloc (Pool);
-}
-
-void
-UFSStoreState::_queued_read::operator delete (void *address)
-{
- memPoolFree (Pool, address);
-}
-
void
-UFSStoreState::queueRead(char *buf, size_t size, off_t offset, STRCB *callback, void *callback_data)
+UFSStoreState::queueRead(char *buf, size_t size, off_t aOffset, STRCB *callback_, void *callback_data_)
{
- debug(79, 3) ("UFSStoreState::queueRead: queueing read\n");
+ debugs(79, 3, "UFSStoreState::queueRead: queueing read");
assert(opening);
assert (pending_reads == NULL);
_queued_read *q = new _queued_read;
q->buf = buf;
q->size = size;
- q->offset = offset;
- q->callback = callback;
- q->callback_data = cbdataReference(callback_data);
+ q->offset = aOffset;
+ q->callback = callback_;
+ q->callback_data = cbdataReference(callback_data_);
linklistPush(&pending_reads, q);
}
-MemPool * UFSStoreState::_queued_write::Pool = NULL;
+/*
+ * DPW 2006-05-24
+ * drainWriteQueue() is a loop around doWrite().
+ */
+void
+UFSStoreState::drainWriteQueue()
+{
+ /*
+ * DPW 2007-04-12
+ * We might find that flags.write_draining is already set
+ * because schemes like diskd can process I/O acks
+ * before sending another I/O request. e.g. the following
+ * sequence of events: open request -> write request ->
+ * drainWriteQueue() -> queue full -> callbacks -> openDone() ->
+ * drainWriteQueue().
+ */
+ if (flags.write_draining)
+ return;
+
+ if (!theFile->canWrite())
+ return;
-void *
-UFSStoreState::_queued_write::operator new(size_t size)
-{
- if (!Pool)
- Pool = memPoolCreate("AUFS Queued write data",sizeof (_queued_write));
+ flags.write_draining = true;
- return memPoolAlloc (Pool);
-}
+ while (pending_writes != NULL) {
+ doWrite();
+ }
-void
-UFSStoreState::_queued_write::operator delete (void *address)
-{
- memPoolFree (Pool, address);
+ flags.write_draining = false;
+
+ if (flags.try_closing)
+ tryClosing();
}
-bool
-UFSStoreState::kickWriteQueue()
+/*
+ * DPW 2006-05-24
+ * This blows. DiskThreadsDiskFile::close() won't actually do the close
+ * if ioInProgress() is true. So we have to check it here. Maybe someday
+ * DiskThreadsDiskFile::close() will be modified to have a return value,
+ * or will remember to do the close for us.
+ */
+void
+UFSStoreState::tryClosing()
{
- _queued_write *q = (_queued_write *)linklistShift(&pending_writes);
-
- if (NULL == q)
- return false;
+ debugs(79,3,HERE << this << " tryClosing()" <<
+ " closing = " << closing <<
+ " flags.try_closing = " << flags.try_closing <<
+ " ioInProgress = " << theFile->ioInProgress());
- debug(79, 3) ("storeAufsKickWriteQueue: writing queued chunk of %ld bytes\n",
- (long int) q->size);
+ if (theFile->ioInProgress()) {
+ debugs(79, 3, HERE << this <<
+ " won't close since ioInProgress is true, bailing");
+ flags.try_closing = true;
+ return;
+ }
- write(const_cast<char *>(q->buf), q->size, q->offset, q->free_func);
- delete q;
- return true;
+ closing = true;
+ flags.try_closing = false;
+ theFile->close();
}
void
-UFSStoreState::queueWrite(char const *buf, size_t size, off_t offset, FREE * free_func)
+UFSStoreState::queueWrite(char const *buf, size_t size, off_t aOffset, FREE * free_func)
{
- debug(79, 3) ("UFSStoreState::queueWrite: queuing write\n");
+ debugs(79, 3, HERE << this << " UFSStoreState::queueWrite: queueing write of size " << size);
_queued_write *q;
q = new _queued_write;
q->buf = buf;
q->size = size;
- q->offset = offset;
+ q->offset = aOffset;
q->free_func = free_func;
linklistPush(&pending_writes, q);
}
StoreIOState::Pointer
-UFSStrategy::open(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
- STIOCB * callback, void *callback_data)
+UFSStrategy::open(SwapDir * SD, StoreEntry * e, StoreIOState::STFNCB * file_callback,
+ StoreIOState::STIOCB * aCallback, void *callback_data)
{
assert (((UFSSwapDir *)SD)->IO == this);
- debug(79, 3) ("UFSStrategy::open: fileno %08X\n", e->swap_filen);
-
- if (shedLoad()) {
- openFailed();
- return NULL;
- }
+ debugs(79, 3, "UFSStrategy::open: fileno "<< std::setfill('0') << std::hex << std::uppercase << std::setw(8) << e->swap_filen);
/* to consider: make createstate a private UFSStrategy call */
- StoreIOState::Pointer sio = createState (SD, e, callback, callback_data);
+ StoreIOState::Pointer sio = createState (SD, e, aCallback, callback_data);
sio->mode |= O_RDONLY;
DiskFile::Pointer myFile = newFile (path);
+ if (myFile.getRaw() == NULL)
+ return NULL;
+
state->theFile = myFile;
state->opening = true;
}
StoreIOState::Pointer
-UFSStrategy::create(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
- STIOCB * callback, void *callback_data)
+UFSStrategy::create(SwapDir * SD, StoreEntry * e, StoreIOState::STFNCB * file_callback,
+ StoreIOState::STIOCB * aCallback, void *callback_data)
{
assert (((UFSSwapDir *)SD)->IO == this);
/* Allocate a number */
sfileno filn = ((UFSSwapDir *)SD)->mapBitAllocate();
- debug(79, 3) ("UFSStrategy::create: fileno %08X\n", filn);
-
- if (shedLoad()) {
- openFailed();
- ((UFSSwapDir *)SD)->mapBitReset (filn);
- return NULL;
- }
+ debugs(79, 3, "UFSStrategy::create: fileno "<< std::setfill('0') << std::hex << std::uppercase << std::setw(8) << filn);
/* Shouldn't we handle a 'bitmap full' error here? */
- StoreIOState::Pointer sio = createState (SD, e, callback, callback_data);
+ StoreIOState::Pointer sio = createState (SD, e, aCallback, callback_data);
sio->mode |= O_WRONLY | O_CREAT | O_TRUNC;
DiskFile::Pointer myFile = newFile (path);
+ if (myFile.getRaw() == NULL) {
+ ((UFSSwapDir *)SD)->mapBitReset (filn);
+ return NULL;
+ }
+
state->theFile = myFile;
state->creating = true;
return sio;
}
-UfsIOModule &
-UfsIOModule::GetInstance()
+int
+UFSStrategy::callback()
{
- if (!Instance)
- Instance = new UfsIOModule;
-
- return *Instance;
+ return io->callback();
}
void
-UfsIOModule::init()
-{}
+UFSStrategy::init()
+{
+ io->init();
+}
void
-UfsIOModule::shutdown()
-{}
+UFSStrategy::sync()
+{
+ io->sync();
+}
-UFSStrategy *
-UfsIOModule::createSwapDirIOStrategy()
+void
+UFSStrategy::statfs(StoreEntry & sentry)const
{
- return new InstanceToSingletonAdapter<UfsIO>(&UfsIO::Instance);
+ io->statfs(sentry);
}
-UfsIOModule *UfsIOModule::Instance = NULL;