dnl
dnl Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9)
dnl
-dnl $Id: configure.in,v 1.307 2002/12/06 23:19:12 hno Exp $
+dnl $Id: configure.in,v 1.308 2002/12/27 10:26:32 robertc Exp $
dnl
dnl
dnl
AC_PREREQ(2.52)
AC_CONFIG_SRCDIR([src/main.cc])
AC_CONFIG_AUX_DIR(cfgaux)
-AM_INIT_AUTOMAKE(squid, 3.0-DEVEL)
+AM_INIT_AUTOMAKE(squid, 3.0-DEVEL-unifyio)
AM_CONFIG_HEADER(include/autoconf.h)
-AC_REVISION($Revision: 1.307 $)dnl
+AC_REVISION($Revision: 1.308 $)dnl
AC_PREFIX_DEFAULT(/usr/local/squid)
AM_MAINTAINER_MODE
dnl remove all but diskd - its the only module that needs to recurse
dnl into the sub directory
STORE_MODULE_SUBDIRS=
+UFS_FOUND=
for fs in $STORE_MODULES none; do
case "$fs" in
diskd)
with_aio=yes
fi
;;
+ ufs)
+ UFS_FOUND="true"
esac
done
+
+if test -z "$UFS_FOUND"; then
+ echo "adding UFS, as it contains core logic for diskd and aufs"
+ STORE_OBJS="$STORE_OBJS fs/libufs.a"
+ AC_SUBST(STORE_OBJS)
+ STORE_LIBS="$STORE_LIBS libufs.a"
+ AC_SUBST(STORE_LIBS)
+ STORE_MODULES="$STORE_MODULES ufs"
+fi
+
AC_SUBST(STORE_MODULES)
AC_SUBST(STORE_MODULE_SUBDIRS)
#
# Makefile for the Squid Object Cache server
#
-# $Id: Makefile.am,v 1.44 2002/12/15 09:00:42 robertc Exp $
+# $Id: Makefile.am,v 1.45 2002/12/27 10:26:33 robertc Exp $
#
# Uncomment and customize the following to suit your needs:
#
Store.h \
store_io.cc \
StoreIOBuffer.h \
+ StoreIOState.cc \
+ StoreIOState.h \
store_client.cc \
StoreClient.h \
store_digest.cc \
store_swapmeta.cc \
store_swapout.cc \
structs.h \
+ SwapDir.cc \
+ SwapDir.h \
tools.cc \
typedefs.h \
ufscommon.cc \
@SSLLIB@ \
-lmiscutil \
@XTRA_LIBS@
-squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a
+squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a @STORE_OBJS@
unlinkd_SOURCES = unlinkd.cc
unlinkd_CXXFLAGS = -DUNLINK_DAEMON
/*
- * $Id: Store.h,v 1.3 2002/10/15 08:03:29 robertc Exp $
+ * $Id: Store.h,v 1.4 2002/12/27 10:26:33 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
SQUIDCEXTERN void storeSwapFileNumberSet(StoreEntry * e, sfileno filn);
SQUIDCEXTERN void storeFsInit(void);
SQUIDCEXTERN void storeFsDone(void);
+typedef void STSETUP(storefs_entry_t *);
SQUIDCEXTERN void storeFsAdd(const char *, STSETUP *);
SQUIDCEXTERN void storeReplAdd(const char *, REMOVALPOLICYCREATE *);
/*
- * $Id: StoreClient.h,v 1.3 2002/10/14 07:35:00 hno Exp $
+ * $Id: StoreClient.h,v 1.4 2002/12/27 10:26:33 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
void *owner;
#endif
StoreEntry *entry; /* ptr to the parent StoreEntry, argh! */
- storeIOState *swapin_sio;
+ StoreIOState::Pointer swapin_sio;
struct {
unsigned int disk_io_pending:1;
unsigned int store_copying:1;
--- /dev/null
+
+/*
+ * $Id: StoreIOState.cc,v 1.1 2002/12/27 10:26:33 robertc Exp $
+ *
+ * DEBUG: section ?? Swap Dir base object
+ * AUTHOR: Robert Collins
+ *
+ * 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.
+ *
+ */
+
+#include "squid.h"
+#include "StoreIOState.h"
+
+void *
+storeIOState::operator new (size_t amount)
+{
+ assert(0);
+ return (void *)1;
+}
+
+void
+storeIOState::operator delete (void *address){assert (0);}
+
+storeIOState::storeIOState()
+{
+ mode = O_BINARY;
+}
+
+off_t
+storeIOState::offset() const
+{
+ return offset_;
+}
+
+storeIOState::~storeIOState()
+{
+ if (read.callback_data)
+ cbdataReferenceDone(read.callback_data);
+ if (callback_data)
+ cbdataReferenceDone(callback_data);
+}
--- /dev/null
+
+/*
+ * $Id: StoreIOState.h,v 1.1 2002/12/27 10:26:33 robertc Exp $
+ *
+ *
+ * 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.
+ *
+ */
+
+#ifndef SQUID_STOREIOSTATE_H
+#define SQUID_STOREIOSTATE_H
+
+#include "RefCount.h"
+class storeIOState : public RefCountable{
+public:
+
+ /* storeIOState does not get mempooled - it's children do */
+ void *operator new (size_t amount);
+ void operator delete (void *address);
+ void deleteSelf() const = 0;
+ virtual ~storeIOState();
+
+ storeIOState();
+
+ off_t offset() const;
+
+ virtual void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data) = 0;
+ virtual void write(char *buf, size_t size, off_t offset, FREE * free_func) = 0;
+ virtual void close() = 0;
+
+ sdirno swap_dirn;
+ sfileno swap_filen;
+ StoreEntry *e; /* Need this so the FS layers can play god */
+ mode_t mode;
+ off_t offset_; /* current on-disk offset pointer */
+ STFNCB *file_callback; /* called on delayed sfileno assignments */
+ STIOCB *callback;
+ void *callback_data;
+ struct {
+ STRCB *callback;
+ void *callback_data;
+ } read;
+ struct {
+ unsigned int closing:1; /* debugging aid */
+ } flags;
+};
+
+class StoreIOState {
+ typedef RefCount<storeIOState> Pointer;
+};
+
+#endif /* SQUID_STOREIOSTATE_H */
--- /dev/null
+
+/*
+ * $Id: SwapDir.cc,v 1.1 2002/12/27 10:26:33 robertc Exp $
+ *
+ * DEBUG: section ?? Swap Dir base object
+ * AUTHOR: Robert Collins
+ *
+ * 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.
+ *
+ */
+
+#include "squid.h"
+#include "SwapDir.h"
+#include "Store.h"
+
+SwapDir *
+SwapDir::Factory (_storefs_entry const &fs)
+{
+ SwapDir *result = fs.newfunc();
+ result->type = fs.typestr;
+ return result;
+}
+
+SwapDir::~SwapDir() {
+ xfree(path);
+}
+
+void
+SwapDir::newFileSystem(){}
+
+void
+SwapDir::dump(StoreEntry &)const{}
+
+bool
+SwapDir::doubleCheck(StoreEntry &)
+{
+ return false;
+}
+
+void
+SwapDir::unlink(StoreEntry &){}
+
+void
+SwapDir::statfs(StoreEntry &)const {}
+
+void
+SwapDir::maintainfs(){}
+
+void
+SwapDir::reference(StoreEntry &){}
+
+void
+SwapDir::dereference(StoreEntry &){}
+
+int
+SwapDir::callback()
+{
+ return 0;
+}
+
+void
+SwapDir::sync(){}
+
+/* Move to StoreEntry ? */
+bool
+SwapDir::canLog(StoreEntry const &e)const
+{
+ if (e.swap_filen < 0)
+ return false;
+ if (e.swap_status != SWAPOUT_DONE)
+ return false;
+ if (e.swap_file_sz <= 0)
+ return false;
+ if (EBIT_TEST(e.flags, RELEASE_REQUEST))
+ return false;
+ if (EBIT_TEST(e.flags, KEY_PRIVATE))
+ return false;
+ if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
+ return false;
+ return true;
+}
+
+void
+SwapDir::openLog(){}
+
+void
+SwapDir::closeLog(){}
+
+int
+SwapDir::writeCleanStart()
+{
+ return 0;
+}
+
+void
+SwapDir::writeCleanDone(){}
+
+void
+SwapDir::logEntry(const StoreEntry & e, int op) const{}
--- /dev/null
+
+/*
+ * $Id: SwapDir.h,v 1.1 2002/12/27 10:26:33 robertc Exp $
+ *
+ *
+ * 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.
+ *
+ */
+
+#ifndef SQUID_SWAPDIR_H
+#define SQUID_SWAPDIR_H
+
+#include "StoreIOState.h"
+
+/* Store dir configuration routines */
+/* SwapDir *sd, char *path ( + char *opt later when the strtok mess is gone) */
+typedef void STFSSTARTUP(void);
+typedef void STFSSHUTDOWN(void);
+typedef SwapDir *STFSNEW(void);
+struct SwapDir {
+public:
+ static SwapDir *Factory (_storefs_entry const &fs);
+ SwapDir() : max_objsize (-1){
+ fs.blksize = 1024;
+ }
+ virtual ~SwapDir();
+ virtual void reconfigure(int, char *) = 0;
+ const char *type;
+ int cur_size;
+ int low_size;
+ int max_size;
+ char *path;
+ int index; /* This entry's index into the swapDirs array */
+ ssize_t max_objsize;
+ RemovalPolicy *repl;
+ int removals;
+ int scanned;
+ struct {
+ unsigned int selected:1;
+ unsigned int read_only:1;
+ } flags;
+ virtual void init() = 0; /* Initialise the fs */
+ virtual void newFileSystem(); /* Create a new fs */
+ virtual void dump(StoreEntry &)const; /* Dump fs config snippet */
+ virtual bool doubleCheck(StoreEntry &); /* Double check the obj integrity */
+ virtual void statfs(StoreEntry &) const; /* Dump fs statistics */
+ virtual void maintainfs(); /* Replacement maintainence */
+ /* <0 == error. > 1000 == error */
+ virtual int canStore(StoreEntry const &)const = 0; /* Check if the fs will store an object */
+ /* These two are notifications */
+ virtual void reference(StoreEntry &); /* Reference this object */
+ virtual void dereference(StoreEntry &); /* Unreference this object */
+ virtual int callback(); /* Handle pending callbacks */
+ virtual void sync(); /* Sync the store prior to shutdown */
+ virtual StoreIOState::Pointer createStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *) = 0;
+ virtual StoreIOState::Pointer openStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *) = 0;
+ virtual void unlink (StoreEntry &);
+ bool canLog(StoreEntry const &e)const;
+ virtual void openLog();
+ virtual void closeLog();
+ virtual void logEntry(const StoreEntry & e, int op) const;
+ class CleanLog {
+ public:
+ virtual ~CleanLog(){}
+ virtual const StoreEntry *nextEntry() = 0;
+ virtual void write(StoreEntry const &) = 0;
+ };
+ CleanLog *cleanLog;
+ virtual int writeCleanStart();
+ virtual void writeCleanDone();
+ virtual void parse(int index, char *path) = 0;
+ struct {
+ int blksize;
+ } fs;
+};
+
+#endif /* SQUID_SWAPDIR_H */
/*
- * $Id: authenticate.cc,v 1.46 2002/10/15 09:25:33 robertc Exp $
+ * $Id: authenticate.cc,v 1.47 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 29 Authenticator
* AUTHOR: Robert Collins
assert (byteCount == sizeof (AuthUser));
if (!pool)
pool = memPoolCreate("Authenticate User Data", sizeof (auth_user_t));
- return static_cast<auth_user_t *> (memPoolAlloc(pool));
+ return memPoolAlloc(pool);
}
AuthUser::AuthUser (const char *scheme) :
/*
- * $Id: cache_cf.cc,v 1.423 2002/12/07 01:55:22 hno Exp $
+ * $Id: cache_cf.cc,v 1.424 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 3 Configuration File Parsing
* AUTHOR: Harvest Derived
#include "squid.h"
#include "authenticate.h"
#include "Store.h"
+#include "SwapDir.h"
#if SQUID_SNMP
#include "snmp.h"
static const char *const list_sep = ", \t\n\r";
static void parse_cachedir_option_readonly(SwapDir * sd, const char *option, const char *value, int reconfiguring);
-static void dump_cachedir_option_readonly(StoreEntry * e, const char *option, SwapDir * sd);
+static void dump_cachedir_option_readonly(StoreEntry * e, const char *option, SwapDir const * sd);
static void parse_cachedir_option_maxsize(SwapDir * sd, const char *option, const char *value, int reconfiguring);
-static void dump_cachedir_option_maxsize(StoreEntry * e, const char *option, SwapDir * sd);
+static void dump_cachedir_option_maxsize(StoreEntry * e, const char *option, SwapDir const * sd);
static struct cache_dir_option common_cachedir_options[] =
{
{"read-only", parse_cachedir_option_readonly, dump_cachedir_option_readonly},
ssize_t ms = -1;
for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- if (Config.cacheSwap.swapDirs[i].max_objsize > ms)
- ms = Config.cacheSwap.swapDirs[i].max_objsize;
+ assert (Config.cacheSwap.swapDirs[i]);
+ if (Config.cacheSwap.swapDirs[i]->max_objsize > ms)
+ ms = Config.cacheSwap.swapDirs[i]->max_objsize;
}
store_maxobjsize = ms;
}
#endif
void
-dump_cachedir_options(StoreEntry * entry, struct cache_dir_option *options, SwapDir * sd)
+dump_cachedir_options(StoreEntry * entry, struct cache_dir_option *options, SwapDir const * sd)
{
struct cache_dir_option *option;
if (!options)
{
SwapDir *s;
int i;
+ assert (entry);
for (i = 0; i < swap.n_configured; i++) {
- s = swap.swapDirs + i;
+ s = swap.swapDirs[i];
storeAppendPrintf(entry, "%s %s %s", name, s->type, s->path);
- if (s->dump)
- s->dump(entry, s);
+ s->dump(*entry);
dump_cachedir_options(entry, common_cachedir_options, s);
storeAppendPrintf(entry, "\n");
}
{
if (swap->swapDirs == NULL) {
swap->n_allocated = 4;
- swap->swapDirs = static_cast<SwapDir *>(xcalloc(swap->n_allocated, sizeof(SwapDir)));
+ swap->swapDirs = static_cast<SwapDir **>(xcalloc(swap->n_allocated, sizeof(SwapDir *)));
}
if (swap->n_allocated == swap->n_configured) {
- SwapDir *tmp;
+ SwapDir **tmp;
swap->n_allocated <<= 1;
- tmp = static_cast<SwapDir *>(xcalloc(swap->n_allocated, sizeof(SwapDir)));
- xmemcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir));
+ tmp = static_cast<SwapDir **>(xcalloc(swap->n_allocated, sizeof(SwapDir *)));
+ xmemcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir *));
xfree(swap->swapDirs);
swap->swapDirs = tmp;
}
*/
for (i = 0; i < swap->n_configured; i++) {
- if (0 == strcasecmp(path_str, swap->swapDirs[i].path)) {
+ assert (swap->swapDirs[i]);
+ if (0 == strcasecmp(path_str, swap->swapDirs[i]->path)) {
/* This is a little weird, you'll appreciate it later */
fs = find_fstype(type_str);
if (fs < 0) {
fatalf("Unknown cache_dir type '%s'\n", type_str);
}
- sd = swap->swapDirs + i;
- storefs_list[fs].reconfigurefunc(sd, i, path_str);
+ sd = swap->swapDirs[i];
+ sd->reconfigure (i, path_str);
update_maxobjsize();
return;
}
fatalf("Unknown cache_dir type '%s'\n", type_str);
}
allocate_new_swapdir(swap);
- sd = swap->swapDirs + swap->n_configured;
- sd->type = storefs_list[fs].typestr;
- /* defaults in case fs implementation fails to set these */
- sd->max_objsize = -1;
- sd->fs.blksize = 1024;
+ swap->swapDirs[swap->n_configured] = SwapDir::Factory(storefs_list[fs]);
+ sd = swap->swapDirs[swap->n_configured];
/* parse the FS parameters and options */
- storefs_list[fs].parsefunc(sd, swap->n_configured, path_str);
- swap->n_configured++;
+ sd->parse(swap->n_configured, path_str);
+ ++swap->n_configured;
/* Update the max object size */
update_maxobjsize();
}
}
static void
-dump_cachedir_option_readonly(StoreEntry * e, const char *option, SwapDir * sd)
+dump_cachedir_option_readonly(StoreEntry * e, const char *option, SwapDir const * sd)
{
if (sd->flags.read_only)
storeAppendPrintf(e, " %s", option);
}
static void
-dump_cachedir_option_maxsize(StoreEntry * e, const char *option, SwapDir * sd)
+dump_cachedir_option_maxsize(StoreEntry * e, const char *option, SwapDir const * sd)
{
if (sd->max_objsize != -1)
storeAppendPrintf(e, " %s=%ld", option, (long int) sd->max_objsize);
static void
free_cachedir(_SquidConfig::_cacheSwap * swap)
{
- SwapDir *s;
int i;
/* DON'T FREE THESE FOR RECONFIGURE */
if (reconfiguring)
return;
for (i = 0; i < swap->n_configured; i++) {
- s = swap->swapDirs + i;
- s->freefs(s);
- xfree(s->path);
+ SwapDir * s = swap->swapDirs[i];
+ swap->swapDirs[i] = NULL;
+ delete s;
}
safe_free(swap->swapDirs);
swap->swapDirs = NULL;
/*
- * $Id: client_side_reply.cc,v 1.26 2002/11/15 14:18:30 hno Exp $
+ * $Id: client_side_reply.cc,v 1.27 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 88 Client-side Reply Routines
* AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
clientProcessMiss(context);
return;
}
- assert(result.length > 0);
+ if (result.length == 0) {
+ /* the store couldn't get enough data from the file for us to id the
+ * object
+ */
+ /* treat as a miss */
+ http->logType = LOG_TCP_MISS;
+ clientProcessMiss(context);
+ return;
+ }
mem = e->mem_obj;
assert(!EBIT_TEST(e->flags, ENTRY_ABORTED));
/* update size of the request */
/*
- * $Id: async_io.cc,v 1.19 2002/11/15 13:16:31 hno Exp $
+ * $Id: async_io.cc,v 1.20 2002/12/27 10:26:35 robertc Exp $
*
* DEBUG: section 32 Asynchronous Disk I/O
* AUTHOR: Pete Bentley <pete@demon.net>
int
-aioCheckCallbacks(SwapDir * SD)
+AUFSSwapDir::callback()
{
squidaio_result_t *resultp;
squidaio_ctrl_t *ctrlp;
/* Flush all pending I/O */
void
-aioSync(SwapDir * SD)
+AUFSSwapDir::sync()
{
if (!initialised)
return; /* nothing to do then */
/* Flush all pending operations */
debug(32, 1) ("aioSync: flushing pending I/O operations\n");
do {
- aioCheckCallbacks(SD);
+ callback();
} while (squidaio_sync());
debug(32, 1) ("aioSync: done\n");
}
void aioStat(char *, struct stat *, AIOCB *, void *);
void aioUnlink(const char *, AIOCB *, void *);
void aioTruncate(const char *, off_t length, AIOCB *, void *);
-int aioCheckCallbacks(SwapDir *);
-void aioSync(SwapDir *);
int aioQueueSize(void);
-struct _squidaiostate_t {
+#include "ufscommon.h"
+
+class AufsIO;
+class AUFSFile : public DiskFile {
+ public:
+ virtual void deleteSelf() const;
+ void * operator new (size_t);
+ void operator delete (void *);
+ AUFSFile (char const *path, AufsIO *);
+ ~AUFSFile();
+ virtual void open (int, mode_t, IORequestor::Pointer);
+ virtual void create (int, mode_t, IORequestor::Pointer);
+ virtual void read(char *, off_t, size_t);
+ virtual void write(char const *buf, size_t size, off_t offset, FREE *free_func);
+ void close();
+ virtual bool error() const;
+ virtual int getFD() const { return fd;}
+ virtual bool canRead() const;
+ virtual bool canWrite() const;
+ private:
+#if ASYNC_READ
+static AIOCB ReadDone;
+#else
+static DRCB ReadDone;
+#endif
+#if ASYNC_WRITE
+static AIOCB WriteDone;
+#else
+static DWCB WriteDone;
+#endif
+ int fd;
+ bool errorOccured;
+ char const *path_;
+ AufsIO* IO;
+ static AIOCB OpenDone;
+ void openDone(int fd, const char *buf, int aio_return, int aio_errno);
+ IORequestor::Pointer ioRequestor;
+ CBDATA_CLASS(AUFSFile);
+ void doClose();
+
+ void readDone(int fd, const char *buf, int len, int errflag);
+ void writeDone (int fd, int errflag, size_t len);
+};
+
+class squidaiostate_t : public UFSStoreState {
+ public:
+ virtual void deleteSelf() const {delete this;}
+ void * operator new (size_t);
+ void operator delete (void *);
+ squidaiostate_t(SwapDir *, StoreEntry *, STIOCB *, void *);
+ ~squidaiostate_t();
+
+ void close();
int fd;
struct {
- unsigned int close_request:1;
- unsigned int reading:1;
- unsigned int writing:1;
- unsigned int opening:1;
unsigned int write_kicking:1;
unsigned int read_kicking:1;
unsigned int inreaddone:1;
} flags;
- char *read_buf;
- link_list *pending_writes;
- link_list *pending_reads;
+ void ioCompletedNotification();
+ void closeCompleted();
+ void readCompleted(const char *buf, int len, int errflag);
+ void writeCompleted(int errflag, size_t len);
+ void writeDone(int fd, int errflag, size_t len);
+ private:
+ CBDATA_CLASS(squidaiostate_t);
+ void openDone();
};
-struct _queued_write {
- char *buf;
- size_t size;
- off_t offset;
- FREE *free_func;
-};
-
-struct _queued_read {
- char *buf;
- size_t size;
- off_t offset;
- STRCB *callback;
- void *callback_data;
-};
-
-typedef struct _squidaiostate_t squidaiostate_t;
-
-/* The squidaio_state memory pools */
-extern MemPool *squidaio_state_pool;
-extern MemPool *aufs_qread_pool;
-extern MemPool *aufs_qwrite_pool;
-
/*
* Store IO stuff
*/
-extern STOBJCREATE storeAufsCreate;
-extern STOBJOPEN storeAufsOpen;
-extern STOBJCLOSE storeAufsClose;
-extern STOBJREAD storeAufsRead;
-extern STOBJWRITE storeAufsWrite;
-extern STOBJUNLINK storeAufsUnlink;
+#include "SwapDir.h"
+class AUFSSwapDir : public UFSSwapDir
+{
+public:
+ virtual void dump(StoreEntry &)const;
+ virtual void unlink(StoreEntry &);
+ virtual int canStore(StoreEntry const &)const;
+ virtual int callback();
+ virtual void sync();
+ virtual void parse (int index, char *path);
+ virtual void reconfigure(int, char *);
+ virtual void unlinkFile(char const *);
+};
+
+class AufsIO : public UFSStrategy
+{
+public:
+ virtual bool shedLoad();
+ virtual void deleteSelf() const;
+ virtual StoreIOState::Pointer createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const;
+ virtual DiskFile::Pointer newFile(char const *path);
+ static AufsIO Instance;
+};
#endif
/*
- * $Id: store_dir_aufs.cc,v 1.52 2002/11/10 02:29:58 hno Exp $
+ * $Id: store_dir_aufs.cc,v 1.53 2002/12/27 10:26:35 robertc Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
#include "store_asyncufs.h"
#include "ufscommon.h"
+#include "SwapDir.h"
-MemPool *squidaio_state_pool = NULL;
MemPool *aufs_qread_pool = NULL;
MemPool *aufs_qwrite_pool = NULL;
static int asyncufs_initialised = 0;
-static STDUMP storeAufsDirDump;
-static STCHECKOBJ storeAufsDirCheckObj;
-static void storeAufsDirIOUnlinkFile(char *path);
-
-
/* The MAIN externally visible function */
STSETUP storeFsSetup_aufs;
* happily store anything as long as the LRU time isn't too small.
*/
int
-storeAufsDirCheckObj(SwapDir * SD, const StoreEntry * e)
+AUFSSwapDir::canStore(StoreEntry const &e) const
{
int loadav;
int ql;
#if OLD_UNUSED_CODE
- if (storeAufsDirExpiredReferenceAge(SD) < 300) {
+ if (storeAufsDirExpiredReferenceAge(this) < 300) {
debug(47, 3) ("storeAufsDirCheckObj: NO: LRU Age = %d\n",
- storeAufsDirExpiredReferenceAge(SD));
+ storeAufsDirExpiredReferenceAge(this));
/* store_check_cachable_hist.no.lru_age_too_low++; */
return -1;
}
}
void
-storeAufsDirIOUnlinkFile(char *path)
+AUFSSwapDir::unlinkFile(char const *path)
{
#if USE_TRUNCATE_NOT_UNLINK
aioTruncate(path, NULL, NULL);
*
* This routine is called when the given swapdir needs reconfiguring
*/
-static void
-storeAufsDirReconfigure(SwapDir * sd, int index, char *path)
+void
+AUFSSwapDir::reconfigure(int anIndex, char *aPath)
{
- int i;
- int size;
- int l1;
- int l2;
-
- i = GetInteger();
- size = i << 10; /* Mbytes to kbytes */
- if (size <= 0)
- fatal("storeAufsDirReconfigure: invalid size value");
- i = GetInteger();
- l1 = i;
- if (l1 <= 0)
- fatal("storeAufsDirReconfigure: invalid level 1 directories value");
- i = GetInteger();
- l2 = i;
- if (l2 <= 0)
- fatal("storeAufsDirReconfigure: invalid level 2 directories value");
-
- /* just reconfigure it */
- if (size == sd->max_size)
- debug(3, 1) ("Cache dir '%s' size remains unchanged at %d KB\n",
- path, size);
- else
- debug(3, 1) ("Cache dir '%s' size changed to %d KB\n",
- path, size);
- sd->max_size = size;
-
- parse_cachedir_options(sd, options, 0);
-
- return;
+ UFSSwapDir::reconfigure (anIndex, aPath);
+
+ parse_cachedir_options(this, options, 0);
}
void
-storeAufsDirDump(StoreEntry * entry, SwapDir * s)
+AUFSSwapDir::dump(StoreEntry & entry) const
{
- commonUfsDirDump(entry, s);
- dump_cachedir_options(entry, options, s);
+ UFSSwapDir::dump(entry);
+ dump_cachedir_options(&entry, options, this);
}
/*
* storeAufsDirParse *
* Called when a *new* fs is being setup.
*/
-static void
-storeAufsDirParse(SwapDir * sd, int index, char *path)
+void
+AUFSSwapDir::parse(int anIndex, char *aPath)
{
- int i;
- int size;
- int l1;
- int l2;
- squidufsinfo_t *aioinfo;
-
- i = GetInteger();
- size = i << 10; /* Mbytes to kbytes */
- if (size <= 0)
- fatal("storeAufsDirParse: invalid size value");
- i = GetInteger();
- l1 = i;
- if (l1 <= 0)
- fatal("storeAufsDirParse: invalid level 1 directories value");
- i = GetInteger();
- l2 = i;
- if (l2 <= 0)
- fatal("storeAufsDirParse: invalid level 2 directories value");
-
- aioinfo = (squidufsinfo_t *)xmalloc(sizeof(squidufsinfo_t));
- if (aioinfo == NULL)
- fatal("storeAufsDirParse: couldn't xmalloc() squidufsinfo_t!\n");
-
- sd->index = index;
- sd->path = xstrdup(path);
- sd->max_size = size;
- sd->fsdata = aioinfo;
- aioinfo->l1 = l1;
- aioinfo->l2 = l2;
- aioinfo->swaplog_fd = -1;
- aioinfo->map = NULL; /* Debugging purposes */
- aioinfo->suggest = 0;
- aioinfo->io.storeDirUnlinkFile = storeAufsDirIOUnlinkFile;
- sd->init = commonUfsDirInit;
- sd->newfs = commonUfsDirNewfs;
- sd->dump = storeAufsDirDump;
- sd->freefs = commonUfsDirFree;
- sd->dblcheck = commonUfsCleanupDoubleCheck;
- sd->statfs = commonUfsDirStats;
- sd->maintainfs = commonUfsDirMaintain;
- sd->checkobj = storeAufsDirCheckObj;
- sd->refobj = commonUfsDirRefObj;
- sd->unrefobj = commonUfsDirUnrefObj;
- sd->callback = aioCheckCallbacks;
- sd->sync = aioSync;
- sd->obj.create = storeAufsCreate;
- sd->obj.open = storeAufsOpen;
- sd->obj.close = storeAufsClose;
- sd->obj.read = storeAufsRead;
- sd->obj.write = storeAufsWrite;
- sd->obj.unlink = storeAufsUnlink;
- sd->log.open = commonUfsDirOpenSwapLog;
- sd->log.close = commonUfsDirCloseSwapLog;
- sd->log.write = commonUfsDirSwapLog;
- sd->log.clean.start = commonUfsDirWriteCleanStart;
- sd->log.clean.nextentry = commonUfsDirCleanLogNextEntry;
- sd->log.clean.done = commonUfsDirWriteCleanDone;
-
- parse_cachedir_options(sd, options, 0);
-
- /* Initialise replacement policy stuff */
- sd->repl = createRemovalPolicy(Config.replPolicy);
+ UFSSwapDir::parse(anIndex, aPath);
+
+ parse_cachedir_options(this, options, 0);
}
/*
storeAufsDirDone(void)
{
aioDone();
- memPoolDestroy(&squidaio_state_pool);
memPoolDestroy(&aufs_qread_pool);
memPoolDestroy(&aufs_qwrite_pool);
asyncufs_initialised = 0;
}
+static SwapDir *
+storeAufsNew(void)
+{
+ AUFSSwapDir *result = new AUFSSwapDir;
+ result->IO = &AufsIO::Instance;
+ return result;
+}
+
void
storeFsSetup_aufs(storefs_entry_t * storefs)
{
assert(!asyncufs_initialised);
- storefs->parsefunc = storeAufsDirParse;
- storefs->reconfigurefunc = storeAufsDirReconfigure;
storefs->donefunc = storeAufsDirDone;
- squidaio_state_pool = memPoolCreate("AUFS IO State data", sizeof(squidaiostate_t));
- aufs_qread_pool = memPoolCreate("AUFS Queued read data",
- sizeof(queued_read));
- aufs_qwrite_pool = memPoolCreate("AUFS Queued write data",
- sizeof(queued_write));
+ storefs->newfunc = storeAufsNew;
asyncufs_initialised = 1;
aioInit();
#include "store_asyncufs.h"
#include "Store.h"
#include "ufscommon.h"
+#include "SwapDir.h"
-#if ASYNC_READ
-static AIOCB storeAufsReadDone;
-#else
-static DRCB storeAufsReadDone;
-#endif
-#if ASYNC_WRITE
-static AIOCB storeAufsWriteDone;
-#else
-static DWCB storeAufsWriteDone;
-#endif
static void storeAufsIOCallback(storeIOState * sio, int errflag);
-static AIOCB storeAufsOpenDone;
static int storeAufsNeedCompletetion(storeIOState *);
-static int storeAufsKickWriteQueue(storeIOState * sio);
-static CBDUNL storeAufsIOFreeEntry;
-
-CBDATA_TYPE(storeIOState);
/* === PUBLIC =========================================================== */
-/* open for reading */
-storeIOState *
-storeAufsOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
- STIOCB * callback, void *callback_data)
+
+
+CBDATA_CLASS_INIT(squidaiostate_t);
+
+void *
+squidaiostate_t::operator new (size_t)
+{
+ CBDATA_INIT_TYPE(squidaiostate_t);
+ squidaiostate_t *result = cbdataAlloc(squidaiostate_t);
+ /* Mark result as being owned - we want the refcounter to do the delete
+ * call */
+ cbdataReference(result);
+ return result;
+}
+
+void
+squidaiostate_t::operator delete (void *address)
+{
+ squidaiostate_t *t = static_cast<squidaiostate_t *>(address);
+ cbdataFree(address);
+ /* And allow the memory to be freed */
+ cbdataReferenceDone (t);
+}
+
+squidaiostate_t::squidaiostate_t(SwapDir * SD, StoreEntry * anEntry, STIOCB * callback_, void *callback_data_)
+{
+ swap_filen = anEntry->swap_filen;
+ swap_dirn = SD->index;
+ mode = O_BINARY;
+ callback = callback_;
+ callback_data = cbdataReference(callback_data_);
+ e = anEntry;
+ fd = -1;
+}
+
+AufsIO AufsIO::Instance;
+bool
+AufsIO::shedLoad()
{
- sfileno f = e->swap_filen;
- char *path = commonUfsDirFullPath(SD, f, NULL);
- storeIOState *sio;
-#if !ASYNC_OPEN
- int fd;
-#endif
- debug(79, 3) ("storeAufsOpen: fileno %08X\n", f);
/*
* we should detect some 'too many files open' condition and return
* NULL here.
*/
#ifdef MAGIC2
if (aioQueueSize() > MAGIC2)
- return NULL;
+ return true;
#endif
+ return false;
+}
+void
+AufsIO::deleteSelf() const
+{
+ /* do nothing, we use a single instance */
+}
+
+StoreIOState::Pointer
+AufsIO::createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const
+{
+ return new squidaiostate_t (SD, e, callback, callback_data);
+}
+
+DiskFile::Pointer
+AufsIO::newFile (char const *path)
+{
+ return new AUFSFile (path, this);
+}
+
+CBDATA_CLASS_INIT(AUFSFile);
+void *
+AUFSFile::operator new (size_t)
+{
+ CBDATA_INIT_TYPE(AUFSFile);
+ AUFSFile *result = cbdataAlloc(AUFSFile);
+ /* Mark result as being owned - we want the refcounter to do the delete
+ * call */
+ cbdataReference(result);
+ return result;
+}
+
+void
+AUFSFile::operator delete (void *address)
+{
+ AUFSFile *t = static_cast<AUFSFile *>(address);
+ cbdataFree(address);
+ /* And allow the memory to be freed */
+ cbdataReferenceDone (t);
+}
+
+void
+AUFSFile::deleteSelf() const {delete this;}
+
+AUFSFile::AUFSFile (char const *aPath, AufsIO *anIO):fd(-1), errorOccured (false), IO(anIO) {
+ assert (aPath);
+ debug (79,0)("UFSFile::UFSFile: %s\n", aPath);
+ path_ = xstrdup (aPath);
+}
+
+AUFSFile::~AUFSFile()
+{
+ safe_free (path_);
+ doClose();
+}
+
+void
+AUFSFile::open (int flags, mode_t mode, IORequestor::Pointer callback)
+{
#if !ASYNC_OPEN
- fd = file_open(path, O_RDONLY | O_BINARY);
+ fd = file_open(path_, flags);
if (fd < 0) {
- debug(79, 3) ("storeAufsOpen: got failure (%d)\n", errno);
- return NULL;
+ debug(79, 3) ("AUFSFile::open: got failure (%d)\n", errno);
+ errorOccured = true;
+ return;
}
#endif
- CBDATA_INIT_TYPE_FREECB(storeIOState, storeAufsIOFreeEntry);
- sio = cbdataAlloc(storeIOState);
- sio->fsstate = memPoolAlloc(squidaio_state_pool);
- ((squidaiostate_t *) (sio->fsstate))->fd = -1;
- ((squidaiostate_t *) (sio->fsstate))->flags.opening = 1;
- sio->swap_filen = f;
- sio->swap_dirn = SD->index;
- sio->mode = O_RDONLY | O_BINARY;
- sio->callback = callback;
- sio->callback_data = cbdataReference(callback_data);
- sio->e = e;
Opening_FD++;
+ ioRequestor = callback;
#if ASYNC_OPEN
- aioOpen(path, O_RDONLY | O_BINARY, 0644, storeAufsOpenDone, sio);
+ aioOpen(path_, flags, mode, AUFSFile::OpenDone, this);
#else
- storeAufsOpenDone(fd, sio, fd, 0);
+ openDone(fd, NULL, fd, 0);
#endif
- return sio;
}
-/* open for creating */
-storeIOState *
-storeAufsCreate(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data)
+void
+AUFSFile::read(char *buf, off_t offset, size_t size)
{
- char *path;
- storeIOState *sio;
- sfileno filn;
- sdirno dirn;
-#if !ASYNC_CREATE
- int fd;
+ assert (fd > -1);
+ assert (ioRequestor.getRaw());
+#if ASYNC_READ
+ aioRead(fd, offset, size, ReadDone, this);
+#else
+ file_read(fd, buf, size, offset, ReadDone, this);
#endif
+}
- /* Allocate a number */
- dirn = SD->index;
- filn = commonUfsDirMapBitAllocate(SD);
- path = commonUfsDirFullPath(SD, filn, NULL);
-
- debug(79, 3) ("storeAufsCreate: fileno %08X\n", filn);
- /*
- * we should detect some 'too many files open' condition and return
- * NULL here.
- */
-#ifdef MAGIC2
- if (aioQueueSize() > MAGIC2)
- return NULL;
-#endif
+void
+AUFSFile::create (int flags, mode_t mode, IORequestor::Pointer callback)
+{
#if !ASYNC_CREATE
- fd = file_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
+ int fd = file_open(path_, flags);
if (fd < 0) {
debug(79, 3) ("storeAufsCreate: got failure (%d)\n", errno);
- return NULL;
+ errorOccured = true;
+ return;
}
#endif
- CBDATA_INIT_TYPE_FREECB(storeIOState, storeAufsIOFreeEntry);
- sio = cbdataAlloc(storeIOState);
- sio->fsstate = memPoolAlloc(squidaio_state_pool);
- ((squidaiostate_t *) (sio->fsstate))->fd = -1;
- ((squidaiostate_t *) (sio->fsstate))->flags.opening = 1;
- sio->swap_filen = filn;
- sio->swap_dirn = dirn;
- sio->mode = O_WRONLY | O_BINARY;
- sio->callback = callback;
- sio->callback_data = cbdataReference(callback_data);
- sio->e = (StoreEntry *) e;
Opening_FD++;
+ ioRequestor = callback;
#if ASYNC_CREATE
- aioOpen(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644, storeAufsOpenDone, sio);
+ aioOpen(path_, flags, mode, AUFSFile::OpenDone, this);
#else
- storeAufsOpenDone(fd, sio, fd, 0);
+ openDone (fd, NULL, fd, 0);
#endif
+}
- /* now insert into the replacement policy */
- commonUfsDirReplAdd(SD, e);
- return sio;
+bool
+AUFSFile::error() const
+{
+ return errorOccured;
+}
+void
+AUFSFile::OpenDone(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno)
+{
+ AUFSFile *myFile = static_cast<AUFSFile *>(cbdata);
+ myFile->openDone (fd, buf, aio_return, aio_errno);
}
+void
+AUFSFile::openDone(int unused, const char *unused2, int anFD, int errflag)
+{
+ debug(79, 3) ("AUFSFile::openDone: FD %d, errflag %d\n", anFD, errflag);
+ Opening_FD--;
+ fd = anFD;
+ if (errflag || fd < 0) {
+ errno = errflag;
+ debug(79, 0) ("AUFSFile::openDone: %s\n", xstrerror());
+ debug(79, 1) ("\t%s\n", path_);
+ errorOccured = true;
+ } else {
+ store_open_disk_fd++;
+ commSetCloseOnExec(fd);
+ fd_open(fd, FD_FILE, path_);
+ }
+
+ debug(79, 3) ("AUFSFile::openDone: exiting\n");
-/* Close */
-void
-storeAufsClose(SwapDir * SD, storeIOState * sio)
+ IORequestor::Pointer t = ioRequestor;
+ t->ioCompletedNotification();
+}
+
+void AUFSFile::doClose()
{
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- debug(79, 3) ("storeAufsClose: dirno %d, fileno %08X, FD %d\n",
- sio->swap_dirn, sio->swap_filen, aiostate->fd);
- if (storeAufsNeedCompletetion(sio)) {
- aiostate->flags.close_request = 1;
- return;
+ if (fd > -1) {
+ aioClose(fd);
+ fd_close(fd);
+ store_open_disk_fd--;
+ fd = -1;
}
- storeAufsIOCallback(sio, DISK_OK);
}
+/* open for reading */
+StoreIOState::Pointer
+storeAufsOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
+ STIOCB * callback, void *callback_data)
+{
+ UFSStrategy *IO = dynamic_cast <UFSStrategy *>(((AUFSSwapDir *)SD)->IO);
+ assert (IO);
+ return IO->open (SD, e, file_callback, callback, callback_data);
+}
+
+/* open for creating */
+StoreIOState::Pointer
+storeAufsCreate(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data)
+{
+ UFSStrategy *IO = dynamic_cast <UFSStrategy *>(((AUFSSwapDir *)SD)->IO);
+ assert (IO);
+ return IO->create (SD, e, file_callback, callback, callback_data);
+}
-/* Read */
+/* Close */
void
-storeAufsRead(SwapDir * SD, storeIOState * sio, char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
-{
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- assert(sio->read.callback == NULL);
- assert(sio->read.callback_data == NULL);
- assert(!aiostate->flags.reading);
- if (aiostate->fd < 0) {
- struct _queued_read *q;
- debug(79, 3) ("storeAufsRead: queueing read because FD < 0\n");
- assert(aiostate->flags.opening);
- assert(aiostate->pending_reads == NULL);
- q = (struct _queued_read *)memPoolAlloc(aufs_qread_pool);
- q->buf = buf;
- q->size = size;
- q->offset = offset;
- q->callback = callback;
- q->callback_data = cbdataReference(callback_data);
- linklistPush(&(aiostate->pending_reads), q);
+squidaiostate_t::close()
+{
+ debug(79, 3) ("storeAufsClose: dirno %d, fileno %08X, FD %d\n",
+ swap_dirn, swap_filen, fd);
+ /* mark the object to be closed on the next io that completes */
+ if (storeAufsNeedCompletetion(this)) {
+ closing = true;
return;
}
- sio->read.callback = callback;
- sio->read.callback_data = cbdataReference(callback_data);
- aiostate->read_buf = buf;
- debug(79, 3) ("storeAufsRead: dirno %d, fileno %08X, FD %d\n",
- sio->swap_dirn, sio->swap_filen, aiostate->fd);
- sio->offset = offset;
- aiostate->flags.reading = 1;
-#if ASYNC_READ
- aioRead(aiostate->fd, offset, size, storeAufsReadDone, sio);
-#else
- file_read(aiostate->fd, buf, size, offset, storeAufsReadDone, sio);
-#endif
+ storeAufsIOCallback(this, DISK_OK);
}
+bool
+AUFSFile::canRead() const
+{
+ debug (79,3)("AUFSFile::canRead: fd is %d\n",fd);
+ return fd > -1;
+}
-/* Write */
void
-storeAufsWrite(SwapDir * SD, storeIOState * sio, char *buf, size_t size, off_t offset, FREE * free_func)
-{
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- debug(79, 3) ("storeAufsWrite: dirno %d, fileno %08X, FD %d\n",
- sio->swap_dirn, sio->swap_filen, aiostate->fd);
- if (aiostate->fd < 0) {
- /* disk file not opened yet */
- struct _queued_write *q;
- assert(aiostate->flags.opening);
- q = (struct _queued_write *)memPoolAlloc(aufs_qwrite_pool);
- q->buf = buf;
- q->size = size;
- q->offset = offset;
- q->free_func = free_func;
- linklistPush(&(aiostate->pending_writes), q);
- return;
- }
+AUFSFile::write(char const *buf, size_t size, off_t offset, FREE *free_func)
+{
+ debug(79, 3) ("storeAufsWrite: FD %d\n", fd);
#if ASYNC_WRITE
- if (aiostate->flags.writing) {
- struct _queued_write *q;
- debug(79, 3) ("storeAufsWrite: queuing write\n");
- q = (struct _queued_write *)memPoolAlloc(aufs_qwrite_pool);
- q->buf = buf;
- q->size = size;
- q->offset = offset;
- q->free_func = free_func;
- linklistPush(&(aiostate->pending_writes), q);
- return;
- }
- aiostate->flags.writing = 1;
- aioWrite(aiostate->fd, offset, buf, size, storeAufsWriteDone, sio,
+ aioWrite(fd, offset, (char *)buf, size, WriteDone, this,
free_func);
#else
- file_write(aiostate->fd, offset, buf, size, storeAufsWriteDone, sio,
+ file_write(fd, offset, (char *)buf, size, WriteDone, this,
free_func);
#endif
}
+bool
+AUFSFile::canWrite() const {
+ return fd > -1;
+}
+
/* Unlink */
void
-storeAufsUnlink(SwapDir * SD, StoreEntry * e)
+AUFSSwapDir::unlink(StoreEntry & e)
{
- debug(79, 3) ("storeAufsUnlink: dirno %d, fileno %08X\n", SD->index, e->swap_filen);
- commonUfsDirReplRemove(e);
- commonUfsDirMapBitReset(SD, e->swap_filen);
- commonUfsDirUnlinkFile(SD, e->swap_filen);
+ debug(79, 3) ("storeAufsUnlink: dirno %d, fileno %08X\n", index, e.swap_filen);
+ replacementRemove(&e);
+ mapBitReset(e.swap_filen);
+ UFSSwapDir::unlinkFile(e.swap_filen);
}
/* === STATIC =========================================================== */
-static int
-storeAufsKickWriteQueue(storeIOState * sio)
+#if ASYNC_READ
+void
+AUFSFile::ReadDone(int fd, void *my_data, const char *buf, int len, int errflag)
+#else
+void
+AUFSFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data)
+#endif
{
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- struct _queued_write *q = (struct _queued_write *)linklistShift(&aiostate->pending_writes);
- if (NULL == q)
- return 0;
- debug(79, 3) ("storeAufsKickWriteQueue: writing queued chunk of %ld bytes\n",
- (long int) q->size);
- storeAufsWrite(INDEXSD(sio->swap_dirn), sio, q->buf, q->size, q->offset, q->free_func);
- memPoolFree(aufs_qwrite_pool, q);
- return 1;
+ AUFSFile *myFile = static_cast<AUFSFile *>(my_data);
+ assert (myFile);
+ myFile->readDone (fd, buf, len, errflag);
}
-static int
-storeAufsKickReadQueue(storeIOState * sio)
+void
+AUFSFile::readDone(int rvfd, const char *buf, int len, int errflag)
{
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- struct _queued_read *q = (struct _queued_read *)linklistShift(&(aiostate->pending_reads));
- void *cbdata;
- if (NULL == q)
- return 0;
- debug(79, 3) ("storeAufsKickReadQueue: reading queued request of %ld bytes\n",
- (long int) q->size);
- if (cbdataReferenceValidDone(q->callback_data, &cbdata))
- storeAufsRead(INDEXSD(sio->swap_dirn), sio, q->buf, q->size, q->offset, q->callback, cbdata);
- memPoolFree(aufs_qread_pool, q);
- return 1;
-}
+ debug (79,3)("AUFSFile::readDone: FD %d\n",rvfd);
+ assert (fd == rvfd);
-static void
-storeAufsOpenDone(int unused, void *my_data, const char *unused2, int fd, int errflag)
-{
- storeIOState *sio = (storeIOState *)my_data;
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- debug(79, 3) ("storeAufsOpenDone: FD %d, errflag %d\n", fd, errflag);
- Opening_FD--;
- aiostate->flags.opening = 0;
- if (errflag || fd < 0) {
- errno = errflag;
- debug(79, 0) ("storeAufsOpenDone: %s\n", xstrerror());
- debug(79, 1) ("\t%s\n", commonUfsDirFullPath(INDEXSD(sio->swap_dirn), sio->swap_filen, NULL));
- storeAufsIOCallback(sio, DISK_ERROR);
- return;
- }
- store_open_disk_fd++;
- aiostate->fd = fd;
- commSetCloseOnExec(fd);
- fd_open(fd, FD_FILE, commonUfsDirFullPath(INDEXSD(sio->swap_dirn), sio->swap_filen, NULL));
- if (FILE_MODE(sio->mode) == O_WRONLY) {
- if (storeAufsKickWriteQueue(sio))
- return;
- } else if ((FILE_MODE(sio->mode) == O_RDONLY) && !aiostate->flags.close_request) {
- if (storeAufsKickReadQueue(sio))
- return;
- }
- if (aiostate->flags.close_request)
- storeAufsIOCallback(sio, errflag);
- debug(79, 3) ("storeAufsOpenDone: exiting\n");
-}
-
-#if ASYNC_READ
-static void
-storeAufsReadDone(int fd, void *my_data, const char *buf, int len, int errflag)
-#else
-static void
-storeAufsReadDone(int fd, const char *buf, int len, int errflag, void *my_data)
-#endif
-{
- storeIOState *sio = (storeIOState *)my_data;
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- STRCB *callback = sio->read.callback;
- void *cbdata;
ssize_t rlen;
- int inreaddone = aiostate->flags.inreaddone; /* Protect from callback loops */
- debug(79, 3) ("storeAufsReadDone: dirno %d, fileno %08X, FD %d, len %d\n",
- sio->swap_dirn, sio->swap_filen, fd, len);
- aiostate->flags.inreaddone = 1;
- aiostate->flags.reading = 0;
if (errflag) {
- debug(79, 3) ("storeAufsReadDone: got failure (%d)\n", errflag);
+ debug(79, 3) ("AUFSFile::readDone: got failure (%d)\n", errflag);
rlen = -1;
} else {
rlen = (ssize_t) len;
- sio->offset += len;
}
#if ASYNC_READ
/* translate errflag from errno to Squid disk error */
if (errflag == DISK_EOF)
errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */
#endif
+ ioRequestor->readCompleted(buf, rlen, errflag);
+}
+
+void
+squidaiostate_t::readCompleted(const char *buf, int len, int errflag)
+{
+ int localinreaddone = flags.inreaddone; /* Protect from callback loops */
+ flags.inreaddone = 1;
+ reading = false;
+ debug(79, 3) ("squidaiostate_t::readCompleted: dirno %d, fileno %08X, len %d\n",
+ swap_dirn, swap_filen, len);
+ if (len > 0)
+ offset_ += len;
+
+ STRCB *callback = read.callback;
assert(callback);
- sio->read.callback = NULL;
- if (!aiostate->flags.close_request && cbdataReferenceValidDone(sio->read.callback_data, &cbdata)) {
-#if ASYNC_READ
- if (rlen > 0)
- memcpy(aiostate->read_buf, buf, rlen);
-#endif
- callback(cbdata, aiostate->read_buf, rlen);
+ read.callback = NULL;
+ void *cbdata;
+ if (!closing && cbdataReferenceValidDone(read.callback_data, &cbdata)) {
+ if (len > 0 && read_buf != buf)
+ memcpy(read_buf, buf, len);
+ callback(cbdata, read_buf, len);
}
- aiostate->flags.inreaddone = 0;
- if (aiostate->flags.close_request && !inreaddone)
- storeAufsIOCallback(sio, errflag);
+
+ flags.inreaddone = 0;
+ if (closing && !localinreaddone)
+ storeAufsIOCallback(this, errflag);
}
+
+
+void
+squidaiostate_t::writeCompleted(int errflag, size_t len)
+{
+ debug(79, 3) ("storeAufsWriteDone: dirno %d, fileno %08X, len %ld, err=%d\n",
+ swap_dirn, swap_filen, (long int) len, errflag);
+ writing = false;
+ if (errflag) {
+ debug(79, 0) ("storeAufsWriteDone: got failure (%d)\n", errflag);
+ storeAufsIOCallback(this, errflag);
+ return;
+ }
+ offset_ += len;
#if ASYNC_WRITE
-static void
-storeAufsWriteDone(int fd, void *my_data, int len, int errflag)
+ if (!kickWriteQueue())
+ 0;
+ else if (closing)
+ storeAufsIOCallback(this, errflag);
#else
-static void
-storeAufsWriteDone(int fd, int errflag, size_t len, void *my_data)
+ if (!flags.write_kicking) {
+ flags.write_kicking = 1;
+ while (kickWriteQueue())
+ (void) 0;
+ flags.write_kicking = 0;
+ if (closing)
+ storeAufsIOCallback(this, errflag);
+ }
+#endif
+}
+
+void
+AUFSFile::
+#if ASYNC_WRITE
+WriteDone(int fd, void *my_data, int len, int errflag)
+#else
+WriteDone(int fd, int errflag, size_t len, void *my_data)
#endif
{
+ AUFSFile *aFile = static_cast<AUFSFile *>(my_data);
+ assert (aFile);
+ aFile->writeDone (fd, errflag, len);
+}
+
+void
+AUFSFile::writeDone (int rvfd, int errflag, size_t len)
+{
+ assert (rvfd == fd);
static int loop_detect = 0;
- storeIOState *sio = (storeIOState *)my_data;
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- debug(79, 3) ("storeAufsWriteDone: dirno %d, fileno %08X, FD %d, len %ld, err=%d\n",
- sio->swap_dirn, sio->swap_filen, fd, (long int) len, errflag);
+ debug(79, 3) ("storeAufsWriteDone: FD %d, len %ld, err=%d\n",
+ fd, (long int) len, errflag);
+
#if ASYNC_WRITE
/* Translate from errno to Squid disk error */
errno = errflag;
errflag = DISK_OK;
#endif
assert(++loop_detect < 10);
- aiostate->flags.writing = 0;
- if (errflag) {
- debug(79, 0) ("storeAufsWriteDone: got failure (%d)\n", errflag);
- storeAufsIOCallback(sio, errflag);
- loop_detect--;
- return;
- }
- sio->offset += len;
-#if ASYNC_WRITE
- if (!storeAufsKickWriteQueue(sio))
- 0;
- else if (aiostate->flags.close_request)
- storeAufsIOCallback(sio, errflag);
-#else
- if (!aiostate->flags.write_kicking) {
- aiostate->flags.write_kicking = 1;
- while (storeAufsKickWriteQueue(sio))
- (void) 0;
- aiostate->flags.write_kicking = 0;
- if (aiostate->flags.close_request)
- storeAufsIOCallback(sio, errflag);
- }
-#endif
- loop_detect--;
+
+ ioRequestor->writeCompleted(errflag, len);
+ --loop_detect;
}
static void
storeAufsIOCallback(storeIOState * sio, int errflag)
{
STIOCB *callback = sio->callback;
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
+ squidaiostate_t *aiostate = dynamic_cast<squidaiostate_t *>(sio);
int fd = aiostate->fd;
debug(79, 3) ("storeAufsIOCallback: errflag=%d\n", errflag);
debug(79, 9) ("%s:%d\n", __FILE__, __LINE__);
}
debug(79, 9) ("%s:%d\n", __FILE__, __LINE__);
aiostate->fd = -1;
- cbdataFree(sio);
- if (aiostate->flags.opening)
+ if (aiostate->opening || aiostate->creating)
Opening_FD--;
if (fd < 0)
return;
debug(79, 9) ("%s:%d\n", __FILE__, __LINE__);
- aioClose(fd);
- fd_close(fd);
- store_open_disk_fd--;
+ aiostate->theFile = NULL;
debug(79, 9) ("%s:%d\n", __FILE__, __LINE__);
}
static int
storeAufsNeedCompletetion(storeIOState * sio)
{
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
+ squidaiostate_t *aiostate = dynamic_cast<squidaiostate_t *>(sio);
- if (aiostate->flags.writing)
+ if (aiostate->writing)
+ return true;
+ if (aiostate->creating && FILE_MODE(sio->mode) == O_WRONLY)
return 1;
- if (aiostate->flags.opening && FILE_MODE(sio->mode) == O_WRONLY)
- return 1;
- if (aiostate->flags.reading)
+ if (aiostate->reading)
return 1;
if (aiostate->flags.inreaddone)
return 1;
* The actuall SIO is managed by cbdata so we do not need
* to bother with that.
*/
-static void
-storeAufsIOFreeEntry(void *siop)
-{
- storeIOState *sio = (storeIOState *) siop;
- squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- struct _queued_write *qw;
- struct _queued_read *qr;
- while ((qw = (struct _queued_write *)linklistShift(&aiostate->pending_writes))) {
- if (qw->free_func)
- qw->free_func(qw->buf);
- memPoolFree(aufs_qwrite_pool, qw);
+squidaiostate_t::~squidaiostate_t()
+{
+}
+
+void
+squidaiostate_t::ioCompletedNotification()
+{
+ if (opening) {
+ opening = false;
+ openDone();
+ return;
}
- while ((qr = (struct _queued_read *)linklistShift(&aiostate->pending_reads))) {
- cbdataReferenceDone(qr->callback_data);
- memPoolFree(aufs_qread_pool, qr);
+ if (creating) {
+ creating = false;
+ openDone();
+ return;
+ }
+ assert (0);
+}
+
+void
+squidaiostate_t::closeCompleted()
+{
+ assert (0);
+}
+
+void
+squidaiostate_t::openDone()
+{
+ if (theFile->error()) {
+ storeAufsIOCallback(this, DISK_ERROR);
+ return;
+ }
+ fd = theFile->getFD();
+ if (FILE_MODE(mode) == O_WRONLY) {
+ if (kickWriteQueue())
+ return;
+ } else if ((FILE_MODE(mode) == O_RDONLY) && !closing) {
+ if (kickReadQueue())
+ return;
}
- if (sio->read.callback_data)
- cbdataReferenceDone(sio->read.callback_data);
- if (sio->callback_data)
- cbdataReferenceDone(sio->callback_data);
- memPoolFree(squidaio_state_pool, aiostate);
+ if (closing)
+ storeAufsIOCallback(this, theFile->error() ? -1 : 0);
+ debug(79, 3) ("squidaiostate_t::openDone: exiting\n");
}
#ifndef __COSS_H__
#define __COSS_H__
+#include "SwapDir.h"
+
#ifndef COSS_MEMBUF_SZ
#define COSS_MEMBUF_SZ 1048576
#endif
#define COSS_ALLOC_NOTIFY 0
#define COSS_ALLOC_ALLOCATE 1
#define COSS_ALLOC_REALLOC 2
-
+class CossSwapDir;
struct _cossmembuf {
dlink_node node;
size_t diskstart; /* in blocks */
size_t diskend; /* in blocks */
- SwapDir *SD;
+ CossSwapDir *SD;
int lockcount;
char buffer[COSS_MEMBUF_SZ];
struct _cossmembuf_flags {
} flags;
};
-
-/* Per-storedir info */
-struct _cossinfo {
- dlink_list membufs;
- struct _cossmembuf *current_membuf;
- size_t current_offset; /* in Blocks */
- int fd;
- int swaplog_fd;
- int numcollisions;
- dlink_list index;
- int count;
- async_queue_t aq;
- dlink_node *walk_current;
-};
-
struct _cossindex {
/* Note: the dlink_node MUST be the first member of the structure.
* This member is later pointer typecasted to coss_index_node *.
};
+
/* Per-storeiostate info */
-struct _cossstate {
+class CossState : public storeIOState {
+public:
+ virtual void deleteSelf() const {delete this;}
+ void * operator new (size_t);
+ void operator delete (void *);
+ CossState(CossSwapDir *);
+ ~CossState();
+
char *readbuffer;
char *requestbuf;
size_t requestlen;
unsigned int reading:1;
unsigned int writing:1;
} flags;
+ size_t st_size;
+ void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data);
+ void write(char *buf, size_t size, off_t offset, FREE * free_func);
+ void close();
+
+ CossSwapDir *SD;
+private:
+ static MemPool *Pool;
};
typedef struct _cossmembuf CossMemBuf;
-typedef struct _cossinfo CossInfo;
-typedef struct _cossstate CossState;
typedef struct _cossindex CossIndexNode;
/* Whether the coss system has been setup or not */
extern int coss_initialised;
extern MemPool *coss_membuf_pool;
-extern MemPool *coss_state_pool;
extern MemPool *coss_index_pool;
-/*
- * Store IO stuff
- */
-extern STOBJCREATE storeCossCreate;
-extern STOBJOPEN storeCossOpen;
-extern STOBJCLOSE storeCossClose;
-extern STOBJREAD storeCossRead;
-extern STOBJWRITE storeCossWrite;
-extern STOBJUNLINK storeCossUnlink;
-extern STSYNC storeCossSync;
-
-extern off_t storeCossAllocate(SwapDir * SD, const StoreEntry * e, int which);
-extern void storeCossAdd(SwapDir *, StoreEntry *);
-extern void storeCossRemove(SwapDir *, StoreEntry *);
-extern void storeCossStartMembuf(SwapDir * SD);
+class CossSwapDir : public SwapDir
+{
+public:
+ CossSwapDir();
+ virtual void init();
+ virtual void newFileSystem();
+ virtual void dump(StoreEntry &)const;
+ ~CossSwapDir();
+ virtual void unlink (StoreEntry &);
+ virtual void statfs (StoreEntry &)const;
+ virtual int canStore(StoreEntry const &)const;
+ virtual int callback();
+ virtual void sync();
+ virtual StoreIOState::Pointer createStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
+ virtual StoreIOState::Pointer openStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
+ virtual void openLog();
+ virtual void closeLog();
+ virtual int writeCleanStart();
+ virtual void writeCleanDone();
+ virtual void logEntry(const StoreEntry & e, int op) const;
+ virtual void parse (int index, char *path);
+ virtual void reconfigure (int, char *);
+//private:
+ int fd;
+ int swaplog_fd;
+ int count;
+ dlink_list membufs;
+ struct _cossmembuf *current_membuf;
+ size_t current_offset; /* in Blocks */
+ int numcollisions;
+ dlink_list cossindex;
+ async_queue_t aq;
+};
+extern off_t storeCossAllocate(CossSwapDir * SD, const StoreEntry * e, int which);
+extern void storeCossAdd(CossSwapDir *, StoreEntry *);
+extern void storeCossRemove(CossSwapDir *, StoreEntry *);
+extern void storeCossStartMembuf(CossSwapDir * SD);
#endif
/*
- * $Id: store_dir_coss.cc,v 1.40 2002/10/15 08:03:33 robertc Exp $
+ * $Id: store_dir_coss.cc,v 1.41 2002/12/27 10:26:36 robertc Exp $
*
* DEBUG: section 47 Store COSS Directory Routines
* AUTHOR: Eric Stern
#include "async_io.h"
#include "store_coss.h"
+#include "SwapDir.h"
#define STORE_META_BUFSZ 4096
int n_coss_dirs = 0;
/* static int last_coss_pick_index = -1; */
int coss_initialised = 0;
-MemPool *coss_state_pool = NULL;
MemPool *coss_index_pool = NULL;
typedef struct _RebuildState RebuildState;
struct _RebuildState {
- SwapDir *sd;
+ CossSwapDir *sd;
int n_read;
FILE *log;
int speed;
static char *storeCossDirSwapLogFile(SwapDir *, const char *);
static EVH storeCossRebuildFromSwapLog;
-static StoreEntry *storeCossAddDiskRestore(SwapDir * SD, const cache_key * key,
+static StoreEntry *storeCossAddDiskRestore(CossSwapDir * SD, const cache_key * key,
int file_number,
size_t swap_file_sz,
time_t expires,
u_int32_t refcount,
u_int16_t flags,
int clean);
-static void storeCossDirRebuild(SwapDir * sd);
-static void storeCossDirCloseTmpSwapLog(SwapDir * sd);
-static FILE *storeCossDirOpenTmpSwapLog(SwapDir *, int *, int *);
-static STLOGOPEN storeCossDirOpenSwapLog;
-static STINIT storeCossDirInit;
-static STLOGCLEANSTART storeCossDirWriteCleanStart;
-static STLOGCLEANNEXTENTRY storeCossDirCleanLogNextEntry;
-static STLOGCLEANWRITE storeCossDirWriteCleanEntry;
-static STLOGCLEANDONE storeCossDirWriteCleanDone;
-static STLOGCLOSE storeCossDirCloseSwapLog;
-static STLOGWRITE storeCossDirSwapLog;
-static STNEWFS storeCossDirNewfs;
-static STCHECKOBJ storeCossDirCheckObj;
-static STFREE storeCossDirShutdown;
-static STFSPARSE storeCossDirParse;
-static STFSRECONFIGURE storeCossDirReconfigure;
-static STDUMP storeCossDirDump;
-static STCALLBACK storeCossDirCallback;
+static void storeCossDirRebuild(CossSwapDir * sd);
+static void storeCossDirCloseTmpSwapLog(CossSwapDir * sd);
+static FILE *storeCossDirOpenTmpSwapLog(CossSwapDir *, int *, int *);
/* The "only" externally visible function */
STSETUP storeFsSetup_coss;
return path;
}
-static void
-storeCossDirOpenSwapLog(SwapDir * sd)
+void
+CossSwapDir::openLog()
{
- CossInfo *cs = (CossInfo *) sd->fsdata;
- char *path;
- int fd;
- path = storeCossDirSwapLogFile(sd, NULL);
- fd = file_open(path, O_WRONLY | O_CREAT | O_BINARY);
- if (fd < 0) {
- debug(47, 1) ("%s: %s\n", path, xstrerror());
+ char *logPath;
+ logPath = storeCossDirSwapLogFile(this, NULL);
+ swaplog_fd = file_open(logPath, O_WRONLY | O_CREAT | O_BINARY);
+ if (swaplog_fd < 0) {
+ debug(47, 1) ("%s: %s\n", logPath, xstrerror());
fatal("storeCossDirOpenSwapLog: Failed to open swap log.");
}
- debug(47, 3) ("Cache COSS Dir #%d log opened on FD %d\n", sd->index, fd);
- cs->swaplog_fd = fd;
+ debug(47, 3) ("Cache COSS Dir #%d log opened on FD %d\n", index, swaplog_fd);
}
-static void
-storeCossDirCloseSwapLog(SwapDir * sd)
+void
+CossSwapDir::closeLog()
{
- CossInfo *cs = (CossInfo *) sd->fsdata;
- if (cs->swaplog_fd < 0) /* not open */
+ if (swaplog_fd < 0) /* not open */
return;
- file_close(cs->swaplog_fd);
+ file_close(swaplog_fd);
debug(47, 3) ("Cache COSS Dir #%d log closed on FD %d\n",
- sd->index, cs->swaplog_fd);
- cs->swaplog_fd = -1;
+ index, swaplog_fd);
+ swaplog_fd = -1;
}
-static void
-storeCossDirInit(SwapDir * sd)
-{
- CossInfo *cs = (CossInfo *) sd->fsdata;
- a_file_setupqueue(&cs->aq);
- storeCossDirOpenSwapLog(sd);
- storeCossDirRebuild(sd);
- cs->fd = file_open(sd->path, O_RDWR | O_CREAT);
- if (cs->fd < 0) {
- debug(47, 1) ("%s: %s\n", sd->path, xstrerror());
+void
+CossSwapDir::init()
+{
+ a_file_setupqueue(&aq);
+ openLog();
+ storeCossDirRebuild(this);
+ fd = file_open(path, O_RDWR | O_CREAT);
+ if (fd < 0) {
+ debug(47, 1) ("%s: %s\n", path, xstrerror());
fatal("storeCossDirInit: Failed to open a COSS directory.");
}
n_coss_dirs++;
- (void) storeDirGetBlkSize(sd->path, &sd->fs.blksize);
+ (void) storeDirGetBlkSize(path, &fs.blksize);
}
void
-storeCossRemove(SwapDir * sd, StoreEntry * e)
+storeCossRemove(CossSwapDir * sd, StoreEntry * e)
{
- CossInfo *cs = (CossInfo *) sd->fsdata;
CossIndexNode *coss_node = (CossIndexNode *)e->repl.data;
e->repl.data = NULL;
- dlinkDelete(&coss_node->node, &cs->index);
+ dlinkDelete(&coss_node->node, &sd->cossindex);
memPoolFree(coss_index_pool, coss_node);
- cs->count -= 1;
+ sd->count -= 1;
}
void
-storeCossAdd(SwapDir * sd, StoreEntry * e)
+storeCossAdd(CossSwapDir * sd, StoreEntry * e)
{
- CossInfo *cs = (CossInfo *) sd->fsdata;
CossIndexNode *coss_node = (CossIndexNode *)memPoolAlloc(coss_index_pool);
assert(!e->repl.data);
e->repl.data = coss_node;
- dlinkAdd(e, &coss_node->node, &cs->index);
- cs->count += 1;
+ dlinkAdd(e, &coss_node->node, &sd->cossindex);
+ sd->count += 1;
}
static void
storeCossRebuildComplete(void *data)
{
RebuildState *rb = (RebuildState *)data;
- SwapDir *sd = rb->sd;
+ CossSwapDir *sd = rb->sd;
storeCossStartMembuf(sd);
store_dirs_rebuilding--;
storeCossDirCloseTmpSwapLog(rb->sd);
StoreEntry *e = NULL;
storeSwapLogData s;
size_t ss = sizeof(storeSwapLogData);
- int count;
double x;
assert(rb != NULL);
/* load a number of objects per invocation */
- for (count = 0; count < rb->speed; count++) {
+ for (int aCount = 0; aCount < rb->speed; aCount++) {
if (fread(&s, ss, 1, rb->log) != 1) {
debug(47, 1) ("Done reading %s swaplog (%d entries)\n",
rb->sd->path, rb->n_read);
/* Add a new object to the cache with empty memory copy and pointer to disk
* use to rebuild store from disk. */
static StoreEntry *
-storeCossAddDiskRestore(SwapDir * SD, const cache_key * key,
+storeCossAddDiskRestore(CossSwapDir * SD, const cache_key * key,
int file_number,
size_t swap_file_sz,
time_t expires,
CBDATA_TYPE(RebuildState);
static void
-storeCossDirRebuild(SwapDir * sd)
+storeCossDirRebuild(CossSwapDir * sd)
{
RebuildState *rb;
int clean = 0;
}
static void
-storeCossDirCloseTmpSwapLog(SwapDir * sd)
+storeCossDirCloseTmpSwapLog(CossSwapDir * sd)
{
- CossInfo *cs = (CossInfo *) sd->fsdata;
char *swaplog_path = xstrdup(storeCossDirSwapLogFile(sd, NULL));
char *new_path = xstrdup(storeCossDirSwapLogFile(sd, ".new"));
- int fd;
- file_close(cs->swaplog_fd);
+ int anfd;
+ file_close(sd->swaplog_fd);
#if defined (_SQUID_OS2_) || defined (_SQUID_CYGWIN_)
if (unlink(swaplog_path) < 0) {
debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror());
if (xrename(new_path, swaplog_path) < 0) {
fatal("storeCossDirCloseTmpSwapLog: rename failed");
}
- fd = file_open(swaplog_path, O_WRONLY | O_CREAT | O_BINARY);
- if (fd < 0) {
+ anfd = file_open(swaplog_path, O_WRONLY | O_CREAT | O_BINARY);
+ if (anfd < 0) {
debug(50, 1) ("%s: %s\n", swaplog_path, xstrerror());
fatal("storeCossDirCloseTmpSwapLog: Failed to open swap log.");
}
safe_free(swaplog_path);
safe_free(new_path);
- cs->swaplog_fd = fd;
- debug(47, 3) ("Cache COSS Dir #%d log opened on FD %d\n", sd->index, fd);
+ sd->swaplog_fd = anfd;
+ debug(47, 3) ("Cache COSS Dir #%d log opened on FD %d\n", sd->index, anfd);
}
static FILE *
-storeCossDirOpenTmpSwapLog(SwapDir * sd, int *clean_flag, int *zero_flag)
+storeCossDirOpenTmpSwapLog(CossSwapDir * sd, int *clean_flag, int *zero_flag)
{
- CossInfo *cs = (CossInfo *) sd->fsdata;
char *swaplog_path = xstrdup(storeCossDirSwapLogFile(sd, NULL));
char *clean_path = xstrdup(storeCossDirSwapLogFile(sd, ".last-clean"));
char *new_path = xstrdup(storeCossDirSwapLogFile(sd, ".new"));
struct stat log_sb;
struct stat clean_sb;
FILE *fp;
- int fd;
+ int anfd;
if (stat(swaplog_path, &log_sb) < 0) {
debug(50, 1) ("Cache COSS Dir #%d: No log file\n", sd->index);
- safe_free(swaplog_path);
+safe_free(swaplog_path);
safe_free(clean_path);
safe_free(new_path);
return NULL;
}
*zero_flag = log_sb.st_size == 0 ? 1 : 0;
/* close the existing write-only FD */
- if (cs->swaplog_fd >= 0)
- file_close(cs->swaplog_fd);
+ if (sd->swaplog_fd >= 0)
+ file_close(sd->swaplog_fd);
/* open a write-only FD for the new log */
- fd = file_open(new_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
- if (fd < 0) {
+ anfd = file_open(new_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
+ if (anfd < 0) {
debug(50, 1) ("%s: %s\n", new_path, xstrerror());
fatal("storeDirOpenTmpSwapLog: Failed to open swap log.");
}
- cs->swaplog_fd = fd;
+ sd->swaplog_fd = anfd;
/* open a read-only stream of the old log */
fp = fopen(swaplog_path, "rb");
if (fp == NULL) {
return fp;
}
-struct _clean_state {
+class CossCleanLog : public SwapDir::CleanLog {
+ public:
+ CossCleanLog(SwapDir *);
+ virtual const StoreEntry *nextEntry();
+ virtual void write(StoreEntry const &);
char *cur;
char *newLog;
char *cln;
off_t outbuf_offset;
int fd;
dlink_node *current;
+ SwapDir *sd;
};
#define CLEAN_BUF_SZ 16384
+
+CossCleanLog::CossCleanLog(SwapDir *aSwapDir) : cur(NULL),newLog(NULL),cln(NULL),outbuf(NULL),
+ outbuf_offset(0), fd(-1),current(NULL), sd(aSwapDir)
+{
+}
+
/*
* Begin the process to write clean cache state. For COSS this means
* opening some log files and allocating write buffers. Return 0 if
* we succeed, and assign the 'func' and 'data' return pointers.
*/
-static int
-storeCossDirWriteCleanStart(SwapDir * sd)
+int
+CossSwapDir::writeCleanStart()
{
- CossInfo *cs = (CossInfo *) sd->fsdata;
- struct _clean_state *state = (struct _clean_state *)xcalloc(1, sizeof(*state));
+ CossCleanLog *state = new CossCleanLog(this);
#if HAVE_FCHMOD
struct stat sb;
#endif
- state->newLog = xstrdup(storeCossDirSwapLogFile(sd, ".clean"));
+ state->newLog = xstrdup(storeCossDirSwapLogFile(this, ".clean"));
state->fd = file_open(state->newLog, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
+ cleanLog = NULL;
if (state->fd < 0) {
xfree(state->newLog);
- xfree(state);
+ delete state;
return -1;
}
- sd->log.clean.write = NULL;
- sd->log.clean.state = NULL;
- state->cur = xstrdup(storeCossDirSwapLogFile(sd, NULL));
- state->cln = xstrdup(storeCossDirSwapLogFile(sd, ".last-clean"));
+ state->cur = xstrdup(storeCossDirSwapLogFile(this, NULL));
+ state->cln = xstrdup(storeCossDirSwapLogFile(this, ".last-clean"));
state->outbuf = (char *)xcalloc(CLEAN_BUF_SZ, 1);
state->outbuf_offset = 0;
- unlink(state->cln);
- state->current = cs->index.tail;
+ ::unlink(state->cln);
+ state->current = cossindex.tail;
debug(50, 3) ("storeCOssDirWriteCleanLogs: opened %s, FD %d\n",
state->newLog, state->fd);
#if HAVE_FCHMOD
if (stat(state->cur, &sb) == 0)
fchmod(state->fd, sb.st_mode);
#endif
- sd->log.clean.write = storeCossDirWriteCleanEntry;
- sd->log.clean.state = state;
+ cleanLog = state;
return 0;
}
-static const StoreEntry *
-storeCossDirCleanLogNextEntry(SwapDir * sd)
+const StoreEntry *
+CossCleanLog::nextEntry()
{
- struct _clean_state *state = (struct _clean_state *)sd->log.clean.state;
const StoreEntry *entry;
- if (!state)
- return NULL;
- if (!state->current)
+ if (!current)
return NULL;
- entry = (const StoreEntry *) state->current->data;
- state->current = state->current->prev;
+ entry = (const StoreEntry *) current->data;
+ current = current->prev;
return entry;
}
/*
* "write" an entry to the clean log file.
*/
-static void
-storeCossDirWriteCleanEntry(SwapDir * sd, const StoreEntry * e)
+void
+CossCleanLog::write(StoreEntry const &e)
{
+ CossCleanLog *state = this;
storeSwapLogData s;
static size_t ss = sizeof(storeSwapLogData);
- struct _clean_state *state = (struct _clean_state *)sd->log.clean.state;
memset(&s, '\0', ss);
s.op = (char) SWAP_LOG_ADD;
- s.swap_filen = e->swap_filen;
- s.timestamp = e->timestamp;
- s.lastref = e->lastref;
- s.expires = e->expires;
- s.lastmod = e->lastmod;
- s.swap_file_sz = e->swap_file_sz;
- s.refcount = e->refcount;
- s.flags = e->flags;
- xmemcpy(&s.key, e->key, MD5_DIGEST_CHARS);
+ s.swap_filen = e.swap_filen;
+ s.timestamp = e.timestamp;
+ s.lastref = e.lastref;
+ s.expires = e.expires;
+ s.lastmod = e.lastmod;
+ s.swap_file_sz = e.swap_file_sz;
+ s.refcount = e.refcount;
+ s.flags = e.flags;
+ xmemcpy(&s.key, e.key, MD5_DIGEST_CHARS);
xmemcpy(state->outbuf + state->outbuf_offset, &s, ss);
state->outbuf_offset += ss;
/* buffered write */
file_close(state->fd);
state->fd = -1;
unlink(state->newLog);
- safe_free(state);
- sd->log.clean.state = NULL;
- sd->log.clean.write = NULL;
+ delete state;
+ sd->cleanLog = NULL;
return;
}
state->outbuf_offset = 0;
}
}
-static void
-storeCossDirWriteCleanDone(SwapDir * sd)
+void
+CossSwapDir::writeCleanDone()
{
- int fd;
- struct _clean_state *state = (struct _clean_state *)sd->log.clean.state;
+ CossCleanLog *state = (CossCleanLog *)cleanLog;
if (NULL == state)
return;
if (state->fd < 0)
"not replaced.\n");
file_close(state->fd);
state->fd = -1;
- unlink(state->newLog);
+ ::unlink(state->newLog);
}
safe_free(state->outbuf);
/*
* You can't rename open files on Microsoft "operating systems"
* so we have to close before renaming.
*/
- storeCossDirCloseSwapLog(sd);
+ closeLog();
/* save the fd value for a later test */
- fd = state->fd;
+ int anfd = state->fd;
/* rename */
if (state->fd >= 0) {
#if defined(_SQUID_OS2_) || defined (_SQUID_CYGWIN_)
/* touch a timestamp file if we're not still validating */
if (store_dirs_rebuilding)
(void) 0;
- else if (fd < 0)
+ else if (anfd < 0)
(void) 0;
else
file_close(file_open(state->cln, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY));
if (state->fd >= 0)
file_close(state->fd);
state->fd = -1;
- safe_free(state);
- sd->log.clean.state = NULL;
- sd->log.clean.write = NULL;
+ delete state;
+ cleanLog = NULL;
}
static void
memFree(s, MEM_SWAP_LOG_DATA);
}
-static void
-storeCossDirSwapLog(const SwapDir * sd, const StoreEntry * e, int op)
+void
+CossSwapDir::logEntry(const StoreEntry & e, int op) const
{
- CossInfo *cs = (CossInfo *) sd->fsdata;
storeSwapLogData *s = (storeSwapLogData *)memAllocate(MEM_SWAP_LOG_DATA);
s->op = (char) op;
- s->swap_filen = e->swap_filen;
- s->timestamp = e->timestamp;
- s->lastref = e->lastref;
- s->expires = e->expires;
- s->lastmod = e->lastmod;
- s->swap_file_sz = e->swap_file_sz;
- s->refcount = e->refcount;
- s->flags = e->flags;
- xmemcpy(s->key, e->key, MD5_DIGEST_CHARS);
- file_write(cs->swaplog_fd,
+ s->swap_filen = e.swap_filen;
+ s->timestamp = e.timestamp;
+ s->lastref = e.lastref;
+ s->expires = e.expires;
+ s->lastmod = e.lastmod;
+ s->swap_file_sz = e.swap_file_sz;
+ s->refcount = e.refcount;
+ s->flags = e.flags;
+ xmemcpy(s->key, e.key, MD5_DIGEST_CHARS);
+ file_write(swaplog_fd,
-1,
s,
sizeof(storeSwapLogData),
(FREE *) storeSwapLogDataFree);
}
-static void
-storeCossDirNewfs(SwapDir * sd)
+void
+CossSwapDir::newFileSystem()
{
- debug(47, 3) ("Creating swap space in %s\n", sd->path);
+ debug(47, 3) ("Creating swap space in %s\n", path);
+ debug (47,0)("COSS autocreation is not implemented. Please create the file manually\n");
}
/* we are shutting down, flush all membufs to disk */
-static void
-storeCossDirShutdown(SwapDir * SD)
+CossSwapDir::~CossSwapDir()
{
- CossInfo *cs = (CossInfo *) SD->fsdata;
+ sync(); /* This'll call a_file_syncqueue() */
+ a_file_closequeue(&aq);
+ file_close(fd);
+ fd = -1;
- storeCossSync(SD); /* This'll call a_file_syncqueue() */
- a_file_closequeue(&cs->aq);
- file_close(cs->fd);
- cs->fd = -1;
-
- if (cs->swaplog_fd > -1) {
- file_close(cs->swaplog_fd);
- cs->swaplog_fd = -1;
- }
+ closeLog();
n_coss_dirs--;
}
* done by the upper layers.
*/
int
-storeCossDirCheckObj(SwapDir * SD, const StoreEntry * e)
+CossSwapDir::canStore(StoreEntry const &e)const
{
- CossInfo *cs = (CossInfo *) SD->fsdata;
int loadav;
/* Check if the object is a special object, we can't cache these */
- if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
+ if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
return -1;
/* Otherwise, we're ok */
/* Return load, cs->aq.aq_numpending out of MAX_ASYNCOP */
- loadav = cs->aq.aq_numpending * 1000 / MAX_ASYNCOP;
+ loadav = aq.aq_numpending * 1000 / MAX_ASYNCOP;
return loadav;
}
-
/*
* storeCossDirCallback - do the IO completions
*/
-static int
-storeCossDirCallback(SwapDir * SD)
+int
+CossSwapDir::callback()
{
- CossInfo *cs = (CossInfo *) SD->fsdata;
-
- return a_file_callback(&cs->aq);
+ return a_file_callback(&aq);
}
/* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */
-static void
-storeCossDirStats(SwapDir * SD, StoreEntry * sentry)
+void
+CossSwapDir::statfs(StoreEntry & sentry) const
{
- CossInfo *cs = (CossInfo *) SD->fsdata;
-
- storeAppendPrintf(sentry, "\n");
- storeAppendPrintf(sentry, "Maximum Size: %d KB\n", SD->max_size);
- storeAppendPrintf(sentry, "Current Size: %d KB\n", SD->cur_size);
- storeAppendPrintf(sentry, "Percent Used: %0.2f%%\n",
- 100.0 * SD->cur_size / SD->max_size);
- storeAppendPrintf(sentry, "Number of object collisions: %d\n", (int) cs->numcollisions);
+ storeAppendPrintf(&sentry, "\n");
+ storeAppendPrintf(&sentry, "Maximum Size: %d KB\n", max_size);
+ storeAppendPrintf(&sentry, "Current Size: %d KB\n", cur_size);
+ storeAppendPrintf(&sentry, "Percent Used: %0.2f%%\n",
+ 100.0 * cur_size / max_size);
+ storeAppendPrintf(&sentry, "Number of object collisions: %d\n", (int) numcollisions);
#if 0
/* is this applicable? I Hope not .. */
storeAppendPrintf(sentry, "Filemap bits in use: %d of %d (%d%%)\n",
SD->map->n_files_in_map, SD->map->max_n_files,
percent(SD->map->n_files_in_map, SD->map->max_n_files));
#endif
- storeAppendPrintf(sentry, "Pending operations: %d out of %d\n", cs->aq.aq_numpending, MAX_ASYNCOP);
- storeAppendPrintf(sentry, "Flags:");
- if (SD->flags.selected)
- storeAppendPrintf(sentry, " SELECTED");
- if (SD->flags.read_only)
- storeAppendPrintf(sentry, " READ-ONLY");
- storeAppendPrintf(sentry, "\n");
+ storeAppendPrintf(&sentry, "Pending operations: %d out of %d\n", aq.aq_numpending, MAX_ASYNCOP);
+ storeAppendPrintf(&sentry, "Flags:");
+ if (flags.selected)
+ storeAppendPrintf(&sentry, " SELECTED");
+ if (flags.read_only)
+ storeAppendPrintf(&sentry, " READ-ONLY");
+ storeAppendPrintf(&sentry, "\n");
}
-static void
-storeCossDirParse(SwapDir * sd, int index, char *path)
+void
+CossSwapDir::parse(int anIndex, char *aPath)
{
unsigned int i;
unsigned int size;
- CossInfo *cs;
i = GetInteger();
size = i << 10; /* Mbytes to Kbytes */
if (size <= 0)
fatal("storeCossDirParse: invalid size value");
- cs = (CossInfo *)xmalloc(sizeof(CossInfo));
- if (cs == NULL)
- fatal("storeCossDirParse: couldn't xmalloc() CossInfo!\n");
-
- sd->index = index;
- sd->path = xstrdup(path);
- sd->max_size = size;
- sd->fsdata = cs;
-
- cs->fd = -1;
- cs->swaplog_fd = -1;
-
- sd->init = storeCossDirInit;
- sd->newfs = storeCossDirNewfs;
- sd->dump = storeCossDirDump;
- sd->freefs = storeCossDirShutdown;
- sd->dblcheck = NULL;
- sd->statfs = storeCossDirStats;
- sd->maintainfs = NULL;
- sd->checkobj = storeCossDirCheckObj;
- sd->refobj = NULL; /* LRU is done in storeCossRead */
- sd->unrefobj = NULL;
- sd->callback = storeCossDirCallback;
- sd->sync = storeCossSync;
-
- sd->obj.create = storeCossCreate;
- sd->obj.open = storeCossOpen;
- sd->obj.close = storeCossClose;
- sd->obj.read = storeCossRead;
- sd->obj.write = storeCossWrite;
- sd->obj.unlink = storeCossUnlink;
-
- sd->log.open = storeCossDirOpenSwapLog;
- sd->log.close = storeCossDirCloseSwapLog;
- sd->log.write = storeCossDirSwapLog;
- sd->log.clean.start = storeCossDirWriteCleanStart;
- sd->log.clean.write = storeCossDirWriteCleanEntry;
- sd->log.clean.nextentry = storeCossDirCleanLogNextEntry;
- sd->log.clean.done = storeCossDirWriteCleanDone;
-
- cs->current_offset = 0;
- cs->fd = -1;
- cs->swaplog_fd = -1;
- cs->numcollisions = 0;
- cs->membufs.head = cs->membufs.tail = NULL; /* set when the rebuild completes */
- cs->current_membuf = NULL;
- cs->index.head = NULL;
- cs->index.tail = NULL;
-
- parse_cachedir_options(sd, NULL, 0);
+ index = anIndex;
+ path = xstrdup(aPath);
+ max_size = size;
+
+ parse_cachedir_options(this, NULL, 0);
/* Enforce maxobjsize being set to something */
- if (sd->max_objsize == -1)
+ if (max_objsize == -1)
fatal("COSS requires max-size to be set to something other than -1!\n");
}
-static void
-storeCossDirReconfigure(SwapDir * sd, int index, char *path)
+void
+CossSwapDir::reconfigure(int index, char *path)
{
unsigned int i;
unsigned int size;
if (size <= 0)
fatal("storeCossDirParse: invalid size value");
- if (size == (size_t)sd->max_size)
+ if (size == (size_t)max_size)
debug(3, 1) ("Cache COSS dir '%s' size remains unchanged at %d KB\n", path, size);
else {
debug(3, 1) ("Cache COSS dir '%s' size changed to %d KB\n", path, size);
- sd->max_size = size;
+ max_size = size;
}
- parse_cachedir_options(sd, NULL, 1);
+ parse_cachedir_options(this, NULL, 1);
/* Enforce maxobjsize being set to something */
- if (sd->max_objsize == -1)
+ if (max_objsize == -1)
fatal("COSS requires max-size to be set to something other than -1!\n");
}
void
-storeCossDirDump(StoreEntry * entry, SwapDir * s)
+CossSwapDir::dump(StoreEntry &entry)const
{
- storeAppendPrintf(entry, " %d",
- s->max_size >> 20);
- dump_cachedir_options(entry, NULL, s);
+ storeAppendPrintf(&entry, " %d",
+ max_size >> 20);
+ dump_cachedir_options(&entry, NULL, this);
}
#if OLD_UNUSED_CODE
static void
storeCossDirDone(void)
{
- memPoolDestroy(&coss_state_pool);
/* memPoolDestroy(&coss_index_pool); XXX Should be here? */
coss_initialised = 0;
}
+static SwapDir *
+storeCossNew(void)
+{
+ SwapDir *result = new CossSwapDir;
+ return result;
+}
+
+CossSwapDir::CossSwapDir() : fd (-1), swaplog_fd(-1), count(0), current_membuf (NULL), current_offset(0), numcollisions(0)
+{
+ membufs.head = NULL;
+ membufs.tail = NULL;
+ cossindex.head = NULL;
+ cossindex.tail = NULL;
+}
+
void
storeFsSetup_coss(storefs_entry_t * storefs)
{
assert(!coss_initialised);
- storefs->parsefunc = storeCossDirParse;
- storefs->reconfigurefunc = storeCossDirReconfigure;
storefs->donefunc = storeCossDirDone;
- coss_state_pool = memPoolCreate("COSS IO State data", sizeof(CossState));
+ storefs->newfunc = storeCossNew;
coss_index_pool = memPoolCreate("COSS index data", sizeof(CossIndexNode));
coss_initialised = 1;
}
/*
- * $Id: store_io_coss.cc,v 1.19 2002/10/13 20:35:25 robertc Exp $
+ * $Id: store_io_coss.cc,v 1.20 2002/12/27 10:26:36 robertc Exp $
*
* DEBUG: section 79 Storage Manager COSS Interface
* AUTHOR: Eric Stern
#include <aio.h>
#include "async_io.h"
#include "store_coss.h"
+#include "SwapDir.h"
static DWCB storeCossWriteMemBufDone;
static DRCB storeCossReadDone;
static void storeCossIOCallback(storeIOState * sio, int errflag);
-static char *storeCossMemPointerFromDiskOffset(SwapDir * SD, size_t offset, CossMemBuf ** mb);
-static void storeCossMemBufLock(SwapDir * SD, storeIOState * e);
-static void storeCossMemBufUnlock(SwapDir * SD, storeIOState * e);
-static void storeCossWriteMemBuf(SwapDir * SD, CossMemBuf * t);
-static void storeCossWriteMemBufDone(int fd, int errflag, size_t len, void *my_data);
-static CossMemBuf *storeCossCreateMemBuf(SwapDir * SD, size_t start,
+static char *storeCossMemPointerFromDiskOffset(CossSwapDir * SD, size_t offset, CossMemBuf ** mb);
+static void storeCossMemBufLock(CossSwapDir * SD, storeIOState * e);
+static void storeCossMemBufUnlock(CossSwapDir * SD, storeIOState * e);
+static void storeCossWriteMemBuf(CossSwapDir * SD, CossMemBuf * t);
+static void storeCossWriteMemBufDone(int, int errflag, size_t len, void *my_data);
+static CossMemBuf *storeCossCreateMemBuf(CossSwapDir * SD, size_t start,
sfileno curfn, int *collision);
-static CBDUNL storeCossIOFreeEntry;
-CBDATA_TYPE(storeIOState);
CBDATA_TYPE(CossMemBuf);
/* === PUBLIC =========================================================== */
+MemPool *CossState::Pool = NULL;
+
+void *
+CossState::operator new (size_t)
+{
+ if (!Pool)
+ Pool = memPoolCreate("Squid COSS State Data", sizeof (CossState));
+ return memPoolAlloc(Pool);
+}
+
+void
+CossState::operator delete (void *address)
+{
+ memPoolFree (Pool, address);
+}
+
+CossState::CossState(CossSwapDir *aCSD):SD (aCSD)
+{
+}
+
+
/*
* This routine sucks. I want to rewrite it when possible, and I also think
* that we should check after creatmembuf() to see if the object has a
* -- Adrian
*/
off_t
-storeCossAllocate(SwapDir * SD, const StoreEntry * e, int which)
+storeCossAllocate(CossSwapDir * SD, const StoreEntry * e, int which)
{
- CossInfo *cs = (CossInfo *) SD->fsdata;
CossMemBuf *newmb;
off_t retofs;
size_t allocsize;
assert(which != COSS_ALLOC_NOTIFY);
/* Check if we have overflowed the disk .. */
- if ((cs->current_offset + allocsize) > (size_t)(SD->max_size << 10)) {
+ if ((SD->current_offset + allocsize) > (size_t)(SD->max_size << 10)) {
/*
* tried to allocate past the end of the disk, so wrap
* back to the beginning
*/
- cs->current_membuf->flags.full = 1;
- cs->current_membuf->diskend = cs->current_offset - 1;
- cs->current_offset = 0; /* wrap back to beginning */
+ SD->current_membuf->flags.full = 1;
+ SD->current_membuf->diskend = SD->current_offset - 1;
+ SD->current_offset = 0; /* wrap back to beginning */
debug(79, 2) ("storeCossAllocate: wrap to 0\n");
newmb = storeCossCreateMemBuf(SD, 0, checkf, &coll);
- cs->current_membuf = newmb;
+ SD->current_membuf = newmb;
/* Check if we have overflowed the MemBuf */
- } else if ((cs->current_offset + allocsize) > cs->current_membuf->diskend) {
+ } else if ((SD->current_offset + allocsize) > SD->current_membuf->diskend) {
/*
* Skip the blank space at the end of the stripe. start over.
*/
- cs->current_membuf->flags.full = 1;
- cs->current_offset = cs->current_membuf->diskend + 1;
+ SD->current_membuf->flags.full = 1;
+ SD->current_offset = SD->current_membuf->diskend + 1;
debug(79, 2) ("storeCossAllocate: New offset - %ld\n",
- (long int) cs->current_offset);
- newmb = storeCossCreateMemBuf(SD, cs->current_offset, checkf, &coll);
- cs->current_membuf = newmb;
+ (long int) SD->current_offset);
+ newmb = storeCossCreateMemBuf(SD, SD->current_offset, checkf, &coll);
+ SD->current_membuf = newmb;
}
/* If we didn't get a collision, then update the current offset and return it */
if (coll == 0) {
- retofs = cs->current_offset;
- cs->current_offset = retofs + allocsize;
+ retofs = SD->current_offset;
+ SD->current_offset = retofs + allocsize;
return retofs;
} else {
debug(79, 3) ("storeCossAllocate: Collision\n");
}
void
-storeCossUnlink(SwapDir * SD, StoreEntry * e)
+CossSwapDir::unlink(StoreEntry & e)
{
- debug(79, 3) ("storeCossUnlink: offset %d\n", e->swap_filen);
- storeCossRemove(SD, e);
+ debug(79, 3) ("storeCossUnlink: offset %d\n", e.swap_filen);
+ storeCossRemove(this, &e);
}
-
-storeIOState *
-storeCossCreate(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data)
+StoreIOState::Pointer
+CossSwapDir::createStoreIO(StoreEntry &e, STFNCB * file_callback, STIOCB * callback, void *callback_data)
{
CossState *cstate;
- storeIOState *sio;
-
- CBDATA_INIT_TYPE_FREECB(storeIOState, storeCossIOFreeEntry);
- sio = cbdataAlloc(storeIOState);
- cstate = (CossState *)memPoolAlloc(coss_state_pool);
- sio->fsstate = cstate;
- sio->offset = 0;
+ StoreIOState::Pointer sio = new CossState(this);
+ cstate = dynamic_cast<CossState *>(sio.getRaw());
+ sio->offset_ = 0;
sio->mode = O_WRONLY | O_BINARY;
/*
* If we get handed an object with a size of -1,
* the squid code is broken
*/
- assert(e->mem_obj->object_sz != -1);
+ assert(e.mem_obj->object_sz != -1);
/*
* this one is kinda strange - Eric called storeCossAllocate(), then
* storeCossOpen(O_RDONLY) .. weird. Anyway, I'm allocating this now.
*/
- sio->st_size = objectLen(e) + e->mem_obj->swap_hdr_sz;
- sio->swap_dirn = SD->index;
- sio->swap_filen = storeCossAllocate(SD, e, COSS_ALLOC_ALLOCATE);
- debug(79, 3) ("storeCossCreate: offset %d, size %ld, end %ld\n", sio->swap_filen, (long int) sio->st_size, (long int) (sio->swap_filen + sio->st_size));
+ cstate->st_size = objectLen(&e) + e.mem_obj->swap_hdr_sz;
+ sio->swap_dirn = index;
+ sio->swap_filen = storeCossAllocate(this, &e, COSS_ALLOC_ALLOCATE);
+ debug(79, 3) ("storeCossCreate: offset %d, size %ld, end %ld\n", sio->swap_filen, (long int) cstate->st_size, (long int) (sio->swap_filen + cstate->st_size));
sio->callback = callback;
sio->file_callback = file_callback;
sio->callback_data = cbdataReference(callback_data);
- sio->e = (StoreEntry *) e;
+ sio->e = &e;
cstate->flags.writing = 0;
cstate->flags.reading = 0;
cstate->reqdiskoffset = -1;
/* Now add it into the index list */
- storeCossAdd(SD, e);
+ storeCossAdd(this, &e);
- storeCossMemBufLock(SD, sio);
+ storeCossMemBufLock(this, sio.getRaw());
return sio;
}
-storeIOState *
-storeCossOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
+StoreIOState::Pointer
+CossSwapDir::openStoreIO(StoreEntry & e, STFNCB * file_callback,
STIOCB * callback, void *callback_data)
{
- storeIOState *sio;
char *p;
CossState *cstate;
- sfileno f = e->swap_filen;
- CossInfo *cs = (CossInfo *) SD->fsdata;
+ sfileno f = e.swap_filen;
debug(79, 3) ("storeCossOpen: offset %d\n", f);
- CBDATA_INIT_TYPE_FREECB(storeIOState, storeCossIOFreeEntry);
- sio = cbdataAlloc(storeIOState);
- cstate = (CossState *)memPoolAlloc(coss_state_pool);
+ StoreIOState::Pointer sio = new CossState (this);
+ cstate = dynamic_cast<CossState *>(sio.getRaw());
- sio->fsstate = cstate;
sio->swap_filen = f;
- sio->swap_dirn = SD->index;
- sio->offset = 0;
+ sio->swap_dirn = index;
+ sio->offset_ = 0;
sio->mode = O_RDONLY | O_BINARY;
sio->callback = callback;
sio->file_callback = file_callback;
sio->callback_data = cbdataReference(callback_data);
- sio->st_size = e->swap_file_sz;
- sio->e = e;
+ cstate->st_size = e.swap_file_sz;
+ sio->e = &e;
cstate->flags.writing = 0;
cstate->flags.reading = 0;
cstate->readbuffer = NULL;
cstate->reqdiskoffset = -1;
- p = storeCossMemPointerFromDiskOffset(SD, f, NULL);
+ p = storeCossMemPointerFromDiskOffset(this, f, NULL);
/* make local copy so we don't have to lock membuf */
if (p) {
- cstate->readbuffer = (char *)xmalloc(sio->st_size);
- xmemcpy(cstate->readbuffer, p, sio->st_size);
+ cstate->readbuffer = (char *)xmalloc(cstate->st_size);
+ xmemcpy(cstate->readbuffer, p, cstate->st_size);
} else {
/* Do the allocation */
/* this is the first time we've been called on a new sio
*/
cstate->reqdiskoffset = sio->swap_filen;
sio->swap_filen = -1;
- sio->swap_filen = storeCossAllocate(SD, e, COSS_ALLOC_REALLOC);
+ sio->swap_filen = storeCossAllocate(this, &e, COSS_ALLOC_REALLOC);
if (sio->swap_filen == -1) {
/* We have to clean up neatly .. */
- cbdataFree(sio);
- cs->numcollisions++;
- debug(79, 2) ("storeCossOpen: Reallocation of %d/%d failed\n", e->swap_dirn, e->swap_filen);
+ numcollisions++;
+ debug(79, 2) ("storeCossOpen: Reallocation of %d/%d failed\n", e.swap_dirn, e.swap_filen);
/* XXX XXX XXX Will squid call storeUnlink for this object? */
return NULL;
}
/* Notify the upper levels that we've changed file number */
- sio->file_callback(sio->callback_data, 0, sio);
+ sio->file_callback(sio->callback_data, 0, sio.getRaw());
/*
* lock the buffer so it doesn't get swapped out on us
* this will get unlocked in storeCossReadDone
*/
- storeCossMemBufLock(SD, sio);
+ storeCossMemBufLock(this, sio.getRaw());
/*
* Do the index magic to keep the disk and memory LRUs identical
*/
- storeCossRemove(SD, e);
- storeCossAdd(SD, e);
+ storeCossRemove(this, &e);
+ storeCossAdd(this, &e);
/*
* Since we've reallocated a spot for this object, we need to
}
void
-storeCossClose(SwapDir * SD, storeIOState * sio)
+CossState::close()
{
- debug(79, 3) ("storeCossClose: offset %d\n", sio->swap_filen);
- if (FILE_MODE(sio->mode) == O_WRONLY)
- storeCossMemBufUnlock(SD, sio);
- storeCossIOCallback(sio, 0);
+ debug(79, 3) ("storeCossClose: offset %d\n", swap_filen);
+ if (FILE_MODE(mode) == O_WRONLY)
+ storeCossMemBufUnlock(SD, this);
+ storeCossIOCallback(this, 0);
}
void
-storeCossRead(SwapDir * SD, storeIOState * sio, char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
+CossState::read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
{
char *p;
- CossState *cstate = (CossState *) sio->fsstate;
- CossInfo *cs = (CossInfo *) SD->fsdata;
+ CossSwapDir *SD = (CossSwapDir *)INDEXSD(swap_dirn);
- assert(sio->read.callback == NULL);
- assert(sio->read.callback_data == NULL);
- sio->read.callback = callback;
- sio->read.callback_data = cbdataReference(callback_data);
+ assert(read.callback == NULL);
+ assert(read.callback_data == NULL);
+ read.callback = callback;
+ read.callback_data = cbdataReference(callback_data);
debug(79, 3) ("storeCossRead: offset %ld\n", (long int) offset);
- sio->offset = offset;
- cstate->flags.reading = 1;
- if ((offset + size) > sio->st_size)
- size = sio->st_size - offset;
- cstate->requestlen = size;
- cstate->requestbuf = buf;
- cstate->requestoffset = offset;
- if (cstate->readbuffer == NULL) {
- p = storeCossMemPointerFromDiskOffset(SD, sio->swap_filen, NULL);
+ offset_ = offset;
+ flags.reading = 1;
+ if ((offset + size) > st_size)
+ size = st_size - offset;
+ requestlen = size;
+ requestbuf = buf;
+ requestoffset = offset;
+ if (readbuffer == NULL) {
+ p = storeCossMemPointerFromDiskOffset(SD, swap_filen, NULL);
/* Remember we need to translate the block offset to a disk offset! */
- a_file_read(&cs->aq, cs->fd,
+ a_file_read(&SD->aq, SD->fd,
p,
- sio->st_size,
- cstate->reqdiskoffset,
+ st_size,
+ reqdiskoffset,
storeCossReadDone,
- sio);
- cstate->reqdiskoffset = 0; /* XXX */
+ this);
+ reqdiskoffset = 0; /* XXX */
} else {
- storeCossReadDone(cs->fd,
- cstate->readbuffer,
- sio->st_size,
+ storeCossReadDone(SD->fd,
+ readbuffer,
+ st_size,
0,
- sio);
+ this);
}
}
void
-storeCossWrite(SwapDir * SD, storeIOState * sio, char *buf, size_t size, off_t offset, FREE * free_func)
+CossState::write(char *buf, size_t size, off_t offset, FREE * free_func)
{
char *dest;
CossMemBuf *membuf;
* If we get handed an object with a size of -1,
* the squid code is broken
*/
- assert(sio->e->mem_obj->object_sz != -1);
+ assert(e->mem_obj->object_sz != -1);
- debug(79, 3) ("storeCossWrite: offset %ld, len %lu\n", (long int) sio->offset, (unsigned long int) size);
- diskoffset = sio->swap_filen + sio->offset;
+ debug(79, 3) ("storeCossWrite: offset %ld, len %lu\n", (long int) offset_, (unsigned long int) size);
+ diskoffset = swap_filen + offset_;
+ CossSwapDir *SD = (CossSwapDir *)INDEXSD(swap_dirn);
dest = storeCossMemPointerFromDiskOffset(SD, diskoffset, &membuf);
assert(dest != NULL);
xmemcpy(dest, buf, size);
- sio->offset += size;
+ offset_ += size;
if (free_func)
(free_func) (buf);
}
/* === STATIC =========================================================== */
static void
-storeCossReadDone(int fd, const char *buf, int len, int errflag, void *my_data)
+storeCossReadDone(int rvfd, const char *buf, int len, int errflag, void *my_data)
{
storeIOState *sio = (storeIOState *)my_data;
char *p;
STRCB *callback = sio->read.callback;
void *cbdata;
- SwapDir *SD = INDEXSD(sio->swap_dirn);
- CossState *cstate = (CossState *) sio->fsstate;
+ CossSwapDir *SD = (CossSwapDir *)INDEXSD(sio->swap_dirn);
+ CossState *cstate = dynamic_cast<CossState *>(sio);
ssize_t rlen;
debug(79, 3) ("storeCossReadDone: fileno %d, FD %d, len %d\n",
- sio->swap_filen, fd, len);
+ sio->swap_filen, rvfd, len);
cstate->flags.reading = 0;
if (errflag) {
debug(79, 3) ("storeCossReadDone: got failure (%d)\n", errflag);
rlen = -1;
} else {
if (cstate->readbuffer == NULL) {
- cstate->readbuffer = (char *)xmalloc(sio->st_size);
+ cstate->readbuffer = (char *)xmalloc(cstate->st_size);
p = storeCossMemPointerFromDiskOffset(SD, sio->swap_filen, NULL);
- xmemcpy(cstate->readbuffer, p, sio->st_size);
+ xmemcpy(cstate->readbuffer, p, cstate->st_size);
storeCossMemBufUnlock(SD, sio);
}
- sio->offset += len;
+ sio->offset_ += len;
xmemcpy(cstate->requestbuf, &cstate->readbuffer[cstate->requestoffset],
cstate->requestlen);
rlen = (size_t) cstate->requestlen;
static void
storeCossIOCallback(storeIOState * sio, int errflag)
{
- CossState *cstate = (CossState *) sio->fsstate;
+ CossState *cstate = dynamic_cast<CossState *>(sio);
STIOCB *callback = sio->callback;
void *cbdata;
debug(79, 3) ("storeCossIOCallback: errflag=%d\n", errflag);
}
static char *
-storeCossMemPointerFromDiskOffset(SwapDir * SD, size_t offset, CossMemBuf ** mb)
+storeCossMemPointerFromDiskOffset(CossSwapDir * SD, size_t offset, CossMemBuf ** mb)
{
CossMemBuf *t;
dlink_node *m;
- CossInfo *cs = (CossInfo *) SD->fsdata;
- for (m = cs->membufs.head; m; m = m->next) {
+ for (m = SD->membufs.head; m; m = m->next) {
t = (CossMemBuf *)m->data;
if ((offset >= t->diskstart) && (offset <= t->diskend)) {
if (mb)
}
static void
-storeCossMemBufLock(SwapDir * SD, storeIOState * e)
+storeCossMemBufLock(CossSwapDir * SD, storeIOState * e)
{
CossMemBuf *t;
dlink_node *m;
- CossInfo *cs = (CossInfo *) SD->fsdata;
- for (m = cs->membufs.head; m; m = m->next) {
+ for (m = SD->membufs.head; m; m = m->next) {
t = (CossMemBuf *)m->data;
if (((size_t)e->swap_filen >= t->diskstart) && ((size_t)e->swap_filen <= t->diskend)) {
debug(79, 3) ("storeCossMemBufLock: locking %p, lockcount %d\n", t, t->lockcount);
}
static void
-storeCossMemBufUnlock(SwapDir * SD, storeIOState * e)
+storeCossMemBufUnlock(CossSwapDir * SD, storeIOState * e)
{
CossMemBuf *t;
dlink_node *m, *n;
- CossInfo *cs = (CossInfo *) SD->fsdata;
- for (m = cs->membufs.head; m; m = n) {
+ for (m = SD->membufs.head; m; m = n) {
/*
* Note that storeCossWriteMemBuf() might call storeCossWriteMemBufDone
* immediately (if the write finishes immediately, of course!) which
}
void
-storeCossSync(SwapDir * SD)
+CossSwapDir::sync()
{
- CossInfo *cs = (CossInfo *) SD->fsdata;
CossMemBuf *t;
dlink_node *m;
int end;
/* First, flush pending IO ops */
- a_file_syncqueue(&cs->aq);
+ a_file_syncqueue(&aq);
/* Then, flush any in-memory partial membufs */
- if (!cs->membufs.head)
+ if (!membufs.head)
return;
- for (m = cs->membufs.head; m; m = m->next) {
+ for (m = membufs.head; m; m = m->next) {
t = (CossMemBuf *)m->data;
if (t->flags.writing)
sleep(5); /* XXX EEEWWW! */
- lseek(cs->fd, t->diskstart, SEEK_SET);
- end = (t == cs->current_membuf) ? cs->current_offset : t->diskend;
- FD_WRITE_METHOD(cs->fd, t->buffer, end - t->diskstart);
+ lseek(fd, t->diskstart, SEEK_SET);
+ end = (t == current_membuf) ? current_offset : t->diskend;
+ FD_WRITE_METHOD(fd, t->buffer, end - t->diskstart);
}
}
static void
-storeCossWriteMemBuf(SwapDir * SD, CossMemBuf * t)
+storeCossWriteMemBuf(CossSwapDir * SD, CossMemBuf * t)
{
- CossInfo *cs = (CossInfo *) SD->fsdata;
debug(79, 3) ("storeCossWriteMemBuf: offset %ld, len %ld\n",
(long int) t->diskstart, (long int) (t->diskend - t->diskstart));
t->flags.writing = 1;
/* Remember that diskstart/diskend are block offsets! */
- a_file_write(&cs->aq, cs->fd, t->diskstart, &t->buffer,
+ a_file_write(&SD->aq, SD->fd, t->diskstart, &t->buffer,
t->diskend - t->diskstart, storeCossWriteMemBufDone, t, NULL);
}
static void
-storeCossWriteMemBufDone(int fd, int errflag, size_t len, void *my_data)
+storeCossWriteMemBufDone(int rvfd, int errflag, size_t len, void *my_data)
{
CossMemBuf *t = (CossMemBuf *)my_data;
- CossInfo *cs = (CossInfo *) t->SD->fsdata;
debug(79, 3) ("storeCossWriteMemBufDone: buf %p, len %ld\n", t, (long int) len);
if (errflag)
debug(79, 0) ("storeCossMemBufWriteDone: got failure (%d)\n", errflag);
- dlinkDelete(&t->node, &cs->membufs);
+ dlinkDelete(&t->node, &t->SD->membufs);
cbdataFree(t);
}
static CossMemBuf *
-storeCossCreateMemBuf(SwapDir * SD, size_t start,
+storeCossCreateMemBuf(CossSwapDir * SD, size_t start,
sfileno curfn, int *collision)
{
CossMemBuf *newmb, *t;
StoreEntry *e;
dlink_node *m, *prev;
int numreleased = 0;
- CossInfo *cs = (CossInfo *) SD->fsdata;
CBDATA_INIT_TYPE_FREECB(CossMemBuf, NULL);
newmb = cbdataAlloc(CossMemBuf);
newmb->lockcount = 0;
newmb->SD = SD;
/* XXX This should be reversed, with the new buffer last in the chain */
- dlinkAdd(newmb, &newmb->node, &cs->membufs);
+ dlinkAdd(newmb, &newmb->node, &SD->membufs);
/* Print out the list of membufs */
- for (m = cs->membufs.head; m; m = m->next) {
+ for (m = SD->membufs.head; m; m = m->next) {
t = (CossMemBuf *)m->data;
debug(79, 3) ("storeCossCreateMemBuf: membuflist %ld lockcount %d\n", (long int) t->diskstart, t->lockcount);
}
/*
* Kill objects from the tail to make space for a new chunk
*/
- for (m = cs->index.tail; m; m = prev) {
+ for (m = SD->cossindex.tail; m; m = prev) {
prev = m->prev;
e = (StoreEntry *)m->data;
if (curfn == e->swap_filen)
* Creates the initial membuf after rebuild
*/
void
-storeCossStartMembuf(SwapDir * sd)
+storeCossStartMembuf(CossSwapDir * sd)
{
- CossInfo *cs = (CossInfo *) sd->fsdata;
- CossMemBuf *newmb = storeCossCreateMemBuf(sd, cs->current_offset, -1, NULL);
- assert(!cs->current_membuf);
- cs->current_membuf = newmb;
+ CossMemBuf *newmb = storeCossCreateMemBuf(sd, sd->current_offset, -1, NULL);
+ assert(!sd->current_membuf);
+ sd->current_membuf = newmb;
}
/*
* Clean up any references from the SIO before it get's released.
*/
-static void
-storeCossIOFreeEntry(void *sio)
+CossState::~CossState()
{
- memPoolFree(coss_state_pool, ((storeIOState *) sio)->fsstate);
}
/*
- * $Id: diskd.cc,v 1.11 2002/10/13 20:35:26 robertc Exp $
+ * $Id: diskd.cc,v 1.12 2002/12/27 10:26:37 robertc Exp $
*
* DEBUG: section -- External DISKD process implementation.
* AUTHOR: Harvest Derived
s->callback_data = r->callback_data;
s->shm_offset = r->shm_offset;
s->id = r->id;
+ s->newstyle = r->newstyle;
if (s->shm_offset > -1)
buf = shmbuf + s->shm_offset;
switch (r->mtype) {
case _MQD_OPEN:
+ case _MQD_CREATE:
s->status = do_open(r, rl, buf);
break;
case _MQD_CLOSE:
/*
- * $Id: store_dir_diskd.cc,v 1.73 2002/10/28 08:53:37 adrian Exp $
+ * $Id: store_dir_diskd.cc,v 1.74 2002/12/27 10:26:37 robertc Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
#include "ufscommon.h"
+#include "SwapDir.h"
+
diskd_stats_t diskd_stats;
-MemPool *diskd_state_pool = NULL;
static int diskd_initialised = 0;
-static STINIT storeDiskdDirInit;
-static STDUMP storeDiskdDirDump;
-static STCHECKOBJ storeDiskdDirCheckObj;
-static void storeDiskdDirStats(SwapDir *, StoreEntry *);
static void storeDiskdStats(StoreEntry * sentry);
-static void storeDiskdDirSync(SwapDir *);
-static void storeDiskdDirIOUnlinkFile(char *path);
/* The only externally visible interface */
STSETUP storeFsSetup_diskd;
-static void
-storeDiskdDirInit(SwapDir * sd)
+
+
+void
+DiskdSwapDir::init()
{
int x;
- int i;
int rfd;
int ikey;
const char *args[5];
char skey1[32];
char skey2[32];
char skey3[32];
- diskdinfo_t *diskdinfo = (diskdinfo_t *)sd->fsdata;
+ DiskdIO *DIO = dynamic_cast<DiskdIO *>(IO);
- ikey = (getpid() << 10) + (sd->index << 2);
+ ikey = (getpid() << 10) + (index << 2);
ikey &= 0x7fffffff;
- diskdinfo->smsgid = msgget((key_t) ikey, 0700 | IPC_CREAT);
- if (diskdinfo->smsgid < 0) {
+ DIO->smsgid = msgget((key_t) ikey, 0700 | IPC_CREAT);
+ if (DIO->smsgid < 0) {
debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror());
fatal("msgget failed");
}
- diskdinfo->rmsgid = msgget((key_t) (ikey + 1), 0700 | IPC_CREAT);
- if (diskdinfo->rmsgid < 0) {
+ DIO->rmsgid = msgget((key_t) (ikey + 1), 0700 | IPC_CREAT);
+ if (DIO->rmsgid < 0) {
debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror());
fatal("msgget failed");
}
- diskdinfo->shm.nbufs = (int)(diskdinfo->magic2 * 1.3);
- diskdinfo->shm.id = shmget((key_t) (ikey + 2),
- diskdinfo->shm.nbufs * SHMBUF_BLKSZ, 0600 | IPC_CREAT);
- if (diskdinfo->shm.id < 0) {
- debug(50, 0) ("storeDiskdInit: shmget: %s\n", xstrerror());
- fatal("shmget failed");
- }
- diskdinfo->shm.buf = (char *)shmat(diskdinfo->shm.id, NULL, 0);
- if (diskdinfo->shm.buf == (void *) -1) {
- debug(50, 0) ("storeDiskdInit: shmat: %s\n", xstrerror());
- fatal("shmat failed");
- }
- diskdinfo->shm.inuse_map = (char *)xcalloc((diskdinfo->shm.nbufs + 7) / 8, 1);
- diskd_stats.shmbuf_count += diskdinfo->shm.nbufs;
- for (i = 0; i < diskdinfo->shm.nbufs; i++) {
- CBIT_SET(diskdinfo->shm.inuse_map, i);
- storeDiskdShmPut(sd, i * SHMBUF_BLKSZ);
- }
+ DIO->shm.init(ikey, DIO->magic2);
snprintf(skey1, 32, "%d", ikey);
snprintf(skey2, 32, "%d", ikey + 1);
snprintf(skey3, 32, "%d", ikey + 2);
args,
"diskd",
&rfd,
- &diskdinfo->wfd);
+ &DIO->wfd);
if (x < 0)
fatalf("execl: %s", Config.Program.diskd);
- if (rfd != diskdinfo->wfd)
+ if (rfd != DIO->wfd)
comm_close(rfd);
- fd_note(diskdinfo->wfd, "squid -> diskd");
- commSetTimeout(diskdinfo->wfd, -1, NULL, NULL);
- commSetNonBlocking(diskdinfo->wfd);
+ fd_note(DIO->wfd, "squid -> diskd");
+ commSetTimeout(DIO->wfd, -1, NULL, NULL);
+ commSetNonBlocking(DIO->wfd);
- commonUfsDirInit (sd);
+ UFSSwapDir::init();
comm_quick_poll_required();
}
* Sync any pending data. We just sit around and read the queue
* until the data has finished writing.
*/
-static void
-storeDiskdDirSync(SwapDir * SD)
+void
+DiskdSwapDir::sync()
{
static time_t lastmsg = 0;
- diskdinfo_t *diskdinfo = (diskdinfo_t *)SD->fsdata;
- while (diskdinfo->away > 0) {
+ DiskdIO *DIO = dynamic_cast<DiskdIO *>(IO);
+ while (DIO->away > 0) {
if (squid_curtime > lastmsg) {
debug(47, 1) ("storeDiskdDirSync: %d messages away\n",
- diskdinfo->away);
+ DIO->away);
lastmsg = squid_curtime;
}
- storeDiskdDirCallback(SD);
+ callback();
}
}
* don't get a message.
*/
int
-storeDiskdDirCallback(SwapDir * SD)
+DiskdSwapDir::callback()
{
diomsg M;
int x;
- diskdinfo_t *diskdinfo = (diskdinfo_t *)SD->fsdata;
int retval = 0;
- if (diskdinfo->away >= diskdinfo->magic2) {
+ DiskdIO *DIO = dynamic_cast<DiskdIO *>(IO);
+ if (DIO->away >= DIO->magic2) {
diskd_stats.block_queue_len++;
retval = 1; /* We might not have anything to do, but our queue
* is full.. */
#ifdef ALWAYS_ZERO_BUFFERS
memset(&M, '\0', sizeof(M));
#endif
- x = msgrcv(diskdinfo->rmsgid, &M, msg_snd_rcv_sz, 0, IPC_NOWAIT);
+ x = msgrcv(DIO->rmsgid, &M, msg_snd_rcv_sz, 0, IPC_NOWAIT);
if (x < 0)
break;
else if (x != msg_snd_rcv_sz) {
break;
}
diskd_stats.recv_count++;
- diskdinfo->away--;
+ --DIO->away;
storeDiskdHandle(&M);
retval = 1; /* Return that we've actually done some work */
if (M.shm_offset > -1)
- storeDiskdShmPut(SD, (off_t) M.shm_offset);
+ DIO->shm.put ((off_t) M.shm_offset);
}
return retval;
}
* happily store anything as long as the LRU time isn't too small.
*/
int
-storeDiskdDirCheckObj(SwapDir * SD, const StoreEntry * e)
+DiskdSwapDir::canStore(StoreEntry const &e)const
{
- diskdinfo_t *diskdinfo = (diskdinfo_t *)SD->fsdata;
- /* Check the queue length */
- if (diskdinfo->away >= diskdinfo->magic1)
+ if (IO->shedLoad())
return -1;
- /* Calculate the storedir load relative to magic2 on a scale of 0 .. 1000 */
- /* the parse function guarantees magic2 is positivie */
- return diskdinfo->away * 1000 / diskdinfo->magic2;
+ return IO->load();
}
void
-storeDiskdDirIOUnlinkFile(char *path)
+DiskdSwapDir::unlinkFile(char const *path)
{
#if USE_UNLINKD
unlinkdUnlink(path);
}
-/*
- * SHM manipulation routines
- */
-
-void *
-storeDiskdShmGet(SwapDir * sd, off_t * shm_offset)
-{
- char *buf = NULL;
- diskdinfo_t *diskdinfo = (diskdinfo_t *)sd->fsdata;
- int i;
- for (i = 0; i < diskdinfo->shm.nbufs; i++) {
- if (CBIT_TEST(diskdinfo->shm.inuse_map, i))
- continue;
- CBIT_SET(diskdinfo->shm.inuse_map, i);
- *shm_offset = i * SHMBUF_BLKSZ;
- buf = diskdinfo->shm.buf + (*shm_offset);
- break;
- }
- assert(buf);
- assert(buf >= diskdinfo->shm.buf);
- assert(buf < diskdinfo->shm.buf + (diskdinfo->shm.nbufs * SHMBUF_BLKSZ));
- diskd_stats.shmbuf_count++;
- if (diskd_stats.max_shmuse < diskd_stats.shmbuf_count)
- diskd_stats.max_shmuse = diskd_stats.shmbuf_count;
- return buf;
-}
-
-void
-storeDiskdShmPut(SwapDir * sd, off_t offset)
-{
- int i;
- diskdinfo_t *diskdinfo = (diskdinfo_t *)sd->fsdata;
- assert(offset >= 0);
- assert(offset < diskdinfo->shm.nbufs * SHMBUF_BLKSZ);
- i = offset / SHMBUF_BLKSZ;
- assert(i < diskdinfo->shm.nbufs);
- assert(CBIT_TEST(diskdinfo->shm.inuse_map, i));
- CBIT_CLR(diskdinfo->shm.inuse_map, i);
- diskd_stats.shmbuf_count--;
-}
-
-
-
-
/* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */
void
-storeDiskdDirStats(SwapDir * SD, StoreEntry * sentry)
+DiskdSwapDir::statfs(StoreEntry & sentry)const
{
- diskdinfo_t *diskdinfo = (diskdinfo_t *)SD->fsdata;
- commonUfsDirStats (SD, sentry);
- storeAppendPrintf(sentry, "Pending operations: %d\n", diskdinfo->away);
+ UFSSwapDir::statfs (sentry);
+ DiskdIO *DIO = dynamic_cast<DiskdIO *>(IO);
+ storeAppendPrintf(&sentry, "Pending operations: %d\n", DIO->away);
}
static void
storeDiskdDirParseQ1(SwapDir * sd, const char *name, const char *value, int reconfiguring)
{
- diskdinfo_t *diskdinfo = (diskdinfo_t *)sd->fsdata;
- int old_magic1 = diskdinfo->magic1;
- diskdinfo->magic1 = atoi(value);
+ DiskdIO *IO = dynamic_cast<DiskdIO *>(((DiskdSwapDir *)sd)->IO);
+ int old_magic1 = IO->magic1;
+ IO->magic1 = atoi(value);
if (!reconfiguring)
return;
- if (old_magic1 < diskdinfo->magic1) {
+ if (old_magic1 < IO->magic1) {
/*
* This is because shm.nbufs is computed at startup, when
* we call shmget(). We can't increase the Q1/Q2 parameters
* will cause an assertion in storeDiskdShmGet().
*/
debug(3, 1) ("WARNING: cannot increase cache_dir '%s' Q1 value while Squid is running.\n", sd->path);
- diskdinfo->magic1 = old_magic1;
+ IO->magic1 = old_magic1;
return;
}
- if (old_magic1 != diskdinfo->magic1)
+ if (old_magic1 != IO->magic1)
debug(3, 1) ("cache_dir '%s' new Q1 value '%d'\n",
- sd->path, diskdinfo->magic1);
+ sd->path, IO->magic1);
}
static void
-storeDiskdDirDumpQ1(StoreEntry * e, const char *option, SwapDir * sd)
+storeDiskdDirDumpQ1(StoreEntry * e, const char *option, SwapDir const * sd)
{
- diskdinfo_t *diskdinfo = (diskdinfo_t *)sd->fsdata;
- storeAppendPrintf(e, " Q1=%d", diskdinfo->magic1);
+ DiskdIO *IO = dynamic_cast<DiskdIO *>(((DiskdSwapDir *)sd)->IO);
+ storeAppendPrintf(e, " Q1=%d", IO->magic1);
}
static void
storeDiskdDirParseQ2(SwapDir * sd, const char *name, const char *value, int reconfiguring)
{
- diskdinfo_t *diskdinfo = (diskdinfo_t *)sd->fsdata;
- int old_magic2 = diskdinfo->magic2;
- diskdinfo->magic2 = atoi(value);
+ DiskdIO *IO = dynamic_cast<DiskdIO *>(((DiskdSwapDir *)sd)->IO);
+ assert (IO);
+ int old_magic2 = IO->magic2;
+ IO->magic2 = atoi(value);
if (!reconfiguring)
return;
- if (old_magic2 < diskdinfo->magic2) {
+ if (old_magic2 < IO->magic2) {
/* See comments in Q1 function above */
debug(3, 1) ("WARNING: cannot increase cache_dir '%s' Q2 value while Squid is running.\n", sd->path);
- diskdinfo->magic2 = old_magic2;
+ IO->magic2 = old_magic2;
return;
}
- if (old_magic2 != diskdinfo->magic2)
+ if (old_magic2 != IO->magic2)
debug(3, 1) ("cache_dir '%s' new Q2 value '%d'\n",
- sd->path, diskdinfo->magic2);
+ sd->path, IO->magic2);
}
static void
-storeDiskdDirDumpQ2(StoreEntry * e, const char *option, SwapDir * sd)
+storeDiskdDirDumpQ2(StoreEntry * e, const char *option, SwapDir const * sd)
{
- diskdinfo_t *diskdinfo = (diskdinfo_t *)sd->fsdata;
- storeAppendPrintf(e, " Q2=%d", diskdinfo->magic2);
+ DiskdIO *IO = dynamic_cast<DiskdIO *>(((DiskdSwapDir *)sd)->IO);
+ storeAppendPrintf(e, " Q2=%d", IO->magic2);
}
struct cache_dir_option options[] =
*
* This routine is called when the given swapdir needs reconfiguring
*/
-static void
-storeDiskdDirReconfigure(SwapDir * sd, int index, char *path)
+void
+DiskdSwapDir::reconfigure(int anIndex, char *aPath)
{
- int i;
- int size;
- int l1;
- int l2;
-
- i = GetInteger();
- size = i << 10; /* Mbytes to kbytes */
- if (size <= 0)
- fatal("storeDiskdDirReconfigure: invalid size value");
- i = GetInteger();
- l1 = i;
- if (l1 <= 0)
- fatal("storeDiskdDirReconfigure: invalid level 1 directories value");
- i = GetInteger();
- l2 = i;
- if (l2 <= 0)
- fatal("storeDiskdDirReconfigure: invalid level 2 directories value");
-
- /* just reconfigure it */
- if (size == sd->max_size)
- debug(3, 1) ("Cache dir '%s' size remains unchanged at %d KB\n",
- path, size);
- else
- debug(3, 1) ("Cache dir '%s' size changed to %d KB\n",
- path, size);
- sd->max_size = size;
- parse_cachedir_options(sd, options, 1);
+ UFSSwapDir::reconfigure (anIndex, aPath);
+
+ parse_cachedir_options(this, options, 1);
}
void
-storeDiskdDirDump(StoreEntry * entry, SwapDir * s)
+DiskdSwapDir::dump(StoreEntry & entry)const
{
- commonUfsDirDump (entry, s);
- dump_cachedir_options(entry, options, s);
+ UFSSwapDir::dump (entry);
+ dump_cachedir_options(&entry, options, this);
}
/*
*
* Called when a *new* fs is being setup.
*/
-static void
-storeDiskdDirParse(SwapDir * sd, int index, char *path)
+void
+DiskdSwapDir::parse(int anIndex, char *aPath)
{
- int i;
- int size;
- int l1;
- int l2;
- diskdinfo_t *diskdinfo;
-
- i = GetInteger();
- size = i << 10; /* Mbytes to kbytes */
- if (size <= 0)
- fatal("storeDiskdDirParse: invalid size value");
- i = GetInteger();
- l1 = i;
- if (l1 <= 0)
- fatal("storeDiskdDirParse: invalid level 1 directories value");
- i = GetInteger();
- l2 = i;
- if (l2 <= 0)
- fatal("storeDiskdDirParse: invalid level 2 directories value");
-
- sd->fsdata = diskdinfo = (diskdinfo_t *)xcalloc(1, sizeof(*diskdinfo));
- sd->index = index;
- sd->path = xstrdup(path);
- sd->max_size = size;
- diskdinfo->commondata.l1 = l1;
- diskdinfo->commondata.l2 = l2;
- diskdinfo->commondata.swaplog_fd = -1;
- diskdinfo->commondata.map = NULL; /* Debugging purposes */
- diskdinfo->commondata.suggest = 0;
- diskdinfo->commondata.io.storeDirUnlinkFile = storeDiskdDirIOUnlinkFile;
- diskdinfo->magic1 = 64;
- diskdinfo->magic2 = 72;
- sd->init = storeDiskdDirInit;
- sd->newfs = commonUfsDirNewfs;
- sd->dump = storeDiskdDirDump;
- sd->freefs = commonUfsDirFree;
- sd->dblcheck = commonUfsCleanupDoubleCheck;
- sd->statfs = storeDiskdDirStats;
- sd->maintainfs = commonUfsDirMaintain;
- sd->checkobj = storeDiskdDirCheckObj;
- sd->refobj = commonUfsDirRefObj;
- sd->unrefobj = commonUfsDirUnrefObj;
- sd->callback = storeDiskdDirCallback;
- sd->sync = storeDiskdDirSync;
- sd->obj.create = storeDiskdCreate;
- sd->obj.open = storeDiskdOpen;
- sd->obj.close = storeDiskdClose;
- sd->obj.read = storeDiskdRead;
- sd->obj.write = storeDiskdWrite;
- sd->obj.unlink = storeDiskdUnlink;
- sd->log.open = commonUfsDirOpenSwapLog;
- sd->log.close = commonUfsDirCloseSwapLog;
- sd->log.write = commonUfsDirSwapLog;
- sd->log.clean.start = commonUfsDirWriteCleanStart;
- sd->log.clean.nextentry = commonUfsDirCleanLogNextEntry;
- sd->log.clean.done = commonUfsDirWriteCleanDone;
-
- parse_cachedir_options(sd, options, 0);
-
- /* Initialise replacement policy stuff */
- sd->repl = createRemovalPolicy(Config.replPolicy);
+ UFSSwapDir::parse(anIndex, aPath);
+
+ parse_cachedir_options(this, options, 0);
}
/*
static void
storeDiskdDirDone(void)
{
- memPoolDestroy(&diskd_state_pool);
diskd_initialised = 0;
}
+static SwapDir *
+storeDiskdNew(void)
+{
+ DiskdSwapDir *result = new DiskdSwapDir;
+ result->IO = new DiskdIO;
+ return result;
+}
+
void
storeFsSetup_diskd(storefs_entry_t * storefs)
{
assert(!diskd_initialised);
- storefs->parsefunc = storeDiskdDirParse;
- storefs->reconfigurefunc = storeDiskdDirReconfigure;
storefs->donefunc = storeDiskdDirDone;
- diskd_state_pool = memPoolCreate("DISKD IO State data", sizeof(diskdstate_t));
+ storefs->newfunc = storeDiskdNew;
memset(&diskd_stats, '\0', sizeof(diskd_stats));
cachemgrRegister("diskd", "DISKD Stats", storeDiskdStats, 0, 1);
debug(47, 1) ("diskd started\n");
* is 75% of SHMBUFS. magic1 is the number of messages away which we
* stop allowing open/create for.
*/
-
-struct _diskdinfo_t {
- /* MUST BE FIRST */
- squidufsinfo_t commondata;
- int smsgid;
- int rmsgid;
- int wfd;
- int away;
- struct {
- char *buf;
- char *inuse_map;
- int id;
- int nbufs;
- } shm;
- int magic1;
- int magic2;
+typedef struct _diomsg diomsg;
+class DiskdIO;
+class DiskdFile : public DiskFile {
+ public:
+ virtual void deleteSelf() const;
+ void * operator new (size_t);
+ void operator delete (void *);
+ DiskdFile (char const *path, DiskdIO *);
+ ~DiskdFile();
+ virtual void open (int, mode_t, IORequestor::Pointer);
+ virtual void create (int, mode_t, IORequestor::Pointer);
+ virtual void read(char *, off_t, size_t);
+ virtual void write(char const *buf, size_t size, off_t offset, FREE *free_func);
+ virtual void close ();
+ virtual bool error() const;
+ virtual bool canRead() const;
+
+ /* Temporary */
+ int getID() const {return id;}
+ void completed (diomsg *);
+
+ private:
+ int id;
+ char const *path_;
+ bool errorOccured;
+ DiskdIO *IO;
+ IORequestor::Pointer ioRequestor;
+ CBDATA_CLASS(DiskdFile);
+ void openDone(diomsg *);
+ void createDone (diomsg *);
+ void readDone (diomsg *);
+ void writeDone (diomsg *);
+ void closeDone (diomsg *);
+ int mode;
+ void notifyClient();
+ bool canNotifyClient() const;
};
-struct _diskdstate_t {
+class SharedMemory{
+public:
+ void put(off_t);
+ void *get(off_t *);
+ void init (int ikey, int magic2);
+ int nbufs;
+ char *buf;
+ char *inuse_map;
int id;
- struct {
- unsigned int close_request:1;
- unsigned int reading:1;
- unsigned int writing:1;
- } flags;
- char *read_buf;
+};
+
+class diskdstate_t : public UFSStoreState {
+ public:
+ virtual void deleteSelf() const {delete this;}
+ void * operator new (size_t);
+ void operator delete (void *);
+ diskdstate_t(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data);
+ ~diskdstate_t();
+
+ void close();
+
+ void ioCompletedNotification();
+ void readCompleted(const char *buf, int len, int errflag);
+ void writeCompleted(int errflag, size_t len);
+ void closeCompleted();
+ private:
+ CBDATA_CLASS(diskdstate_t);
+ void doCallback(int);
};
enum {
_MQD_NOP,
_MQD_OPEN,
+ _MQD_CREATE,
_MQD_CLOSE,
_MQD_READ,
_MQD_WRITE,
_MQD_UNLINK
};
-typedef struct _diomsg {
+struct _diomsg {
mtyp_t mtype;
int id;
int seq_no;
- void *callback_data;
+ void * callback_data;
int size;
int offset;
int status;
+ bool newstyle;
int shm_offset;
-} diomsg;
+};
struct _diskd_stats {
int open_fail_queue_len;
};
typedef struct _diskd_stats diskd_stats_t;
-typedef struct _diskdinfo_t diskdinfo_t;
-typedef struct _diskdstate_t diskdstate_t;
-static const int msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t);
-/* The diskd_state memory pool */
-extern MemPool *diskd_state_pool;
+static const int msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t);
-extern void storeDiskdShmPut(SwapDir *, off_t);
-extern void *storeDiskdShmGet(SwapDir *, off_t *);
extern void storeDiskdHandle(diomsg * M);
-extern int storeDiskdDirCallback(SwapDir *);
-
-/*
- * Store IO stuff
- */
-extern STOBJCREATE storeDiskdCreate;
-extern STOBJOPEN storeDiskdOpen;
-extern STOBJCLOSE storeDiskdClose;
-extern STOBJREAD storeDiskdRead;
-extern STOBJWRITE storeDiskdWrite;
-extern STOBJUNLINK storeDiskdUnlink;
+#include "SwapDir.h"
+class DiskdSwapDir : public UFSSwapDir
+{
+public:
+ virtual void init();
+ virtual void dump(StoreEntry &)const;
+ virtual void unlink(StoreEntry &);
+ virtual void statfs (StoreEntry &) const;
+ virtual int canStore(StoreEntry const &) const;
+ virtual int callback();
+ virtual void sync();
+ virtual void parse (int index, char *path);
+ virtual void reconfigure (int, char *);
+ virtual void unlinkFile(char const *);
+};
#define SHMBUF_BLKSZ SM_PAGE_SIZE
extern diskd_stats_t diskd_stats;
+class DiskdIO : public UFSStrategy
+{
+public:
+ DiskdIO();
+ virtual bool shedLoad();
+ virtual void deleteSelf() const;
+ virtual void openFailed();
+ virtual int load();
+ virtual StoreIOState::Pointer createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const;
+ virtual DiskFile::Pointer newFile (char const *path);
+ int away;
+ int magic1;
+ int magic2;
+ int smsgid;
+ int rmsgid;
+ int wfd;
+ SharedMemory shm;
+};
#endif
/*
- * $Id: store_io_diskd.cc,v 1.29 2002/10/13 20:35:26 robertc Exp $
+ * $Id: store_io_diskd.cc,v 1.30 2002/12/27 10:26:37 robertc Exp $
*
* DEBUG: section 79 Squid-side DISKD I/O functions.
* AUTHOR: Duane Wessels
#include <sys/shm.h>
#include "store_diskd.h"
+#include "SwapDir.h"
-static int storeDiskdSend(int, SwapDir *, int, storeIOState *, int, int, off_t);
-static void storeDiskdIOCallback(storeIOState * sio, int errflag);
-static CBDUNL storeDiskdIOFreeEntry;
-
-CBDATA_TYPE(storeIOState);
+static int storeDiskdSend(int, DiskdIO *, int, StoreIOState::Pointer, int, int, off_t);
+static int storeDiskdSend(int, DiskdIO *, int, DiskdFile *, int, int, off_t);
/* === PUBLIC =========================================================== */
+DiskdIO::DiskdIO() : away (0), magic1(64), magic2(72)
+{
+}
-storeIOState *
-storeDiskdOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
- STIOCB * callback, void *callback_data)
+bool
+DiskdIO::shedLoad()
{
- sfileno f = e->swap_filen;
- int x;
- storeIOState *sio;
- char *buf;
- diskdstate_t *diskdstate;
- off_t shm_offset;
- diskdinfo_t *diskdinfo = (diskdinfo_t *)SD->fsdata;
- debug(79, 3) ("storeDiskdOpen: fileno %08X\n", f);
/*
* Fail on open() if there are too many requests queued.
*/
- if (diskdinfo->away > diskdinfo->magic1) {
- debug(79, 3) ("storeDiskdOpen: FAILING, too many requests away\n");
- diskd_stats.open_fail_queue_len++;
- return NULL;
+ if (away > magic1) {
+ debug(79, 3) ("storeDiskdIO::sheLoad: Shedding, too many requests away\n");
+
+ return true;
+ }
+ return false;
+}
+
+int
+DiskdIO::load()
+{
+ /* Calculate the storedir load relative to magic2 on a scale of 0 .. 1000 */
+ /* the parse function guarantees magic2 is positivie */
+ return away * 1000 / magic2;
+}
+
+void
+DiskdIO::deleteSelf() const
+{
+ /* do nothing, we use a single instance */
+}
+
+void
+DiskdIO::openFailed()
+{
+ diskd_stats.open_fail_queue_len++;
+}
+
+StoreIOState::Pointer
+DiskdIO::createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const
+{
+ return new diskdstate_t (SD, e, callback, callback_data);
+}
+
+DiskFile::Pointer
+DiskdIO::newFile (char const *path)
+{
+ return new DiskdFile (path, this);
+}
+
+
+/*
+ * SHM manipulation routines
+ */
+void
+SharedMemory::put (off_t offset)
+{
+ int i;
+ assert(offset >= 0);
+ assert(offset < nbufs * SHMBUF_BLKSZ);
+ i = offset / SHMBUF_BLKSZ;
+ assert(i < nbufs);
+ assert(CBIT_TEST(inuse_map, i));
+ CBIT_CLR(inuse_map, i);
+ --diskd_stats.shmbuf_count;
+}
+
+void *
+SharedMemory::get (off_t * shm_offset)
+{
+ char *aBuf = NULL;
+ int i;
+ for (i = 0; i < nbufs; i++) {
+ if (CBIT_TEST(inuse_map, i))
+ continue;
+ CBIT_SET(inuse_map, i);
+ *shm_offset = i * SHMBUF_BLKSZ;
+ aBuf = buf + (*shm_offset);
+ break;
}
- CBDATA_INIT_TYPE_FREECB(storeIOState, storeDiskdIOFreeEntry);
- sio = cbdataAlloc(storeIOState);
- sio->fsstate = diskdstate = (diskdstate_t *)memPoolAlloc(diskd_state_pool);
-
- sio->swap_filen = f;
- sio->swap_dirn = SD->index;
- sio->mode = O_RDONLY | O_BINARY;
- sio->callback = callback;
- sio->callback_data = cbdataReference(callback_data);
- sio->e = e;
-
- diskdstate->flags.writing = 0;
- diskdstate->flags.reading = 0;
- diskdstate->flags.close_request = 0;
- diskdstate->id = diskd_stats.sio_id++;
-
- buf = (char *)storeDiskdShmGet(SD, &shm_offset);
- xstrncpy(buf, commonUfsDirFullPath(SD, f, NULL), SHMBUF_BLKSZ);
- x = storeDiskdSend(_MQD_OPEN,
- SD,
- diskdstate->id,
- sio,
+ assert(aBuf);
+ assert(aBuf >= buf);
+ assert(aBuf < buf + (nbufs * SHMBUF_BLKSZ));
+ diskd_stats.shmbuf_count++;
+ if (diskd_stats.max_shmuse < diskd_stats.shmbuf_count)
+ diskd_stats.max_shmuse = diskd_stats.shmbuf_count;
+ return aBuf;
+}
+
+void
+SharedMemory::init(int ikey, int magic2)
+{
+ nbufs = (int)(magic2 * 1.3);
+ id = shmget((key_t) (ikey + 2),
+ nbufs * SHMBUF_BLKSZ, 0600 | IPC_CREAT);
+ if (id < 0) {
+ debug(50, 0) ("storeDiskdInit: shmget: %s\n", xstrerror());
+ fatal("shmget failed");
+ }
+ buf = (char *)shmat(id, NULL, 0);
+ if (buf == (void *) -1) {
+ debug(50, 0) ("storeDiskdInit: shmat: %s\n", xstrerror());
+ fatal("shmat failed");
+ }
+ inuse_map = (char *)xcalloc((nbufs + 7) / 8, 1);
+ diskd_stats.shmbuf_count += nbufs;
+ for (int i = 0; i < nbufs; i++) {
+ CBIT_SET(inuse_map, i);
+ put (i * SHMBUF_BLKSZ);
+ }
+}
+
+CBDATA_CLASS_INIT(DiskdFile);
+
+void *
+DiskdFile::operator new (size_t)
+{
+ CBDATA_INIT_TYPE(DiskdFile);
+ DiskdFile *result = cbdataAlloc(DiskdFile);
+ /* Mark result as being owned - we want the refcounter to do the delete
+ * call */
+ cbdataReference(result);
+ debug (0,0)("diskdFile with base %p allocating\n", result);
+ return result;
+}
+
+void
+DiskdFile::operator delete (void *address)
+{
+ debug (0,0)("diskdFile with base %p deleting\n",address);
+ DiskdFile *t = static_cast<DiskdFile *>(address);
+ cbdataFree(address);
+ /* And allow the memory to be freed */
+ cbdataReferenceDone (t);
+}
+
+void
+DiskdFile::deleteSelf() const {delete this;}
+
+DiskdFile::DiskdFile (char const *aPath, DiskdIO *anIO) : errorOccured (false), IO(anIO)
+{
+ assert (aPath);
+ debug (79,0)("DiskdFile::DiskdFile: %s\n", aPath);
+ path_ = xstrdup (aPath);
+ id = diskd_stats.sio_id++;
+}
+
+DiskdFile::~DiskdFile()
+{
+ safe_free (path_);
+}
+
+void
+DiskdFile::open (int flags, mode_t aMode, IORequestor::Pointer callback)
+{
+ debug (79,0)("DiskdFile::open: %p opening for %p\n", this, callback.getRaw());
+ assert (ioRequestor.getRaw() == NULL);
+ ioRequestor = callback;
+ assert (callback.getRaw());
+ mode = flags;
+ off_t shm_offset;
+ char *buf = (char *)IO->shm.get(&shm_offset);
+ xstrncpy(buf, path_, SHMBUF_BLKSZ);
+ int x = storeDiskdSend(_MQD_OPEN,
+ IO,
+ id,
+ this,
strlen(buf) + 1,
- O_RDONLY,
+ mode,
shm_offset);
if (x < 0) {
- debug(79, 1) ("storeDiskdSend OPEN: %s\n", xstrerror());
- storeDiskdShmPut(SD, shm_offset);
- cbdataReferenceDone(sio->callback_data);
- cbdataFree(sio);
- return NULL;
+ errorOccured = true;
+ IO->shm.put (shm_offset);
+ ioRequestor->ioCompletedNotification();
+ ioRequestor = NULL;
}
diskd_stats.open.ops++;
- return sio;
}
-storeIOState *
-storeDiskdCreate(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
- STIOCB * callback, void *callback_data)
-{
- sfileno f;
- int x;
- storeIOState *sio;
- char *buf;
+void
+DiskdFile::create (int flags, mode_t aMode, IORequestor::Pointer callback){
+ debug (79,0)("DiskdFile::create: %p creating for %p\n", this, callback.getRaw());
+ assert (ioRequestor.getRaw() == NULL);
+ ioRequestor = callback;
+ assert (callback.getRaw());
+ mode = flags;
off_t shm_offset;
- diskdinfo_t *diskdinfo = (diskdinfo_t *)SD->fsdata;
- diskdstate_t *diskdstate;
- /*
- * Fail on open() if there are too many requests queued.
- */
- if (diskdinfo->away > diskdinfo->magic1) {
- diskd_stats.open_fail_queue_len++;
- return NULL;
- }
- /* Allocate a number */
- f = commonUfsDirMapBitAllocate(SD);
- debug(79, 3) ("storeDiskdCreate: fileno %08X\n", f);
-
- CBDATA_INIT_TYPE_FREECB(storeIOState, storeDiskdIOFreeEntry);
- sio = cbdataAlloc(storeIOState);
- sio->fsstate = diskdstate = (diskdstate_t *)memPoolAlloc(diskd_state_pool);
-
- sio->swap_filen = f;
- sio->swap_dirn = SD->index;
- sio->mode = O_WRONLY | O_CREAT | O_TRUNC;
- sio->callback = callback;
- sio->callback_data = cbdataReference(callback_data);
- sio->e = e;
-
- diskdstate->flags.writing = 0;
- diskdstate->flags.reading = 0;
- diskdstate->flags.close_request = 0;
- diskdstate->id = diskd_stats.sio_id++;
-
- buf = (char *)storeDiskdShmGet(SD, &shm_offset);
- xstrncpy(buf, commonUfsDirFullPath(SD, f, NULL), SHMBUF_BLKSZ);
- x = storeDiskdSend(_MQD_OPEN,
- SD,
- diskdstate->id,
- sio,
- strlen(buf) + 1,
- sio->mode,
- shm_offset);
+ char *buf = (char *)IO->shm.get(&shm_offset);
+ xstrncpy(buf, path_, SHMBUF_BLKSZ);
+ int x = storeDiskdSend(_MQD_CREATE,
+ IO,
+ id,
+ this,
+ strlen(buf) + 1,
+ mode,
+ shm_offset);
if (x < 0) {
- debug(79, 1) ("storeDiskdSend OPEN: %s\n", xstrerror());
- storeDiskdShmPut(SD, shm_offset);
- cbdataReferenceDone(sio->callback_data);
- cbdataFree(sio);
- return NULL;
+ errorOccured = true;
+ IO->shm.put (shm_offset);
+ debug(79, 1) ("storeDiskdSend CREATE: %s\n", xstrerror());
+ notifyClient();
+ ioRequestor = NULL;
+ return;
}
- commonUfsDirReplAdd(SD, e);
diskd_stats.create.ops++;
- return sio;
}
+void
+DiskdFile::read(char *buf, off_t offset, size_t size)
+{
+ assert (ioRequestor.getRaw() != NULL);
+ off_t shm_offset;
+ char *rbuf = (char *)IO->shm.get(&shm_offset);
+ assert(rbuf);
+ int x = storeDiskdSend(_MQD_READ,
+ IO,
+ id,
+ this,
+ (int) size,
+ (int) offset,
+ shm_offset);
+ if (x < 0) {
+ errorOccured = true;
+ IO->shm.put (shm_offset);
+ debug(79, 1) ("storeDiskdSend READ: %s\n", xstrerror());
+ notifyClient();
+ ioRequestor = NULL;
+ return;
+ }
+ diskd_stats.read.ops++;
+}
void
-storeDiskdClose(SwapDir * SD, storeIOState * sio)
+DiskdFile::close()
{
- int x;
- diskdstate_t *diskdstate = (diskdstate_t *)sio->fsstate;
- debug(79, 3) ("storeDiskdClose: dirno %d, fileno %08X\n", SD->index,
- sio->swap_filen);
- x = storeDiskdSend(_MQD_CLOSE,
- SD,
- diskdstate->id,
- sio,
+ debug (79,0)("DiskdFile::close: %p closing for %p\n", this, ioRequestor.getRaw());
+ assert (ioRequestor.getRaw());
+ int x = storeDiskdSend(_MQD_CLOSE,
+ IO,
+ id,
+ this,
0,
0,
-1);
if (x < 0) {
+ errorOccured = true;
debug(79, 1) ("storeDiskdSend CLOSE: %s\n", xstrerror());
- storeDiskdIOCallback(sio, DISK_ERROR);
+ notifyClient();
+ ioRequestor = NULL;
+ return;
}
- diskdstate->flags.close_request = 1;
diskd_stats.close.ops++;
}
+bool
+DiskdFile::error() const
+{
+ return errorOccured;
+}
+
+bool
+DiskdFile::canRead() const
+{
+ return !error();
+}
+
+bool
+DiskdFile::canNotifyClient() const
+{
+ if (!ioRequestor.getRaw()) {
+ debug (79,3)("DiskdFile::canNotifyClient: No ioRequestor to notify\n");
+ return false;
+ }
+ return true;
+}
+
void
-storeDiskdRead(SwapDir * SD, storeIOState * sio, char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
+DiskdFile::notifyClient()
{
- int x;
- off_t shm_offset;
- char *rbuf;
- diskdstate_t *diskdstate = (diskdstate_t *)sio->fsstate;
- debug(79, 3) ("storeDiskdRead: dirno %d, fileno %08X\n", sio->swap_dirn, sio->swap_filen);
- assert(!diskdstate->flags.close_request);
- if (!cbdataReferenceValid(sio))
- return;
- if (diskdstate->flags.reading) {
- debug(79, 1) ("storeDiskdRead: already reading!\n");
+ if (!canNotifyClient()) {
return;
}
- assert(sio->read.callback == NULL);
- assert(sio->read.callback_data == NULL);
- sio->read.callback = callback;
- sio->read.callback_data = cbdataReference(callback_data);
- diskdstate->read_buf = buf; /* the one passed from above */
- sio->offset = offset;
- diskdstate->flags.reading = 1;
- rbuf = (char *)storeDiskdShmGet(SD, &shm_offset);
- assert(rbuf);
- x = storeDiskdSend(_MQD_READ,
- SD,
- diskdstate->id,
- sio,
- (int) size,
- (int) offset,
- shm_offset);
- if (x < 0) {
- debug(79, 1) ("storeDiskdSend READ: %s\n", xstrerror());
- storeDiskdShmPut(SD, shm_offset);
- storeDiskdIOCallback(sio, DISK_ERROR);
+ 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++;
+ debug(79, 3) ("storeDiskdOpenDone: status %d\n", M->status);
+ assert (FILE_MODE(mode) == O_RDONLY);
+ if (M->status < 0) {
+ diskd_stats.open.fail++;
+ errorOccured = true;
+ } else {
+ diskd_stats.open.success++;
}
- diskd_stats.read.ops++;
+ notifyClient();
}
void
-storeDiskdWrite(SwapDir * SD, storeIOState * sio, char *buf, size_t size, off_t offset, FREE * free_func)
+DiskdFile::createDone(diomsg *M) {
+ statCounter.syscalls.disk.opens++;
+ debug(79, 3) ("storeDiskdCreateDone: status %d\n", M->status);
+ if (M->status < 0) {
+ diskd_stats.create.fail++;
+ errorOccured = true;
+ } else {
+ diskd_stats.create.success++;
+ }
+ notifyClient();
+}
+
+CBDATA_CLASS_INIT(diskdstate_t);
+
+void *
+diskdstate_t::operator new (size_t)
{
- int x;
- char *sbuf;
- off_t shm_offset;
- diskdstate_t *diskdstate = (diskdstate_t *)sio->fsstate;
- debug(79, 3) ("storeDiskdWrite: dirno %d, fileno %08X\n", SD->index, sio->swap_filen);
- assert(!diskdstate->flags.close_request);
- if (!cbdataReferenceValid(sio)) {
- free_func(buf);
+ CBDATA_INIT_TYPE(diskdstate_t);
+ diskdstate_t *result = cbdataAlloc(diskdstate_t);
+ /* Mark result as being owned - we want the refcounter to do the delete
+ * call */
+ cbdataReference(result);
+ debug (0,0)("diskdstate with base %p allocating\n", result);
+ return result;
+}
+
+void
+diskdstate_t::operator delete (void *address)
+{
+ debug (0,0)("diskdstate with base %p deleting\n",address);
+ diskdstate_t *t = static_cast<diskdstate_t *>(address);
+ cbdataFree(address);
+ /* And allow the memory to be freed */
+ cbdataReferenceDone (t);
+}
+
+diskdstate_t::diskdstate_t(SwapDir *SD, StoreEntry *e_, STIOCB * callback_, void *callback_data_)
+{
+ swap_filen = e_->swap_filen;
+ swap_dirn = SD->index;
+ mode = O_BINARY;
+ callback = callback_;
+ callback_data = cbdataReference(callback_data_);
+ e = e_;
+}
+
+/*
+ * We can't pass memFree() as a free function here, because we need to free
+ * the fsdata variable ..
+ */
+diskdstate_t::~diskdstate_t()
+{
+}
+
+void
+diskdstate_t::ioCompletedNotification()
+{
+ if (opening) {
+ opening = false;
+ debug(79, 3) ("storeDiskdOpenDone: dirno %d, fileno %08x status %d\n",
+ swap_dirn, swap_filen, theFile->error());
+ assert (FILE_MODE(mode) == O_RDONLY);
+ if (theFile->error()) {
+ doCallback(DISK_ERROR);
+ }
return;
}
- diskdstate->flags.writing = 1;
- sbuf = (char *)storeDiskdShmGet(SD, &shm_offset);
+ if (creating) {
+ creating = false;
+ debug(79, 3) ("storeDiskdCreateDone: dirno %d, fileno %08x status %d\n",
+ swap_dirn, swap_filen, theFile->error());
+ if (theFile->error()) {
+ doCallback(DISK_ERROR);
+ }
+ return;
+ }
+ assert (!closing);
+ debug(79, 3) ("diskd::ioCompleted: dirno %d, fileno %08x status %d\n", swap_dirn, swap_filen, theFile->error());
+ /* Ok, notification past open means an error has occured */
+ assert (theFile->error());
+ doCallback(DISK_ERROR);
+}
+
+void
+diskdstate_t::closeCompleted()
+{
+ assert (closing);
+ debug(79, 3) ("storeDiskdCloseDone: dirno %d, fileno %08x status %d\n",
+ swap_dirn, swap_filen, theFile->error());
+ if (theFile->error()) {
+ doCallback(DISK_ERROR);
+ } else {
+ doCallback(DISK_OK);
+ }
+}
+
+void
+diskdstate_t::close()
+{
+ debug(79, 3) ("storeDiskdClose: dirno %d, fileno %08X\n", swap_dirn,
+ swap_filen);
+ closing = true;
+ ((DiskdFile *)theFile.getRaw())->close();
+}
+
+void
+DiskdFile::write(char const *buf, size_t size, off_t offset, FREE *free_func)
+{
+ off_t shm_offset;
+ char *sbuf = (char *)IO->shm.get(&shm_offset);
xmemcpy(sbuf, buf, size);
if (free_func)
- free_func(buf);
- x = storeDiskdSend(_MQD_WRITE,
- SD,
- diskdstate->id,
- sio,
+ free_func(const_cast<char *>(buf));
+ int x = storeDiskdSend(_MQD_WRITE,
+ IO,
+ id,
+ this,
(int) size,
(int) offset,
shm_offset);
if (x < 0) {
+ errorOccured = true;
debug(79, 1) ("storeDiskdSend WRITE: %s\n", xstrerror());
- storeDiskdShmPut(SD, shm_offset);
- storeDiskdIOCallback(sio, DISK_ERROR);
+ IO->shm.put (shm_offset);
+ notifyClient();
+ ioRequestor = NULL;
+ return;
}
diskd_stats.write.ops++;
}
-
+
void
-storeDiskdUnlink(SwapDir * SD, StoreEntry * e)
+DiskdSwapDir::unlink(StoreEntry & e)
{
int x;
off_t shm_offset;
char *buf;
- diskdinfo_t *diskdinfo = (diskdinfo_t *)SD->fsdata;
- debug(79, 3) ("storeDiskdUnlink: dirno %d, fileno %08X\n", SD->index,
- e->swap_filen);
- commonUfsDirReplRemove(e);
- commonUfsDirMapBitReset(SD, e->swap_filen);
- if (diskdinfo->away >= diskdinfo->magic1) {
+ debug(79, 3) ("storeDiskdUnlink: dirno %d, fileno %08X\n", index,
+ e.swap_filen);
+ replacementRemove(&e);
+ mapBitReset(e.swap_filen);
+ if (IO->shedLoad()) {
/* Damn, we need to issue a sync unlink here :( */
debug(79, 2) ("storeDiskUnlink: Out of queue space, sync unlink\n");
- commonUfsDirUnlinkFile(SD, e->swap_filen);
+ UFSSwapDir::unlinkFile(e.swap_filen);
return;
}
/* We can attempt a diskd unlink */
- buf = (char *)storeDiskdShmGet(SD, &shm_offset);
- xstrncpy(buf, commonUfsDirFullPath(SD, e->swap_filen, NULL), SHMBUF_BLKSZ);
+ buf = (char *)((DiskdIO *)IO)->shm.get(&shm_offset);
+ xstrncpy(buf, fullPath(e.swap_filen, NULL), SHMBUF_BLKSZ);
x = storeDiskdSend(_MQD_UNLINK,
- SD,
- e->swap_filen,
- NULL,
+ (DiskdIO *)IO,
+ e.swap_filen,
+ (StoreIOState::Pointer )NULL,
0,
0,
shm_offset);
if (x < 0) {
debug(79, 1) ("storeDiskdSend UNLINK: %s\n", xstrerror());
- unlink(buf); /* XXX EWW! */
- storeDiskdShmPut(SD, shm_offset);
+ ::unlink(buf); /* XXX EWW! */
+ ((DiskdIO *)IO)->shm.put (shm_offset);
}
diskd_stats.unlink.ops++;
}
/* === STATIC =========================================================== */
-static void
-storeDiskdOpenDone(diomsg * M)
-{
- storeIOState *sio = (storeIOState *)M->callback_data;
- statCounter.syscalls.disk.opens++;
- debug(79, 3) ("storeDiskdOpenDone: dirno %d, fileno %08x status %d\n",
- sio->swap_dirn, sio->swap_filen, M->status);
- if (M->status < 0) {
- FILE_MODE(sio->mode) == O_RDONLY ? diskd_stats.open.fail++ : diskd_stats.create.fail++;
- storeDiskdIOCallback(sio, DISK_ERROR);
- } else {
- FILE_MODE(sio->mode) == O_RDONLY ? diskd_stats.open.success++ : diskd_stats.create.success++;
- }
-}
-
-static void
-storeDiskdCloseDone(diomsg * M)
+void
+DiskdFile::closeDone(diomsg * M)
{
- storeIOState *sio = (storeIOState *)M->callback_data;
statCounter.syscalls.disk.closes++;
- debug(79, 3) ("storeDiskdCloseDone: dirno %d, fileno %08x status %d\n",
- sio->swap_dirn, sio->swap_filen, M->status);
+ debug(79, 3) ("storeDiskdCloseDone: status %d\n", M->status);
if (M->status < 0) {
diskd_stats.close.fail++;
- storeDiskdIOCallback(sio, DISK_ERROR);
- return;
+ errorOccured = true;
+ } else {
+ diskd_stats.close.success++;
}
- diskd_stats.close.success++;
- storeDiskdIOCallback(sio, DISK_OK);
+ if (canNotifyClient())
+ ioRequestor->closeCompleted();
+ ioRequestor = NULL;
}
-static void
-storeDiskdReadDone(diomsg * M)
+void
+DiskdFile::readDone(diomsg * M)
{
- storeIOState *sio = (storeIOState *)M->callback_data;
- STRCB *callback = sio->read.callback;
- void *cbdata;
- SwapDir *sd = INDEXSD(sio->swap_dirn);
- diskdstate_t *diskdstate = (diskdstate_t *)sio->fsstate;
- diskdinfo_t *diskdinfo = (diskdinfo_t *)sd->fsdata;
- char *their_buf = diskdstate->read_buf;
- char *sbuf;
- size_t len;
statCounter.syscalls.disk.reads++;
- diskdstate->flags.reading = 0;
- debug(79, 3) ("storeDiskdReadDone: dirno %d, fileno %08x status %d\n",
- sio->swap_dirn, sio->swap_filen, M->status);
+ debug(79, 3) ("DiskdFile::readDone: status %d\n", M->status);
+
if (M->status < 0) {
diskd_stats.read.fail++;
- storeDiskdIOCallback(sio, DISK_ERROR);
+ errorOccured = true;
+ ioRequestor->readCompleted(NULL, -1, DISK_ERROR);
return;
}
diskd_stats.read.success++;
- sbuf = diskdinfo->shm.buf + M->shm_offset;
- len = M->status;
- sio->offset += len;
+
+ ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK);
+}
+
+void
+diskdstate_t::readCompleted(const char *buf, int len, int errflag)
+{
+ reading = false;
+ debug(79, 3) ("storeDiskdReadDone: dirno %d, fileno %08x len %d\n",
+ swap_dirn, swap_filen, len);
+ if (len > 0)
+ offset_ += len;
+
+ STRCB *callback = read.callback;
assert(callback);
- sio->read.callback = NULL;
- if (cbdataReferenceValidDone(sio->read.callback_data, &cbdata)) {
- assert(!diskdstate->flags.close_request);
+ read.callback = NULL;
+ void *cbdata;
+ if (cbdataReferenceValidDone(read.callback_data, &cbdata)) {
+ assert (!closing);
/*
* Only copy the data if the callback is still valid,
* if it isn't valid then the request should have been
* aborted.
* -- adrian
*/
- xmemcpy(their_buf, sbuf, len); /* yucky copy */
- callback(cbdata, their_buf, len);
+ if (len > 0 && read_buf != buf)
+ memcpy(read_buf, buf, len);
+ callback(cbdata, read_buf, len);
}
}
-static void
-storeDiskdWriteDone(diomsg * M)
+void
+diskdstate_t::writeCompleted(int errflag, size_t len)
{
- storeIOState *sio = (storeIOState *)M->callback_data;
- diskdstate_t *diskdstate = (diskdstate_t *)sio->fsstate;
- statCounter.syscalls.disk.writes++;
- diskdstate->flags.writing = 0;
+ writing = false;
debug(79, 3) ("storeDiskdWriteDone: dirno %d, fileno %08x status %d\n",
- sio->swap_dirn, sio->swap_filen, M->status);
+ swap_dirn, swap_filen, len);
+ offset_ += len;
+ if (errflag)
+ doCallback(DISK_ERROR);
+}
+
+void
+DiskdFile::writeDone(diomsg *M)
+{
+ statCounter.syscalls.disk.writes++;
+ debug(79, 3) ("storeDiskdWriteDone: status %d\n", M->status);
if (M->status < 0) {
+ errorOccured = true;
diskd_stats.write.fail++;
- storeDiskdIOCallback(sio, DISK_ERROR);
+ ioRequestor->writeCompleted (DISK_ERROR,0);
return;
}
diskd_stats.write.success++;
- sio->offset += M->status;
+ ioRequestor->writeCompleted (DISK_OK,M->status);
}
static void
void
storeDiskdHandle(diomsg * M)
{
- if (cbdataReferenceValid(M->callback_data)) {
- switch (M->mtype) {
+ if (!cbdataReferenceValid (M->callback_data)) {
+ debug(79, 3) ("storeDiskdHandle: Invalid callback_data %p\n",
+ M->callback_data);
+ cbdataReferenceDone (M->callback_data);
+ return;
+ }
+
+
+ if (M->newstyle) {
+ DiskdFile *theFile = (DiskdFile *)M->callback_data;
+ theFile->completed (M);
+ } else
+ switch (M->mtype) {
case _MQD_OPEN:
- storeDiskdOpenDone(M);
- break;
+ case _MQD_CREATE:
case _MQD_CLOSE:
- storeDiskdCloseDone(M);
- break;
case _MQD_READ:
- storeDiskdReadDone(M);
- break;
case _MQD_WRITE:
- storeDiskdWriteDone(M);
+ assert (0);
break;
case _MQD_UNLINK:
storeDiskdUnlinkDone(M);
assert(0);
break;
}
- } else {
- debug(79, 3) ("storeDiskdHandle: Invalid callback_data %p\n",
- M->callback_data);
- /*
- * The read operation has its own callback. If we don't
- * call storeDiskdReadDone(), then we must make sure the
- * callback_data gets unlocked!
- */
- if (_MQD_READ == M->mtype) {
- /* XXX This cannot be the correct approach. This
- * is most likely the wrong place for this. It should
- * be done before the sio becomes invalid, not here.
- */
- storeIOState *sio = (storeIOState *)M->callback_data;
- cbdataReferenceDone(sio->read.callback_data);
- }
- }
- cbdataReferenceDone(M->callback_data);
+ cbdataReferenceDone (M->callback_data);
}
-static void
-storeDiskdIOCallback(storeIOState * sio, int errflag)
+void
+diskdstate_t::doCallback(int errflag)
{
+ if (!this || !cbdataReferenceValid(this)) {
+ debug (79, 0) ("storeDiskdIOCallback: invalid siocb %p\n",this);
+ return;
+ }
void *cbdata;
- STIOCB *callback = sio->callback;
+ STIOCB *theCallback = callback;
debug(79, 3) ("storeUfsIOCallback: errflag=%d\n", errflag);
- sio->callback = NULL;
- if (cbdataReferenceValidDone(sio->callback_data, &cbdata))
- callback(cbdata, errflag, sio);
- cbdataFree(sio);
+ callback = NULL;
+ if (cbdataReferenceValidDone(callback_data, &cbdata) && theCallback)
+ theCallback(cbdata, errflag, this);
}
-static int
-storeDiskdSend(int mtype, SwapDir * sd, int id, storeIOState * sio, int size, int offset, off_t shm_offset)
+int
+storeDiskdSend(int mtype, DiskdIO *IO, int id, DiskdFile *theFile, int size, int offset, off_t shm_offset)
{
int x;
diomsg M;
static int send_errors = 0;
static int last_seq_no = 0;
static int seq_no = 0;
- diskdinfo_t *diskdinfo = (diskdinfo_t *)sd->fsdata;
M.mtype = mtype;
- M.callback_data = cbdataReference(sio);
+ M.callback_data = cbdataReference(theFile);
M.size = size;
M.offset = offset;
M.status = -1;
M.shm_offset = (int) shm_offset;
M.id = id;
M.seq_no = ++seq_no;
+ M.newstyle = true;
if (M.seq_no < last_seq_no)
debug(79, 1) ("WARNING: sequencing out of order\n");
- x = msgsnd(diskdinfo->smsgid, &M, msg_snd_rcv_sz, IPC_NOWAIT);
+ x = msgsnd(IO->smsgid, &M, msg_snd_rcv_sz, IPC_NOWAIT);
last_seq_no = M.seq_no;
if (0 == x) {
diskd_stats.sent_count++;
- diskdinfo->away++;
+ IO->away++;
} else {
debug(79, 1) ("storeDiskdSend: msgsnd: %s\n", xstrerror());
cbdataReferenceDone(M.callback_data);
assert(++send_errors < 100);
+ IO->shm.put (shm_offset);
}
/*
* We have to drain the queue here if necessary. If we don't,
* we're "blocking" on this SD we can also handle callbacks
* from other SDs that might be ready.
*/
- while (diskdinfo->away > diskdinfo->magic2) {
+ while (IO->away > IO->magic2) {
struct timeval delay =
{0, 1};
select(0, NULL, NULL, NULL, &delay);
return x;
}
-
-/*
- * We can't pass memFree() as a free function here, because we need to free
- * the fsstate variable ..
- */
-static void
-storeDiskdIOFreeEntry(void *sio)
+static int
+storeDiskdSend(int mtype, DiskdIO *IO, int id, StoreIOState::Pointer sio, int size, int offset, off_t shm_offset)
{
- memPoolFree(diskd_state_pool, ((storeIOState *) sio)->fsstate);
+ int x;
+ diomsg M;
+ static int send_errors = 0;
+ static int last_seq_no = 0;
+ static int seq_no = 0;
+ M.mtype = mtype;
+ M.callback_data = cbdataReference(sio.getRaw());
+ M.size = size;
+ M.offset = offset;
+ M.status = -1;
+ M.shm_offset = (int) shm_offset;
+ M.id = id;
+ M.seq_no = ++seq_no;
+ M.newstyle = false;
+ if (M.seq_no < last_seq_no)
+ debug(79, 1) ("WARNING: sequencing out of order\n");
+ x = msgsnd(IO->smsgid, &M, msg_snd_rcv_sz, IPC_NOWAIT);
+ last_seq_no = M.seq_no;
+ if (0 == x) {
+ diskd_stats.sent_count++;
+ IO->away++;
+ } else {
+ debug(79, 1) ("storeDiskdSend: msgsnd: %s\n", xstrerror());
+ cbdataReferenceDone(M.callback_data);
+ assert(++send_errors < 100);
+ }
+ /*
+ * We have to drain the queue here if necessary. If we don't,
+ * then we can have a lot of messages in the queue (probably
+ * up to 2*magic1) and we can run out of shared memory buffers.
+ */
+ /*
+ * Note that we call storeDirCallback (for all SDs), rather
+ * than storeDiskdDirCallback for just this SD, so that while
+ * we're "blocking" on this SD we can also handle callbacks
+ * from other SDs that might be ready.
+ */
+ while (IO->away > IO->magic2) {
+ struct timeval delay =
+ {0, 1};
+ select(0, NULL, NULL, NULL, &delay);
+ storeDirCallback();
+ if (delay.tv_usec < 1000000)
+ delay.tv_usec <<= 1;
+ }
+ return x;
}
+
+
/*
- * $Id: store_null.cc,v 1.3 2002/04/16 22:43:05 wessels Exp $
+ * $Id: store_null.cc,v 1.4 2002/12/27 10:26:38 robertc Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
#include <sys/statvfs.h>
#endif
#endif
+#include "SwapDir.h"
+#include "Store.h"
+
+class NullSwapDir : public SwapDir
+{
+public:
+ virtual void init();
+ virtual int canStore(StoreEntry const &)const;
+ virtual StoreIOState::Pointer createStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
+ virtual StoreIOState::Pointer openStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
+ virtual void parse(int, char*);
+ virtual void reconfigure (int, char *);
+};
static int null_initialised = 0;
-static void storeNullDirInit(SwapDir * sd);
-static void storeNullDirStats(SwapDir * SD, StoreEntry * sentry);
-static STCHECKOBJ storeNullDirCheckObj;
-static STFSRECONFIGURE storeNullDirReconfigure;
-static STLOGCLEANSTART storeNullDirWriteCleanStart;
-static STLOGCLEANDONE storeNullDirWriteCleanDone;
static EVH storeNullDirRebuildComplete;
/* The only externally visible interface */
STSETUP storeFsSetup_null;
-static void
-storeNullDirReconfigure(SwapDir * sd, int index, char *path)
+void
+NullSwapDir::reconfigure(int index, char *path)
{
(void) 0;
}
null_initialised = 0;
}
-static void
-storeNullDirStats(SwapDir * SD, StoreEntry * sentry)
+static SwapDir *
+storeNullNew(void)
{
- (void) 0;
+ SwapDir *result = new NullSwapDir;
+ return result;
}
-static void
-storeNullDirInit(SwapDir * sd)
+void
+NullSwapDir::init()
{
store_dirs_rebuilding++;
eventAdd("storeNullDirRebuildComplete", storeNullDirRebuildComplete,
NULL, 0.0, 1);
}
+StoreIOState::Pointer
+NullSwapDir::createStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *)
+{
+ fatal ("Attempt to get a StoreIO from the NULL store!\n");
+ return NULL;
+}
+
+StoreIOState::Pointer
+NullSwapDir::openStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *)
+{
+ fatal ("Attempt to get a StoreIO from the NULL store!\n");
+ return NULL;
+}
+
static void
storeNullDirRebuildComplete(void *unused)
{
storeRebuildComplete(&counts);
}
-static int
-storeNullDirCheckObj(SwapDir * SD, const StoreEntry * e)
+int
+NullSwapDir::canStore(StoreEntry const &)const
{
return -1;
}
-static int
-storeNullDirWriteCleanStart(SwapDir * unused)
-{
- return 0;
-}
-
-static void
-storeNullDirWriteCleanDone(SwapDir * unused)
-{
- (void) 0;
-}
-
-static void
-storeNullDirParse(SwapDir * sd, int index, char *path)
+void
+NullSwapDir::parse(int anIndex, char *aPath)
{
- sd->index = index;
- sd->path = xstrdup(path);
- sd->statfs = storeNullDirStats;
- sd->init = storeNullDirInit;
- sd->checkobj = storeNullDirCheckObj;
- sd->log.clean.start = storeNullDirWriteCleanStart;
- sd->log.clean.done = storeNullDirWriteCleanDone;
- parse_cachedir_options(sd, NULL, 0);
+ index = anIndex;
+ path = xstrdup(aPath);
+ parse_cachedir_options(this, NULL, 0);
}
/* Setup and register the store module */
storeFsSetup_null(storefs_entry_t * storefs)
{
assert(!null_initialised);
- storefs->parsefunc = storeNullDirParse;
- storefs->reconfigurefunc = storeNullDirReconfigure;
storefs->donefunc = storeNullDirDone;
+ storefs->newfunc = storeNullNew;
null_initialised = 1;
}
/*
- * $Id: store_dir_ufs.cc,v 1.51 2002/10/13 20:35:27 robertc Exp $
+ * $Id: store_dir_ufs.cc,v 1.52 2002/12/27 10:26:39 robertc Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
#include "store_ufs.h"
#include "ufscommon.h"
-MemPool *ufs_state_pool = NULL;
+#include "SwapDir.h"
static int ufs_initialised = 0;
-static STDUMP storeUfsDirDump;
-static STCHECKOBJ storeUfsDirCheckObj;
-static void storeUfsDirIOUnlinkFile(char *path);
+int UFSSwapDir::NumberOfUFSDirs = 0;
+int *UFSSwapDir::UFSDirToGlobalDirMapping = NULL;
STSETUP storeFsSetup_ufs;
* happily store anything as long as the LRU time isn't too small.
*/
int
-storeUfsDirCheckObj(SwapDir * SD, const StoreEntry * e)
+UfsSwapDir::canStore(StoreEntry const &e)const
{
/* Return 999 (99.9%) constant load */
return 999;
}
void
-storeUfsDirIOUnlinkFile(char *path)
+UfsSwapDir::unlinkFile(char const *path)
{
#if USE_UNLINKD
unlinkdUnlink(path);
*
* This routine is called when the given swapdir needs reconfiguring
*/
-static void
-storeUfsDirReconfigure(SwapDir * sd, int index, char *path)
+void
+UfsSwapDir::reconfigure(int anIndex, char *aPath)
+{
+ UFSSwapDir::reconfigure (anIndex, aPath);
+ parse_cachedir_options(this, options, 1);
+}
+
+void
+UFSSwapDir::reconfigure(int index, char *path)
{
int i;
int size;
- int l1;
- int l2;
i = GetInteger();
size = i << 10; /* Mbytes to kbytes */
if (size <= 0)
- fatal("storeUfsDirReconfigure: invalid size value");
- i = GetInteger();
- l1 = i;
+ fatal("storeDiskdDirReconfigure: invalid size value");
+ l1 = GetInteger();
if (l1 <= 0)
- fatal("storeUfsDirReconfigure: invalid level 1 directories value");
- i = GetInteger();
- l2 = i;
+ fatal("storeDiskdDirReconfigure: invalid level 1 directories value");
+ l2 = GetInteger();
if (l2 <= 0)
- fatal("storeUfsDirReconfigure: invalid level 2 directories value");
+ fatal("storeDiskdDirReconfigure: invalid level 2 directories value");
/* just reconfigure it */
- if (size == sd->max_size)
+ if (size == max_size)
debug(3, 1) ("Cache dir '%s' size remains unchanged at %d KB\n",
path, size);
else
debug(3, 1) ("Cache dir '%s' size changed to %d KB\n",
path, size);
- sd->max_size = size;
-
- parse_cachedir_options(sd, options, 1);
+ max_size = size;
}
void
-storeUfsDirDump(StoreEntry * entry, SwapDir * s)
+UfsSwapDir::dump(StoreEntry & entry)const
{
- commonUfsDirDump (entry, s);
- dump_cachedir_options(entry, options, s);
+ UFSSwapDir::dump (entry);
+ dump_cachedir_options(&entry, options, this);
}
/*
*
* Called when a *new* fs is being setup.
*/
-static void
-storeUfsDirParse(SwapDir * sd, int index, char *path)
+void
+UfsSwapDir::parse(int anIndex, char *aPath)
{
- int i;
- int size;
- int l1;
- int l2;
- squidufsinfo_t *ufsinfo;
+ UFSSwapDir::parse (anIndex, aPath);
- i = GetInteger();
- size = i << 10; /* Mbytes to kbytes */
- if (size <= 0)
- fatal("storeUfsDirParse: invalid size value");
- i = GetInteger();
- l1 = i;
+ parse_cachedir_options(this, options, 1);
+}
+
+void
+UFSSwapDir::parse (int anIndex, char *aPath)
+{
+ max_size = GetInteger() << 10; /* Mbytes to kbytes */
+ if (max_size <= 0)
+ fatal("storeAufsDirParse: invalid size value");
+ l1 = GetInteger();
if (l1 <= 0)
- fatal("storeUfsDirParse: invalid level 1 directories value");
- i = GetInteger();
- l2 = i;
+ fatal("storeAufsDirParse: invalid level 1 directories value");
+ l2 = GetInteger();
if (l2 <= 0)
- fatal("storeUfsDirParse: invalid level 2 directories value");
-
- ufsinfo = (squidufsinfo_t *)xmalloc(sizeof(squidufsinfo_t));
- if (ufsinfo == NULL)
- fatal("storeUfsDirParse: couldn't xmalloc() squidufsinfo_t!\n");
-
- sd->index = index;
- sd->path = xstrdup(path);
- sd->max_size = size;
- sd->fsdata = ufsinfo;
- ufsinfo->l1 = l1;
- ufsinfo->l2 = l2;
- ufsinfo->swaplog_fd = -1;
- ufsinfo->map = NULL; /* Debugging purposes */
- ufsinfo->suggest = 0;
- ufsinfo->io.storeDirUnlinkFile = storeUfsDirIOUnlinkFile;
- sd->init = commonUfsDirInit;
- sd->newfs = commonUfsDirNewfs;
- sd->dump = storeUfsDirDump;
- sd->freefs = commonUfsDirFree;
- sd->dblcheck = commonUfsCleanupDoubleCheck;
- sd->statfs = commonUfsDirStats;
- sd->maintainfs = commonUfsDirMaintain;
- sd->checkobj = storeUfsDirCheckObj;
- sd->refobj = commonUfsDirRefObj;
- sd->unrefobj = commonUfsDirUnrefObj;
- sd->callback = NULL;
- sd->sync = NULL;
- sd->obj.create = storeUfsCreate;
- sd->obj.open = storeUfsOpen;
- sd->obj.close = storeUfsClose;
- sd->obj.read = storeUfsRead;
- sd->obj.write = storeUfsWrite;
- sd->obj.unlink = storeUfsUnlink;
- sd->log.open = commonUfsDirOpenSwapLog;
- sd->log.close = commonUfsDirCloseSwapLog;
- sd->log.write = commonUfsDirSwapLog;
- sd->log.clean.start = commonUfsDirWriteCleanStart;
- sd->log.clean.nextentry = commonUfsDirCleanLogNextEntry;
- sd->log.clean.done = commonUfsDirWriteCleanDone;
-
- parse_cachedir_options(sd, options, 1);
+ fatal("storeAufsDirParse: invalid level 2 directories value");
+
+ index = anIndex;
+ path = xstrdup(aPath);
/* Initialise replacement policy stuff */
- sd->repl = createRemovalPolicy(Config.replPolicy);
+ repl = createRemovalPolicy(Config.replPolicy);
}
/*
* Initial setup / end destruction
*/
+void
+UFSSwapDir::init()
+{
+ static int started_clean_event = 0;
+ static const char *errmsg =
+ "\tFailed to verify one of the swap directories, Check cache.log\n"
+ "\tfor details. Run 'squid -z' to create swap directories\n"
+ "\tif needed, or if running Squid for the first time.";
+ initBitmap();
+ if (verifyCacheDirs())
+ fatal(errmsg);
+ openLog();
+ rebuild();
+ if (!started_clean_event) {
+ eventAdd("UFS storeDirClean", CleanEvent, NULL, 15.0, 1);
+ started_clean_event = 1;
+ }
+ (void) storeDirGetBlkSize(path, &fs.blksize);
+}
+
+void
+UFSSwapDir::newFileSystem()
+{
+ debug(47, 3) ("Creating swap space in %s\n", path);
+ createDirectory(path, 0);
+ createSwapSubDirs();
+}
+
+UFSSwapDir::UFSSwapDir() : IO(NULL), map(NULL), suggest(0), swaplog_fd (-1) {}
+
+UFSSwapDir::~UFSSwapDir()
+{
+ if (swaplog_fd > -1) {
+ file_close(swaplog_fd);
+ swaplog_fd = -1;
+ }
+ filemapFreeMemory(map);
+ if (IO)
+ IO->deleteSelf();
+ IO = NULL;
+}
+
static void
storeUfsDirDone(void)
{
- memPoolDestroy(&ufs_state_pool);
ufs_initialised = 0;
}
+static SwapDir *
+storeUfsNew(void)
+{
+ UfsSwapDir *result = new UfsSwapDir;
+ result->IO = &UfsIO::Instance;
+ return result;
+}
+
void
storeFsSetup_ufs(storefs_entry_t * storefs)
{
assert(!ufs_initialised);
- storefs->parsefunc = storeUfsDirParse;
- storefs->reconfigurefunc = storeUfsDirReconfigure;
storefs->donefunc = storeUfsDirDone;
- ufs_state_pool = memPoolCreate("UFS IO State data", sizeof(ufsstate_t));
+ storefs->newfunc = storeUfsNew;
ufs_initialised = 1;
}
+
+void
+UFSSwapDir::dumpEntry(StoreEntry &e) const
+{
+ debug(47, 0) ("UFSSwapDir::dumpEntry: FILENO %08X\n", e.swap_filen);
+ debug(47, 0) ("UFSSwapDir::dumpEntry: PATH %s\n",
+ fullPath(e.swap_filen, NULL));
+ storeEntryDump(&e, 0);
+}
+
+/*
+ * UFSSwapDir::doubleCheck
+ *
+ * This is called by storeCleanup() if -S was given on the command line.
+ */
+bool
+UFSSwapDir::doubleCheck(StoreEntry & e)
+{
+ struct stat sb;
+ if (stat(fullPath(e.swap_filen, NULL), &sb) < 0) {
+ debug(47, 0) ("UFSSwapDir::doubleCheck: MISSING SWAP FILE\n");
+ dumpEntry(e);
+ return true;
+ }
+ if ((off_t)e.swap_file_sz != sb.st_size) {
+ debug(47, 0) ("UFSSwapDir::doubleCheck: SIZE MISMATCH\n");
+ debug(47, 0) ("UFSSwapDir::doubleCheck: ENTRY SIZE: %ld, FILE SIZE: %ld\n",
+ (long int) e.swap_file_sz, (long int) sb.st_size);
+ dumpEntry(e);
+ return true;
+ }
+ return false;
+}
+
+void
+UFSSwapDir::statfs(StoreEntry & sentry) const
+{
+ int totl_kb = 0;
+ int free_kb = 0;
+ int totl_in = 0;
+ int free_in = 0;
+ int x;
+ storeAppendPrintf(&sentry, "First level subdirectories: %d\n", l1);
+ storeAppendPrintf(&sentry, "Second level subdirectories: %d\n", l2);
+ storeAppendPrintf(&sentry, "Maximum Size: %d KB\n", max_size);
+ storeAppendPrintf(&sentry, "Current Size: %d KB\n", cur_size);
+ storeAppendPrintf(&sentry, "Percent Used: %0.2f%%\n",
+ 100.0 * cur_size / max_size);
+ storeAppendPrintf(&sentry, "Filemap bits in use: %d of %d (%d%%)\n",
+ map->n_files_in_map, map->max_n_files,
+ percent(map->n_files_in_map, map->max_n_files));
+ x = storeDirGetUFSStats(path, &totl_kb, &free_kb, &totl_in, &free_in);
+ if (0 == x) {
+ storeAppendPrintf(&sentry, "Filesystem Space in use: %d/%d KB (%d%%)\n",
+ totl_kb - free_kb,
+ totl_kb,
+ percent(totl_kb - free_kb, totl_kb));
+ storeAppendPrintf(&sentry, "Filesystem Inodes in use: %d/%d (%d%%)\n",
+ totl_in - free_in,
+ totl_in,
+ percent(totl_in - free_in, totl_in));
+ }
+ storeAppendPrintf(&sentry, "Flags:");
+ if (flags.selected)
+ storeAppendPrintf(&sentry, " SELECTED");
+ if (flags.read_only)
+ storeAppendPrintf(&sentry, " READ-ONLY");
+ storeAppendPrintf(&sentry, "\n");
+}
+
+void
+UFSSwapDir::maintainfs()
+{
+ StoreEntry *e = NULL;
+ int removed = 0;
+ int max_scan;
+ int max_remove;
+ double f;
+ RemovalPurgeWalker *walker;
+ /* We can't delete objects while rebuilding swap */
+ if (store_dirs_rebuilding) {
+ return;
+ } else {
+ f = (double) (cur_size - low_size) / (max_size - low_size);
+ f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f;
+ max_scan = (int) (f * 400.0 + 100.0);
+ max_remove = (int) (f * 70.0 + 10.0);
+ /*
+ * This is kinda cheap, but so we need this priority hack?
+ */
+ }
+ debug(47, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n",
+ f, max_scan, max_remove);
+ walker = repl->PurgeInit(repl, max_scan);
+ while (1) {
+ if (cur_size < low_size)
+ break;
+ if (removed >= max_remove)
+ break;
+ e = walker->Next(walker);
+ if (!e)
+ break; /* no more objects */
+ removed++;
+ storeRelease(e);
+ }
+ walker->Done(walker);
+ debug(47, (removed ? 2 : 3)) ("UFSSwapDir::maintainfs: %s removed %d/%d f=%.03f max_scan=%d\n",
+ path, removed, max_remove, f, max_scan);
+}
+
+/*
+ * UFSSwapDir::reference
+ *
+ * This routine is called whenever an object is referenced, so we can
+ * maintain replacement information within the storage fs.
+ */
+void
+UFSSwapDir::reference(StoreEntry &e)
+{
+ debug(47, 3) ("UFSSwapDir::reference: referencing %p %d/%d\n", &e, e.swap_dirn,
+ e.swap_filen);
+ if (repl->Referenced)
+ repl->Referenced(repl, &e, &e.repl);
+}
+
+/*
+ * UFSSwapDir::dereference
+ * This routine is called whenever the last reference to an object is
+ * removed, to maintain replacement information within the storage fs.
+ */
+void
+UFSSwapDir::dereference(StoreEntry & e)
+{
+ debug(47, 3) ("UFSSwapDir::dereference: referencing %p %d/%d\n", &e, e.swap_dirn,
+ e.swap_filen);
+ if (repl->Dereferenced)
+ repl->Dereferenced(repl, &e, &e.repl);
+}
+
+StoreIOState::Pointer
+UFSSwapDir::createStoreIO(StoreEntry &e, STFNCB * file_callback, STIOCB * callback, void *callback_data)
+{
+ return IO->create (this, &e, file_callback, callback, callback_data);
+}
+
+StoreIOState::Pointer
+UFSSwapDir::openStoreIO(StoreEntry &e, STFNCB * file_callback, STIOCB * callback, void *callback_data)
+{
+ return IO->open (this, &e, file_callback, callback, callback_data);
+}
+
+int
+UFSSwapDir::mapBitTest(sfileno filn)
+{
+ return file_map_bit_test(map, filn);
+}
+
+void
+UFSSwapDir::mapBitSet(sfileno filn)
+{
+ file_map_bit_set(map, filn);
+}
+
+void
+UFSSwapDir::mapBitReset(sfileno filn)
+{
+ /*
+ * We have to test the bit before calling file_map_bit_reset.
+ * file_map_bit_reset doesn't do bounds checking. It assumes
+ * filn is a valid file number, but it might not be because
+ * the map is dynamic in size. Also clearing an already clear
+ * bit puts the map counter of-of-whack.
+ */
+ if (file_map_bit_test(map, filn))
+ file_map_bit_reset(map, filn);
+}
+
+int
+UFSSwapDir::mapBitAllocate()
+{
+ int fn;
+ fn = file_map_allocate(map, suggest);
+ file_map_bit_set(map, fn);
+ suggest = fn + 1;
+ return fn;
+}
+
+/*
+ * Initialise the asyncufs bitmap
+ *
+ * If there already is a bitmap, and the numobjects is larger than currently
+ * configured, we allocate a new bitmap and 'grow' the old one into it.
+ */
+void
+UFSSwapDir::initBitmap()
+{
+ if (map == NULL) {
+ /* First time */
+ map = file_map_create();
+ } else if (map->max_n_files) {
+ /* it grew, need to expand */
+ /* XXX We don't need it anymore .. */
+ }
+ /* else it shrunk, and we leave the old one in place */
+}
+
+char *
+UFSSwapDir::swapSubDir(int subdirn)const
+{
+ LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN);
+ assert(0 <= subdirn && subdirn < l1);
+ snprintf(fullfilename, SQUID_MAXPATHLEN, "%s/%02X", path, subdirn);
+ return fullfilename;
+}
+
+int
+UFSSwapDir::createDirectory(const char *path, int should_exist)
+{
+ int created = 0;
+ struct stat st;
+ getCurrentTime();
+ if (0 == stat(path, &st)) {
+ if (S_ISDIR(st.st_mode)) {
+ debug(47, should_exist ? 3 : 1) ("%s exists\n", path);
+ } else {
+ fatalf("Swap directory %s is not a directory.", path);
+ }
+#ifdef _SQUID_MSWIN_
+ } else if (0 == mkdir(path)) {
+#else
+ } else if (0 == mkdir(path, 0755)) {
+#endif
+ debug(47, should_exist ? 1 : 3) ("%s created\n", path);
+ created = 1;
+ } else {
+ fatalf("Failed to make swap directory %s: %s",
+ path, xstrerror());
+ }
+ return created;
+}
+
+bool
+UFSSwapDir::pathIsDirectory(const char *path)const
+{
+ struct stat sb;
+ if (stat(path, &sb) < 0) {
+ debug(47, 0) ("%s: %s\n", path, xstrerror());
+ return false;
+ }
+ if (S_ISDIR(sb.st_mode) == 0) {
+ debug(47, 0) ("%s is not a directory\n", path);
+ return false;
+ }
+ return true;
+}
+
+/*
+ * This function is called by commonUfsDirInit(). If this returns < 0,
+ * then Squid exits, complains about swap directories not
+ * existing, and instructs the admin to run 'squid -z'
+ */
+bool
+UFSSwapDir::verifyCacheDirs()
+{
+ if (!pathIsDirectory(path))
+ return true;
+ for (int j = 0; j < l1; j++) {
+ char const *aPath = swapSubDir(j);
+ if (!pathIsDirectory(aPath))
+ return true;
+ }
+ return false;
+}
+
+void
+UFSSwapDir::createSwapSubDirs()
+{
+ int i, k;
+ int should_exist;
+ LOCAL_ARRAY(char, name, MAXPATHLEN);
+ for (i = 0; i < l1; i++) {
+ snprintf(name, MAXPATHLEN, "%s/%02X", path, i);
+ if (createDirectory(name, 0))
+ should_exist = 0;
+ else
+ should_exist = 1;
+ debug(47, 1) ("Making directories in %s\n", name);
+ for (k = 0; k < l2; k++) {
+ snprintf(name, MAXPATHLEN, "%s/%02X/%02X", path, i, k);
+ createDirectory(name, should_exist);
+ }
+ }
+}
+
+char *
+UFSSwapDir::logFile(char const *ext) const
+{
+ LOCAL_ARRAY(char, lpath, SQUID_MAXPATHLEN);
+ LOCAL_ARRAY(char, pathtmp, SQUID_MAXPATHLEN);
+ LOCAL_ARRAY(char, digit, 32);
+ char *pathtmp2;
+ if (Config.Log.swap) {
+ xstrncpy(pathtmp, path, SQUID_MAXPATHLEN - 64);
+ pathtmp2 = pathtmp;
+ while ((pathtmp2 = strchr(pathtmp2, '/')) != NULL)
+ *pathtmp2 = '.';
+ while (strlen(pathtmp) && pathtmp[strlen(pathtmp) - 1] == '.')
+ pathtmp[strlen(pathtmp) - 1] = '\0';
+ for (pathtmp2 = pathtmp; *pathtmp2 == '.'; pathtmp2++);
+ snprintf(lpath, SQUID_MAXPATHLEN - 64, Config.Log.swap, pathtmp2);
+ if (strncmp(lpath, Config.Log.swap, SQUID_MAXPATHLEN - 64) == 0) {
+ strcat(lpath, ".");
+ snprintf(digit, 32, "%02d", index);
+ strncat(lpath, digit, 3);
+ }
+ } else {
+ xstrncpy(lpath, path, SQUID_MAXPATHLEN - 64);
+ strcat(lpath, "/swap.state");
+ }
+ if (ext)
+ strncat(lpath, ext, 16);
+ return lpath;
+}
+
+void
+UFSSwapDir::openLog()
+{
+ char *logPath;
+ logPath = logFile();
+ swaplog_fd = file_open(logPath, O_WRONLY | O_CREAT | O_BINARY);
+ if (swaplog_fd < 0) {
+ debug(50, 1) ("%s: %s\n", logPath, xstrerror());
+ fatal("commonUfsDirOpenSwapLog: Failed to open swap log.");
+ }
+ debug(50, 3) ("Cache Dir #%d log opened on FD %d\n", index, swaplog_fd);
+ if (0 == NumberOfUFSDirs)
+ assert(NULL == UFSDirToGlobalDirMapping);
+ ++NumberOfUFSDirs;
+ assert(NumberOfUFSDirs <= Config.cacheSwap.n_configured);
+}
+
+void
+UFSSwapDir::closeLog()
+{
+ if (swaplog_fd < 0) /* not open */
+ return;
+ file_close(swaplog_fd);
+ debug(47, 3) ("Cache Dir #%d log closed on FD %d\n",
+ index, swaplog_fd);
+ swaplog_fd = -1;
+ NumberOfUFSDirs--;
+ assert(NumberOfUFSDirs >= 0);
+ if (0 == NumberOfUFSDirs)
+ safe_free(UFSDirToGlobalDirMapping);
+}
+
+bool
+UFSSwapDir::validL1(int anInt) const
+{
+ return anInt < l1;
+}
+
+bool
+UFSSwapDir::validL2(int anInt) const
+{
+ return anInt < l2;
+}
+
+/* Add a new object to the cache with empty memory copy and pointer to disk
+ * use to rebuild store from disk. */
+StoreEntry *
+UFSSwapDir::addDiskRestore(const cache_key * key,
+ sfileno file_number,
+ size_t swap_file_sz,
+ time_t expires,
+ time_t timestamp,
+ time_t lastref,
+ time_t lastmod,
+ u_int32_t refcount,
+ u_int16_t flags,
+ int clean)
+{
+ StoreEntry *e = NULL;
+ debug(47, 5) ("commonUfsAddDiskRestore: %s, fileno=%08X\n", storeKeyText(key), file_number);
+ /* if you call this you'd better be sure file_number is not
+ * already in use! */
+ e = new_StoreEntry(STORE_ENTRY_WITHOUT_MEMOBJ, NULL, NULL);
+ e->store_status = STORE_OK;
+ storeSetMemStatus(e, NOT_IN_MEMORY);
+ e->swap_status = SWAPOUT_DONE;
+ e->swap_filen = file_number;
+ e->swap_dirn = index;
+ e->swap_file_sz = swap_file_sz;
+ e->lock_count = 0;
+ e->lastref = lastref;
+ e->timestamp = timestamp;
+ e->expires = expires;
+ e->lastmod = lastmod;
+ e->refcount = refcount;
+ e->flags = flags;
+ EBIT_SET(e->flags, ENTRY_CACHABLE);
+ EBIT_CLR(e->flags, RELEASE_REQUEST);
+ EBIT_CLR(e->flags, KEY_PRIVATE);
+ e->ping_status = PING_NONE;
+ EBIT_CLR(e->flags, ENTRY_VALIDATED);
+ mapBitSet(e->swap_filen);
+ storeHashInsert(e, key); /* do it after we clear KEY_PRIVATE */
+ replacementAdd (e);
+ return e;
+}
+
+void
+UFSSwapDir::rebuild()
+{
+ int clean = 0;
+ int zero = 0;
+ FILE *fp;
+ EVH *func = NULL;
+ RebuildState *rb = new RebuildState;
+ rb->sd = this;
+ rb->speed = opt_foreground_rebuild ? 1 << 30 : 50;
+ /*
+ * If the swap.state file exists in the cache_dir, then
+ * we'll use commonUfsDirRebuildFromSwapLog(), otherwise we'll
+ * use commonUfsDirRebuildFromDirectory() to open up each file
+ * and suck in the meta data.
+ */
+ fp = openTmpSwapLog(&clean, &zero);
+ if (fp == NULL || zero) {
+ if (fp != NULL)
+ fclose(fp);
+ func = RebuildState::RebuildFromDirectory;
+ } else {
+ func = RebuildState::RebuildFromSwapLog;
+ rb->log = fp;
+ rb->flags.clean = (unsigned int) clean;
+ }
+ if (!clean)
+ rb->flags.need_to_validate = 1;
+ debug(47, 1) ("Rebuilding storage in %s (%s)\n",
+ path, clean ? "CLEAN" : "DIRTY");
+ store_dirs_rebuilding++;
+ eventAdd("storeRebuild", func, rb, 0.0, 1);
+}
+
+void
+UFSSwapDir::closeTmpSwapLog()
+{
+ char *swaplog_path = xstrdup(logFile(NULL));
+ char *new_path = xstrdup(logFile(".new"));
+ int fd;
+ file_close(swaplog_fd);
+#if defined (_SQUID_OS2_) || defined (_SQUID_CYGWIN_) || defined(_SQUID_MSWIN_)
+ if (unlink(swaplog_path) < 0) {
+ debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror());
+ fatal("commonUfsDirCloseTmpSwapLog: unlink failed");
+ }
+#endif
+ if (xrename(new_path, swaplog_path) < 0) {
+ fatal("commonUfsDirCloseTmpSwapLog: rename failed");
+ }
+ fd = file_open(swaplog_path, O_WRONLY | O_CREAT | O_BINARY);
+ if (fd < 0) {
+ debug(50, 1) ("%s: %s\n", swaplog_path, xstrerror());
+ fatal("commonUfsDirCloseTmpSwapLog: Failed to open swap log.");
+ }
+ safe_free(swaplog_path);
+ safe_free(new_path);
+ swaplog_fd = fd;
+ debug(47, 3) ("Cache Dir #%d log opened on FD %d\n", index, fd);
+}
+
+FILE *
+UFSSwapDir::openTmpSwapLog(int *clean_flag, int *zero_flag)
+{
+ char *swaplog_path = xstrdup(logFile(NULL));
+ char *clean_path = xstrdup(logFile(".last-clean"));
+ char *new_path = xstrdup(logFile(".new"));
+ struct stat log_sb;
+ struct stat clean_sb;
+ FILE *fp;
+ int fd;
+ if (stat(swaplog_path, &log_sb) < 0) {
+ debug(47, 1) ("Cache Dir #%d: No log file\n", index);
+ safe_free(swaplog_path);
+ safe_free(clean_path);
+ safe_free(new_path);
+ return NULL;
+ }
+ *zero_flag = log_sb.st_size == 0 ? 1 : 0;
+ /* close the existing write-only FD */
+ if (swaplog_fd >= 0)
+ file_close(swaplog_fd);
+ /* open a write-only FD for the new log */
+ fd = file_open(new_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
+ if (fd < 0) {
+ debug(50, 1) ("%s: %s\n", new_path, xstrerror());
+ fatal("storeDirOpenTmpSwapLog: Failed to open swap log.");
+ }
+ swaplog_fd = fd;
+ /* open a read-only stream of the old log */
+ fp = fopen(swaplog_path, "rb");
+ if (fp == NULL) {
+ debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror());
+ fatal("Failed to open swap log for reading");
+ }
+ memset(&clean_sb, '\0', sizeof(struct stat));
+ if (stat(clean_path, &clean_sb) < 0)
+ *clean_flag = 0;
+ else if (clean_sb.st_mtime < log_sb.st_mtime)
+ *clean_flag = 0;
+ else
+ *clean_flag = 1;
+ safeunlink(clean_path, 1);
+ safe_free(swaplog_path);
+ safe_free(clean_path);
+ safe_free(new_path);
+ return fp;
+}
+
+class UFSCleanLog : public SwapDir::CleanLog {
+ public:
+ UFSCleanLog(SwapDir *);
+ virtual const StoreEntry *nextEntry();
+ virtual void write(StoreEntry const &);
+ char *cur;
+ char *newLog;
+ char *cln;
+ char *outbuf;
+ off_t outbuf_offset;
+ int fd;
+ RemovalPolicyWalker *walker;
+ SwapDir *sd;
+};
+
+#define CLEAN_BUF_SZ 16384
+
+/*
+ * Begin the process to write clean cache state. For AUFS this means
+ * opening some log files and allocating write buffers. Return 0 if
+ * we succeed, and assign the 'func' and 'data' return pointers.
+ */
+
+UFSCleanLog::UFSCleanLog(SwapDir *aSwapDir) : cur(NULL),newLog(NULL),cln(NULL),outbuf(NULL),
+ outbuf_offset(0), fd(-1),walker(NULL), sd(aSwapDir)
+{
+}
+
+int
+UFSSwapDir::writeCleanStart()
+{
+ UFSCleanLog *state = new UFSCleanLog(this);
+#if HAVE_FCHMOD
+ struct stat sb;
+#endif
+ cleanLog = NULL;
+ state->newLog = xstrdup(logFile(".clean"));
+ state->fd = file_open(state->newLog, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
+ if (state->fd < 0) {
+ xfree(state->newLog);
+ delete state;
+ return -1;
+ }
+ state->cur = xstrdup(logFile(NULL));
+ state->cln = xstrdup(logFile(".last-clean"));
+ state->outbuf = (char *)xcalloc(CLEAN_BUF_SZ, 1);
+ state->outbuf_offset = 0;
+ state->walker = repl->WalkInit(repl);
+ ::unlink(state->cln);
+ debug(47, 3) ("storeDirWriteCleanLogs: opened %s, FD %d\n",
+ state->newLog, state->fd);
+#if HAVE_FCHMOD
+ if (stat(state->cur, &sb) == 0)
+ fchmod(state->fd, sb.st_mode);
+#endif
+ cleanLog = state;
+ return 0;
+}
+
+/*
+ * Get the next entry that is a candidate for clean log writing
+ */
+const StoreEntry *
+UFSCleanLog::nextEntry()
+{
+ const StoreEntry *entry = NULL;
+ if (walker)
+ entry = walker->Next(walker);
+ return entry;
+}
+
+/*
+ * "write" an entry to the clean log file.
+ */
+void
+UFSCleanLog::write(StoreEntry const &e)
+{
+ storeSwapLogData s;
+ static size_t ss = sizeof(storeSwapLogData);
+ memset(&s, '\0', ss);
+ s.op = (char) SWAP_LOG_ADD;
+ s.swap_filen = e.swap_filen;
+ s.timestamp = e.timestamp;
+ s.lastref = e.lastref;
+ s.expires = e.expires;
+ s.lastmod = e.lastmod;
+ s.swap_file_sz = e.swap_file_sz;
+ s.refcount = e.refcount;
+ s.flags = e.flags;
+ xmemcpy(&s.key, e.key, MD5_DIGEST_CHARS);
+ UFSCleanLog *state = this;
+ xmemcpy(state->outbuf + state->outbuf_offset, &s, ss);
+ state->outbuf_offset += ss;
+ /* buffered write */
+ if (state->outbuf_offset + ss > CLEAN_BUF_SZ) {
+ if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) {
+ debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
+ state->newLog, xstrerror());
+ debug(50, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.\n");
+ file_close(state->fd);
+ state->fd = -1;
+ unlink(state->newLog);
+ delete state;
+ sd->cleanLog = NULL;
+ return;
+ }
+ state->outbuf_offset = 0;
+ }
+}
+
+void
+UFSSwapDir::writeCleanDone()
+{
+ UFSCleanLog *state = (UFSCleanLog *)cleanLog;
+ int fd;
+ if (NULL == state)
+ return;
+ if (state->fd < 0)
+ return;
+ state->walker->Done(state->walker);
+ if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) {
+ debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
+ state->newLog, xstrerror());
+ debug(50, 0) ("storeDirWriteCleanLogs: Current swap logfile "
+ "not replaced.\n");
+ file_close(state->fd);
+ state->fd = -1;
+ ::unlink(state->newLog);
+ }
+ safe_free(state->outbuf);
+ /*
+ * You can't rename open files on Microsoft "operating systems"
+ * so we have to close before renaming.
+ */
+ closeLog();
+ /* save the fd value for a later test */
+ fd = state->fd;
+ /* rename */
+ if (state->fd >= 0) {
+#if defined(_SQUID_OS2_) || defined (_SQUID_CYGWIN_) || defined(_SQUID_MSWIN_)
+ file_close(state->fd);
+ state->fd = -1;
+ if (unlink(state->cur) < 0)
+ debug(50, 0) ("storeDirWriteCleanLogs: unlinkd failed: %s, %s\n",
+ xstrerror(), state->cur);
+#endif
+ xrename(state->newLog, state->cur);
+ }
+ /* touch a timestamp file if we're not still validating */
+ if (store_dirs_rebuilding)
+ (void) 0;
+ else if (fd < 0)
+ (void) 0;
+ else
+ file_close(file_open(state->cln, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY));
+ /* close */
+ safe_free(state->cur);
+ safe_free(state->newLog);
+ safe_free(state->cln);
+ if (state->fd >= 0)
+ file_close(state->fd);
+ state->fd = -1;
+ delete state;
+ cleanLog = NULL;
+}
+
+void
+storeSwapLogDataFree(void *s)
+{
+ memFree(s, MEM_SWAP_LOG_DATA);
+}
+
+void
+UFSSwapDir::logEntry(const StoreEntry & e, int op) const
+{
+ storeSwapLogData *s = (storeSwapLogData *)memAllocate(MEM_SWAP_LOG_DATA);
+ s->op = (char) op;
+ s->swap_filen = e.swap_filen;
+ s->timestamp = e.timestamp;
+ s->lastref = e.lastref;
+ s->expires = e.expires;
+ s->lastmod = e.lastmod;
+ s->swap_file_sz = e.swap_file_sz;
+ s->refcount = e.refcount;
+ s->flags = e.flags;
+ xmemcpy(s->key, e.key, MD5_DIGEST_CHARS);
+ file_write(swaplog_fd,
+ -1,
+ s,
+ sizeof(storeSwapLogData),
+ NULL,
+ NULL,
+ (FREE *) storeSwapLogDataFree);
+}
+
+static QS rev_int_sort;
+static int
+rev_int_sort(const void *A, const void *B)
+{
+ const int *i1 = (const int *)A;
+ const int *i2 = (const int *)B;
+ return *i2 - *i1;
+}
+
+int
+UFSSwapDir::DirClean(int swap_index)
+{
+ DIR *dp = NULL;
+ struct dirent *de = NULL;
+ LOCAL_ARRAY(char, p1, MAXPATHLEN + 1);
+ LOCAL_ARRAY(char, p2, MAXPATHLEN + 1);
+#if USE_TRUNCATE
+ struct stat sb;
+#endif
+ int files[20];
+ int swapfileno;
+ int fn; /* same as swapfileno, but with dirn bits set */
+ int n = 0;
+ int k = 0;
+ int N0, N1, N2;
+ int D0, D1, D2;
+ UFSSwapDir *SD;
+ N0 = NumberOfUFSDirs;
+ D0 = UFSDirToGlobalDirMapping[swap_index % N0];
+ SD = dynamic_cast<UFSSwapDir *>(INDEXSD(D0));
+ assert (SD);
+ N1 = SD->l1;
+ D1 = (swap_index / N0) % N1;
+ N2 = SD->l2;
+ D2 = ((swap_index / N0) / N1) % N2;
+ snprintf(p1, SQUID_MAXPATHLEN, "%s/%02X/%02X",
+ SD->path, D1, D2);
+ debug(36, 3) ("storeDirClean: Cleaning directory %s\n", p1);
+ dp = opendir(p1);
+ if (dp == NULL) {
+ if (errno == ENOENT) {
+ debug(36, 0) ("storeDirClean: WARNING: Creating %s\n", p1);
+#ifdef _SQUID_MSWIN_
+ if (mkdir(p1) == 0)
+#else
+ if (mkdir(p1, 0777) == 0)
+#endif
+ return 0;
+ }
+ debug(50, 0) ("storeDirClean: %s: %s\n", p1, xstrerror());
+ safeunlink(p1, 1);
+ return 0;
+ }
+ while ((de = readdir(dp)) != NULL && k < 20) {
+ if (sscanf(de->d_name, "%X", &swapfileno) != 1)
+ continue;
+ fn = swapfileno; /* XXX should remove this cruft ! */
+ if (SD->validFileno(fn, 1))
+ if (SD->mapBitTest(fn))
+ if (UFSSwapDir::FilenoBelongsHere(fn, D0, D1, D2))
+ continue;
+#if USE_TRUNCATE
+ if (!stat(de->d_name, &sb))
+ if (sb.st_size == 0)
+ continue;
+#endif
+ files[k++] = swapfileno;
+ }
+ closedir(dp);
+ if (k == 0)
+ return 0;
+ qsort(files, k, sizeof(int), rev_int_sort);
+ if (k > 10)
+ k = 10;
+ for (n = 0; n < k; n++) {
+ debug(36, 3) ("storeDirClean: Cleaning file %08X\n", files[n]);
+ snprintf(p2, MAXPATHLEN + 1, "%s/%08X", p1, files[n]);
+#if USE_TRUNCATE
+ truncate(p2, 0);
+#else
+ safeunlink(p2, 0);
+#endif
+ statCounter.swap.files_cleaned++;
+ }
+ debug(36, 3) ("Cleaned %d unused files from %s\n", k, p1);
+ return k;
+}
+
+void
+UFSSwapDir::CleanEvent(void *unused)
+{
+ static int swap_index = 0;
+ int i;
+ int j = 0;
+ int n = 0;
+ /*
+ * Assert that there are UFS cache_dirs configured, otherwise
+ * we should never be called.
+ */
+ assert(NumberOfUFSDirs);
+ if (NULL == UFSDirToGlobalDirMapping) {
+ SwapDir *sd;
+ /*
+ * Initialize the little array that translates UFS cache_dir
+ * number into the Config.cacheSwap.swapDirs array index.
+ */
+ UFSDirToGlobalDirMapping = (int *)xcalloc(NumberOfUFSDirs, sizeof(*UFSDirToGlobalDirMapping));
+ for (i = 0, n = 0; i < Config.cacheSwap.n_configured; i++) {
+ sd = INDEXSD(i);
+ if (!UFSSwapDir::IsUFSDir(sd))
+ continue;
+ UFSSwapDir *usd = dynamic_cast<UFSSwapDir *>(sd);
+ assert (usd);
+ UFSDirToGlobalDirMapping[n++] = i;
+ j += (usd->l1 * usd->l2);
+ }
+ assert(n == NumberOfUFSDirs);
+ /*
+ * Start the commonUfsDirClean() swap_index with a random
+ * value. j equals the total number of UFS level 2
+ * swap directories
+ */
+ swap_index = (int) (squid_random() % j);
+ }
+ if (0 == store_dirs_rebuilding) {
+ n = DirClean(swap_index);
+ swap_index++;
+ }
+ eventAdd("storeDirClean", CleanEvent, NULL,
+ 15.0 * exp(-0.25 * n), 1);
+}
+
+int
+UFSSwapDir::IsUFSDir(SwapDir * sd)
+{
+ UFSSwapDir *mySD = dynamic_cast<UFSSwapDir *>(sd);
+ return mySD ? 1 : 0 ;
+}
+
+/*
+ * Does swapfile number 'fn' belong in cachedir #F0,
+ * level1 dir #F1, level2 dir #F2?
+ * XXX: this is broken - it assumes all cache dirs use the same
+ * l1 and l2 scheme. -RBC 20021215. Partial fix is in place -
+ * if not UFSSwapDir return 0;
+ */
+int
+UFSSwapDir::FilenoBelongsHere(int fn, int F0, int F1, int F2)
+{
+ int D1, D2;
+ int L1, L2;
+ int filn = fn;
+ assert(F0 < Config.cacheSwap.n_configured);
+ assert (UFSSwapDir::IsUFSDir (INDEXSD(F0)));
+ UFSSwapDir *sd = dynamic_cast<UFSSwapDir *>(INDEXSD(F0));
+ if (!sd)
+ return 0;
+ L1 = sd->l1;
+ L2 = sd->l2;
+ D1 = ((filn / L2) / L2) % L1;
+ if (F1 != D1)
+ return 0;
+ D2 = (filn / L2) % L2;
+ if (F2 != D2)
+ return 0;
+ return 1;
+}
+
+int
+UFSSwapDir::validFileno(sfileno filn, int flag) const
+{
+ if (filn < 0)
+ return 0;
+ /*
+ * If flag is set it means out-of-range file number should
+ * be considered invalid.
+ */
+ if (flag)
+ if (filn > map->max_n_files)
+ return 0;
+ return 1;
+}
+
+/*
+ * UFSSwapDir::unlinkFile
+ *
+ * This routine unlinks a file and pulls it out of the bitmap.
+ * It used to be in commonUfsUnlink(), however an interface change
+ * forced this bit of code here. Eeek.
+ */
+void
+UFSSwapDir::unlinkFile(sfileno f)
+{
+ debug(79, 3) ("UFSSwapDir::unlinkFile: unlinking fileno %08X\n", f);
+ /* commonUfsDirMapBitReset(this, f); */
+ unlinkFile(fullPath(f, NULL));
+}
+
+/*
+ * Add and remove the given StoreEntry from the replacement policy in
+ * use.
+ */
+
+void
+UFSSwapDir::replacementAdd(StoreEntry * e)
+{
+ debug(47, 4) ("UFSSwapDir::replacementAdd: added node %p to dir %d\n", e,
+ index);
+ repl->Add(repl, e, &e->repl);
+}
+
+
+void
+UFSSwapDir::replacementRemove(StoreEntry * e)
+{
+ SwapDir *SD;
+ if (e->swap_dirn < 0)
+ return;
+ SD = INDEXSD(e->swap_dirn);
+ assert (dynamic_cast<UFSSwapDir *>(SD) == this);
+ debug(47, 4) ("UFSSwapDir::replacementRemove: remove node %p from dir %d\n", e,
+ index);
+ repl->Remove(repl, e, &e->repl);
+}
+
+void
+UFSSwapDir::dump(StoreEntry & entry) const
+{
+ storeAppendPrintf(&entry, " %d %d %d",
+ max_size >> 10,
+ l1,
+ l2);
+}
+
+char *
+UFSSwapDir::fullPath(sfileno filn, char *fullpath) const
+{
+ LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN);
+ int L1 = l1;
+ int L2 = l2;
+ if (!fullpath)
+ fullpath = fullfilename;
+ fullpath[0] = '\0';
+ snprintf(fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X/%08X",
+ path,
+ ((filn / L2) / L2) % L1,
+ (filn / L2) % L2,
+ filn);
+ return fullpath;
+}
/*
- * $Id: store_io_ufs.cc,v 1.13 2002/10/13 20:35:27 robertc Exp $
+ * $Id: store_io_ufs.cc,v 1.14 2002/12/27 10:26:39 robertc Exp $
*
* DEBUG: section 79 Storage Manager UFS Interface
* AUTHOR: Duane Wessels
#include "Store.h"
#include "ufscommon.h"
+#include "SwapDir.h"
-static DRCB storeUfsReadDone;
-static DWCB storeUfsWriteDone;
-static void storeUfsIOCallback(storeIOState * sio, int errflag);
-static CBDUNL storeUfsIOFreeEntry;
+UfsIO UfsIO::Instance;
+bool
+UfsIO::shedLoad()
+{
+ return false;
+}
+void
+UfsIO::deleteSelf() const
+{
+ /* Do nothing, we use a single instance */
+}
+
+StoreIOState::Pointer
+UfsIO::createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const
+{
+ return new ufsstate_t (SD, e, callback, callback_data);
+}
+
+DiskFile::Pointer
+UfsIO::newFile (char const *path)
+{
+ return new UFSFile (path);
+}
-CBDATA_TYPE(storeIOState);
+CBDATA_CLASS_INIT(ufsstate_t);
-/* === PUBLIC =========================================================== */
+void *
+ufsstate_t::operator new (size_t)
+{
+ CBDATA_INIT_TYPE(ufsstate_t);
+ ufsstate_t *result = cbdataAlloc(ufsstate_t);
+ /* Mark result as being owned - we want the refcounter to do the delete
+ * call */
+ cbdataReference(result);
+ return result;
+}
+
+void
+ufsstate_t::operator delete (void *address)
+{
+ ufsstate_t *t = static_cast<ufsstate_t *>(address);
+ cbdataFree(address);
+ /* And allow the memory to be freed */
+ cbdataReferenceDone (t);
+}
+
+ufsstate_t::ufsstate_t(SwapDir * SD, StoreEntry * anEntry, STIOCB * callback_, void *callback_data_)
+{
+ swap_filen = anEntry->swap_filen;
+ swap_dirn = SD->index;
+ mode = O_BINARY;
+ callback = callback_;
+ callback_data = cbdataReference(callback_data_);
+ e = anEntry;
+}
-storeIOState *
-storeUfsOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
- STIOCB * callback, void *callback_data)
+CBDATA_CLASS_INIT(UFSFile);
+void *
+UFSFile::operator new (size_t)
{
- sfileno f = e->swap_filen;
- char *path = commonUfsDirFullPath(SD, f, NULL);
- storeIOState *sio;
- struct stat sb;
- int fd;
- debug(79, 3) ("storeUfsOpen: fileno %08X\n", f);
- fd = file_open(path, O_RDONLY | O_BINARY);
+ 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);
+}
+
+void
+UFSFile::deleteSelf() const {delete this;}
+
+UFSFile::UFSFile (char const *aPath) : fd (-1)
+{
+ assert (aPath);
+ debug (79,0)("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) ("storeUfsOpen: got failure (%d)\n", errno);
- return NULL;
+ debug(79, 3) ("UFSFile::open: got failure (%d)\n", errno);
+ } else {
+ store_open_disk_fd++;
+ debug(79, 3) ("UFSFile::open: opened FD %d\n", fd);
}
- debug(79, 3) ("storeUfsOpen: opened FD %d\n", fd);
- CBDATA_INIT_TYPE_FREECB(storeIOState, storeUfsIOFreeEntry);
- sio = cbdataAlloc(storeIOState);
- sio->fsstate = memPoolAlloc(ufs_state_pool);
-
- sio->swap_filen = f;
- sio->swap_dirn = SD->index;
- sio->mode = O_RDONLY | O_BINARY;
- sio->callback = callback;
- sio->callback_data = cbdataReference(callback_data);
- sio->e = e;
- ((ufsstate_t *) (sio->fsstate))->fd = fd;
- ((ufsstate_t *) (sio->fsstate))->flags.writing = 0;
- ((ufsstate_t *) (sio->fsstate))->flags.reading = 0;
- ((ufsstate_t *) (sio->fsstate))->flags.close_request = 0;
- if (fstat(fd, &sb) == 0)
- sio->st_size = sb.st_size;
- store_open_disk_fd++;
-
- /* We should update the heap/dlink position here ! */
- return sio;
+ callback->ioCompletedNotification();
}
-storeIOState *
-storeUfsCreate(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data)
+void
+UFSFile::create (int flags, mode_t mode, IORequestor::Pointer callback)
{
- storeIOState *sio;
- int fd;
- int mode = (O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
- char *path;
- squidufsinfo_t *ufsinfo = (squidufsinfo_t *) SD->fsdata;
- sfileno filn;
- sdirno dirn;
+ /* We use the same logic path for open */
+ open(flags, mode, callback);
+}
- /* Allocate a number */
- dirn = SD->index;
- filn = commonUfsDirMapBitAllocate(SD);
- ufsinfo->suggest = filn + 1;
- /* Shouldn't we handle a 'bitmap full' error here? */
- path = commonUfsDirFullPath(SD, filn, NULL);
- debug(79, 3) ("storeUfsCreate: fileno %08X\n", filn);
- fd = file_open(path, mode);
- if (fd < 0) {
- debug(79, 3) ("storeUfsCreate: got failure (%d)\n", errno);
- return NULL;
+void UFSFile::doClose()
+{
+ if (fd > -1) {
+ file_close(fd);
+ store_open_disk_fd--;
+ fd = -1;
}
- debug(79, 3) ("storeUfsCreate: opened FD %d\n", fd);
- CBDATA_INIT_TYPE_FREECB(storeIOState, storeUfsIOFreeEntry);
- sio = cbdataAlloc(storeIOState);
- sio->fsstate = memPoolAlloc(ufs_state_pool);
+}
- sio->swap_filen = filn;
- sio->swap_dirn = dirn;
- sio->mode = mode;
- sio->callback = callback;
- sio->callback_data = cbdataReference(callback_data);
- sio->e = (StoreEntry *) e;
- ((ufsstate_t *) (sio->fsstate))->fd = fd;
- ((ufsstate_t *) (sio->fsstate))->flags.writing = 0;
- ((ufsstate_t *) (sio->fsstate))->flags.reading = 0;
- ((ufsstate_t *) (sio->fsstate))->flags.close_request = 0;
- store_open_disk_fd++;
+void
+UFSFile::close ()
+{
+ debug (79,0)("UFSFile::close: %p closing for %p\n", this, ioRequestor.getRaw());
+ doClose();
+ assert (ioRequestor.getRaw());
+ ioRequestor->closeCompleted();
+}
- /* now insert into the replacement policy */
- commonUfsDirReplAdd(SD, e);
- return sio;
+bool
+UFSFile::canRead() const
+{
+ return fd > -1;
+}
+
+bool
+UFSFile::error() const
+{
+ if (fd < 0)
+ return true;
+ return false;
}
void
-storeUfsClose(SwapDir * SD, storeIOState * sio)
+ufsstate_t::ioCompletedNotification()
{
- ufsstate_t *ufsstate = (ufsstate_t *) sio->fsstate;
+ if (opening) {
+ opening = false;
+ /* There is no 'opened' callback */
+ return;
+ }
+ if (creating) {
+ creating = false;
+ return;
+ }
+ assert(0);
+}
- debug(79, 3) ("storeUfsClose: dirno %d, fileno %08X, FD %d\n",
- sio->swap_dirn, sio->swap_filen, ufsstate->fd);
- if (ufsstate->flags.reading || ufsstate->flags.writing) {
- ufsstate->flags.close_request = 1;
+void
+ufsstate_t::closeCompleted()
+{
+ doCallback(theFile->error() ? 0 : -1);
+}
+
+void
+ufsstate_t::close()
+{
+ debug(79, 3) ("storeUfsClose: dirno %d, fileno %08X\n",
+ swap_dirn, swap_filen);
+ closing = true;
+ if (!(reading || writing)) {
+ ((UFSFile *)theFile.getRaw())->close();
+ }
+}
+
+void
+UFSStoreState::read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
+{
+ assert(read.callback == NULL);
+ assert(read.callback_data == NULL);
+ assert(!reading);
+ assert(!closing);
+ assert (callback);
+ if (!theFile->canRead()) {
+ debug(79, 3) ("UFSStoreState::read_: queueing read because theFile can't read\n");
+ queueRead (buf, size, offset, callback, callback_data);
return;
}
- storeUfsIOCallback(sio, 0);
+ 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_buf = buf;
+ reading = true;
+ theFile->read(buf, offset, size);
}
void
-storeUfsRead(SwapDir * SD, storeIOState * sio, char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
-{
- ufsstate_t *ufsstate = (ufsstate_t *) sio->fsstate;
-
- assert(sio->read.callback == NULL);
- assert(sio->read.callback_data == NULL);
- sio->read.callback = callback;
- sio->read.callback_data = cbdataReference(callback_data);
- debug(79, 3) ("storeUfsRead: dirno %d, fileno %08X, FD %d\n",
- sio->swap_dirn, sio->swap_filen, ufsstate->fd);
- sio->offset = offset;
- ufsstate->flags.reading = 1;
- file_read(ufsstate->fd,
- buf,
- size,
- offset,
- storeUfsReadDone,
- sio);
+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
-storeUfsWrite(SwapDir * SD, storeIOState * sio, char *buf, size_t size, off_t offset, FREE * free_func)
+UFSFile::write(char const *buf, size_t size, off_t offset, FREE *free_func)
{
- ufsstate_t *ufsstate = (ufsstate_t *) sio->fsstate;
- debug(79, 3) ("storeUfsWrite: dirn %d, fileno %08X, FD %d\n", sio->swap_dirn, sio->swap_filen, ufsstate->fd);
- ufsstate->flags.writing = 1;
- file_write(ufsstate->fd,
+ debug(79, 3) ("storeUfsWrite: FD %d\n",fd);
+ file_write(fd,
offset,
- buf,
+ (char *)buf,
size,
- storeUfsWriteDone,
- sio,
+ WriteDone,
+ this,
free_func);
}
void
-storeUfsUnlink(SwapDir * SD, StoreEntry * e)
+UFSStoreState::write(char *buf, size_t size, off_t offset, FREE * free_func)
+{
+ debug(79, 3) ("UFSStoreState::write: dirn %d, fileno %08X\n", swap_dirn, swap_filen);
+ if (!theFile->canWrite() || writing) {
+ assert(creating || writing);
+ queueWrite(buf, size, offset, free_func);
+ return;
+ }
+ writing = true;
+ theFile->write(buf,size,offset,free_func);
+}
+
+void
+UfsSwapDir::unlink(StoreEntry & e)
{
- debug(79, 3) ("storeUfsUnlink: fileno %08X\n", e->swap_filen);
- commonUfsDirReplRemove(e);
- commonUfsDirMapBitReset(SD, e->swap_filen);
- commonUfsDirUnlinkFile(SD, e->swap_filen);
+ debug(79, 3) ("storeUfsUnlink: fileno %08X\n", e.swap_filen);
+ replacementRemove(&e);
+ mapBitReset(e.swap_filen);
+ UFSSwapDir::unlinkFile(e.swap_filen);
}
/* === STATIC =========================================================== */
-static void
-storeUfsReadDone(int fd, const char *buf, int len, int errflag, void *my_data)
+void
+UFSFile::readDone(int rvfd, const char *buf, int len, int errflag)
{
- storeIOState *sio = (storeIOState *)my_data;
- ufsstate_t *ufsstate = (ufsstate_t *) sio->fsstate;
- STRCB *callback;
- void *cbdata;
- ssize_t rlen;
+ debug (79,3)("UFSFile::readDone: FD %d\n",rvfd);
+ assert (fd == rvfd);
- debug(79, 3) ("storeUfsReadDone: dirno %d, fileno %08X, FD %d, len %d\n",
- sio->swap_dirn, sio->swap_filen, fd, len);
- ufsstate->flags.reading = 0;
+ ssize_t rlen;
if (errflag) {
- debug(79, 3) ("storeUfsReadDone: got failure (%d)\n", errflag);
+ debug(79, 3) ("UFSFile::readDone: got failure (%d)\n", errflag);
rlen = -1;
} else {
rlen = (ssize_t) len;
- sio->offset += len;
}
- assert(sio->read.callback);
- assert(sio->read.callback_data);
- callback = sio->read.callback;
- sio->read.callback = NULL;
- if (cbdataReferenceValidDone(sio->read.callback_data, &cbdata))
- callback(cbdata, buf, (size_t) rlen);
-}
-
-static void
-storeUfsWriteDone(int fd, int errflag, size_t len, void *my_data)
-{
- storeIOState *sio = (storeIOState *)my_data;
- ufsstate_t *ufsstate = (ufsstate_t *) sio->fsstate;
- debug(79, 3) ("storeUfsWriteDone: dirno %d, fileno %08X, FD %d, len %ld\n",
- sio->swap_dirn, sio->swap_filen, fd, (long int) len);
- ufsstate->flags.writing = 0;
+ if (errflag == DISK_EOF)
+ errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */
+ ioRequestor->readCompleted(buf, rlen, errflag);
+}
+
+void
+ufsstate_t::readCompleted(const char *buf, int len, int errflag)
+{
+
+ reading = false;
+ debug(79, 3) ("storeUfsReadDone: dirno %d, fileno %08X, len %d\n",
+ swap_dirn, swap_filen, len);
+ if (len > 0)
+ offset_ += len;
+ STRCB *callback = read.callback;
+ assert(callback);
+ read.callback = NULL;
+ void *cbdata;
+ if (!closing && cbdataReferenceValidDone(read.callback_data, &cbdata)) {
+ if (len > 0 && read_buf != buf)
+ memcpy(read_buf, buf, len);
+ callback(cbdata, read_buf, len);
+ }
+ if (closing)
+ fatal("Sync ufs doesn't support overlapped close and read calls\n");
+}
+
+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);
- storeUfsIOCallback(sio, errflag);
+ doClose();
+ ioRequestor->writeCompleted (DISK_ERROR,0);
return;
}
- sio->offset += len;
- if (ufsstate->flags.close_request)
- storeUfsIOCallback(sio, errflag);
+ ioRequestor->writeCompleted(DISK_OK, len);
}
-static void
-storeUfsIOCallback(storeIOState * sio, int errflag)
+void
+ufsstate_t::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;
+ if (theFile->error())
+ doCallback(DISK_ERROR);
+ offset_ += len;
+ if (closing)
+ ((UFSFile *)theFile.getRaw())->close();
+}
+
+void
+ufsstate_t::doCallback(int errflag)
{
- ufsstate_t *ufsstate = (ufsstate_t *) sio->fsstate;
- void *cbdata;
debug(79, 3) ("storeUfsIOCallback: errflag=%d\n", errflag);
- if (ufsstate->fd > -1) {
- file_close(ufsstate->fd);
- store_open_disk_fd--;
- }
- if (cbdataReferenceValidDone(sio->callback_data, &cbdata))
- sio->callback(cbdata, errflag, sio);
- sio->callback = NULL;
- cbdataFree(sio);
+ /* We are finished with the file */
+ theFile = NULL;
+ void *cbdata;
+ if (cbdataReferenceValidDone(callback_data, &cbdata))
+ callback(cbdata, errflag, this);
+ callback = NULL;
}
/*
* Clean up any references from the SIO before it get's released.
*/
-static void
-storeUfsIOFreeEntry(void *sio)
+ufsstate_t::~ufsstate_t()
+{}
+
+
+
+/* ============= THE REAL UFS CODE ================ */
+
+UFSStoreState::UFSStoreState() : opening (false), creating (false), closing (false), reading(false), writing(false), pending_reads(NULL), pending_writes (NULL){}
+UFSStoreState::~UFSStoreState()
+{
+ _queued_read *qr;
+ while ((qr = (_queued_read *)linklistShift(&pending_reads))) {
+ cbdataReferenceDone(qr->callback_data);
+ delete qr;
+ }
+
+ struct _queued_write *qw;
+ while ((qw = (struct _queued_write *)linklistShift(&pending_writes))) {
+ if (qw->free_func)
+ qw->free_func(qw->buf);
+ delete qw;
+ }
+}
+
+bool
+UFSStoreState::kickReadQueue()
+{
+ _queued_read *q = (_queued_read *)linklistShift(&pending_reads);
+ if (NULL == q)
+ return false;
+ debug(79, 3) ("UFSStoreState::kickReadQueue: reading queued request of %ld bytes\n",
+ (long int) q->size);
+ void *cbdata;
+ if (cbdataReferenceValidDone(q->callback_data, &cbdata))
+ read_(q->buf, q->size, q->offset, q->callback, cbdata);
+ 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)
+{
+ debug(79, 3) ("UFSStoreState::queueRead: queueing read\n");
+ 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);
+ linklistPush(&pending_reads, q);
+}
+
+MemPool * UFSStoreState::_queued_write::Pool = NULL;
+
+void *
+UFSStoreState::_queued_write::operator new(size_t size)
+{
+ if (!Pool)
+ Pool = memPoolCreate("AUFS Queued write data",sizeof (_queued_write));
+ return memPoolAlloc (Pool);
+}
+
+void
+UFSStoreState::_queued_write::operator delete (void *address)
+{
+ memPoolFree (Pool, address);
+}
+
+bool
+UFSStoreState::kickWriteQueue()
{
- memPoolFree(ufs_state_pool, ((storeIOState *) sio)->fsstate);
+ _queued_write *q = (_queued_write *)linklistShift(&pending_writes);
+ if (NULL == q)
+ return false;
+ debug(79, 3) ("storeAufsKickWriteQueue: writing queued chunk of %ld bytes\n",
+ (long int) q->size);
+ write(q->buf, q->size, q->offset, q->free_func);
+ delete q;
+ return true;
+}
+
+void
+UFSStoreState::queueWrite(char *buf, size_t size, off_t offset, FREE * free_func)
+{
+ debug(79, 3) ("UFSStoreState::queueWrite: queuing write\n");
+ struct _queued_write *q;
+ q = new _queued_write;
+ q->buf = buf;
+ q->size = size;
+ q->offset = offset;
+ 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)
+{
+ assert (((UfsSwapDir *)SD)->IO == this);
+ debug(79, 3) ("UFSStrategy::open: fileno %08X\n", e->swap_filen);
+ if (shedLoad()) {
+ openFailed();
+ return NULL;
+ }
+ /* to consider: make createstate a private UFSStrategy call */
+ StoreIOState::Pointer sio = createState (SD, e, callback, callback_data);
+
+ sio->mode |= O_RDONLY;
+
+ UFSStoreState *state = dynamic_cast <UFSStoreState *>(sio.getRaw());
+ assert (state);
+ char *path = ((UFSSwapDir *)SD)->fullPath(e->swap_filen, NULL);
+
+ DiskFile::Pointer myFile = newFile (path);
+
+ state->theFile = myFile;
+ state->opening = true;
+ myFile->open (sio->mode, 0644, state);
+ if (myFile->error())
+ return NULL;
+
+ return sio;
+}
+
+StoreIOState::Pointer
+UFSStrategy::create(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
+ STIOCB * callback, 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;
+ }
+
+ /* Shouldn't we handle a 'bitmap full' error here? */
+
+ StoreIOState::Pointer sio = createState (SD, e, callback, callback_data);
+
+ sio->mode |= O_WRONLY | O_CREAT | O_TRUNC;
+ sio->swap_filen = filn;
+
+ UFSStoreState *state = dynamic_cast <UFSStoreState *>(sio.getRaw());
+ assert (state);
+ char *path = ((UFSSwapDir *)SD)->fullPath(filn, NULL);
+
+ DiskFile::Pointer myFile = newFile (path);
+
+ state->theFile = myFile;
+ state->creating = true;
+ myFile->create (state->mode, 0644, state);
+ if (myFile->error()) {
+ ((UFSSwapDir *)SD)->mapBitReset (filn);
+ return NULL;
+ }
+
+ /* now insert into the replacement policy */
+ ((UFSSwapDir *)SD)->replacementAdd(e);
+ return sio;
}
#ifndef __STORE_UFS_H__
#define __STORE_UFS_H__
-struct _ufsstate_t {
+#include "ufscommon.h"
+class UFSFile : public DiskFile {
+ public:
+ void *operator new(size_t);
+ void operator delete(void *);
+ virtual void deleteSelf() const;
+ UFSFile (char const *path);
+ ~UFSFile();
+ virtual void open (int, mode_t, IORequestor::Pointer);
+ virtual void create (int, mode_t, IORequestor::Pointer);
+ virtual void read(char *, off_t, size_t);
+ virtual void write(char const *buf, size_t size, off_t offset, FREE *free_func);
+ virtual void close ();
+ virtual bool error() const;
+ virtual int getFD() const { return fd;}
+ virtual bool canRead() const;
+ private:
+ static DRCB ReadDone;
+ static DWCB WriteDone;
+ CBDATA_CLASS(UFSFile);
int fd;
- struct {
- unsigned int close_request:1;
- unsigned int reading:1;
- unsigned int writing:1;
- } flags;
+ char const *path_;
+ IORequestor::Pointer ioRequestor;
+ void doClose();
+ void readDone(int fd, const char *buf, int len, int errflag);
+ void writeDone(int fd, int errflag, size_t len);
};
-typedef struct _ufsstate_t ufsstate_t;
+class ufsstate_t : public UFSStoreState {
+ public:
+ virtual void deleteSelf() const {delete this;}
+ void * operator new (size_t);
+ void operator delete (void *);
+ ufsstate_t(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data);
+ ~ufsstate_t();
+ void close();
+ void ioCompletedNotification();
+ void readCompleted(const char *buf, int len, int errflag);
+ void writeCompleted(int errflag, size_t len);
+ void closeCompleted();
+ private:
+ CBDATA_CLASS(ufsstate_t);
+ void doCallback (int);
+};
-/* The ufs_state memory pool */
-extern MemPool *ufs_state_pool;
+#include "SwapDir.h"
/*
* Store IO stuff
*/
-extern STOBJCREATE storeUfsCreate;
-extern STOBJOPEN storeUfsOpen;
-extern STOBJCLOSE storeUfsClose;
-extern STOBJREAD storeUfsRead;
-extern STOBJWRITE storeUfsWrite;
-extern STOBJUNLINK storeUfsUnlink;
+/* For things that aren't factored well yet */
+class UfsSwapDir: public UFSSwapDir {
+ virtual void dump(StoreEntry &)const;
+ virtual void unlink(StoreEntry &);
+ virtual int canStore(StoreEntry const&)const;
+ virtual void parse (int index, char *path);
+ virtual void reconfigure (int, char *);
+ virtual void unlinkFile (char const *);
+};
+
+class UfsIO : public UFSStrategy
+{
+public:
+ virtual bool shedLoad();
+ virtual void deleteSelf() const;
+ virtual StoreIOState::Pointer createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const;
+ virtual DiskFile::Pointer newFile (char const *path);
+ static UfsIO Instance;
+};
#endif
/*
- * $Id: protos.h,v 1.457 2002/11/15 13:29:20 hno Exp $
+ * $Id: protos.h,v 1.458 2002/12/27 10:26:33 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
SQUIDCEXTERN void requirePathnameExists(const char *name, const char *path);
SQUIDCEXTERN void parse_time_t(time_t * var);
SQUIDCEXTERN void parse_cachedir_options(SwapDir * sd, struct cache_dir_option *options, int reconfiguring);
-SQUIDCEXTERN void dump_cachedir_options(StoreEntry * e, struct cache_dir_option *options, SwapDir * sd);
+SQUIDCEXTERN void dump_cachedir_options(StoreEntry * e, struct cache_dir_option *options, SwapDir const * sd);
SQUIDCEXTERN void parse_sockaddr_in_list_token(sockaddr_in_list **, char *);
SQUIDCEXTERN void storeReplSetup(void);
/* store_io.c */
-SQUIDCEXTERN storeIOState *storeCreate(StoreEntry *, STFNCB *, STIOCB *, void *);
-SQUIDCEXTERN storeIOState *storeOpen(StoreEntry *, STFNCB *, STIOCB *, void *);
-SQUIDCEXTERN void storeClose(storeIOState *);
-SQUIDCEXTERN void storeRead(storeIOState *, char *, size_t, off_t, STRCB *, void *);
-SQUIDCEXTERN void storeWrite(storeIOState *, char *, size_t, off_t, FREE *);
+SQUIDCEXTERN StoreIOState::Pointer storeCreate(StoreEntry *, STFNCB *, STIOCB *, void *);
+SQUIDCEXTERN StoreIOState::Pointer storeOpen(StoreEntry *, STFNCB *, STIOCB *, void *);
+SQUIDCEXTERN void storeClose(StoreIOState::Pointer);
+SQUIDCEXTERN void storeRead(StoreIOState::Pointer, char *, size_t, off_t, STRCB *, void *);
+SQUIDCEXTERN void storeWrite(StoreIOState::Pointer, char *, size_t, off_t, FREE *);
SQUIDCEXTERN void storeUnlink(StoreEntry *);
-SQUIDCEXTERN off_t storeOffset(storeIOState *);
/*
* store_log.c
/*
- * $Id: squid.h,v 1.227 2002/11/10 02:04:39 hno Exp $
+ * $Id: squid.h,v 1.228 2002/12/27 10:26:33 robertc Exp $
*
* AUTHOR: Duane Wessels
*
/*
* I'm sick of having to keep doing this ..
*/
-#define INDEXSD(i) (&Config.cacheSwap.swapDirs[(i)])
+#define INDEXSD(i) (Config.cacheSwap.swapDirs[(i)])
#define FD_READ_METHOD(fd, buf, len) (*fd_table[fd].read_method)(fd, buf, len)
#define FD_WRITE_METHOD(fd, buf, len) (*fd_table[fd].write_method)(fd, buf, len)
/*
- * $Id: stat.cc,v 1.363 2002/10/25 01:00:42 adrian Exp $
+ * $Id: stat.cc,v 1.364 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 18 Cache Manager Statistics
* AUTHOR: Harvest Derived
storeAppendPrintf(s, "\tinmem_hi: %d\n", (int) mem->inmem_hi);
storeAppendPrintf(s, "\tswapout: %d bytes queued\n",
(int) mem->swapout.queue_offset);
- if (mem->swapout.sio)
+ if (mem->swapout.sio.getRaw())
storeAppendPrintf(s, "\tswapout: %d bytes written\n",
- (int) storeOffset(mem->swapout.sio));
+ (int) mem->swapout.sio->offset());
for (i = 0, node = mem->clients.head; node; node = node->next, i++)
storeClientDumpStats((store_client *)node->data, s, i);
}
/*
- * $Id: store.cc,v 1.551 2002/10/15 09:25:33 robertc Exp $
+ * $Id: store.cc,v 1.552 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 20 Storage Manager
* AUTHOR: Harvest Derived
#include "squid.h"
#include "Store.h"
#include "StoreClient.h"
+#include "SwapDir.h"
#define REBUILD_TIMESTAMP_DELTA_MAX 2
static void
storeEntryReferenced(StoreEntry * e)
{
- SwapDir *SD;
-
/* Notify the fs that we're referencing this object again */
- if (e->swap_dirn > -1) {
- SD = INDEXSD(e->swap_dirn);
- if (SD->refobj)
- SD->refobj(SD, e);
- }
+ if (e->swap_dirn > -1)
+ INDEXSD(e->swap_dirn)->reference(*e);
/* Notify the memory cache that we're referencing this object again */
if (e->mem_obj) {
if (mem_policy->Referenced)
static void
storeEntryDereferenced(StoreEntry * e)
{
- SwapDir *SD;
-
/* Notify the fs that we're not referencing this object any more */
- if (e->swap_filen > -1) {
- SD = INDEXSD(e->swap_dirn);
- if (SD->unrefobj != NULL)
- SD->unrefobj(SD, e);
- }
+ if (e->swap_filen > -1)
+ INDEXSD(e->swap_dirn)->dereference(*e);
/* Notify the memory cache that we're not referencing this object any more */
if (e->mem_obj) {
if (mem_policy->Dereferenced)
/*
* This routine is to be called by main loop in main.c.
* It removes expired objects on only one bucket for each time called.
- * returns the number of objects removed
*
* This should get called 1/s from main().
*/
/* XXX FixMe: This should be done "in parallell" on the different
* cache_dirs, not one at a time.
*/
- if (SD->maintainfs != NULL)
- SD->maintainfs(SD);
+ SD->maintainfs();
}
if (store_swap_size > Config.Swap.maxSize) {
if (squid_curtime - last_warn_time > 10) {
storeUnlink(e);
if (e->swap_status == SWAPOUT_DONE)
if (EBIT_TEST(e->flags, ENTRY_VALIDATED))
- storeDirUpdateSwapSize(&Config.cacheSwap.swapDirs[e->swap_dirn], e->swap_file_sz, -1);
+ storeDirUpdateSwapSize(INDEXSD(e->swap_dirn), e->swap_file_sz, -1);
if (!EBIT_TEST(e->flags, KEY_PRIVATE))
storeDirSwapLog(e, SWAP_LOG_DEL);
#if 0
/*
- * $Id: store_client.cc,v 1.118 2002/10/15 08:03:30 robertc Exp $
+ * $Id: store_client.cc,v 1.119 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 20 Storage Manager Client-Side Interface
* AUTHOR: Duane Wessels
* if needed.
*/
- if (STORE_DISK_CLIENT == sc->type && NULL == sc->swapin_sio) {
+ if (STORE_DISK_CLIENT == sc->type && sc->swapin_sio.getRaw() == NULL) {
debug(20, 3) ("storeClientCopy3: Need to open swap in file\n");
/* gotta open the swapin file */
if (storeTooManyDiskFilesOpen()) {
} else if (!sc->flags.disk_io_pending) {
/* Don't set store_io_pending here */
storeSwapInStart(sc);
- if (NULL == sc->swapin_sio) {
+ if (sc->swapin_sio == NULL) {
storeClientCallback(sc, -1);
return;
}
sc);
} else {
if (sc->entry->swap_status == SWAPOUT_WRITING)
- assert(storeOffset(mem->swapout.sio) > sc->copyInto.offset + (off_t)mem->swap_hdr_sz);
+ assert(mem->swapout.sio->offset() > sc->copyInto.offset + (off_t)mem->swap_hdr_sz);
storeRead(sc->swapin_sio,
sc->copyInto.data,
sc->copyInto.length,
mem->nclients--;
if (e->store_status == STORE_OK && e->swap_status != SWAPOUT_DONE)
storeSwapOut(e);
- if (sc->swapin_sio) {
+ if (sc->swapin_sio.getRaw()) {
storeClose(sc->swapin_sio);
- cbdataReferenceDone(sc->swapin_sio);
+ sc->swapin_sio = NULL;
statCounter.swap.ins++;
}
if (NULL != sc->callback) {
if (sc->type != STORE_MEM_CLIENT)
continue;
if (sc->type == STORE_DISK_CLIENT)
- if (NULL != sc->swapin_sio)
+ if (sc->swapin_sio.getRaw())
continue;
if (sc->copyInto.offset < lowest)
lowest = sc->copyInto.offset;
/*
- * $Id: store_dir.cc,v 1.139 2002/10/15 08:03:30 robertc Exp $
+ * $Id: store_dir.cc,v 1.140 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
#include "squid.h"
#include "Store.h"
+#include "SwapDir.h"
#if HAVE_STATVFS
#if HAVE_SYS_STATVFS_H
storeDirInit(void)
{
int i;
- SwapDir *sd;
- for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- sd = &Config.cacheSwap.swapDirs[i];
- sd->init(sd);
- }
+ for (i = 0; i < Config.cacheSwap.n_configured; i++)
+ INDEXSD(i)->init();
if (0 == strcasecmp(Config.store_dir_select_algorithm, "round-robin")) {
storeDirSelectSwapDir = storeDirSelectSwapDirRoundRobin;
debug(47, 1) ("Using Round Robin store dir selection\n");
storeCreateSwapDirectories(void)
{
int i;
- SwapDir *sd;
pid_t pid;
int status;
for (i = 0; i < Config.cacheSwap.n_configured; i++) {
if (fork())
continue;
- sd = &Config.cacheSwap.swapDirs[i];
- if (NULL != sd->newfs)
- sd->newfs(sd);
+ INDEXSD(i)->newFileSystem();
exit(0);
}
do {
/*
* If the swapdir's max_obj_size is -1, then it definitely can
*/
- if (Config.cacheSwap.swapDirs[swapdir].max_objsize == -1)
+ if (INDEXSD(swapdir)->max_objsize == -1)
return 1;
/*
* can't store it
*/
if ((objsize == -1) &&
- (Config.cacheSwap.swapDirs[swapdir].max_objsize != -1))
+ (INDEXSD(swapdir)->max_objsize != -1))
return 0;
/*
* Else, make sure that the max object size is larger than objsize
*/
- if (Config.cacheSwap.swapDirs[swapdir].max_objsize > objsize)
+ if (INDEXSD(swapdir)->max_objsize > objsize)
return 1;
else
return 0;
for (i = 0; i <= Config.cacheSwap.n_configured; i++) {
if (++dirn >= Config.cacheSwap.n_configured)
dirn = 0;
- sd = &Config.cacheSwap.swapDirs[dirn];
+ sd = INDEXSD(dirn);
if (sd->flags.read_only)
continue;
if (sd->cur_size > sd->max_size)
if (!storeDirValidSwapDirSize(i, objsize))
continue;
/* check for error or overload condition */
- load = sd->checkobj(sd, e);
+ load = sd->canStore(*e);
if (load < 0 || load > 1000) {
continue;
}
if (objsize != -1)
objsize += e->mem_obj->swap_hdr_sz;
for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- SD = &Config.cacheSwap.swapDirs[i];
+ SD = INDEXSD(i);
SD->flags.selected = 0;
- load = SD->checkobj(SD, e);
+ load = SD->canStore(*e);
if (load < 0 || load > 1000) {
continue;
}
dirn = i;
}
if (dirn >= 0)
- Config.cacheSwap.swapDirs[dirn].flags.selected = 1;
+ INDEXSD(dirn)->flags.selected = 1;
return dirn;
}
storeSwapDir(int dirn)
{
assert(0 <= dirn && dirn < Config.cacheSwap.n_configured);
- return Config.cacheSwap.swapDirs[dirn].path;
+ return INDEXSD(dirn)->path;
}
/*
void
storeDirSwapLog(const StoreEntry * e, int op)
{
- SwapDir *sd;
+ assert (e);
assert(!EBIT_TEST(e->flags, KEY_PRIVATE));
assert(e->swap_filen >= 0);
/*
e->getMD5Text(),
e->swap_dirn,
e->swap_filen);
- sd = &Config.cacheSwap.swapDirs[e->swap_dirn];
- sd->log.write(sd, e, op);
+ INDEXSD(e->swap_dirn)->logEntry(*e, op);
}
void
{
int i;
SwapDir *SD;
+ assert (sentry);
storeAppendPrintf(sentry, "Store Directory Statistics:\n");
storeAppendPrintf(sentry, "Store Entries : %lu\n",
/* Now go through each swapdir, calling its statfs routine */
for (i = 0; i < Config.cacheSwap.n_configured; i++) {
storeAppendPrintf(sentry, "\n");
- SD = &(Config.cacheSwap.swapDirs[i]);
+ SD = INDEXSD(i);
storeAppendPrintf(sentry, "Store Directory #%d (%s): %s\n", i, SD->type,
storeSwapDir(i));
storeAppendPrintf(sentry, "FS Block Size %d Bytes\n",
SD->fs.blksize);
- SD->statfs(SD, sentry);
+ SD->statfs(*sentry);
if (SD->repl) {
storeAppendPrintf(sentry, "Removal policy: %s\n", SD->repl->_type);
if (SD->repl->Stats)
int i;
Config.Swap.maxSize = 0;
for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- SD = &Config.cacheSwap.swapDirs[i];
+ SD = INDEXSD(i);
Config.Swap.maxSize += SD->max_size;
SD->low_size = (int) (((float) SD->max_size *
(float) Config.Swap.lowWaterMark) / 100.0);
void
storeDirDiskFull(sdirno dirn)
{
- SwapDir *SD = &Config.cacheSwap.swapDirs[dirn];
+ SwapDir *SD = INDEXSD(dirn);
assert(0 <= dirn && dirn < Config.cacheSwap.n_configured);
if (SD->cur_size >= SD->max_size)
return;
void
storeDirOpenSwapLogs(void)
{
- int dirn;
- SwapDir *sd;
- for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
- sd = &Config.cacheSwap.swapDirs[dirn];
- if (sd->log.open)
- sd->log.open(sd);
- }
+ for (int dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
+ INDEXSD(dirn)->openLog();
}
void
storeDirCloseSwapLogs(void)
{
- int dirn;
- SwapDir *sd;
- for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
- sd = &Config.cacheSwap.swapDirs[dirn];
- if (sd->log.close)
- sd->log.close(sd);
- }
+ for (int dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
+ INDEXSD(dirn)->closeLog();
}
/*
* the run. Thanks goes to Eric Stern, since this solution
* came out of his COSS code.
*/
-#define CLEAN_BUF_SZ 16384
int
storeDirWriteCleanLogs(int reopen)
{
getCurrentTime();
start = current_time;
for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
- sd = &Config.cacheSwap.swapDirs[dirn];
- if (sd->log.clean.start(sd) < 0) {
+ sd = INDEXSD(dirn);
+ if (sd->writeCleanStart() < 0) {
debug(20, 1) ("log.clean.start() failed for dir #%d\n", sd->index);
continue;
}
}
+ /* This writes all logs in parallel. It seems to me to be more efficient
+ * to write them sequentially. - RBC 20021214
+ */
while (notdone) {
notdone = 0;
for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
- sd = &Config.cacheSwap.swapDirs[dirn];
- if (NULL == sd->log.clean.write)
+ sd = INDEXSD(dirn);
+ if (NULL == sd->cleanLog)
continue;
- e = sd->log.clean.nextentry(sd);
+ e = sd->cleanLog->nextEntry();
if (!e)
continue;
notdone = 1;
- if (e->swap_filen < 0)
+ if (!sd->canLog(*e))
continue;
- if (e->swap_status != SWAPOUT_DONE)
- continue;
- if (e->swap_file_sz <= 0)
- continue;
- if (EBIT_TEST(e->flags, RELEASE_REQUEST))
- continue;
- if (EBIT_TEST(e->flags, KEY_PRIVATE))
- continue;
- if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
- continue;
- sd->log.clean.write(sd, e);
+ sd->cleanLog->write(*e);
if ((++n & 0xFFFF) == 0) {
getCurrentTime();
debug(20, 1) (" %7d entries written so far.\n", n);
}
}
/* Flush */
- for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
- sd = &Config.cacheSwap.swapDirs[dirn];
- sd->log.clean.done(sd);
- }
+ for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++)
+ INDEXSD(dirn)->writeCleanDone();
if (reopen)
storeDirOpenSwapLogs();
getCurrentTime();
dt, (double) n / (dt > 0.0 ? dt : 1.0));
return n;
}
-#undef CLEAN_BUF_SZ
/*
* sync all avaliable fs'es ..
void
storeDirSync(void)
{
- int i;
- SwapDir *SD;
-
- for (i = 0; i < Config.cacheSwap.n_configured; i++) {
- SD = &Config.cacheSwap.swapDirs[i];
- if (SD->sync != NULL)
- SD->sync(SD);
- }
+ for (int i = 0; i < Config.cacheSwap.n_configured; ++i)
+ INDEXSD(i)->sync();
}
/*
for (i = 0; i < Config.cacheSwap.n_configured; i++) {
if (ndir >= Config.cacheSwap.n_configured)
ndir = ndir % Config.cacheSwap.n_configured;
- SD = &Config.cacheSwap.swapDirs[ndir++];
- if (NULL == SD->callback)
- continue;
- j += SD->callback(SD);
+ SD = INDEXSD(ndir);
+ ++ndir;
+ j += SD->callback();
}
} while (j > 0);
ndir++;
#include "squid.h"
#include "Store.h"
-
+#include "SwapDir.h"
static struct {
struct {
* to what will be stored in this object, to allow the filesystem
* to select different polices depending on object size or type.
*/
-storeIOState *
+StoreIOState::Pointer
storeCreate(StoreEntry * e, STIOCB * file_callback, STIOCB * close_callback, void *callback_data)
{
+ assert (e);
ssize_t objsize;
sdirno dirn;
SwapDir *SD;
- storeIOState *sio;
store_io_stats.create.calls++;
/* This is just done for logging purposes */
return NULL;
}
debug(20, 2) ("storeCreate: Selected dir '%d' for obj size '%ld'\n", dirn, (long int) objsize);
- SD = &Config.cacheSwap.swapDirs[dirn];
+ SD = INDEXSD(dirn);
/* Now that we have a fs to use, call its storeCreate function */
- sio = SD->obj.create(SD, e, file_callback, close_callback, callback_data);
- if (NULL == sio)
+ StoreIOState::Pointer sio = SD->createStoreIO(*e, file_callback, close_callback, callback_data);
+ if (sio == NULL)
store_io_stats.create.create_fail++;
else
store_io_stats.create.success++;
return sio;
}
-
/*
* storeOpen() is purely for reading ..
*/
-storeIOState *
+StoreIOState::Pointer
storeOpen(StoreEntry * e, STFNCB * file_callback, STIOCB * callback,
void *callback_data)
{
- SwapDir *SD = &Config.cacheSwap.swapDirs[e->swap_dirn];
- return SD->obj.open(SD, e, file_callback, callback, callback_data);
+ return INDEXSD(e->swap_dirn)->openStoreIO(*e, file_callback, callback, callback_data);
}
void
-storeClose(storeIOState * sio)
+storeClose(StoreIOState::Pointer sio)
{
- SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_dirn];
if (sio->flags.closing)
return;
sio->flags.closing = 1;
- SD->obj.close(SD, sio);
+ sio->close();
}
void
-storeRead(storeIOState * sio, char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
+storeRead(StoreIOState::Pointer sio, char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data)
{
- SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_dirn];
- SD->obj.read(SD, sio, buf, size, offset, callback, callback_data);
+ sio->read_(buf, size, offset, callback, callback_data);
}
void
-storeWrite(storeIOState * sio, char *buf, size_t size, off_t offset, FREE * free_func)
+storeWrite(StoreIOState::Pointer sio, char *buf, size_t size, off_t offset, FREE * free_func)
{
- SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_dirn];
- SD->obj.write(SD, sio, buf, size, offset, free_func);
+ sio->write(buf,size,offset,free_func);
}
void
storeUnlink(StoreEntry * e)
{
- SwapDir *SD = INDEXSD(e->swap_dirn);
- SD->obj.unlink(SD, e);
-}
-
-off_t
-storeOffset(storeIOState * sio)
-{
- return sio->offset;
+ assert (e);
+ INDEXSD(e->swap_dirn)->unlink(*e);
}
/*
/*
- * $Id: store_rebuild.cc,v 1.78 2002/10/13 20:35:05 robertc Exp $
+ * $Id: store_rebuild.cc,v 1.79 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 20 Store Rebuild Routines
* AUTHOR: Duane Wessels
#include "squid.h"
#include "Store.h"
+#include "SwapDir.h"
static struct _store_rebuild_data counts;
static struct timeval rebuild_start;
static int
storeCleanupDoubleCheck(StoreEntry * e)
{
- SwapDir *SD = &Config.cacheSwap.swapDirs[e->swap_dirn];
- return (SD->dblcheck(SD, e));
+ SwapDir *SD = INDEXSD(e->swap_dirn);
+ return (SD->doubleCheck(*e));
}
static void
* Only set the file bit if we know its a valid entry
* otherwise, set it in the validation procedure
*/
- storeDirUpdateSwapSize(&Config.cacheSwap.swapDirs[e->swap_dirn], e->swap_file_sz, 1);
+ storeDirUpdateSwapSize(INDEXSD(e->swap_dirn), e->swap_file_sz, 1);
if ((++validnum & 0x3FFFF) == 0)
debug(20, 1) (" %7d Entries Validated so far.\n", validnum);
}
/*
- * $Id: store_swapin.cc,v 1.32 2002/10/15 08:03:30 robertc Exp $
+ * $Id: store_swapin.cc,v 1.33 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 20 Storage Manager Swapin Functions
* AUTHOR: Duane Wessels
storeSwapInStart(store_client * sc)
{
StoreEntry *e = sc->entry;
- storeIOState *sio;
assert(e->mem_status == NOT_IN_MEMORY);
if (!EBIT_TEST(e->flags, ENTRY_VALIDATED)) {
/* We're still reloading and haven't validated this entry yet */
assert(e->mem_obj != NULL);
debug(20, 3) ("storeSwapInStart: Opening fileno %08X\n",
e->swap_filen);
- sio = storeOpen(e, storeSwapInFileNotify, storeSwapInFileClosed, sc);
- sc->swapin_sio = cbdataReference(sio);
+ sc->swapin_sio = storeOpen(e, storeSwapInFileNotify, storeSwapInFileClosed, sc);
}
static void
sio, errflag);
if (errflag)
result.flags.error = 1;
- cbdataReferenceDone(sc->swapin_sio);
+ sc->swapin_sio = NULL;
if ((callback = sc->callback)) {
assert(errflag <= 0);
sc->callback = NULL;
/*
- * $Id: store_swapout.cc,v 1.90 2002/10/15 08:03:31 robertc Exp $
+ * $Id: store_swapout.cc,v 1.91 2002/12/27 10:26:33 robertc Exp $
*
* DEBUG: section 20 Storage Manager Swapout Functions
* AUTHOR: Duane Wessels
#include "squid.h"
#include "StoreClient.h"
#include "Store.h"
+#include "SwapDir.h"
static off_t storeSwapOutObjectBytesOnDisk(const MemObject *);
static void storeSwapOutStart(StoreEntry * e);
int swap_hdr_sz = 0;
tlv *tlv_list;
char *buf;
- storeIOState *sio;
+ StoreIOState::Pointer sio;
assert(mem);
/* Build the swap metadata, so the filesystem will know how much
* metadata there is to store
c = cbdataAlloc(generic_cbdata);
c->data = e;
sio = storeCreate(e, storeSwapOutFileNotify, storeSwapOutFileClosed, c);
- mem->swapout.sio = cbdataReference(sio);
- if (NULL == mem->swapout.sio) {
+ mem->swapout.sio = sio;
+ if (mem->swapout.sio == NULL) {
e->swap_status = SWAPOUT_NONE;
cbdataFree(c);
xfree(buf);
(int) mem->inmem_hi);
debug(20, 7) ("storeSwapOut: swapout.queue_offset = %d\n",
(int) mem->swapout.queue_offset);
- if (mem->swapout.sio)
- debug(20, 7) ("storeSwapOut: storeOffset() = %d\n",
- (int) storeOffset(mem->swapout.sio));
+ if (mem->swapout.sio.getRaw())
+ debug(20, 7) ("storeSwapOut: offset() = %d\n",
+ (int) mem->swapout.sio->offset());
assert(mem->inmem_hi >= mem->swapout.queue_offset);
lowest_offset = storeLowestMemReaderOffset(e);
debug(20, 7) ("storeSwapOut: lowest_offset = %d\n",
return;
/* ENTRY_CACHABLE will be cleared and we'll never get here again */
}
- if (NULL == mem->swapout.sio)
+ if (mem->swapout.sio == NULL)
return;
do {
/*
if (swapout_size < SM_PAGE_SIZE)
break;
} while (swapout_size > 0);
- if (NULL == mem->swapout.sio)
+ if (mem->swapout.sio == NULL)
/* oops, we're not swapping out any more */
return;
if (e->store_status == STORE_OK) {
MemObject *mem = e->mem_obj;
assert(mem != NULL);
debug(20, 3) ("storeSwapOutFileClose: %s\n", e->getMD5Text());
- debug(20, 3) ("storeSwapOutFileClose: sio = %p\n", mem->swapout.sio);
+ debug(20, 3) ("storeSwapOutFileClose: sio = %p\n", mem->swapout.sio.getRaw());
if (mem->swapout.sio == NULL)
return;
storeClose(mem->swapout.sio);
storeUrl(e), e->swap_dirn, e->swap_filen);
e->swap_file_sz = objectLen(e) + mem->swap_hdr_sz;
e->swap_status = SWAPOUT_DONE;
- storeDirUpdateSwapSize(&Config.cacheSwap.swapDirs[e->swap_dirn], e->swap_file_sz, 1);
+ storeDirUpdateSwapSize(INDEXSD(e->swap_dirn), e->swap_file_sz, 1);
if (storeCheckCachable(e)) {
storeLog(STORE_LOG_SWAPOUT, e);
storeDirSwapLog(e, SWAP_LOG_ADD);
statCounter.swap.outs++;
}
debug(20, 3) ("storeSwapOutFileClosed: %s:%d\n", __FILE__, __LINE__);
- cbdataReferenceDone(mem->swapout.sio);
+ mem->swapout.sio = NULL;
storeUnlockObject(e);
}
storeSwapOutObjectBytesOnDisk(const MemObject * mem)
{
/*
- * NOTE: storeOffset() represents the disk file size,
+ * NOTE: offset() represents the disk file size,
* not the amount of object data on disk.
*
* If we don't have at least 'swap_hdr_sz' bytes
* meaning we haven't even opened the swapout file
* yet.
*/
- off_t nwritten;
if (mem->swapout.sio == NULL)
return 0;
- nwritten = storeOffset(mem->swapout.sio);
+ off_t nwritten = mem->swapout.sio->offset();
if (nwritten <= (off_t)mem->swap_hdr_sz)
return 0;
return nwritten - mem->swap_hdr_sz;
storeSwapOutAble(const StoreEntry * e)
{
dlink_node *node;
- if (e->mem_obj->swapout.sio != NULL)
+ if (e->mem_obj->swapout.sio.getRaw() != NULL)
return 1;
if (e->mem_obj->inmem_lo > 0)
return 0;
/*
- * $Id: structs.h,v 1.440 2002/12/19 09:57:09 robertc Exp $
+ * $Id: structs.h,v 1.441 2002/12/27 10:26:34 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
} Ftp;
refresh_t *Refresh;
struct _cacheSwap {
- SwapDir *swapDirs;
+ SwapDir **swapDirs;
int n_allocated;
int n_configured;
} cacheSwap;
void (*Done) (RemovalPurgeWalker * walker);
};
+/* TODO: Move this include and the memobject header to another file
+ * - see the fix_ranges branch
+ */
+#include "StoreIOState.h"
/* This structure can be freed while object is purged out from memory */
struct _MemObject {
method_t method;
struct {
off_t queue_offset; /* relative to in-mem data */
mem_node *memnode; /* which node we're currently paging out */
- storeIOState *sio;
+ StoreIOState::Pointer sio;
} swapout;
HttpReply *reply;
request_t *request;
const char *vary_headers;
};
-struct _SwapDir {
- const char *type;
- int cur_size;
- int low_size;
- int max_size;
- char *path;
- int index; /* This entry's index into the swapDirs array */
- ssize_t max_objsize;
- RemovalPolicy *repl;
- int removals;
- int scanned;
- struct {
- unsigned int selected:1;
- unsigned int read_only:1;
- } flags;
- STINIT *init; /* Initialise the fs */
- STNEWFS *newfs; /* Create a new fs */
- STDUMP *dump; /* Dump fs config snippet */
- STFREE *freefs; /* Free the fs data */
- STDBLCHECK *dblcheck; /* Double check the obj integrity */
- STSTATFS *statfs; /* Dump fs statistics */
- STMAINTAINFS *maintainfs; /* Replacement maintainence */
- STCHECKOBJ *checkobj; /* Check if the fs will store an object */
- /* These two are notifications */
- STREFOBJ *refobj; /* Reference this object */
- STUNREFOBJ *unrefobj; /* Unreference this object */
- STCALLBACK *callback; /* Handle pending callbacks */
- STSYNC *sync; /* Sync the directory */
- struct {
- STOBJCREATE *create;
- STOBJOPEN *open;
- STOBJCLOSE *close;
- STOBJREAD *read;
- STOBJWRITE *write;
- STOBJUNLINK *unlink;
- } obj;
- struct {
- STLOGOPEN *open;
- STLOGCLOSE *close;
- STLOGWRITE *write;
- struct {
- STLOGCLEANSTART *start;
- STLOGCLEANNEXTENTRY *nextentry;
- STLOGCLEANWRITE *write;
- STLOGCLEANDONE *done;
- void *state;
- } clean;
- int writes_since_clean;
- } log;
- struct {
- int blksize;
- } fs;
- void *fsdata;
-};
-
/* To hard to pull this into another file just yet.
* SO, we stop globals.c seeing it
*/
struct _link_list *next;
};
-struct _storeIOState {
- sdirno swap_dirn;
- sfileno swap_filen;
- StoreEntry *e; /* Need this so the FS layers can play god */
- mode_t mode;
- size_t st_size; /* do stat(2) after read open */
- off_t offset; /* current on-disk offset pointer */
- STFNCB *file_callback; /* called on delayed sfileno assignments */
- STIOCB *callback;
- void *callback_data;
- struct {
- STRCB *callback;
- void *callback_data;
- } read;
- struct {
- unsigned int closing:1; /* debugging aid */
- } flags;
- void *fsstate;
-};
struct _request_t {
method_t method;
struct _storefs_entry {
const char *typestr;
- STFSPARSE *parsefunc;
- STFSRECONFIGURE *reconfigurefunc;
STFSSHUTDOWN *donefunc;
+ STFSNEW *newfunc;
};
/*
struct cache_dir_option {
const char *name;
void (*parse) (SwapDir * sd, const char *option, const char *value, int reconfiguring);
- void (*dump) (StoreEntry * e, const char *option, SwapDir * sd);
+ void (*dump) (StoreEntry * e, const char *option, SwapDir const * sd);
};
#endif /* SQUID_STRUCTS_H */
/*
- * $Id: typedefs.h,v 1.143 2002/12/06 23:19:16 hno Exp $
+ * $Id: typedefs.h,v 1.144 2002/12/27 10:26:34 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
typedef struct _store_client store_client;
typedef struct _MemObject MemObject;
typedef struct _StoreEntry StoreEntry;
-typedef struct _SwapDir SwapDir;
+class SwapDir;
typedef struct _helper_flags helper_flags;
typedef struct _helper_stateful_flags helper_stateful_flags;
typedef struct _http_state_flags http_state_flags;
typedef struct _helper_request helper_request;
typedef struct _helper_stateful_request helper_stateful_request;
typedef struct _generic_cbdata generic_cbdata;
-typedef struct _storeIOState storeIOState;
-typedef struct _queued_read queued_read;
-typedef struct _queued_write queued_write;
+class storeIOState;
typedef struct _link_list link_list;
typedef struct _storefs_entry storefs_entry_t;
typedef struct _storerepl_entry storerepl_entry_t;
typedef void HLPCMDOPTS(int *argc, char **argv);
typedef void IDNSCB(void *, rfc1035_rr *, int);
-typedef void STINIT(SwapDir *);
-typedef void STNEWFS(SwapDir *);
-typedef void STDUMP(StoreEntry *, SwapDir *);
-typedef void STFREE(SwapDir *);
-typedef int STDBLCHECK(SwapDir *, StoreEntry *);
-typedef void STSTATFS(SwapDir *, StoreEntry *);
-typedef void STMAINTAINFS(SwapDir *);
-typedef int STCHECKOBJ(SwapDir *, const StoreEntry *);
-typedef void STREFOBJ(SwapDir *, StoreEntry *);
-typedef void STUNREFOBJ(SwapDir *, StoreEntry *);
-typedef void STSETUP(storefs_entry_t *);
-typedef void STDONE(void);
-typedef int STCALLBACK(SwapDir *);
-typedef void STSYNC(SwapDir *);
-
-typedef storeIOState *STOBJCREATE(SwapDir *, StoreEntry *, STFNCB *, STIOCB *, void *);
-typedef storeIOState *STOBJOPEN(SwapDir *, StoreEntry *, STFNCB *, STIOCB *, void *);
-typedef void STOBJCLOSE(SwapDir *, storeIOState *);
-typedef void STOBJREAD(SwapDir *, storeIOState *, char *, size_t, off_t, STRCB *, void *);
-typedef void STOBJWRITE(SwapDir *, storeIOState *, char *, size_t, off_t, FREE *);
-typedef void STOBJUNLINK(SwapDir *, StoreEntry *);
-
-typedef void STLOGOPEN(SwapDir *);
-typedef void STLOGCLOSE(SwapDir *);
-typedef void STLOGWRITE(const SwapDir *, const StoreEntry *, int);
-typedef int STLOGCLEANSTART(SwapDir *);
-typedef const StoreEntry *STLOGCLEANNEXTENTRY(SwapDir *);
-typedef void STLOGCLEANWRITE(SwapDir *, const StoreEntry *);
-typedef void STLOGCLEANDONE(SwapDir *);
-
-/* Store dir configuration routines */
-/* SwapDir *sd, char *path ( + char *opt later when the strtok mess is gone) */
-typedef void STFSPARSE(SwapDir *, int, char *);
-typedef void STFSRECONFIGURE(SwapDir *, int, char *);
-typedef void STFSSTARTUP(void);
typedef void STFSSHUTDOWN(void);
+typedef SwapDir *STFSNEW(void);
typedef double hbase_f(double);
typedef void StatHistBinDumper(StoreEntry *, int idx, double val, double size, int count);
/*
- * $Id: ufscommon.cc,v 1.4 2002/10/15 08:03:31 robertc Exp $
+ * $Id: ufscommon.cc,v 1.5 2002/12/27 10:26:34 robertc Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
#include "ufscommon.h"
#include "Store.h"
+#include "RefCount.h"
-typedef struct _RebuildState RebuildState;
-struct _RebuildState {
- SwapDir *sd;
- int n_read;
- FILE *log;
- int speed;
- int curlvl1;
- int curlvl2;
- struct {
- unsigned int need_to_validate:1;
- unsigned int clean:1;
- unsigned int init:1;
- } flags;
- int done;
- int in_dir;
- int fn;
- struct dirent *entry;
- DIR *td;
- char fullpath[SQUID_MAXPATHLEN];
- char fullfilename[SQUID_MAXPATHLEN];
- struct _store_rebuild_data counts;
-};
+CBDATA_CLASS_INIT(RebuildState);
-static int n_dirs = 0;
-static int *dir_index = NULL;
-#if 0
-MemPool *squidaio_state_pool = NULL;
-MemPool *aufs_qread_pool = NULL;
-MemPool *aufs_qwrite_pool = NULL;
-static int asyncufs_initialised = 0;
-#endif
-static int commonUfsFilenoBelongsHere(int fn, int F0, int F1, int F2);
-static char *commonUfsDirSwapSubDir(SwapDir *, int subdirn);
-static int commonUfsDirCreateDirectory(const char *path, int);
-static int commonUfsDirVerifyCacheDirs(SwapDir * sd);
-static int commonUfsDirVerifyDirectory(const char *path);
-static void commonUfsDirCreateSwapSubDirs(SwapDir *);
-static int commonUfsDirMapBitTest(SwapDir * SD, sfileno filn);
-static char *commonUfsDirSwapLogFile(SwapDir *, const char *);
-static EVH commonUfsDirRebuildFromDirectory;
-static EVH commonUfsDirRebuildFromSwapLog;
-static int commonUfsDirGetNextFile(RebuildState *, sfileno *, int *size);
-static StoreEntry *commonUfsDirAddDiskRestore(SwapDir * SD, const cache_key * key,
- sfileno file_number,
- size_t swap_file_sz,
- time_t expires,
- time_t timestamp,
- time_t lastref,
- time_t lastmod,
- u_int32_t refcount,
- u_int16_t flags,
- int clean);
-static void commonUfsDirRebuild(SwapDir * sd);
-static void commonUfsDirCloseTmpSwapLog(SwapDir * sd);
-static FILE *commonUfsDirOpenTmpSwapLog(SwapDir *, int *, int *);
-#if 0
-static STLOGOPEN commonUfsDirOpenSwapLog;
-static STINIT commonUfsDirInit;
-static STFREE commonUfsDirFree;
-static STLOGCLEANSTART commonUfsDirWriteCleanStart;
-static STLOGCLEANNEXTENTRY commonUfsDirCleanLogNextEntry;
-#endif
-static STLOGCLEANWRITE commonUfsDirWriteCleanEntry;
-#if 0
-static STLOGCLEANDONE commonUfsDirWriteCleanDone;
-static STLOGCLOSE commonUfsDirCloseSwapLog;
-static STLOGWRITE commonUfsDirSwapLog;
-static STNEWFS commonUfsDirNewfs;
-static STCHECKOBJ commonUfsDirCheckObj;
-#endif
-static QS rev_int_sort;
-static void commonUfsDirMapBitSet(SwapDir * SD, sfileno filn);
-static EVH commonUfsDirCleanEvent;
-static int commonUfsDirClean(int swap_index);
-static int commonUfsDirIs(SwapDir * sd);
-#if 0
-static int commonUfsCleanupDoubleCheck(SwapDir *, StoreEntry *);
-#endif
-static void commonUfsDirInitBitmap(SwapDir *);
-static int commonUfsDirValidFileno(SwapDir * SD, sfileno filn, int flag);
-static int commonUfsDirMapBitTest(SwapDir * SD, sfileno filn);
-void commonUfsDirMapBitReset(SwapDir * SD, sfileno filn);
-
-#if 0
-
-/* The MAIN externally visible function */
-STSETUP storeFsSetup_aufs;
-
-/*
- * These functions were ripped straight out of the heart of store_dir.c.
- * They assume that the given filenum is on a asyncufs partiton, which may or
- * may not be true..
- * XXX this evilness should be tidied up at a later date!
- */
-
-#endif
-int
-commonUfsDirMapBitTest(SwapDir * SD, sfileno filn)
-{
- squidufsinfo_t *ioinfo;
- ioinfo = (squidufsinfo_t *) SD->fsdata;
- return file_map_bit_test(ioinfo->map, filn);
-}
-
-void
-commonUfsDirMapBitSet(SwapDir * SD, sfileno filn)
-{
- squidufsinfo_t *ioinfo;
- ioinfo = (squidufsinfo_t *) SD->fsdata;
- file_map_bit_set(ioinfo->map, filn);
-}
-
-void
-commonUfsDirMapBitReset(SwapDir * SD, sfileno filn)
-{
- squidufsinfo_t *ioinfo;
- ioinfo = (squidufsinfo_t *) SD->fsdata;
- /*
- * We have to test the bit before calling file_map_bit_reset.
- * file_map_bit_reset doesn't do bounds checking. It assumes
- * filn is a valid file number, but it might not be because
- * the map is dynamic in size. Also clearing an already clear
- * bit puts the map counter of-of-whack.
- */
- if (file_map_bit_test(ioinfo->map, filn))
- file_map_bit_reset(ioinfo->map, filn);
-}
-
-int
-commonUfsDirMapBitAllocate(SwapDir * SD)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) SD->fsdata;
- int fn;
- fn = file_map_allocate(ioinfo->map, ioinfo->suggest);
- file_map_bit_set(ioinfo->map, fn);
- ioinfo->suggest = fn + 1;
- return fn;
-}
-
-/*
- * Initialise the asyncufs bitmap
- *
- * If there already is a bitmap, and the numobjects is larger than currently
- * configured, we allocate a new bitmap and 'grow' the old one into it.
- */
-void
-commonUfsDirInitBitmap(SwapDir * sd)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) sd->fsdata;
-
- if (ioinfo->map == NULL) {
- /* First time */
- ioinfo->map = file_map_create();
- } else if (ioinfo->map->max_n_files) {
- /* it grew, need to expand */
- /* XXX We don't need it anymore .. */
- }
- /* else it shrunk, and we leave the old one in place */
-}
-
-char *
-commonUfsDirSwapSubDir(SwapDir * sd, int subdirn)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) sd->fsdata;
-
- LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN);
- assert(0 <= subdirn && subdirn < ioinfo->l1);
- snprintf(fullfilename, SQUID_MAXPATHLEN, "%s/%02X", sd->path, subdirn);
- return fullfilename;
-}
-
-int
-commonUfsDirCreateDirectory(const char *path, int should_exist)
+void *
+RebuildState::operator new (size_t size)
{
- int created = 0;
- struct stat st;
- getCurrentTime();
- if (0 == stat(path, &st)) {
- if (S_ISDIR(st.st_mode)) {
- debug(47, should_exist ? 3 : 1) ("%s exists\n", path);
- } else {
- fatalf("Swap directory %s is not a directory.", path);
- }
-#ifdef _SQUID_MSWIN_
- } else if (0 == mkdir(path)) {
-#else
- } else if (0 == mkdir(path, 0755)) {
-#endif
- debug(47, should_exist ? 1 : 3) ("%s created\n", path);
- created = 1;
- } else {
- fatalf("Failed to make swap directory %s: %s",
- path, xstrerror());
- }
- return created;
-}
-
-int
-commonUfsDirVerifyDirectory(const char *path)
-{
- struct stat sb;
- if (stat(path, &sb) < 0) {
- debug(47, 0) ("%s: %s\n", path, xstrerror());
- return -1;
- }
- if (S_ISDIR(sb.st_mode) == 0) {
- debug(47, 0) ("%s is not a directory\n", path);
- return -1;
- }
- return 0;
-}
-
-/*
- * This function is called by commonUfsDirInit(). If this returns < 0,
- * then Squid exits, complains about swap directories not
- * existing, and instructs the admin to run 'squid -z'
- */
-int
-commonUfsDirVerifyCacheDirs(SwapDir * sd)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) sd->fsdata;
- int j;
- const char *path = sd->path;
-
- if (commonUfsDirVerifyDirectory(path) < 0)
- return -1;
- for (j = 0; j < ioinfo->l1; j++) {
- path = commonUfsDirSwapSubDir(sd, j);
- if (commonUfsDirVerifyDirectory(path) < 0)
- return -1;
- }
- return 0;
+ assert (size == sizeof(RebuildState));
+ CBDATA_INIT_TYPE(RebuildState);
+ RebuildState *result = cbdataAlloc(RebuildState);
+ /* Mark result as being owned - we want the refcounter to do the delete
+ * call */
+ cbdataReference(result);
+ return result;
}
-
+
void
-commonUfsDirCreateSwapSubDirs(SwapDir * sd)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) sd->fsdata;
- int i, k;
- int should_exist;
- LOCAL_ARRAY(char, name, MAXPATHLEN);
- for (i = 0; i < ioinfo->l1; i++) {
- snprintf(name, MAXPATHLEN, "%s/%02X", sd->path, i);
- if (commonUfsDirCreateDirectory(name, 0))
- should_exist = 0;
- else
- should_exist = 1;
- debug(47, 1) ("Making directories in %s\n", name);
- for (k = 0; k < ioinfo->l2; k++) {
- snprintf(name, MAXPATHLEN, "%s/%02X/%02X", sd->path, i, k);
- commonUfsDirCreateDirectory(name, should_exist);
- }
- }
-}
-
-char *
-commonUfsDirSwapLogFile(SwapDir * sd, const char *ext)
+RebuildState::operator delete (void *address)
{
- LOCAL_ARRAY(char, path, SQUID_MAXPATHLEN);
- LOCAL_ARRAY(char, pathtmp, SQUID_MAXPATHLEN);
- LOCAL_ARRAY(char, digit, 32);
- char *pathtmp2;
- if (Config.Log.swap) {
- xstrncpy(pathtmp, sd->path, SQUID_MAXPATHLEN - 64);
- pathtmp2 = pathtmp;
- while ((pathtmp2 = strchr(pathtmp2, '/')) != NULL)
- *pathtmp2 = '.';
- while (strlen(pathtmp) && pathtmp[strlen(pathtmp) - 1] == '.')
- pathtmp[strlen(pathtmp) - 1] = '\0';
- for (pathtmp2 = pathtmp; *pathtmp2 == '.'; pathtmp2++);
- snprintf(path, SQUID_MAXPATHLEN - 64, Config.Log.swap, pathtmp2);
- if (strncmp(path, Config.Log.swap, SQUID_MAXPATHLEN - 64) == 0) {
- strcat(path, ".");
- snprintf(digit, 32, "%02d", sd->index);
- strncat(path, digit, 3);
- }
- } else {
- xstrncpy(path, sd->path, SQUID_MAXPATHLEN - 64);
- strcat(path, "/swap.state");
- }
- if (ext)
- strncat(path, ext, 16);
- return path;
+ RebuildState *t = static_cast<RebuildState *>(address);
+ cbdataFree(address);
+ /* And allow the memory to be freed */
+ cbdataReferenceDone (t);
}
void
-commonUfsDirOpenSwapLog(SwapDir * sd)
+RebuildState::deleteSelf() const
{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) sd->fsdata;
- char *path;
- int fd;
- path = commonUfsDirSwapLogFile(sd, NULL);
- fd = file_open(path, O_WRONLY | O_CREAT | O_BINARY);
- if (fd < 0) {
- debug(50, 1) ("%s: %s\n", path, xstrerror());
- fatal("commonUfsDirOpenSwapLog: Failed to open swap log.");
- }
- debug(50, 3) ("Cache Dir #%d log opened on FD %d\n", sd->index, fd);
- ioinfo->swaplog_fd = fd;
- if (0 == n_dirs)
- assert(NULL == dir_index);
- ++n_dirs;
- assert(n_dirs <= Config.cacheSwap.n_configured);
+ delete this;
}
-void
-commonUfsDirCloseSwapLog(SwapDir * sd)
+RebuildState::~RebuildState()
{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) sd->fsdata;
- if (ioinfo->swaplog_fd < 0) /* not open */
- return;
- file_close(ioinfo->swaplog_fd);
- debug(47, 3) ("Cache Dir #%d log closed on FD %d\n",
- sd->index, ioinfo->swaplog_fd);
- ioinfo->swaplog_fd = -1;
- n_dirs--;
- assert(n_dirs >= 0);
- if (0 == n_dirs)
- safe_free(dir_index);
+ store_dirs_rebuilding--;
+ sd->closeTmpSwapLog();
+ storeRebuildComplete(&counts);
}
void
-commonUfsDirInit(SwapDir * sd)
+RebuildState::RebuildFromDirectory(void *data)
{
- static int started_clean_event = 0;
- static const char *errmsg =
- "\tFailed to verify one of the swap directories, Check cache.log\n"
- "\tfor details. Run 'squid -z' to create swap directories\n"
- "\tif needed, or if running Squid for the first time.";
- commonUfsDirInitBitmap(sd);
- if (commonUfsDirVerifyCacheDirs(sd) < 0)
- fatal(errmsg);
- commonUfsDirOpenSwapLog(sd);
- commonUfsDirRebuild(sd);
- if (!started_clean_event) {
- eventAdd("storeDirClean", commonUfsDirCleanEvent, NULL, 15.0, 1);
- started_clean_event = 1;
- }
- (void) storeDirGetBlkSize(sd->path, &sd->fs.blksize);
+ RebuildState *rb = (RebuildState *)data;
+ rb->rebuildFromDirectory();
}
void
-commonUfsDirRebuildFromDirectory(void *data)
+RebuildState::rebuildFromDirectory()
{
- RebuildState *rb = (RebuildState *)data;
- SwapDir *SD = rb->sd;
LOCAL_ARRAY(char, hdr_buf, SM_PAGE_SIZE);
StoreEntry *e = NULL;
StoreEntry tmpe;
cache_key key[MD5_DIGEST_CHARS];
- sfileno filn = 0;
- int count;
- int size;
struct stat sb;
int swap_hdr_len;
int fd = -1;
tlv *tlv_list;
tlv *t;
- assert(rb != NULL);
- debug(47, 3) ("commonUfsDirRebuildFromDirectory: DIR #%d\n", rb->sd->index);
- for (count = 0; count < rb->speed; count++) {
+ assert(this != NULL);
+ debug(47, 3) ("commonUfsDirRebuildFromDirectory: DIR #%d\n", sd->index);
+ for (int count = 0; count < speed; count++) {
assert(fd == -1);
- fd = commonUfsDirGetNextFile(rb, &filn, &size);
+ sfileno filn = 0;
+ int size;
+ fd = getNextFile(&filn, &size);
if (fd == -2) {
debug(47, 1) ("Done scanning %s swaplog (%d entries)\n",
- rb->sd->path, rb->n_read);
- store_dirs_rebuilding--;
- commonUfsDirCloseTmpSwapLog(rb->sd);
- storeRebuildComplete(&rb->counts);
- cbdataFree(rb);
+ sd->path, n_read);
+ deleteSelf();
return;
} else if (fd < 0) {
continue;
fd = -1;
continue;
}
- if ((++rb->counts.scancount & 0xFFFF) == 0)
+ if ((++counts.scancount & 0xFFFF) == 0)
debug(47, 3) (" %s %7d files opened so far.\n",
- rb->sd->path, rb->counts.scancount);
+ sd->path, counts.scancount);
debug(47, 9) ("file_in: fd=%d %08X\n", fd, filn);
statCounter.syscalls.disk.reads++;
if (FD_READ_METHOD(fd, hdr_buf, SM_PAGE_SIZE) < 0) {
if (tlv_list == NULL) {
debug(47, 1) ("commonUfsDirRebuildFromDirectory: failed to get meta data\n");
/* XXX shouldn't this be a call to commonUfsUnlink ? */
- commonUfsDirUnlinkFile(SD, filn);
+ sd->unlinkFile (filn);
continue;
}
debug(47, 3) ("commonUfsDirRebuildFromDirectory: successful swap meta unpacking\n");
tlv_list = NULL;
if (storeKeyNull(key)) {
debug(47, 1) ("commonUfsDirRebuildFromDirectory: NULL key\n");
- commonUfsDirUnlinkFile(SD, filn);
+ sd->unlinkFile(filn);
continue;
}
tmpe.key = key;
} else if (tmpe.swap_file_sz != (size_t)sb.st_size) {
debug(47, 1) ("commonUfsDirRebuildFromDirectory: SIZE MISMATCH %ld!=%ld\n",
(long int) tmpe.swap_file_sz, (long int) sb.st_size);
- commonUfsDirUnlinkFile(SD, filn);
+ sd->unlinkFile(filn);
continue;
}
if (EBIT_TEST(tmpe.flags, KEY_PRIVATE)) {
- commonUfsDirUnlinkFile(SD, filn);
- rb->counts.badflags++;
+ sd->unlinkFile(filn);
+ counts.badflags++;
continue;
}
e = storeGet(key);
if (e && e->lastref >= tmpe.lastref) {
/* key already exists, current entry is newer */
/* keep old, ignore new */
- rb->counts.dupcount++;
+ counts.dupcount++;
continue;
} else if (NULL != e) {
/* URL already exists, this swapfile not being used */
/* junk old, load new */
storeRelease(e); /* release old entry */
- rb->counts.dupcount++;
+ counts.dupcount++;
}
- rb->counts.objcount++;
+ counts.objcount++;
storeEntryDump(&tmpe, 5);
- e = commonUfsDirAddDiskRestore(SD, key,
+ e = sd->addDiskRestore(key,
filn,
tmpe.swap_file_sz,
tmpe.expires,
tmpe.lastmod,
tmpe.refcount, /* refcount */
tmpe.flags, /* flags */
- (int) rb->flags.clean);
+ (int) flags.clean);
storeDirSwapLog(e, SWAP_LOG_ADD);
}
- eventAdd("storeRebuild", commonUfsDirRebuildFromDirectory, rb, 0.0, 1);
+ eventAdd("storeRebuild", RebuildFromDirectory, this, 0.0, 1);
}
void
-commonUfsDirRebuildFromSwapLog(void *data)
+RebuildState::RebuildFromSwapLog(void *data)
{
RebuildState *rb = (RebuildState *)data;
- SwapDir *SD = rb->sd;
+ rb->rebuildFromSwapLog();
+}
+
+void
+RebuildState::rebuildFromSwapLog()
+{
StoreEntry *e = NULL;
- storeSwapLogData s;
- size_t ss = sizeof(storeSwapLogData);
- int count;
- int used; /* is swapfile already in use? */
- int disk_entry_newer; /* is the log entry newer than current entry? */
double x;
- assert(rb != NULL);
/* load a number of objects per invocation */
- for (count = 0; count < rb->speed; count++) {
- if (fread(&s, ss, 1, rb->log) != 1) {
+ for (int count = 0; count < speed; count++) {
+ storeSwapLogData s;
+ size_t ss = sizeof(storeSwapLogData);
+ if (fread(&s, ss, 1, log) != 1) {
debug(47, 1) ("Done reading %s swaplog (%d entries)\n",
- rb->sd->path, rb->n_read);
- fclose(rb->log);
- rb->log = NULL;
- store_dirs_rebuilding--;
- commonUfsDirCloseTmpSwapLog(rb->sd);
- storeRebuildComplete(&rb->counts);
- cbdataFree(rb);
+ sd->path, n_read);
+ fclose(log);
+ log = NULL;
+ delete this;
return;
}
- rb->n_read++;
+ n_read++;
if (s.op <= SWAP_LOG_NOP)
continue;
if (s.op >= SWAP_LOG_MAX)
storeExpireNow(e);
storeReleaseRequest(e);
if (e->swap_filen > -1) {
- commonUfsDirReplRemove(e);
- commonUfsDirMapBitReset(SD, e->swap_filen);
+ sd->replacementRemove(e);
+ sd->mapBitReset(e->swap_filen);
e->swap_filen = -1;
e->swap_dirn = -1;
}
storeRelease(e);
- rb->counts.objcount--;
- rb->counts.cancelcount++;
+ counts.objcount--;
+ counts.cancelcount++;
}
continue;
} else {
- x = log(++rb->counts.bad_log_op) / log(10.0);
+ x = ::log(++counts.bad_log_op) / ::log(10.0);
if (0.0 == x - (double) (int) x)
debug(47, 1) ("WARNING: %d invalid swap log entries found\n",
- rb->counts.bad_log_op);
- rb->counts.invalid++;
+ counts.bad_log_op);
+ counts.invalid++;
continue;
}
- if ((++rb->counts.scancount & 0xFFF) == 0) {
+ if ((++counts.scancount & 0xFFF) == 0) {
struct stat sb;
- if (0 == fstat(fileno(rb->log), &sb))
- storeRebuildProgress(SD->index,
- (int) sb.st_size / ss, rb->n_read);
+ if (0 == fstat(fileno(log), &sb))
+ storeRebuildProgress(sd->index,
+ (int) sb.st_size / ss, n_read);
}
- if (!commonUfsDirValidFileno(SD, s.swap_filen, 0)) {
- rb->counts.invalid++;
+ if (!sd->validFileno(s.swap_filen, 0)) {
+ counts.invalid++;
continue;
}
if (EBIT_TEST(s.flags, KEY_PRIVATE)) {
- rb->counts.badflags++;
+ counts.badflags++;
continue;
}
e = storeGet(s.key);
- used = commonUfsDirMapBitTest(SD, s.swap_filen);
+ int used; /* is swapfile already in use? */
+ used = sd->mapBitTest(s.swap_filen);
/* If this URL already exists in the cache, does the swap log
* appear to have a newer entry? Compare 'lastref' from the
* swap log to e->lastref. */
- disk_entry_newer = e ? (s.lastref > e->lastref ? 1 : 0) : 0;
+ /* is the log entry newer than current entry? */
+ int disk_entry_newer = e ? (s.lastref > e->lastref ? 1 : 0) : 0;
if (used && !disk_entry_newer) {
/* log entry is old, ignore it */
- rb->counts.clashcount++;
+ counts.clashcount++;
continue;
- } else if (used && e && e->swap_filen == s.swap_filen && e->swap_dirn == SD->index) {
+ } else if (used && e && e->swap_filen == s.swap_filen && e->swap_dirn == sd->index) {
/* swapfile taken, same URL, newer, update meta */
if (e->store_status == STORE_OK) {
e->lastref = s.timestamp;
e->lastmod = s.lastmod;
e->flags = s.flags;
e->refcount += s.refcount;
- commonUfsDirUnrefObj(SD, e);
+ sd->dereference(*e);
} else {
debug_trap("commonUfsDirRebuildFromSwapLog: bad condition");
debug(47, 1) ("\tSee %s:%d\n", __FILE__, __LINE__);
* caught this. If the log is clean, there should never be a
* newer entry. */
debug(47, 1) ("WARNING: newer swaplog entry for dirno %d, fileno %08X\n",
- SD->index, s.swap_filen);
+ sd->index, s.swap_filen);
/* I'm tempted to remove the swapfile here just to be safe,
* but there is a bad race condition in the NOVM version if
* the swapfile has recently been opened for writing, but
/* We'll assume the existing entry is valid, probably because
* were in a slow rebuild and the the swap file number got taken
* and the validation procedure hasn't run. */
- assert(rb->flags.need_to_validate);
- rb->counts.clashcount++;
+ assert(flags.need_to_validate);
+ counts.clashcount++;
continue;
} else if (e && !disk_entry_newer) {
/* key already exists, current entry is newer */
/* keep old, ignore new */
- rb->counts.dupcount++;
+ counts.dupcount++;
continue;
} else if (e) {
/* key already exists, this swapfile not being used */
storeExpireNow(e);
storeReleaseRequest(e);
if (e->swap_filen > -1) {
- commonUfsDirReplRemove(e);
+ sd->replacementRemove(e);
/* Make sure we don't actually unlink the file */
- commonUfsDirMapBitReset(SD, e->swap_filen);
+ sd->mapBitReset(e->swap_filen);
e->swap_filen = -1;
e->swap_dirn = -1;
}
storeRelease(e);
- rb->counts.dupcount++;
+ counts.dupcount++;
} else {
/* URL doesnt exist, swapfile not in use */
/* load new */
(void) 0;
}
/* update store_swap_size */
- rb->counts.objcount++;
- e = commonUfsDirAddDiskRestore(SD, s.key,
+ counts.objcount++;
+ e = sd->addDiskRestore(s.key,
s.swap_filen,
s.swap_file_sz,
s.expires,
s.lastmod,
s.refcount,
s.flags,
- (int) rb->flags.clean);
+ (int) flags.clean);
storeDirSwapLog(e, SWAP_LOG_ADD);
}
- eventAdd("storeRebuild", commonUfsDirRebuildFromSwapLog, rb, 0.0, 1);
+ eventAdd("storeRebuild", RebuildFromSwapLog, this, 0.0, 1);
}
int
-commonUfsDirGetNextFile(RebuildState * rb, sfileno * filn_p, int *size)
+RebuildState::getNextFile(sfileno * filn_p, int *size)
{
- SwapDir *SD = rb->sd;
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) SD->fsdata;
int fd = -1;
- int used = 0;
int dirs_opened = 0;
debug(47, 3) ("commonUfsDirGetNextFile: flag=%d, %d: /%02X/%02X\n",
- rb->flags.init,
- rb->sd->index,
- rb->curlvl1,
- rb->curlvl2);
- if (rb->done)
+ flags.init,
+ sd->index,
+ curlvl1,
+ curlvl2);
+ if (done)
return -2;
- while (fd < 0 && rb->done == 0) {
+ while (fd < 0 && done == 0) {
fd = -1;
- if (0 == rb->flags.init) { /* initialize, open first file */
- rb->done = 0;
- rb->curlvl1 = 0;
- rb->curlvl2 = 0;
- rb->in_dir = 0;
- rb->flags.init = 1;
+ if (0 == flags.init) { /* initialize, open first file */
+ done = 0;
+ curlvl1 = 0;
+ curlvl2 = 0;
+ in_dir = 0;
+ flags.init = 1;
assert(Config.cacheSwap.n_configured > 0);
}
- if (0 == rb->in_dir) { /* we need to read in a new directory */
- snprintf(rb->fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X",
- rb->sd->path,
- rb->curlvl1, rb->curlvl2);
+ if (0 == in_dir) { /* we need to read in a new directory */
+ snprintf(fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X",
+ sd->path,
+ curlvl1, curlvl2);
if (dirs_opened)
return -1;
- rb->td = opendir(rb->fullpath);
+ td = opendir(fullpath);
dirs_opened++;
- if (rb->td == NULL) {
+ if (td == NULL) {
debug(47, 1) ("commonUfsDirGetNextFile: opendir: %s: %s\n",
- rb->fullpath, xstrerror());
+ fullpath, xstrerror());
} else {
- rb->entry = readdir(rb->td); /* skip . and .. */
- rb->entry = readdir(rb->td);
- if (rb->entry == NULL && errno == ENOENT)
+ entry = readdir(td); /* skip . and .. */
+ entry = readdir(td);
+ if (entry == NULL && errno == ENOENT)
debug(47, 1) ("commonUfsDirGetNextFile: directory does not exist!.\n");
- debug(47, 3) ("commonUfsDirGetNextFile: Directory %s\n", rb->fullpath);
+ debug(47, 3) ("commonUfsDirGetNextFile: Directory %s\n", fullpath);
}
}
- if (rb->td != NULL && (rb->entry = readdir(rb->td)) != NULL) {
- rb->in_dir++;
- if (sscanf(rb->entry->d_name, "%x", &rb->fn) != 1) {
+ if (td != NULL && (entry = readdir(td)) != NULL) {
+ in_dir++;
+ if (sscanf(entry->d_name, "%x", &fn) != 1) {
debug(47, 3) ("commonUfsDirGetNextFile: invalid %s\n",
- rb->entry->d_name);
+ entry->d_name);
continue;
}
- if (!commonUfsFilenoBelongsHere(rb->fn, rb->sd->index, rb->curlvl1, rb->curlvl2)) {
+ if (!UFSSwapDir::FilenoBelongsHere(fn, sd->index, curlvl1, curlvl2)) {
debug(47, 3) ("commonUfsDirGetNextFile: %08X does not belong in %d/%d/%d\n",
- rb->fn, rb->sd->index, rb->curlvl1, rb->curlvl2);
+ fn, sd->index, curlvl1, curlvl2);
continue;
}
- used = commonUfsDirMapBitTest(SD, rb->fn);
- if (used) {
+ if (sd->mapBitTest(fn)) {
debug(47, 3) ("commonUfsDirGetNextFile: Locked, continuing with next.\n");
continue;
}
- snprintf(rb->fullfilename, SQUID_MAXPATHLEN, "%s/%s",
- rb->fullpath, rb->entry->d_name);
- debug(47, 3) ("commonUfsDirGetNextFile: Opening %s\n", rb->fullfilename);
- fd = file_open(rb->fullfilename, O_RDONLY | O_BINARY);
+ snprintf(fullfilename, SQUID_MAXPATHLEN, "%s/%s",
+ fullpath, entry->d_name);
+ debug(47, 3) ("commonUfsDirGetNextFile: Opening %s\n", fullfilename);
+ fd = file_open(fullfilename, O_RDONLY | O_BINARY);
if (fd < 0)
- debug(47, 1) ("commonUfsDirGetNextFile: %s: %s\n", rb->fullfilename, xstrerror());
+ debug(47, 1) ("commonUfsDirGetNextFile: %s: %s\n", fullfilename, xstrerror());
else
store_open_disk_fd++;
continue;
}
- if (rb->td != NULL)
- closedir(rb->td);
- rb->td = NULL;
- rb->in_dir = 0;
- if (++rb->curlvl2 < ioinfo->l2)
+ if (td != NULL)
+ closedir(td);
+ td = NULL;
+ in_dir = 0;
+ if (sd->validL2(++curlvl2))
continue;
- rb->curlvl2 = 0;
- if (++rb->curlvl1 < ioinfo->l1)
+ curlvl2 = 0;
+ if (sd->validL1(++curlvl1))
continue;
- rb->curlvl1 = 0;
- rb->done = 1;
+ curlvl1 = 0;
+ done = 1;
}
- *filn_p = rb->fn;
+ *filn_p = fn;
return fd;
}
-
-/* Add a new object to the cache with empty memory copy and pointer to disk
- * use to rebuild store from disk. */
-StoreEntry *
-commonUfsDirAddDiskRestore(SwapDir * SD, const cache_key * key,
- sfileno file_number,
- size_t swap_file_sz,
- time_t expires,
- time_t timestamp,
- time_t lastref,
- time_t lastmod,
- u_int32_t refcount,
- u_int16_t flags,
- int clean)
-{
- StoreEntry *e = NULL;
- debug(47, 5) ("commonUfsAddDiskRestore: %s, fileno=%08X\n", storeKeyText(key), file_number);
- /* if you call this you'd better be sure file_number is not
- * already in use! */
- e = new_StoreEntry(STORE_ENTRY_WITHOUT_MEMOBJ, NULL, NULL);
- e->store_status = STORE_OK;
- storeSetMemStatus(e, NOT_IN_MEMORY);
- e->swap_status = SWAPOUT_DONE;
- e->swap_filen = file_number;
- e->swap_dirn = SD->index;
- e->swap_file_sz = swap_file_sz;
- e->lock_count = 0;
- e->lastref = lastref;
- e->timestamp = timestamp;
- e->expires = expires;
- e->lastmod = lastmod;
- e->refcount = refcount;
- e->flags = flags;
- EBIT_SET(e->flags, ENTRY_CACHABLE);
- EBIT_CLR(e->flags, RELEASE_REQUEST);
- EBIT_CLR(e->flags, KEY_PRIVATE);
- e->ping_status = PING_NONE;
- EBIT_CLR(e->flags, ENTRY_VALIDATED);
- commonUfsDirMapBitSet(SD, e->swap_filen);
- storeHashInsert(e, key); /* do it after we clear KEY_PRIVATE */
- commonUfsDirReplAdd(SD, e);
- return e;
-}
-
-CBDATA_TYPE(RebuildState);
-
-void
-commonUfsDirRebuild(SwapDir * sd)
-{
- RebuildState *rb;
- int clean = 0;
- int zero = 0;
- FILE *fp;
- EVH *func = NULL;
- CBDATA_INIT_TYPE(RebuildState);
- rb = cbdataAlloc(RebuildState);
- rb->sd = sd;
- rb->speed = opt_foreground_rebuild ? 1 << 30 : 50;
- /*
- * If the swap.state file exists in the cache_dir, then
- * we'll use commonUfsDirRebuildFromSwapLog(), otherwise we'll
- * use commonUfsDirRebuildFromDirectory() to open up each file
- * and suck in the meta data.
- */
- fp = commonUfsDirOpenTmpSwapLog(sd, &clean, &zero);
- if (fp == NULL || zero) {
- if (fp != NULL)
- fclose(fp);
- func = commonUfsDirRebuildFromDirectory;
- } else {
- func = commonUfsDirRebuildFromSwapLog;
- rb->log = fp;
- rb->flags.clean = (unsigned int) clean;
- }
- if (!clean)
- rb->flags.need_to_validate = 1;
- debug(47, 1) ("Rebuilding storage in %s (%s)\n",
- sd->path, clean ? "CLEAN" : "DIRTY");
- store_dirs_rebuilding++;
- eventAdd("storeRebuild", func, rb, 0.0, 1);
-}
-
-void
-commonUfsDirCloseTmpSwapLog(SwapDir * sd)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) sd->fsdata;
- char *swaplog_path = xstrdup(commonUfsDirSwapLogFile(sd, NULL));
- char *new_path = xstrdup(commonUfsDirSwapLogFile(sd, ".new"));
- int fd;
- file_close(ioinfo->swaplog_fd);
-#if defined (_SQUID_OS2_) || defined (_SQUID_CYGWIN_) || defined(_SQUID_MSWIN_)
- if (unlink(swaplog_path) < 0) {
- debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror());
- fatal("commonUfsDirCloseTmpSwapLog: unlink failed");
- }
-#endif
- if (xrename(new_path, swaplog_path) < 0) {
- fatal("commonUfsDirCloseTmpSwapLog: rename failed");
- }
- fd = file_open(swaplog_path, O_WRONLY | O_CREAT | O_BINARY);
- if (fd < 0) {
- debug(50, 1) ("%s: %s\n", swaplog_path, xstrerror());
- fatal("commonUfsDirCloseTmpSwapLog: Failed to open swap log.");
- }
- safe_free(swaplog_path);
- safe_free(new_path);
- ioinfo->swaplog_fd = fd;
- debug(47, 3) ("Cache Dir #%d log opened on FD %d\n", sd->index, fd);
-}
-
-FILE *
-commonUfsDirOpenTmpSwapLog(SwapDir * sd, int *clean_flag, int *zero_flag)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) sd->fsdata;
- char *swaplog_path = xstrdup(commonUfsDirSwapLogFile(sd, NULL));
- char *clean_path = xstrdup(commonUfsDirSwapLogFile(sd, ".last-clean"));
- char *new_path = xstrdup(commonUfsDirSwapLogFile(sd, ".new"));
- struct stat log_sb;
- struct stat clean_sb;
- FILE *fp;
- int fd;
- if (stat(swaplog_path, &log_sb) < 0) {
- debug(47, 1) ("Cache Dir #%d: No log file\n", sd->index);
- safe_free(swaplog_path);
- safe_free(clean_path);
- safe_free(new_path);
- return NULL;
- }
- *zero_flag = log_sb.st_size == 0 ? 1 : 0;
- /* close the existing write-only FD */
- if (ioinfo->swaplog_fd >= 0)
- file_close(ioinfo->swaplog_fd);
- /* open a write-only FD for the new log */
- fd = file_open(new_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
- if (fd < 0) {
- debug(50, 1) ("%s: %s\n", new_path, xstrerror());
- fatal("storeDirOpenTmpSwapLog: Failed to open swap log.");
- }
- ioinfo->swaplog_fd = fd;
- /* open a read-only stream of the old log */
- fp = fopen(swaplog_path, "rb");
- if (fp == NULL) {
- debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror());
- fatal("Failed to open swap log for reading");
- }
- memset(&clean_sb, '\0', sizeof(struct stat));
- if (stat(clean_path, &clean_sb) < 0)
- *clean_flag = 0;
- else if (clean_sb.st_mtime < log_sb.st_mtime)
- *clean_flag = 0;
- else
- *clean_flag = 1;
- safeunlink(clean_path, 1);
- safe_free(swaplog_path);
- safe_free(clean_path);
- safe_free(new_path);
- return fp;
-}
-
-struct _clean_state {
- char *cur;
- char *newLog;
- char *cln;
- char *outbuf;
- off_t outbuf_offset;
- int fd;
- RemovalPolicyWalker *walker;
-};
-
-#define CLEAN_BUF_SZ 16384
-
-/*
- * Begin the process to write clean cache state. For AUFS this means
- * opening some log files and allocating write buffers. Return 0 if
- * we succeed, and assign the 'func' and 'data' return pointers.
- */
-int
-commonUfsDirWriteCleanStart(SwapDir * sd)
-{
- struct _clean_state *state = (struct _clean_state *)xcalloc(1, sizeof(*state));
-#if HAVE_FCHMOD
- struct stat sb;
-#endif
- sd->log.clean.write = NULL;
- sd->log.clean.state = NULL;
- state->newLog = xstrdup(commonUfsDirSwapLogFile(sd, ".clean"));
- state->fd = file_open(state->newLog, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
- if (state->fd < 0) {
- xfree(state->newLog);
- xfree(state);
- return -1;
- }
- state->cur = xstrdup(commonUfsDirSwapLogFile(sd, NULL));
- state->cln = xstrdup(commonUfsDirSwapLogFile(sd, ".last-clean"));
- state->outbuf = (char *)xcalloc(CLEAN_BUF_SZ, 1);
- state->outbuf_offset = 0;
- state->walker = sd->repl->WalkInit(sd->repl);
- unlink(state->cln);
- debug(47, 3) ("storeDirWriteCleanLogs: opened %s, FD %d\n",
- state->newLog, state->fd);
-#if HAVE_FCHMOD
- if (stat(state->cur, &sb) == 0)
- fchmod(state->fd, sb.st_mode);
-#endif
- sd->log.clean.write = commonUfsDirWriteCleanEntry;
- sd->log.clean.state = state;
- return 0;
-}
-
-/*
- * Get the next entry that is a candidate for clean log writing
- */
-const StoreEntry *
-commonUfsDirCleanLogNextEntry(SwapDir * sd)
-{
- const StoreEntry *entry = NULL;
- struct _clean_state *state = (struct _clean_state *)sd->log.clean.state;
- if (state->walker)
- entry = state->walker->Next(state->walker);
- return entry;
-}
-
-/*
- * "write" an entry to the clean log file.
- */
-void
-commonUfsDirWriteCleanEntry(SwapDir * sd, const StoreEntry * e)
-{
- storeSwapLogData s;
- static size_t ss = sizeof(storeSwapLogData);
- struct _clean_state *state = (struct _clean_state *)sd->log.clean.state;
- memset(&s, '\0', ss);
- s.op = (char) SWAP_LOG_ADD;
- s.swap_filen = e->swap_filen;
- s.timestamp = e->timestamp;
- s.lastref = e->lastref;
- s.expires = e->expires;
- s.lastmod = e->lastmod;
- s.swap_file_sz = e->swap_file_sz;
- s.refcount = e->refcount;
- s.flags = e->flags;
- xmemcpy(&s.key, e->key, MD5_DIGEST_CHARS);
- xmemcpy(state->outbuf + state->outbuf_offset, &s, ss);
- state->outbuf_offset += ss;
- /* buffered write */
- if (state->outbuf_offset + ss > CLEAN_BUF_SZ) {
- if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) {
- debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
- state->newLog, xstrerror());
- debug(50, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.\n");
- file_close(state->fd);
- state->fd = -1;
- unlink(state->newLog);
- safe_free(state);
- sd->log.clean.state = NULL;
- sd->log.clean.write = NULL;
- return;
- }
- state->outbuf_offset = 0;
- }
-}
-
-void
-commonUfsDirWriteCleanDone(SwapDir * sd)
-{
- int fd;
- struct _clean_state *state = (struct _clean_state *)sd->log.clean.state;
- if (NULL == state)
- return;
- if (state->fd < 0)
- return;
- state->walker->Done(state->walker);
- if (FD_WRITE_METHOD(state->fd, state->outbuf, state->outbuf_offset) < 0) {
- debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
- state->newLog, xstrerror());
- debug(50, 0) ("storeDirWriteCleanLogs: Current swap logfile "
- "not replaced.\n");
- file_close(state->fd);
- state->fd = -1;
- unlink(state->newLog);
- }
- safe_free(state->outbuf);
- /*
- * You can't rename open files on Microsoft "operating systems"
- * so we have to close before renaming.
- */
- commonUfsDirCloseSwapLog(sd);
- /* save the fd value for a later test */
- fd = state->fd;
- /* rename */
- if (state->fd >= 0) {
-#if defined(_SQUID_OS2_) || defined (_SQUID_CYGWIN_) || defined(_SQUID_MSWIN_)
- file_close(state->fd);
- state->fd = -1;
- if (unlink(state->cur) < 0)
- debug(50, 0) ("storeDirWriteCleanLogs: unlinkd failed: %s, %s\n",
- xstrerror(), state->cur);
-#endif
- xrename(state->newLog, state->cur);
- }
- /* touch a timestamp file if we're not still validating */
- if (store_dirs_rebuilding)
- (void) 0;
- else if (fd < 0)
- (void) 0;
- else
- file_close(file_open(state->cln, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY));
- /* close */
- safe_free(state->cur);
- safe_free(state->newLog);
- safe_free(state->cln);
- if (state->fd >= 0)
- file_close(state->fd);
- state->fd = -1;
- safe_free(state);
- sd->log.clean.state = NULL;
- sd->log.clean.write = NULL;
-}
-
-void
-storeSwapLogDataFree(void *s)
-{
- memFree(s, MEM_SWAP_LOG_DATA);
-}
-
-void
-commonUfsDirSwapLog(const SwapDir * sd, const StoreEntry * e, int op)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) sd->fsdata;
- storeSwapLogData *s = (storeSwapLogData *)memAllocate(MEM_SWAP_LOG_DATA);
- s->op = (char) op;
- s->swap_filen = e->swap_filen;
- s->timestamp = e->timestamp;
- s->lastref = e->lastref;
- s->expires = e->expires;
- s->lastmod = e->lastmod;
- s->swap_file_sz = e->swap_file_sz;
- s->refcount = e->refcount;
- s->flags = e->flags;
- xmemcpy(s->key, e->key, MD5_DIGEST_CHARS);
- file_write(ioinfo->swaplog_fd,
- -1,
- s,
- sizeof(storeSwapLogData),
- NULL,
- NULL,
- (FREE *) storeSwapLogDataFree);
-}
-
-void
-commonUfsDirNewfs(SwapDir * sd)
-{
- debug(47, 3) ("Creating swap space in %s\n", sd->path);
- commonUfsDirCreateDirectory(sd->path, 0);
- commonUfsDirCreateSwapSubDirs(sd);
-}
-
-static int
-rev_int_sort(const void *A, const void *B)
-{
- const int *i1 = (const int *)A;
- const int *i2 = (const int *)B;
- return *i2 - *i1;
-}
-
-int
-commonUfsDirClean(int swap_index)
-{
- DIR *dp = NULL;
- struct dirent *de = NULL;
- LOCAL_ARRAY(char, p1, MAXPATHLEN + 1);
- LOCAL_ARRAY(char, p2, MAXPATHLEN + 1);
-#if USE_TRUNCATE
- struct stat sb;
-#endif
- int files[20];
- int swapfileno;
- int fn; /* same as swapfileno, but with dirn bits set */
- int n = 0;
- int k = 0;
- int N0, N1, N2;
- int D0, D1, D2;
- SwapDir *SD;
- squidufsinfo_t *ioinfo;
- N0 = n_dirs;
- D0 = dir_index[swap_index % N0];
- SD = &Config.cacheSwap.swapDirs[D0];
- ioinfo = (squidufsinfo_t *) SD->fsdata;
- N1 = ioinfo->l1;
- D1 = (swap_index / N0) % N1;
- N2 = ioinfo->l2;
- D2 = ((swap_index / N0) / N1) % N2;
- snprintf(p1, SQUID_MAXPATHLEN, "%s/%02X/%02X",
- Config.cacheSwap.swapDirs[D0].path, D1, D2);
- debug(36, 3) ("storeDirClean: Cleaning directory %s\n", p1);
- dp = opendir(p1);
- if (dp == NULL) {
- if (errno == ENOENT) {
- debug(36, 0) ("storeDirClean: WARNING: Creating %s\n", p1);
-#ifdef _SQUID_MSWIN_
- if (mkdir(p1) == 0)
-#else
- if (mkdir(p1, 0777) == 0)
-#endif
- return 0;
- }
- debug(50, 0) ("storeDirClean: %s: %s\n", p1, xstrerror());
- safeunlink(p1, 1);
- return 0;
- }
- while ((de = readdir(dp)) != NULL && k < 20) {
- if (sscanf(de->d_name, "%X", &swapfileno) != 1)
- continue;
- fn = swapfileno; /* XXX should remove this cruft ! */
- if (commonUfsDirValidFileno(SD, fn, 1))
- if (commonUfsDirMapBitTest(SD, fn))
- if (commonUfsFilenoBelongsHere(fn, D0, D1, D2))
- continue;
-#if USE_TRUNCATE
- if (!stat(de->d_name, &sb))
- if (sb.st_size == 0)
- continue;
-#endif
- files[k++] = swapfileno;
- }
- closedir(dp);
- if (k == 0)
- return 0;
- qsort(files, k, sizeof(int), rev_int_sort);
- if (k > 10)
- k = 10;
- for (n = 0; n < k; n++) {
- debug(36, 3) ("storeDirClean: Cleaning file %08X\n", files[n]);
- snprintf(p2, MAXPATHLEN + 1, "%s/%08X", p1, files[n]);
-#if USE_TRUNCATE
- truncate(p2, 0);
-#else
- safeunlink(p2, 0);
-#endif
- statCounter.swap.files_cleaned++;
- }
- debug(36, 3) ("Cleaned %d unused files from %s\n", k, p1);
- return k;
-}
-
-void
-commonUfsDirCleanEvent(void *unused)
-{
- static int swap_index = 0;
- int i;
- int j = 0;
- int n = 0;
- /*
- * Assert that there are AUFS cache_dirs configured, otherwise
- * we should never be called.
- */
- assert(n_dirs);
- if (NULL == dir_index) {
- SwapDir *sd;
- squidufsinfo_t *ioinfo;
- /*
- * Initialize the little array that translates AUFS cache_dir
- * number into the Config.cacheSwap.swapDirs array index.
- */
- dir_index = (int *)xcalloc(n_dirs, sizeof(*dir_index));
- for (i = 0, n = 0; i < Config.cacheSwap.n_configured; i++) {
- sd = &Config.cacheSwap.swapDirs[i];
- if (!commonUfsDirIs(sd))
- continue;
- dir_index[n++] = i;
- ioinfo = (squidufsinfo_t *) sd->fsdata;
- j += (ioinfo->l1 * ioinfo->l2);
- }
- assert(n == n_dirs);
- /*
- * Start the commonUfsDirClean() swap_index with a random
- * value. j equals the total number of AUFS level 2
- * swap directories
- */
- swap_index = (int) (squid_random() % j);
- }
- if (0 == store_dirs_rebuilding) {
- n = commonUfsDirClean(swap_index);
- swap_index++;
- }
- eventAdd("storeDirClean", commonUfsDirCleanEvent, NULL,
- 15.0 * exp(-0.25 * n), 1);
-}
-
-int
-commonUfsDirIs(SwapDir * sd)
-{
- if (strncmp(sd->type, "aufs", 4) == 0)
- return 1;
- if (strncmp(sd->type, "diskd", 5) == 0)
- return 1;
- if (strncmp(sd->type, "ufs", 3) == 0)
- return 1;
- return 0;
-}
-
-/*
- * Does swapfile number 'fn' belong in cachedir #F0,
- * level1 dir #F1, level2 dir #F2?
- */
-int
-commonUfsFilenoBelongsHere(int fn, int F0, int F1, int F2)
-{
- int D1, D2;
- int L1, L2;
- int filn = fn;
- squidufsinfo_t *ioinfo;
- assert(F0 < Config.cacheSwap.n_configured);
- ioinfo = (squidufsinfo_t *) Config.cacheSwap.swapDirs[F0].fsdata;
- L1 = ioinfo->l1;
- L2 = ioinfo->l2;
- D1 = ((filn / L2) / L2) % L1;
- if (F1 != D1)
- return 0;
- D2 = (filn / L2) % L2;
- if (F2 != D2)
- return 0;
- return 1;
-}
-
-int
-commonUfsDirValidFileno(SwapDir * SD, sfileno filn, int flag)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) SD->fsdata;
- if (filn < 0)
- return 0;
- /*
- * If flag is set it means out-of-range file number should
- * be considered invalid.
- */
- if (flag)
- if (filn > ioinfo->map->max_n_files)
- return 0;
- return 1;
-}
-
-void
-commonUfsDirMaintain(SwapDir * SD)
-{
- StoreEntry *e = NULL;
- int removed = 0;
- int max_scan;
- int max_remove;
- double f;
- RemovalPurgeWalker *walker;
- /* We can't delete objects while rebuilding swap */
- if (store_dirs_rebuilding) {
- return;
- } else {
- f = (double) (SD->cur_size - SD->low_size) / (SD->max_size - SD->low_size);
- f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f;
- max_scan = (int) (f * 400.0 + 100.0);
- max_remove = (int) (f * 70.0 + 10.0);
- /*
- * This is kinda cheap, but so we need this priority hack?
- */
- }
- debug(47, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n",
- f, max_scan, max_remove);
- walker = SD->repl->PurgeInit(SD->repl, max_scan);
- while (1) {
- if (SD->cur_size < SD->low_size)
- break;
- if (removed >= max_remove)
- break;
- e = walker->Next(walker);
- if (!e)
- break; /* no more objects */
- removed++;
- storeRelease(e);
- }
- walker->Done(walker);
- debug(47, (removed ? 2 : 3)) ("commonUfsDirMaintain: %s removed %d/%d f=%.03f max_scan=%d\n",
- SD->path, removed, max_remove, f, max_scan);
-}
-
-#if 0
-/*
- * commonUfsDirCheckObj
- *
- * This routine is called by storeDirSelectSwapDir to see if the given
- * object is able to be stored on this filesystem. AUFS filesystems will
- * happily store anything as long as the LRU time isn't too small.
- */
-int
-commonUfsDirCheckObj(SwapDir * SD, const StoreEntry * e)
-{
- int loadav;
- int ql;
-
-#if OLD_UNUSED_CODE
- if (commonUfsDirExpiredReferenceAge(SD) < 300) {
- debug(47, 3) ("commonUfsDirCheckObj: NO: LRU Age = %d\n",
- commonUfsDirExpiredReferenceAge(SD));
- /* store_check_cachable_hist.no.lru_age_too_low++; */
- return -1;
- }
-#endif
- ql = aioQueueSize();
- if (ql == 0)
- loadav = 0;
- loadav = ql * 1000 / MAGIC1;
- debug(47, 9) ("commonUfsDirCheckObj: load=%d\n", loadav);
- return loadav;
-}
-#endif
-/*
- * commonUfsDirRefObj
- *
- * This routine is called whenever an object is referenced, so we can
- * maintain replacement information within the storage fs.
- */
-void
-commonUfsDirRefObj(SwapDir * SD, StoreEntry * e)
-{
- debug(47, 3) ("commonUfsDirRefObj: referencing %p %d/%d\n", e, e->swap_dirn,
- e->swap_filen);
- if (SD->repl->Referenced)
- SD->repl->Referenced(SD->repl, e, &e->repl);
-}
-
-/*
- * commonUfsDirUnrefObj
- * This routine is called whenever the last reference to an object is
- * removed, to maintain replacement information within the storage fs.
- */
-void
-commonUfsDirUnrefObj(SwapDir * SD, StoreEntry * e)
-{
- debug(47, 3) ("commonUfsDirUnrefObj: referencing %p %d/%d\n", e, e->swap_dirn,
- e->swap_filen);
- if (SD->repl->Dereferenced)
- SD->repl->Dereferenced(SD->repl, e, &e->repl);
-}
-
-/*
- * commonUfsDirUnlinkFile
- *
- * This routine unlinks a file and pulls it out of the bitmap.
- * It used to be in commonUfsUnlink(), however an interface change
- * forced this bit of code here. Eeek.
- */
-void
-commonUfsDirUnlinkFile(SwapDir * SD, sfileno f)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *)SD->fsdata;
- debug(79, 3) ("commonUfsDirUnlinkFile: unlinking fileno %08X\n", f);
- /* commonUfsDirMapBitReset(SD, f); */
- assert(ioinfo->io.storeDirUnlinkFile);
- ioinfo->io.storeDirUnlinkFile(commonUfsDirFullPath(SD, f, NULL));
-}
-
-
-/*
- * Add and remove the given StoreEntry from the replacement policy in
- * use.
- */
-
-void
-commonUfsDirReplAdd(SwapDir * SD, StoreEntry * e)
-{
- debug(47, 4) ("commonUfsDirReplAdd: added node %p to dir %d\n", e,
- SD->index);
- SD->repl->Add(SD->repl, e, &e->repl);
-}
-
-
-void
-commonUfsDirReplRemove(StoreEntry * e)
-{
- SwapDir *SD;
- if (e->swap_dirn < 0)
- return;
- SD = INDEXSD(e->swap_dirn);
- debug(47, 4) ("commonUfsDirReplRemove: remove node %p from dir %d\n", e,
- SD->index);
- SD->repl->Remove(SD->repl, e, &e->repl);
-}
-
-
-
-/* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */
-
-void
-commonUfsDirStats(SwapDir * SD, StoreEntry * sentry)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *)SD->fsdata;
- int totl_kb = 0;
- int free_kb = 0;
- int totl_in = 0;
- int free_in = 0;
- int x;
- storeAppendPrintf(sentry, "First level subdirectories: %d\n", ioinfo->l1);
- storeAppendPrintf(sentry, "Second level subdirectories: %d\n", ioinfo->l2);
- storeAppendPrintf(sentry, "Maximum Size: %d KB\n", SD->max_size);
- storeAppendPrintf(sentry, "Current Size: %d KB\n", SD->cur_size);
- storeAppendPrintf(sentry, "Percent Used: %0.2f%%\n",
- 100.0 * SD->cur_size / SD->max_size);
- storeAppendPrintf(sentry, "Filemap bits in use: %d of %d (%d%%)\n",
- ioinfo->map->n_files_in_map, ioinfo->map->max_n_files,
- percent(ioinfo->map->n_files_in_map, ioinfo->map->max_n_files));
- x = storeDirGetUFSStats(SD->path, &totl_kb, &free_kb, &totl_in, &free_in);
- if (0 == x) {
- storeAppendPrintf(sentry, "Filesystem Space in use: %d/%d KB (%d%%)\n",
- totl_kb - free_kb,
- totl_kb,
- percent(totl_kb - free_kb, totl_kb));
- storeAppendPrintf(sentry, "Filesystem Inodes in use: %d/%d (%d%%)\n",
- totl_in - free_in,
- totl_in,
- percent(totl_in - free_in, totl_in));
- }
- storeAppendPrintf(sentry, "Flags:");
- if (SD->flags.selected)
- storeAppendPrintf(sentry, " SELECTED");
- if (SD->flags.read_only)
- storeAppendPrintf(sentry, " READ-ONLY");
- storeAppendPrintf(sentry, "\n");
-}
-
-#if 0
-static struct cache_dir_option options[] =
-{
-#if NOT_YET_DONE
- {"L1", commonUfsDirParseL1, commonUfsDirDumpL1},
- {"L2", commonUfsDirParseL2, commonUfsDirDumpL2},
-#endif
- {NULL, NULL}
-};
-
-/*
- * commonUfsDirReconfigure
- *
- * This routine is called when the given swapdir needs reconfiguring
- */
-static void
-commonUfsDirReconfigure(SwapDir * sd, int index, char *path)
-{
- int i;
- int size;
- int l1;
- int l2;
-
- i = GetInteger();
- size = i << 10; /* Mbytes to kbytes */
- if (size <= 0)
- fatal("commonUfsDirReconfigure: invalid size value");
- i = GetInteger();
- l1 = i;
- if (l1 <= 0)
- fatal("commonUfsDirReconfigure: invalid level 1 directories value");
- i = GetInteger();
- l2 = i;
- if (l2 <= 0)
- fatal("commonUfsDirReconfigure: invalid level 2 directories value");
-
- /* just reconfigure it */
- if (size == sd->max_size)
- debug(3, 1) ("Cache dir '%s' size remains unchanged at %d KB\n",
- path, size);
- else
- debug(3, 1) ("Cache dir '%s' size changed to %d KB\n",
- path, size);
- sd->max_size = size;
-
- parse_cachedir_options(sd, options, 0);
-
- return;
-}
-
-#endif
-
-void
-commonUfsDirDump(StoreEntry * entry, SwapDir * s)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) s->fsdata;
- storeAppendPrintf(entry, " %d %d %d",
- s->max_size >> 10,
- ioinfo->l1,
- ioinfo->l2);
-}
-
-/*
- * Only "free" the filesystem specific stuff here
- */
-void
-commonUfsDirFree(SwapDir * s)
-{
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) s->fsdata;
- if (ioinfo->swaplog_fd > -1) {
- file_close(ioinfo->swaplog_fd);
- ioinfo->swaplog_fd = -1;
- }
- filemapFreeMemory(ioinfo->map);
- xfree(ioinfo);
- s->fsdata = NULL; /* Will aid debugging... */
-}
-
-
-char *
-commonUfsDirFullPath(SwapDir * SD, sfileno filn, char *fullpath)
-{
- LOCAL_ARRAY(char, fullfilename, SQUID_MAXPATHLEN);
- squidufsinfo_t *ioinfo = (squidufsinfo_t *) SD->fsdata;
- int L1 = ioinfo->l1;
- int L2 = ioinfo->l2;
- if (!fullpath)
- fullpath = fullfilename;
- fullpath[0] = '\0';
- snprintf(fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X/%08X",
- SD->path,
- ((filn / L2) / L2) % L1,
- (filn / L2) % L2,
- filn);
- return fullpath;
-}
-
-/*
- * commonUfsCleanupDoubleCheck
- *
- * This is called by storeCleanup() if -S was given on the command line.
- */
-int
-commonUfsCleanupDoubleCheck(SwapDir * sd, StoreEntry * e)
-{
- struct stat sb;
- if (stat(commonUfsDirFullPath(sd, e->swap_filen, NULL), &sb) < 0) {
- debug(47, 0) ("commonUfsCleanupDoubleCheck: MISSING SWAP FILE\n");
- debug(47, 0) ("commonUfsCleanupDoubleCheck: FILENO %08X\n", e->swap_filen);
- debug(47, 0) ("commonUfsCleanupDoubleCheck: PATH %s\n",
- commonUfsDirFullPath(sd, e->swap_filen, NULL));
- storeEntryDump(e, 0);
- return -1;
- }
- if ((off_t)e->swap_file_sz != sb.st_size) {
- debug(47, 0) ("commonUfsCleanupDoubleCheck: SIZE MISMATCH\n");
- debug(47, 0) ("commonUfsCleanupDoubleCheck: FILENO %08X\n", e->swap_filen);
- debug(47, 0) ("commonUfsCleanupDoubleCheck: PATH %s\n",
- commonUfsDirFullPath(sd, e->swap_filen, NULL));
- debug(47, 0) ("commonUfsCleanupDoubleCheck: ENTRY SIZE: %ld, FILE SIZE: %ld\n",
- (long int) e->swap_file_sz, (long int) sb.st_size);
- storeEntryDump(e, 0);
- return -1;
- }
- return 0;
-}
/*
- * $Id: ufscommon.h,v 1.1 2002/10/12 09:45:56 robertc Exp $
+ * $Id: ufscommon.h,v 1.2 2002/12/27 10:26:34 robertc Exp $
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
#define DefaultLevelTwoDirs 256
#define STORE_META_BUFSZ 4096
-typedef struct _iospecific_t iospecific_t;
-struct _iospecific_t {
- void (*storeDirUnlinkFile) (char *);
-};
+/* Common UFS routines */
+FREE storeSwapLogDataFree;
+#include "SwapDir.h"
-typedef struct _squidufsinfo_t squidufsinfo_t;
-struct _squidufsinfo_t {
- int swaplog_fd;
- int l1;
- int l2;
+class UFSStrategy;
+
+class UFSSwapDir : public SwapDir {
+public:
+ static int IsUFSDir(SwapDir* sd);
+ static int DirClean(int swap_index);
+ static int FilenoBelongsHere(int fn, int F0, int F1, int F2);
+
+ UFSSwapDir();
+ virtual void init();
+ virtual void newFileSystem();
+ virtual void dump(StoreEntry &) const;
+ ~UFSSwapDir();
+ virtual bool doubleCheck(StoreEntry &);
+ virtual void unlink(StoreEntry &) = 0;
+ virtual void statfs(StoreEntry &)const;
+ virtual void maintainfs();
+ virtual int canStore(StoreEntry const &)const = 0;
+ virtual void reference(StoreEntry &);
+ virtual void dereference(StoreEntry &);
+ virtual StoreIOState::Pointer createStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
+ virtual StoreIOState::Pointer openStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *);
+ virtual void openLog();
+ virtual void closeLog();
+ virtual int writeCleanStart();
+ virtual void writeCleanDone();
+ virtual void logEntry(const StoreEntry & e, int op) const;
+ virtual void parse(int index, char *path);
+ virtual void reconfigure(int, char *);
+
+ void unlinkFile(sfileno f);
+ virtual void unlinkFile (char const *) = 0;
+ // move down when unlink is a virtual method
+//protected:
+ UFSStrategy *IO;
+ char *fullPath(sfileno, char *) const;
+ /* temp */
+ void closeTmpSwapLog();
+ FILE *openTmpSwapLog(int *clean_flag, int *zero_flag);
+ char *swapSubDir(int subdirn) const;
+ int mapBitTest(sfileno filn);
+ void mapBitReset(sfileno filn);
+ void mapBitSet(sfileno filn);
+ StoreEntry *addDiskRestore(const cache_key * key,
+ sfileno file_number,
+ size_t swap_file_sz,
+ time_t expires,
+ time_t timestamp,
+ time_t lastref,
+ time_t lastmod,
+ u_int32_t refcount,
+ u_int16_t flags,
+ int clean);
+ int validFileno(sfileno filn, int flag) const;
+ int mapBitAllocate();
+ void *fsdata;
+
+ bool validL2(int) const;
+ bool validL1(int) const;
+
+ void replacementAdd(StoreEntry *e);
+ void replacementRemove(StoreEntry *e);
+protected:
fileMap *map;
int suggest;
- iospecific_t io;
+ int l1;
+ int l2;
+private:
+ static int NumberOfUFSDirs;
+ static int * UFSDirToGlobalDirMapping;
+ bool pathIsDirectory(const char *path)const;
+ int swaplog_fd;
+ static EVH CleanEvent;
+ void initBitmap();
+ bool verifyCacheDirs();
+ void rebuild();
+ int createDirectory(const char *path, int);
+ void createSwapSubDirs();
+ void dumpEntry(StoreEntry &) const;
+ char *logFile(char const *ext = NULL)const;
+
+};
+
+#include "RefCount.h"
+
+class IORequestor : public RefCountable{
+ public:
+ typedef RefCount<IORequestor> Pointer;
+ virtual void ioCompletedNotification() = 0;
+ virtual void closeCompleted() = 0;
+ virtual void readCompleted(const char *buf, int len, int errflag) = 0;
+ virtual void writeCompleted(int errflag, size_t len) = 0;
+};
+
+class DiskFile : public RefCountable {
+ public:
+ typedef RefCount<DiskFile> Pointer;
+ virtual void deleteSelf() const = 0;
+ virtual void open (int, mode_t, IORequestor::Pointer) = 0;
+ virtual void create (int, mode_t, IORequestor::Pointer) = 0;
+ virtual void read(char *, off_t, size_t) = 0;
+ virtual void write(char const *buf, size_t size, off_t offset, FREE *free_func) = 0;
+ virtual bool canRead() const = 0;
+ virtual bool canWrite() const {return true;}
+ /* During miogration only */
+ virtual int getFD() const {return -1;}
+ virtual bool error() const = 0;
+};
+
+/* UFS dir specific IO calls */
+class UFSStrategy
+{
+public:
+ virtual bool shedLoad() = 0;
+ virtual void deleteSelf() const = 0;
+ virtual void openFailed(){}
+ virtual int load(){return -1;}
+ virtual StoreIOState::Pointer createState(SwapDir *, StoreEntry *, STIOCB *, void *)const = 0;
+ /* UFS specific */
+ virtual DiskFile::Pointer newFile (char const *path) = 0;
+ StoreIOState::Pointer open(SwapDir *, StoreEntry *, STFNCB *,
+ STIOCB *, void *);
+ StoreIOState::Pointer create(SwapDir *, StoreEntry *, STFNCB *,
+ STIOCB *, void *);
+ /* virtual void strategyStats(StoreEntry *sentry) const = 0; */
+ /* virtual void dumpCacheDirParams(StoreEntry * e, const char *option) const = 0; */
+};
+
+/* Common ufs-store-dir logic */
+class UFSStoreState : public storeIOState, public IORequestor {
+ public:
+ virtual void deleteSelf() const = 0;
+ UFSStoreState();
+ ~UFSStoreState();
+// protected:
+ DiskFile::Pointer theFile;
+ bool opening;
+ bool creating;
+ bool closing;
+ bool reading;
+ bool writing;
+ void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data);
+ void write(char *buf, size_t size, off_t offset, FREE * free_func);
+ protected:
+ class _queued_read {
+ public:
+ void *operator new(size_t);
+ void operator delete (void *);
+ char *buf;
+ size_t size;
+ off_t offset;
+ STRCB *callback;
+ void *callback_data;
+ private:
+ static MemPool *Pool;
+ };
+ class _queued_write {
+ public:
+ void *operator new(size_t);
+ void operator delete (void *);
+ char *buf;
+ size_t size;
+ off_t offset;
+ FREE *free_func;
+ private:
+ static MemPool *Pool;
+ };
+ link_list *pending_reads;
+ link_list *pending_writes;
+ void queueRead(char *, size_t, off_t, STRCB *, void *);
+ void queueWrite(char *, size_t, off_t, FREE *);
+ bool kickReadQueue();
+ bool kickWriteQueue();
+ char *read_buf;
+};
+
+class RebuildState : public RefCountable {
+public:
+ void *operator new(size_t);
+ void operator delete(void *);
+ void deleteSelf() const;
+ static EVH RebuildFromDirectory;
+ static EVH RebuildFromSwapLog;
+
+ ~RebuildState();
+ UFSSwapDir *sd;
+ int n_read;
+ FILE *log;
+ int speed;
+ int curlvl1;
+ int curlvl2;
+ struct {
+ unsigned int need_to_validate:1;
+ unsigned int clean:1;
+ unsigned int init:1;
+ } flags;
+ int done;
+ int in_dir;
+ int fn;
+ struct dirent *entry;
+ DIR *td;
+ char fullpath[SQUID_MAXPATHLEN];
+ char fullfilename[SQUID_MAXPATHLEN];
+ struct _store_rebuild_data counts;
+private:
+ CBDATA_CLASS(RebuildState);
+ void rebuildFromDirectory();
+ void rebuildFromSwapLog();
+ int getNextFile(sfileno *, int *size);
};
-/* Common UFS routines */
-void commonUfsDirSwapLog(const SwapDir * sd, const StoreEntry * e, int op);
-FREE storeSwapLogDataFree;
-void commonUfsDirWriteCleanDone(SwapDir * sd);
-const StoreEntry *commonUfsDirCleanLogNextEntry(SwapDir * sd);
-void commonUfsDirCloseSwapLog(SwapDir * sd);
-int commonUfsDirWriteCleanStart(SwapDir * sd);
-void commonUfsDirInit(SwapDir * sd);
-void commonUfsDirUnlinkFile(SwapDir * SD, sfileno f);
-void commonUfsDirOpenSwapLog(SwapDir * sd);
-void commonUfsDirNewfs(SwapDir * sd);
-void commonUfsDirMaintain(SwapDir * SD);
-void commonUfsDirRefObj(SwapDir * SD, StoreEntry * e);
-void commonUfsDirUnrefObj(SwapDir * SD, StoreEntry * e);
-void commonUfsDirReplAdd(SwapDir * SD, StoreEntry * e);
-void commonUfsDirReplRemove(StoreEntry * e);
-void commonUfsDirStats(SwapDir * SD, StoreEntry * sentry);
-void commonUfsDirDump(StoreEntry * entry, SwapDir * s);
-void commonUfsDirFree(SwapDir * s);
-char *commonUfsDirFullPath(SwapDir * SD, sfileno filn, char *fullpath);
-int commonUfsCleanupDoubleCheck(SwapDir * sd, StoreEntry * e);
-int commonUfsDirMapBitAllocate(SwapDir * SD);
-void commonUfsDirMapBitReset(SwapDir * SD, sfileno filn);
#endif /* SQUID_UFSCOMMON_H */
#
# Makefile for the Squid Object Cache server
#
-# $Id: Makefile.am,v 1.1 2002/11/21 12:35:53 robertc Exp $
+# $Id: Makefile.am,v 1.2 2002/12/27 10:26:40 robertc Exp $
#
+AUTOMAKE_OPTIONS = subdir-objects
+
AM_CFLAGS = -Werror -Wall
AM_CXXFLAGS = -Werror -Wall
refcount_SOURCES = refcount.cc
-
## membanger won't link today. Bitrot..
##CC = gcc
##CFLAGS = -g -Wall -I../include -I../src