/src/DiskIO/DiskDaemon/DiskdFile.cc
C++ | 427 lines | 323 code | 62 blank | 42 comment | 23 complexity | c886b0d5a0e8a2a861b8104c534bb20d MD5 | raw file
- /*
- * $Id$
- *
- * DEBUG: section 79 Squid-side DISKD I/O functions.
- * AUTHOR: Duane Wessels
- *
- * SQUID Web Proxy Cache http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from
- * the Internet community; see the CONTRIBUTORS file for full
- * details. Many organizations have provided support for Squid's
- * development; see the SPONSORS file for full details. Squid is
- * Copyrighted (C) 2001 by the Regents of the University of
- * California; see the COPYRIGHT file for full details. Squid
- * incorporates software developed and/or copyrighted by other
- * sources; see the CREDITS file for full details.
- *
- * This program is free software; you can redistribute it and/or modify
- * 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.
- *
- * CopyRight (c) 2003, Robert Collins <robertc@squid-cache.org>
- */
- #include "squid.h"
- #include <sys/ipc.h>
- #include <sys/msg.h>
- #include <sys/shm.h>
- #include "DiskdFile.h"
- #include "ConfigOption.h"
- #include "diomsg.h"
- #include "DiskdIOStrategy.h"
- #include "DiskIO/IORequestor.h"
- #include "DiskIO/ReadRequest.h"
- #include "DiskIO/WriteRequest.h"
- CBDATA_CLASS_INIT(DiskdFile);
- void *
- DiskdFile::operator new(size_t unused)
- {
- CBDATA_INIT_TYPE(DiskdFile);
- DiskdFile *result = cbdataAlloc(DiskdFile);
- /* Mark result as being owned - we want the refcounter to do the delete
- * call */
- debugs(79, 3, "diskdFile with base " << result << " allocating");
- return result;
- }
- void
- DiskdFile::operator delete(void *address)
- {
- DiskdFile *t = static_cast<DiskdFile *>(address);
- debugs(79, 3, "diskdFile with base " << t << " deleting");
- cbdataFree(t);
- }
- DiskdFile::DiskdFile(char const *aPath, DiskdIOStrategy *anIO) : errorOccured (false), IO(anIO),
- inProgressIOs (0)
- {
- assert (aPath);
- debugs(79, 3, "DiskdFile::DiskdFile: " << aPath);
- path_ = xstrdup (aPath);
- id = diskd_stats.sio_id++;
- }
- DiskdFile::~DiskdFile()
- {
- assert (inProgressIOs == 0);
- safe_free (path_);
- }
- void
- DiskdFile::open(int flags, mode_t aMode, RefCount< IORequestor > callback)
- {
- debugs(79, 3, "DiskdFile::open: " << this << " opening for " << callback.getRaw());
- assert (ioRequestor.getRaw() == NULL);
- ioRequestor = callback;
- assert (callback.getRaw());
- mode = flags;
- ssize_t shm_offset;
- char *buf = (char *)IO->shm.get(&shm_offset);
- xstrncpy(buf, path_, SHMBUF_BLKSZ);
- ioAway();
- int x = IO->send(_MQD_OPEN,
- id,
- this,
- strlen(buf) + 1,
- mode,
- shm_offset,
- NULL);
- if (x < 0) {
- ioCompleted();
- errorOccured = true;
- // IO->shm.put (shm_offset);
- ioRequestor->ioCompletedNotification();
- ioRequestor = NULL;
- }
- diskd_stats.open.ops++;
- }
- void
- DiskdFile::create(int flags, mode_t aMode, RefCount< IORequestor > callback)
- {
- debugs(79, 3, "DiskdFile::create: " << this << " creating for " << callback.getRaw());
- assert (ioRequestor.getRaw() == NULL);
- ioRequestor = callback;
- assert (callback.getRaw());
- mode = flags;
- ssize_t shm_offset;
- char *buf = (char *)IO->shm.get(&shm_offset);
- xstrncpy(buf, path_, SHMBUF_BLKSZ);
- ioAway();
- int x = IO->send(_MQD_CREATE,
- id,
- this,
- strlen(buf) + 1,
- mode,
- shm_offset,
- NULL);
- if (x < 0) {
- ioCompleted();
- errorOccured = true;
- // IO->shm.put (shm_offset);
- debugs(79, 1, "storeDiskdSend CREATE: " << xstrerror());
- notifyClient();
- ioRequestor = NULL;
- return;
- }
- diskd_stats.create.ops++;
- }
- void
- DiskdFile::read(ReadRequest *aRead)
- {
- assert (ioRequestor.getRaw() != NULL);
- ssize_t shm_offset;
- char *rbuf = (char *)IO->shm.get(&shm_offset);
- assert(rbuf);
- ioAway();
- int x = IO->send(_MQD_READ,
- id,
- this,
- aRead->len,
- aRead->offset,
- shm_offset,
- aRead);
- if (x < 0) {
- ioCompleted();
- errorOccured = true;
- // IO->shm.put (shm_offset);
- debugs(79, 1, "storeDiskdSend READ: " << xstrerror());
- notifyClient();
- ioRequestor = NULL;
- return;
- }
- diskd_stats.read.ops++;
- }
- void
- DiskdFile::close()
- {
- debugs(79, 3, "DiskdFile::close: " << this << " closing for " << ioRequestor.getRaw());
- assert (ioRequestor.getRaw());
- ioAway();
- int x = IO->send(_MQD_CLOSE,
- id,
- this,
- 0,
- 0,
- -1,
- NULL);
- if (x < 0) {
- ioCompleted();
- errorOccured = true;
- debugs(79, 1, "storeDiskdSend CLOSE: " << xstrerror());
- notifyClient();
- ioRequestor = NULL;
- return;
- }
- diskd_stats.close.ops++;
- }
- bool
- DiskdFile::error() const
- {
- return errorOccured;
- }
- bool
- DiskdFile::canRead() const
- {
- return !error();
- }
- bool
- DiskdFile::canNotifyClient() const
- {
- if (!ioRequestor.getRaw()) {
- debugs(79, 3, "DiskdFile::canNotifyClient: No ioRequestor to notify");
- return false;
- }
- return true;
- }
- void
- DiskdFile::notifyClient()
- {
- if (!canNotifyClient()) {
- return;
- }
- ioRequestor->ioCompletedNotification();
- }
- void
- DiskdFile::completed(diomsg *M)
- {
- assert (M->newstyle);
- switch (M->mtype) {
- case _MQD_OPEN:
- openDone(M);
- break;
- case _MQD_CREATE:
- createDone(M);
- break;
- case _MQD_CLOSE:
- closeDone(M);
- break;
- case _MQD_READ:
- readDone(M);
- break;
- case _MQD_WRITE:
- writeDone(M);
- break;
- case _MQD_UNLINK:
- assert (0);
- break;
- default:
- assert(0);
- break;
- }
- }
- void
- DiskdFile::openDone(diomsg *M)
- {
- statCounter.syscalls.disk.opens++;
- debugs(79, 3, "storeDiskdOpenDone: status " << M->status);
- if (M->status < 0) {
- diskd_stats.open.fail++;
- errorOccured = true;
- } else {
- diskd_stats.open.success++;
- }
- ioCompleted();
- notifyClient();
- }
- void
- DiskdFile::createDone(diomsg *M)
- {
- statCounter.syscalls.disk.opens++;
- debugs(79, 3, "storeDiskdCreateDone: status " << M->status);
- if (M->status < 0) {
- diskd_stats.create.fail++;
- errorOccured = true;
- } else {
- diskd_stats.create.success++;
- }
- ioCompleted();
- notifyClient();
- }
- void
- DiskdFile::write(WriteRequest *aRequest)
- {
- debugs(79, 3, "DiskdFile::write: this " << (void *)this << ", buf " << (void *)aRequest->buf << ", off " << aRequest->offset << ", len " << aRequest->len);
- ssize_t shm_offset;
- char *sbuf = (char *)IO->shm.get(&shm_offset);
- memcpy(sbuf, aRequest->buf, aRequest->len);
- if (aRequest->free_func)
- aRequest->free_func(const_cast<char *>(aRequest->buf));
- ioAway();
- int x = IO->send(_MQD_WRITE,
- id,
- this,
- aRequest->len,
- aRequest->offset,
- shm_offset,
- aRequest);
- if (x < 0) {
- ioCompleted();
- errorOccured = true;
- debugs(79, 1, "storeDiskdSend WRITE: " << xstrerror());
- // IO->shm.put (shm_offset);
- notifyClient();
- ioRequestor = NULL;
- return;
- }
- diskd_stats.write.ops++;
- }
- void
- DiskdFile::ioAway()
- {
- ++inProgressIOs;
- }
- void
- DiskdFile::ioCompleted()
- {
- --inProgressIOs;
- }
- void
- DiskdFile::closeDone(diomsg * M)
- {
- statCounter.syscalls.disk.closes++;
- debugs(79, 3, "DiskdFile::closeDone: status " << M->status);
- if (M->status < 0) {
- diskd_stats.close.fail++;
- errorOccured = true;
- } else {
- diskd_stats.close.success++;
- }
- ioCompleted();
- if (canNotifyClient())
- ioRequestor->closeCompleted();
- ioRequestor = NULL;
- }
- void
- DiskdFile::readDone(diomsg * M)
- {
- statCounter.syscalls.disk.reads++;
- debugs(79, 3, "DiskdFile::readDone: status " << M->status);
- assert (M->requestor);
- ReadRequest::Pointer readRequest = dynamic_cast<ReadRequest *>(M->requestor);
- /* remove the free protection */
- readRequest->RefCountDereference();
- if (M->status < 0) {
- diskd_stats.read.fail++;
- ioCompleted();
- errorOccured = true;
- ioRequestor->readCompleted(NULL, -1, DISK_ERROR, readRequest);
- return;
- }
- diskd_stats.read.success++;
- ioCompleted();
- ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK, readRequest);
- }
- void
- DiskdFile::writeDone(diomsg *M)
- {
- statCounter.syscalls.disk.writes++;
- debugs(79, 3, "storeDiskdWriteDone: status " << M->status);
- assert (M->requestor);
- WriteRequest::Pointer writeRequest = dynamic_cast<WriteRequest *>(M->requestor);
- /* remove the free protection */
- writeRequest->RefCountDereference();
- if (M->status < 0) {
- errorOccured = true;
- diskd_stats.write.fail++;
- ioCompleted();
- ioRequestor->writeCompleted (DISK_ERROR,0, writeRequest);
- return;
- }
- diskd_stats.write.success++;
- ioCompleted();
- ioRequestor->writeCompleted (DISK_OK,M->status, writeRequest);
- }
- bool
- DiskdFile::ioInProgress()const
- {
- return inProgressIOs != 0;
- }