From: robertc <> Date: Tue, 22 Jul 2003 21:23:01 +0000 (+0000) Subject: Summary: Merge disk-factoring. X-Git-Tag: SQUID_3_0_PRE2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=59b2d47f54f8988d0dd74430a78b7a8599d819ff;p=thirdparty%2Fsquid.git Summary: Merge disk-factoring. Keywords: Patches applied: * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-14 Merge of robertc@squid-cache.org--squid/squid--HEAD--3.0--patch-283-285 * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-13 Further OOification of the store drivers. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-12 And more OOification. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-11 And more OOification of the store drivers. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-10 And more OOification. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-9 More store OOification. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-8 Dist missing files. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-7 And moe OOification. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-6 And more OOification. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-5 More store FS OOification. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-4 More OOification for the store. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-3 OO'ing the store layer. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-2 BUGFIX: array.cc compilation. * robertc@squid-cache.org--squid/squid--disk-io--3.0--patch-1 Update to latest HEAD code. * robertc@squid-cache.org--squid/squid--disk-io--3.0--base-0 tag of robertc@squid-cache.org--squid/squid--HEAD--3.0--patch-220 --- diff --git a/configure.in b/configure.in index 24ca1357f9..f3731fe159 100644 --- a/configure.in +++ b/configure.in @@ -3,7 +3,7 @@ dnl Configuration input file for Squid dnl dnl Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9) dnl -dnl $Id: configure.in,v 1.339 2003/07/16 12:09:08 robertc Exp $ +dnl $Id: configure.in,v 1.340 2003/07/22 15:24:00 robertc Exp $ dnl dnl dnl @@ -13,7 +13,7 @@ AC_CONFIG_SRCDIR([src/main.cc]) AC_CONFIG_AUX_DIR(cfgaux) AM_INIT_AUTOMAKE(squid, 3.0-PRE1-CVS) AM_CONFIG_HEADER(include/autoconf.h) -AC_REVISION($Revision: 1.339 $)dnl +AC_REVISION($Revision: 1.340 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -428,6 +428,10 @@ if test -n "$STORE_MODULES"; then echo "Store modules built: $STORE_MODULES" STORE_OBJS="fs/lib`echo $STORE_MODULES|sed -e 's% %.a fs/lib%g'`.a" STORE_LIBS="`echo $STORE_OBJS|sed -e 's%fs/%%g'`" + STORE_LINKOBJS= + for module in $STORE_MODULES; do + STORE_LINKOBJS="$STORE_LINKOBJS fs/${module}/StoreFS${module}.o" + done fi dnl remove all but diskd - its the only module that needs to recurse dnl into the sub directory @@ -464,13 +468,14 @@ if test -z "$UFS_FOUND" && test -n "$NEED_UFS"; then STORE_OBJS="$STORE_OBJS fs/libufs.a" STORE_LIBS="$STORE_LIBS libufs.a" STORE_MODULES="$STORE_MODULES ufs" + STORE_LINKOBJS="$STORE_SOURCE fs/ufs/StoreFSufs.o" fi AC_SUBST(STORE_OBJS) AC_SUBST(STORE_LIBS) -AC_SUBST(STORE_MODULES) AC_SUBST(STORE_PROGRAMS) AC_SUBST(STORE_MODULE_SUBDIRS) +AC_SUBST(STORE_LINKOBJS) AC_ARG_ENABLE(removal-policies, [ --enable-removal-policies=\"list of policies\" diff --git a/doc/debug-sections.txt b/doc/debug-sections.txt index 197f72cdcb..a7d44c5643 100644 --- a/doc/debug-sections.txt +++ b/doc/debug-sections.txt @@ -95,3 +95,4 @@ section 88 Client side reply management - from store to stream section 89 NAT / IP Interception section 90 Store Client section 91 Http Surrogate-Control Header +section 92 Store File System diff --git a/lib/Array.cc b/lib/Array.cc index 0b1cfd805f..24397a30c3 100644 --- a/lib/Array.cc +++ b/lib/Array.cc @@ -1,5 +1,5 @@ /* - * $Id: Array.cc,v 1.10 2003/01/23 00:37:00 robertc Exp $ + * $Id: Array.cc,v 1.11 2003/07/22 15:23:18 robertc Exp $ * * AUTHOR: Alex Rousskov * @@ -51,16 +51,3 @@ #endif #include "util.h" #include "Array.h" - -Array *arrayCreate(void) {return new Array;} -void arrayClean(Array * s) {s->clean();} -void arrayDestroy(Array * s) { delete s;} -void arrayAppend(Array * s, void *obj) {s->push_back(obj);} -void arrayPreAppend(Array * s, int app_count) {s->preAppend(app_count);} - -void -arrayInit(Array * a) -{ - assert(a); - memset(a, 0, sizeof(Array)); -} diff --git a/src/Makefile.am b/src/Makefile.am index 83d34be0fb..a0d508f240 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,12 +1,13 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.85 2003/07/15 13:15:04 robertc Exp $ +# $Id: Makefile.am,v 1.86 2003/07/22 15:23:01 robertc Exp $ # # Uncomment and customize the following to suit your needs: # +AUTOMAKE_OPTIONS = subdir-objects if USE_DNSSERVER DNSSOURCE = dns.cc DNSSERVER = dnsserver @@ -185,7 +186,15 @@ cf_gen.$(OBJEXT): cf_gen_defines.h squidclient_SOURCES = client.cc cachemgr__CGIEXT__SOURCES = cachemgr.cc +all_FSMODULES = \ + fs/aufs/StoreFSaufs.cc \ + fs/coss/StoreFScoss.cc \ + fs/diskd/StoreFSdiskd.cc \ + fs/null/StoreFSnull.cc \ + fs/ufs/StoreFSufs.cc + EXTRA_squid_SOURCES = \ + $(all_FSMODULES) \ $(ARP_ACL_ALL_SOURCE) \ $(DELAY_POOL_ALL_SOURCE) \ dns.cc \ @@ -400,6 +409,8 @@ squid_SOURCES = \ stmem.h \ store.cc \ Store.h \ + StoreFileSystem.cc \ + StoreFileSystem.h \ store_io.cc \ StoreIOBuffer.h \ StoreIOState.cc \ @@ -426,6 +437,7 @@ squid_SOURCES = \ StoreMetaURL.h \ StoreMetaVary.cc \ StoreMetaVary.h \ + $(STORE_SOURCES) \ StoreSwapLogData.cc \ StoreSwapLogData.h \ structs.h \ @@ -457,7 +469,6 @@ noinst_HEADERS = ACLChecklist.cci \ nodist_squid_SOURCES = \ repl_modules.cc \ auth_modules.cc \ - store_modules.cc \ cf_parser.h \ globals.cc \ string_arrays.c @@ -466,6 +477,7 @@ squid_LDADD = \ -L../lib \ @XTRA_OBJS@ \ @REPL_OBJS@ \ + @STORE_LINKOBJS@ \ @STORE_OBJS@ \ @AUTH_OBJS@ \ @CRYPTLIB@ \ @@ -476,7 +488,7 @@ squid_LDADD = \ -lmiscutil \ @XTRA_LIBS@ \ @EPOLL_LIBS@ -squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a @STORE_OBJS@ +squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a @STORE_OBJS@ @STORE_LINKOBJS@ unlinkd_SOURCES = unlinkd.cc SquidNew.cc unlinkd_CXXFLAGS = -DUNLINK_DAEMON @@ -652,7 +664,6 @@ ufsdump_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a nodist_ufsdump_SOURCES = \ repl_modules.cc \ auth_modules.cc \ - store_modules.cc \ cf_parser.h \ globals.cc \ string_arrays.c @@ -666,8 +677,7 @@ BUILT_SOURCES = \ globals.cc \ string_arrays.c \ repl_modules.cc \ - auth_modules.cc \ - store_modules.cc + auth_modules.cc sysconf_DATA = \ squid.conf.default \ @@ -684,7 +694,6 @@ EXTRA_DIST = \ mk-globals-c.pl \ mk-string-arrays.pl \ auth_modules.sh \ - store_modules.sh \ repl_modules.sh \ mib.txt \ mime.conf.default @@ -760,9 +769,6 @@ cf.data: cf.data.pre Makefile s%@[V]ERSION@%$(VERSION)%g;"\ < $(srcdir)/cf.data.pre >$@ -store_modules.cc: store_modules.sh Makefile - $(SHELL) $(srcdir)/store_modules.sh $(STORE_MODULES) >store_modules.cc - repl_modules.cc: repl_modules.sh Makefile $(SHELL) $(srcdir)/repl_modules.sh $(REPL_POLICIES) > repl_modules.cc @@ -797,7 +803,7 @@ uninstall-local: # fi DISTCLEANFILES = cf_gen_defines.h cf.data cf_parser.h squid.conf.default \ - globals.cc string_arrays.c repl_modules.cc auth_modules.cc store_modules.cc + globals.cc string_arrays.c repl_modules.cc auth_modules.cc ##install-pinger: ## @f=$(PINGER_EXE); \ diff --git a/src/Store.h b/src/Store.h index 7699254e36..696a73af14 100644 --- a/src/Store.h +++ b/src/Store.h @@ -1,6 +1,6 @@ /* - * $Id: Store.h,v 1.10 2003/03/15 04:17:39 robertc Exp $ + * $Id: Store.h,v 1.11 2003/07/22 15:23:01 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -46,13 +46,10 @@ class StoreClient; class MemObject; -typedef void STSETUP(storefs_entry_t *); - class StoreEntry : public hash_link { public: - static void FsAdd(const char *, STSETUP *); static DeferredRead::DeferrableRead DeferReader; bool checkDeferRead(int fd) const; @@ -218,12 +215,8 @@ SQUIDCEXTERN void storeHeapPositionUpdate(StoreEntry *, SwapDir *); SQUIDCEXTERN void storeSwapFileNumberSet(StoreEntry * e, sfileno filn); SQUIDCEXTERN void storeFsInit(void); SQUIDCEXTERN void storeFsDone(void); -typedef void STSETUP(storefs_entry_t *); SQUIDCEXTERN void storeReplAdd(const char *, REMOVALPOLICYCREATE *); -/* store_modules.c */ -SQUIDCEXTERN void storeFsSetup(void); - #ifdef _USE_INLINE_ #include "Store.cci" #endif diff --git a/src/StoreFileSystem.cc b/src/StoreFileSystem.cc new file mode 100644 index 0000000000..5f516ac912 --- /dev/null +++ b/src/StoreFileSystem.cc @@ -0,0 +1,91 @@ + +/* + * $Id: StoreFileSystem.cc,v 1.1 2003/07/22 15:23:01 robertc Exp $ + * + * DEBUG: section 92 Storage File System + * 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. + * + * Copyright (c) 2003, Robert Collins + */ + +#include "squid.h" +#include "StoreFileSystem.h" + +Vector *StoreFileSystem::_FileSystems = NULL; + +void +StoreFileSystem::SetupAllFs() +{ + for (iterator i = GetFileSystems().begin(); i != GetFileSystems().end(); ++i) + /* Call the FS to set up capabilities and initialize the FS driver */ + (*i)->setup(); +} + +void +StoreFileSystem::FsAdd(StoreFileSystem &instance) +{ + iterator i = GetFileSystems().begin(); + + while (i != GetFileSystems().end()) { + assert(strcmp((*i)->type(), instance.type()) != 0); + ++i; + } + + GetFileSystems().push_back (&instance); +} + +Vector const & +StoreFileSystem::FileSystems() +{ + return GetFileSystems(); +} + +Vector & +StoreFileSystem::GetFileSystems() +{ + if (!_FileSystems) + _FileSystems = new Vector; + + return *_FileSystems; +} + +/* + * called when a graceful shutdown is to occur + * of each fs module. + */ +void +StoreFileSystem::FreeAllFs() +{ + while (GetFileSystems().size()) { + StoreFileSystem *fs = GetFileSystems().back(); + GetFileSystems().pop_back(); + fs->done(); + } +} + diff --git a/src/StoreFileSystem.h b/src/StoreFileSystem.h new file mode 100644 index 0000000000..3be1789379 --- /dev/null +++ b/src/StoreFileSystem.h @@ -0,0 +1,73 @@ + +/* + * $Id: StoreFileSystem.h,v 1.1 2003/07/22 15:23:01 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. + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef SQUID_STOREFILESYSTEM_H +#define SQUID_STOREFILESYSTEM_H + +#include "squid.h" +#include "Array.h" + +class StoreFileSystem +{ + +public: + static void SetupAllFs(); + static void FsAdd(StoreFileSystem &); + static void FreeAllFs(); + static Vector const &FileSystems(); + typedef Vector::iterator iterator; + typedef Vector::const_iterator const_iterator; + StoreFileSystem() : initialised (false) {} + + virtual ~StoreFileSystem(){} + + virtual char const *type () const = 0; + virtual SwapDir *createSwapDir() = 0; + virtual void done() = 0; + virtual void setup() = 0; + // Not implemented + StoreFileSystem(StoreFileSystem const &); + StoreFileSystem &operator=(StoreFileSystem const&); + +protected: + bool initialised; + +private: + static Vector &GetFileSystems(); + static Vector *_FileSystems; +}; + +typedef StoreFileSystem storefs_entry_t; + + +#endif /* SQUID_STOREFILESYSTEM_H */ diff --git a/src/StoreIOState.h b/src/StoreIOState.h index 5695deef5f..7e08d09ba9 100644 --- a/src/StoreIOState.h +++ b/src/StoreIOState.h @@ -1,6 +1,6 @@ /* - * $Id: StoreIOState.h,v 1.4 2003/02/21 22:50:06 robertc Exp $ + * $Id: StoreIOState.h,v 1.5 2003/07/22 15:23:01 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -44,7 +44,7 @@ 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 void deleteSelf() const = 0; virtual ~storeIOState(); storeIOState(); diff --git a/src/SwapDir.cc b/src/SwapDir.cc index 002a88b371..f022ca865c 100644 --- a/src/SwapDir.cc +++ b/src/SwapDir.cc @@ -1,6 +1,6 @@ /* - * $Id: SwapDir.cc,v 1.3 2003/02/21 22:50:06 robertc Exp $ + * $Id: SwapDir.cc,v 1.4 2003/07/22 15:23:01 robertc Exp $ * * DEBUG: section ?? Swap Dir base object * AUTHOR: Robert Collins @@ -36,14 +36,7 @@ #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; -} +#include "StoreFileSystem.h" SwapDir::~SwapDir() { @@ -128,3 +121,149 @@ SwapDir::writeCleanDone(){} void SwapDir::logEntry(const StoreEntry & e, int op) const{} + +char const * +SwapDir::type() const +{ + return theType; +} + +/* NOT performance critical. Really. Don't bother optimising for speed + * - RBC 20030718 + */ +SwapDirOption * +SwapDir::getOptionTree() const +{ + SwapDirOptionVector *result = new SwapDirOptionVector; + result->options.push_back(new SwapDirOptionAdapter(*const_cast(this), &SwapDir::optionReadOnlyParse, &SwapDir::optionReadOnlyDump)); + result->options.push_back(new SwapDirOptionAdapter(*const_cast(this), &SwapDir::optionMaxSizeParse, &SwapDir::optionMaxSizeDump)); + return result; +} + +void +SwapDir::parseOptions(int reconfiguring) +{ + unsigned int old_read_only = flags.read_only; + char *name, *value; + + SwapDirOption *newOption = getOptionTree(); + + while ((name = strtok(NULL, w_space)) != NULL) { + value = strchr(name, '='); + + if (value) + *value++ = '\0'; /* cut on = */ + + if (newOption) + if (!newOption->parse(name, value, reconfiguring)) + self_destruct(); + } + + delete newOption; + + /* + * Handle notifications about reconfigured single-options with no value + * where the removal of the option cannot be easily detected in the + * parsing... + */ + + if (reconfiguring) { + if (old_read_only != flags.read_only) { + debug(3, 1) ("Cache dir '%s' now %s\n", + path, flags.read_only ? "Read-Only" : "Read-Write"); + } + } +} + +void +SwapDir::dumpOptions(StoreEntry * entry) const +{ + SwapDirOption *newOption = getOptionTree(); + + if (newOption) + newOption->dump(entry); + + delete newOption; +} + +bool +SwapDir::optionReadOnlyParse(char const *option, const char *value, int reconfiguring) +{ + if (strcmp(option, "read-only") != 0) + return false; + + int read_only = 0; + + if (value) + read_only = xatoi(value); + else + read_only = 1; + + flags.read_only = read_only; + + return true; +} + +void +SwapDir::optionReadOnlyDump(StoreEntry * e) const +{ + if (flags.read_only) + storeAppendPrintf(e, " read-only"); +} + +bool +SwapDir::optionMaxSizeParse(char const *option, const char *value, int reconfiguring) +{ + if (strcmp(option, "max-size") != 0) + return false; + + if (!value) + self_destruct(); + + ssize_t size = xatoi(value); + + if (reconfiguring && max_objsize != size) + debug(3, 1) ("Cache dir '%s' max object size now %ld\n", path, (long int) size); + + max_objsize = size; + + return true; +} + +void +SwapDir::optionMaxSizeDump(StoreEntry * e) const +{ + if (max_objsize != -1) + storeAppendPrintf(e, " max-size=%ld", (long int) max_objsize); +} + +SwapDirOptionVector::~SwapDirOptionVector() +{ + while (options.size()) { + delete options.back(); + options.pop_back(); + } +} + +bool +SwapDirOptionVector::parse(char const *option, const char *value, int reconfiguring) +{ + Vector::iterator i = options.begin(); + + while (i != options.end()) { + if ((*i)->parse(option,value, reconfiguring)) + return true; + + ++i; + } + + return false; +} + +void +SwapDirOptionVector::dump(StoreEntry * e) const +{ + for(Vector::const_iterator i = options.begin(); + i != options.end(); ++i) + (*i)->dump(e); +} diff --git a/src/SwapDir.h b/src/SwapDir.h index b5e67018f7..e13580123f 100644 --- a/src/SwapDir.h +++ b/src/SwapDir.h @@ -1,6 +1,6 @@ /* - * $Id: SwapDir.h,v 1.5 2003/07/15 23:12:02 robertc Exp $ + * $Id: SwapDir.h,v 1.6 2003/07/22 15:23:01 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -35,26 +35,87 @@ #define SQUID_SWAPDIR_H #include "StoreIOState.h" +#include "Array.h" + +/* cache option parsers */ + +class SwapDirOption +{ + +public: + virtual ~SwapDirOption() {} + + virtual bool parse(char const *option, const char *value, int reconfiguring) = 0; + virtual void dump (StoreEntry * e) const = 0; +}; + +class SwapDirOptionVector : public SwapDirOption +{ + +public: + virtual ~SwapDirOptionVector(); + virtual bool parse(char const *option, const char *value, int reconfiguring); + virtual void dump(StoreEntry * e) const; + Vectoroptions; +}; + +template + +class SwapDirOptionAdapter : public SwapDirOption +{ + +public: + SwapDirOptionAdapter (C& theObject, bool (C::*parseFP)(char const *option, const char *value, int reconfiguring), void (C::*dumpFP) (StoreEntry * e) const) : object(theObject), parser (parseFP), dumper(dumpFP) {} + + bool parse(char const *option, const char *value, int reconfiguring) + { + if (parser) + return (object.*parser)(option, value, reconfiguring); + + return false; + } + + void dump (StoreEntry * e) const + { + if (dumper) + (object.*dumper) (e); + } + +private: + C &object; + bool (C::*parser) (char const *option, const char *value, int reconfiguring) ; + void (C::*dumper)(StoreEntry * e) const; +}; /* 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); class SwapDir { public: - static SwapDir *Factory (_storefs_entry const &fs); - SwapDir() : cur_size (0), low_size(0), max_size(0), max_objsize (-1) + SwapDir(char const *aType) : theType (aType), cur_size (0), low_size(0), max_size(0), max_objsize (-1) { fs.blksize = 1024; } virtual ~SwapDir(); virtual void reconfigure(int, char *) = 0; - const char *type; + char const *type() const; + +protected: + void parseOptions(int reconfiguring); + void dumpOptions(StoreEntry * e) const; + virtual SwapDirOption *getOptionTree() const; + +private: + bool optionReadOnlyParse(char const *option, const char *value, int reconfiguring); + void optionReadOnlyDump(StoreEntry * e) const; + bool optionMaxSizeParse(char const *option, const char *value, int reconfiguring); + void optionMaxSizeDump(StoreEntry * e) const; + char const *theType; + +public: int cur_size; int low_size; int max_size; diff --git a/src/cache_cf.cc b/src/cache_cf.cc index afb31adad4..65ac7cce9f 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.cc,v 1.446 2003/07/16 12:54:42 hno Exp $ + * $Id: cache_cf.cc,v 1.447 2003/07/22 15:23:01 robertc Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -39,6 +39,7 @@ #include "SwapDir.h" #include "ConfigParser.h" #include "ACL.h" +#include "StoreFileSystem.h" #if SQUID_SNMP #include "snmp.h" @@ -64,10 +65,6 @@ static const char *const B_GBYTES_STR = "GB"; 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 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 const * sd); static void parse_logformat(logformat ** logformat_definitions); static void parse_access_log(customlog ** customlog_definitions); static int check_null_access_log(customlog *customlog_definitions); @@ -78,13 +75,6 @@ static void free_logformat(logformat ** definitions); static void free_access_log(customlog ** definitions); -static struct cache_dir_option common_cachedir_options[] = - { - {"read-only", parse_cachedir_option_readonly, dump_cachedir_option_readonly}, - - {"max-size", parse_cachedir_option_maxsize, dump_cachedir_option_maxsize}, - {NULL, NULL} - }; static void update_maxobjsize(void); @@ -221,7 +211,7 @@ wordlistDup(const wordlist * w) * These functions is the same as atoi/l/f, except that they check for errors */ -static long +long xatol(const char *token) { char *end; @@ -233,7 +223,7 @@ xatol(const char *token) return ret; } -static int +int xatoi(const char *token) { return xatol(token); @@ -1204,19 +1194,6 @@ free_http_header_replace(header_mangler header[]) #endif -void - -dump_cachedir_options(StoreEntry * entry, struct cache_dir_option *options, SwapDir const * sd) -{ - - struct cache_dir_option *option; - - if (!options) - return; - - for (option = options; option->name; option++) - option->dump(entry, option->name, sd); -} static void dump_cachedir(StoreEntry * entry, const char *name, _SquidConfig::_cacheSwap swap) @@ -1227,13 +1204,13 @@ dump_cachedir(StoreEntry * entry, const char *name, _SquidConfig::_cacheSwap swa for (i = 0; i < swap.n_configured; i++) { s = swap.swapDirs[i]; - storeAppendPrintf(entry, "%s %s %s", name, s->type, s->path); + storeAppendPrintf(entry, "%s %s %s", name, s->type(), s->path); s->dump(*entry); - dump_cachedir_options(entry, common_cachedir_options, s); storeAppendPrintf(entry, "\n"); } } + static int check_null_cachedir(_SquidConfig::_cacheSwap swap) { @@ -1351,16 +1328,13 @@ allocate_new_swapdir(_SquidConfig::_cacheSwap * swap) } } +/* TODO: just return the object, the # is irrelevant */ static int find_fstype(char *type) { - int i; - - for (i = 0; storefs_list[i].typestr != NULL; i++) { - if (strcasecmp(type, storefs_list[i].typestr) == 0) { - return i; - } - } + for (size_t i = 0; i < StoreFileSystem::FileSystems().size(); ++i) + if (strcasecmp(type, StoreFileSystem::FileSystems().items[i]->type()) == 0) + return (int)i; return (-1); } @@ -1426,7 +1400,7 @@ parse_cachedir(_SquidConfig::_cacheSwap * swap) } allocate_new_swapdir(swap); - swap->swapDirs[swap->n_configured] = SwapDir::Factory(storefs_list[fs]); + swap->swapDirs[swap->n_configured] = StoreFileSystem::FileSystems().items[fs]->createSwapDir(); sd = swap->swapDirs[swap->n_configured]; /* parse the FS parameters and options */ sd->parse(swap->n_configured, path_str); @@ -1435,103 +1409,6 @@ parse_cachedir(_SquidConfig::_cacheSwap * swap) update_maxobjsize(); } -static void -parse_cachedir_option_readonly(SwapDir * sd, const char *option, const char *value, int reconfiguring) -{ - int read_only = 0; - - if (value) - read_only = xatoi(value); - else - read_only = 1; - - sd->flags.read_only = read_only; -} - -static void -dump_cachedir_option_readonly(StoreEntry * e, const char *option, SwapDir const * sd) -{ - if (sd->flags.read_only) - storeAppendPrintf(e, " %s", option); -} - -static void -parse_cachedir_option_maxsize(SwapDir * sd, const char *option, const char *value, int reconfiguring) -{ - ssize_t size; - - if (!value) - self_destruct(); - - size = xatoi(value); - - if (reconfiguring && sd->max_objsize != size) - debug(3, 1) ("Cache dir '%s' max object size now %ld\n", sd->path, (long int) size); - - sd->max_objsize = size; -} - -static void -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); -} - -void - -parse_cachedir_options(SwapDir * sd, struct cache_dir_option *options, int reconfiguring) -{ - unsigned int old_read_only = sd->flags.read_only; - char *name, *value; - - struct cache_dir_option *option, *op; - - while ((name = strtok(NULL, w_space)) != NULL) - { - value = strchr(name, '='); - - if (value) - *value++ = '\0'; /* cut on = */ - - option = NULL; - - if (options) { - for (op = options; !option && op->name; op++) { - if (strcmp(op->name, name) == 0) { - option = op; - break; - } - } - } - - for (op = common_cachedir_options; !option && op->name; op++) { - if (strcmp(op->name, name) == 0) { - option = op; - break; - } - } - - if (!option || !option->parse) - self_destruct(); - - option->parse(sd, name, value, reconfiguring); - } - - /* - * Handle notifications about reconfigured single-options with no value - * where the removal of the option cannot be easily detected in the - * parsing... - */ - if (reconfiguring) - { - if (old_read_only != sd->flags.read_only) { - debug(3, 1) ("Cache dir '%s' now %s\n", - sd->path, sd->flags.read_only ? "Read-Only" : "Read-Write"); - } - } -} - static void free_cachedir(_SquidConfig::_cacheSwap * swap) { diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am index c01b8717c4..354bfc8edb 100644 --- a/src/fs/Makefile.am +++ b/src/fs/Makefile.am @@ -1,6 +1,6 @@ # Makefile for storage modules in the Squid Object Cache server # -# $Id: Makefile.am,v 1.7 2003/03/11 22:11:39 robertc Exp $ +# $Id: Makefile.am,v 1.8 2003/07/22 15:23:18 robertc Exp $ # AUTOMAKE_OPTIONS = subdir-objects @@ -13,10 +13,10 @@ EXTRA_LIBRARIES = libaufs.a libcoss.a libdiskd.a libnull.a libufs.a noinst_LIBRARIES = @STORE_LIBS@ libaufs_a_SOURCES = aufs/aiops.cc aufs/async_io.cc aufs/store_asyncufs.h \ - aufs/store_dir_aufs.cc aufs/store_io_aufs.cc + aufs/store_io_aufs.cc libcoss_a_SOURCES = coss/store_coss.h coss/store_io_coss.cc coss/store_dir_coss.cc \ coss/async_io.cc coss/async_io.h -libdiskd_a_SOURCES = diskd/diskd.cc diskd/store_dir_diskd.cc \ +libdiskd_a_SOURCES = diskd/diskd.cc \ diskd/store_diskd.h \ diskd/store_io_diskd.cc @@ -32,7 +32,9 @@ libnull_a_SOURCES = null/store_null.cc libufs_a_SOURCES = ufs/store_dir_ufs.cc ufs/store_io_ufs.cc ufs/store_ufs.h EXTRA_DIST = \ - coss/coss-notes.txt + coss/coss-notes.txt \ + ufs/IOModule.h \ + ufs/StoreFSufs.h INCLUDES = -I. -I$(top_builddir)/include -I$(top_srcdir)/include \ -I$(top_srcdir)/src/ diff --git a/src/fs/aufs/StoreFSaufs.cc b/src/fs/aufs/StoreFSaufs.cc new file mode 100644 index 0000000000..577e379749 --- /dev/null +++ b/src/fs/aufs/StoreFSaufs.cc @@ -0,0 +1,42 @@ + +/* + * $Id: StoreFSaufs.cc,v 1.1 2003/07/22 15:23:10 robertc Exp $ + * + * DEBUG: section 47 Store Directory Routines + * 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. + * + * Copyright (c) 2003, Robert Collins + */ + +#include "squid.h" +#include "StoreFileSystem.h" +#include "fs/ufs/StoreFSufs.h" +#include "fs/aufs/store_asyncufs.h" + +static StoreFSufs AufsInstance(AufsIOModule::GetInstance(), "aufs"); diff --git a/src/fs/aufs/async_io.cc b/src/fs/aufs/async_io.cc index 605dae6661..c949b27470 100644 --- a/src/fs/aufs/async_io.cc +++ b/src/fs/aufs/async_io.cc @@ -1,6 +1,6 @@ /* - * $Id: async_io.cc,v 1.23 2003/02/21 22:50:29 robertc Exp $ + * $Id: async_io.cc,v 1.24 2003/07/22 15:23:10 robertc Exp $ * * DEBUG: section 32 Asynchronous Disk I/O * AUTHOR: Pete Bentley @@ -95,7 +95,6 @@ typedef struct squidaio_unlinkq_t squidaio_unlinkq_t; static dlink_list used_list; -static int initialised = 0; static OBJH aioStats; static MemPool *squidaio_ctrl_pool; static void aioFDWasClosed(int fd); @@ -107,9 +106,8 @@ aioFDWasClosed(int fd) fd_close(fd); } - void -aioInit(void) +AufsIO::init(void) { if (initialised) return; @@ -119,14 +117,18 @@ aioInit(void) cachemgrRegister("squidaio_counts", "Async IO Function Counters", aioStats, 0, 1); - initialised = 1; + initialised = true; } void -aioDone(void) +AufsIO::done(void) { + if (!initialised) + return; + memPoolDestroy(&squidaio_ctrl_pool); - initialised = 0; + + initialised = false; } void @@ -134,7 +136,7 @@ aioOpen(const char *path, int oflag, mode_t mode, AIOCB * callback, void *callba { squidaio_ctrl_t *ctrlp; - assert(initialised); + assert(AufsIO::Instance.initialised); squidaio_counts.open_start++; ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool); ctrlp->fd = -2; @@ -152,7 +154,7 @@ aioClose(int fd) { squidaio_ctrl_t *ctrlp; - assert(initialised); + assert(AufsIO::Instance.initialised); squidaio_counts.close_start++; aioCancel(fd); ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool); @@ -172,7 +174,7 @@ aioCancel(int fd) squidaio_ctrl_t *ctrlp; dlink_node *m, *next; - assert(initialised); + assert(AufsIO::Instance.initialised); squidaio_counts.cancel++; for (m = used_list.head; m; m = next) { @@ -214,7 +216,7 @@ aioWrite(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callba squidaio_ctrl_t *ctrlp; int seekmode; - assert(initialised); + assert(AufsIO::Instance.initialised); squidaio_counts.write_start++; ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool); ctrlp->fd = fd; @@ -243,7 +245,7 @@ aioRead(int fd, int offset, int len, AIOCB * callback, void *callback_data) squidaio_ctrl_t *ctrlp; int seekmode; - assert(initialised); + assert(AufsIO::Instance.initialised); squidaio_counts.read_start++; ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool); ctrlp->fd = fd; @@ -272,7 +274,7 @@ aioStat(char *path, struct stat *sb, AIOCB * callback, void *callback_data) { squidaio_ctrl_t *ctrlp; - assert(initialised); + assert(AufsIO::Instance.initialised); squidaio_counts.stat_start++; ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool); ctrlp->fd = -2; @@ -289,7 +291,7 @@ void aioUnlink(const char *path, AIOCB * callback, void *callback_data) { squidaio_ctrl_t *ctrlp; - assert(initialised); + assert(AufsIO::Instance.initialised); squidaio_counts.unlink_start++; ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool); ctrlp->fd = -2; @@ -305,7 +307,7 @@ void aioTruncate(const char *path, off_t length, AIOCB * callback, void *callback_data) { squidaio_ctrl_t *ctrlp; - assert(initialised); + assert(AufsIO::Instance.initialised); squidaio_counts.unlink_start++; ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool); ctrlp->fd = -2; @@ -319,7 +321,7 @@ aioTruncate(const char *path, off_t length, AIOCB * callback, void *callback_dat int -AUFSSwapDir::callback() +AufsIO::callback() { squidaio_result_t *resultp; squidaio_ctrl_t *ctrlp; @@ -428,7 +430,7 @@ aioStats(StoreEntry * sentry) /* Flush all pending I/O */ void -AUFSSwapDir::sync() +AufsIO::sync() { if (!initialised) return; /* nothing to do then */ @@ -443,6 +445,8 @@ AUFSSwapDir::sync() debug(32, 1) ("aioSync: done\n"); } +AufsIO::AufsIO() : initialised (false) {} + int aioQueueSize(void) { diff --git a/src/fs/aufs/store_asyncufs.h b/src/fs/aufs/store_asyncufs.h index e2da87ebae..2c498763a8 100644 --- a/src/fs/aufs/store_asyncufs.h +++ b/src/fs/aufs/store_asyncufs.h @@ -98,12 +98,13 @@ public: 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 void close (); virtual bool error() const; virtual int getFD() const { return fd;} virtual bool canRead() const; virtual bool canWrite() const; + virtual bool ioInProgress()const; private: #if ASYNC_READ @@ -125,6 +126,7 @@ private: bool errorOccured; char const *path_; AufsIO* IO; + size_t inProgressIOs; static AIOCB OpenDone; void openDone(int fd, const char *buf, int aio_return, int aio_errno); IORequestor::Pointer ioRequestor; @@ -135,73 +137,45 @@ private: 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 write_kicking: - 1; - -unsigned int read_kicking: - 1; - -unsigned int inreaddone: - 1; - } - - flags; - 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(); -}; - /* * Store IO stuff */ -#include "SwapDir.h" -class AUFSSwapDir : public UFSSwapDir +class SwapDir; + +#include "fs/ufs/IOModule.h" + +class AufsIOModule : public IOModule { 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 *); + static AufsIOModule &GetInstance(); + virtual void init(); + virtual void shutdown(); + virtual UFSStrategy *createSwapDirIOStrategy(); + +private: + static AufsIOModule *Instance; }; class AufsIO : public UFSStrategy { public: + AufsIO(); virtual bool shedLoad(); + virtual int load(); 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); + virtual void unlinkFile (char const *); + virtual void sync(); + virtual int callback(); + void init(); + void done(); static AufsIO Instance; + bool initialised; }; + #endif diff --git a/src/fs/aufs/store_dir_aufs.cc b/src/fs/aufs/store_dir_aufs.cc deleted file mode 100644 index a837c043cd..0000000000 --- a/src/fs/aufs/store_dir_aufs.cc +++ /dev/null @@ -1,164 +0,0 @@ - -/* - * $Id: store_dir_aufs.cc,v 1.56 2003/05/11 10:00:41 hno Exp $ - * - * DEBUG: section 47 Store Directory Routines - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "Store.h" - -#include "store_asyncufs.h" -#include "ufscommon.h" -#include "SwapDir.h" - -static int asyncufs_initialised = 0; - -/* The MAIN externally visible function */ -STSETUP storeFsSetup_aufs; - -/* - * storeAufsDirCheckObj - * - * 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 -AUFSSwapDir::canStore(StoreEntry const &e) const -{ - int loadav; - int ql; - -#if OLD_UNUSED_CODE - - if (storeAufsDirExpiredReferenceAge(this) < 300) { - debug(47, 3) ("storeAufsDirCheckObj: NO: LRU Age = %d\n", - storeAufsDirExpiredReferenceAge(this)); - /* 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) ("storeAufsDirCheckObj: load=%d\n", loadav); - - return loadav; -} - -void -AUFSSwapDir::unlinkFile(char const *path) -{ -#if USE_TRUNCATE_NOT_UNLINK - aioTruncate(path, NULL, NULL); -#else - - aioUnlink(path, NULL, NULL); -#endif -} - -/* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */ - -static struct cache_dir_option options[] = - { -#if NOT_YET_DONE - {"L1", storeAufsDirParseL1, storeAufsDirDumpL1}, - {"L2", storeAufsDirParseL2, storeAufsDirDumpL2}, -#endif - {NULL, NULL} - }; - -/* - * storeAufsDirReconfigure - * - * This routine is called when the given swapdir needs reconfiguring - */ -void -AUFSSwapDir::reconfigure(int anIndex, char *aPath) -{ - UFSSwapDir::reconfigure (anIndex, aPath); - - parse_cachedir_options(this, options, 0); -} - -void -AUFSSwapDir::dump(StoreEntry & entry) const -{ - UFSSwapDir::dump(entry); - dump_cachedir_options(&entry, options, this); -} - -/* - * storeAufsDirParse * - * Called when a *new* fs is being setup. - */ -void -AUFSSwapDir::parse(int anIndex, char *aPath) -{ - UFSSwapDir::parse(anIndex, aPath); - - parse_cachedir_options(this, options, 0); -} - -/* - * Initial setup / end destruction - */ -static void -storeAufsDirDone(void) -{ - aioDone(); - 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->donefunc = storeAufsDirDone; - storefs->newfunc = storeAufsNew; - - asyncufs_initialised = 1; - aioInit(); -} diff --git a/src/fs/aufs/store_io_aufs.cc b/src/fs/aufs/store_io_aufs.cc index a546e5cfbc..820375a7a5 100644 --- a/src/fs/aufs/store_io_aufs.cc +++ b/src/fs/aufs/store_io_aufs.cc @@ -9,45 +9,10 @@ #include "ufscommon.h" #include "SwapDir.h" -static void storeAufsIOCallback(storeIOState * sio, int errflag); -static int storeAufsNeedCompletetion(storeIOState *); - /* === PUBLIC =========================================================== */ -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(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 @@ -67,6 +32,24 @@ AufsIO::shedLoad() return false; } +int +AufsIO::load() +{ + int loadav; + int ql; + + ql = aioQueueSize(); + + if (ql == 0) + loadav = 0; + + loadav = ql * 1000 / MAGIC1; + + debug(47, 9) ("storeAufsDirCheckObj: load=%d\n", loadav); + + return loadav; +} + void AufsIO::deleteSelf() const { @@ -76,7 +59,7 @@ AufsIO::deleteSelf() const StoreIOState::Pointer AufsIO::createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const { - return new squidaiostate_t (SD, e, callback, callback_data); + return new UFSStoreState (SD, e, callback, callback_data); } DiskFile::Pointer @@ -85,6 +68,47 @@ AufsIO::newFile (char const *path) return new AUFSFile (path, this); } +void +AufsIO::unlinkFile(char const *path) +{ + statCounter.syscalls.disk.unlinks++; +#if USE_TRUNCATE_NOT_UNLINK + + aioTruncate(path, NULL, NULL); +#else + + aioUnlink(path, NULL, NULL); +#endif +} + +AufsIOModule *AufsIOModule::Instance = NULL; +AufsIOModule & +AufsIOModule::GetInstance() +{ + if (!Instance) + Instance = new AufsIOModule; + + return *Instance; +} + +void +AufsIOModule::init() +{ + AufsIO::Instance.init(); +} + +void +AufsIOModule::shutdown() +{ + AufsIO::Instance.done(); +} + +UFSStrategy * +AufsIOModule::createSwapDirIOStrategy() +{ + return new InstanceToSingletonAdapter(&AufsIO::Instance); +} + CBDATA_CLASS_INIT(AUFSFile); void * AUFSFile::operator new (size_t) @@ -109,7 +133,8 @@ AUFSFile::operator delete (void *address) void AUFSFile::deleteSelf() const {delete this;} -AUFSFile::AUFSFile (char const *aPath, AufsIO *anIO):fd(-1), errorOccured (false), IO(anIO) +AUFSFile::AUFSFile (char const *aPath, AufsIO *anIO):fd(-1), errorOccured (false), IO(anIO), + inProgressIOs (0) { assert (aPath); debug (79,3)("UFSFile::UFSFile: %s\n", aPath); @@ -141,6 +166,8 @@ AUFSFile::open (int flags, mode_t mode, IORequestor::Pointer callback) ioRequestor = callback; + ++inProgressIOs; + #if ASYNC_OPEN aioOpen(path_, flags, mode, AUFSFile::OpenDone, this); @@ -158,6 +185,7 @@ AUFSFile::read(char *buf, off_t offset, size_t size) assert (fd > -1); assert (ioRequestor.getRaw()); statCounter.syscalls.disk.reads++; + ++inProgressIOs; #if ASYNC_READ aioRead(fd, offset, size, ReadDone, this); @@ -186,6 +214,8 @@ AUFSFile::create (int flags, mode_t mode, IORequestor::Pointer callback) ioRequestor = callback; + ++inProgressIOs; + #if ASYNC_CREATE aioOpen(path_, flags, mode, AUFSFile::OpenDone, this); @@ -232,6 +262,7 @@ AUFSFile::openDone(int unused, const char *unused2, int anFD, int errflag) debug(79, 3) ("AUFSFile::openDone: exiting\n"); IORequestor::Pointer t = ioRequestor; + --inProgressIOs; t->ioCompletedNotification(); } @@ -251,7 +282,7 @@ StoreIOState::Pointer storeAufsOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data) { - UFSStrategy *IO = dynamic_cast (((AUFSSwapDir *)SD)->IO); + UFSStrategy *IO = dynamic_cast (((UFSSwapDir *)SD)->IO); assert (IO); return IO->open (SD, e, file_callback, callback, callback_data); } @@ -260,25 +291,22 @@ storeAufsOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, StoreIOState::Pointer storeAufsCreate(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data) { - UFSStrategy *IO = dynamic_cast (((AUFSSwapDir *)SD)->IO); + UFSStrategy *IO = dynamic_cast (((UFSSwapDir *)SD)->IO); assert (IO); return IO->create (SD, e, file_callback, callback, callback_data); } -/* Close */ + void -squidaiostate_t::close() +AUFSFile::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 */ + debug (79,3)("AUFSFile::close: %p closing for %p\n", this, ioRequestor.getRaw()); - if (storeAufsNeedCompletetion(this)) { - closing = true; - return; + if (!ioInProgress()) { + doClose(); + assert (ioRequestor.getRaw()); + ioRequestor->closeCompleted(); } - - storeAufsIOCallback(this, DISK_OK); } bool @@ -293,6 +321,7 @@ AUFSFile::write(char const *buf, size_t size, off_t offset, FREE *free_func) { debug(79, 3) ("storeAufsWrite: FD %d\n", fd); statCounter.syscalls.disk.writes++; + ++inProgressIOs; #if ASYNC_WRITE aioWrite(fd, offset, (char *)buf, size, WriteDone, this, @@ -310,15 +339,10 @@ AUFSFile::canWrite() const return fd > -1; } -/* Unlink */ -void -AUFSSwapDir::unlink(StoreEntry & e) +bool +AUFSFile::ioInProgress()const { - debug(79, 3) ("storeAufsUnlink: dirno %d, fileno %08X\n", index, e.swap_filen); - statCounter.syscalls.disk.unlinks++; - replacementRemove(&e); - mapBitReset(e.swap_filen); - UFSSwapDir::unlinkFile(e.swap_filen); + return inProgressIOs > 0; } /* === STATIC =========================================================== */ @@ -367,80 +391,9 @@ AUFSFile::readDone(int rvfd, const char *buf, int len, int errflag) #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); - - 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); - } - - 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; + --inProgressIOs; -#if ASYNC_WRITE - - if (!kickWriteQueue()) - 0; - else if (closing) - storeAufsIOCallback(this, errflag); - -#else - - if (!flags.write_kicking) { - flags.write_kicking = 1; - - while (kickWriteQueue()) - (void) 0; - - flags.write_kicking = 0; - - if (closing) - storeAufsIOCallback(this, errflag); - } - -#endif + ioRequestor->readCompleted(buf, rlen, errflag); } void @@ -477,118 +430,10 @@ AUFSFile::writeDone (int rvfd, int errflag, size_t len) assert(++loop_detect < 10); + --inProgressIOs; + ioRequestor->writeCompleted(errflag, len); --loop_detect; } -static void -storeAufsIOCallback(storeIOState * sio, int errflag) -{ - STIOCB *callback = sio->callback; - squidaiostate_t *aiostate = dynamic_cast(sio); - int fd = aiostate->fd; - debug(79, 3) ("storeAufsIOCallback: errflag=%d\n", errflag); - debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); - - if (callback) { - void *cbdata; - sio->callback = NULL; - - if (cbdataReferenceValidDone(sio->callback_data, &cbdata)) - callback(cbdata, errflag, sio); - } - - debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); - aiostate->fd = -1; - - if (aiostate->opening || aiostate->creating) - Opening_FD--; - - if (fd < 0) - return; - - debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); - - aiostate->theFile = NULL; - - debug(79, 9) ("%s:%d\n", __FILE__, __LINE__); -} - - -static int -storeAufsNeedCompletetion(storeIOState * sio) -{ - squidaiostate_t *aiostate = dynamic_cast(sio); - - if (aiostate->writing) - return true; - - if (aiostate->creating && FILE_MODE(sio->mode) == O_WRONLY) - return 1; - - if (aiostate->reading) - return 1; - - if (aiostate->flags.inreaddone) - return 1; - - return 0; -} - - -/* - * Clean up references from the SIO before it gets released. - * The actuall SIO is managed by cbdata so we do not need - * to bother with that. - */ -squidaiostate_t::~squidaiostate_t() -{} - -void -squidaiostate_t::ioCompletedNotification() -{ - if (opening) { - opening = false; - openDone(); - return; - } - - 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 (closing) - storeAufsIOCallback(this, theFile->error() ? -1 : 0); - - debug(79, 3) ("squidaiostate_t::openDone: exiting\n"); -} diff --git a/src/fs/coss/StoreFScoss.cc b/src/fs/coss/StoreFScoss.cc new file mode 100644 index 0000000000..e01725cca4 --- /dev/null +++ b/src/fs/coss/StoreFScoss.cc @@ -0,0 +1,82 @@ + +/* + * $Id: StoreFScoss.cc,v 1.1 2003/07/22 15:23:10 robertc Exp $ + * + * DEBUG: section 47 Store Directory Routines + * 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. + * + * Copyright (c) 2003, Robert Collins + */ + +#include "StoreFileSystem.h" +#include "fs/coss/StoreFScoss.h" +#include "store_coss.h" + +StoreFScoss StoreFScoss::_instance; + +StoreFileSystem & +StoreFScoss::GetInstance() +{ + return _instance; +} + +StoreFScoss::StoreFScoss() +{ + FsAdd(*this); +} + +char const * +StoreFScoss::type() const +{ + return "coss"; +} + +void +StoreFScoss::done() +{ + /* memPoolDestroy(&coss_index_pool); XXX Should be here? */ + initialised = false; +} + +SwapDir * +StoreFScoss::createSwapDir() +{ + SwapDir *result = new CossSwapDir; + return result; +} + + +void +StoreFScoss::setup() +{ + assert(!initialised); + + coss_index_pool = memPoolCreate("COSS index data", sizeof(CossIndexNode)); + initialised = true; +} diff --git a/src/fs/coss/StoreFScoss.h b/src/fs/coss/StoreFScoss.h new file mode 100644 index 0000000000..16cf45cb88 --- /dev/null +++ b/src/fs/coss/StoreFScoss.h @@ -0,0 +1,59 @@ + +/* + * $Id: StoreFScoss.h,v 1.1 2003/07/22 15:23:10 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. + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef SQUID_STOREFSCOSS_H +#define SQUID_STOREFSCOSS_H + +#include "squid.h" + +class StoreFScoss : public StoreFileSystem +{ + +public: + static StoreFileSystem &GetInstance(); + StoreFScoss(); + virtual ~StoreFScoss() {} + + virtual char const *type() const; + virtual SwapDir *createSwapDir(); + virtual void done(); + virtual void setup(); + /* Not implemented */ + StoreFScoss (StoreFScoss const &); + StoreFScoss &operator=(StoreFScoss const &); + +private: + static StoreFScoss _instance; +}; + +#endif /* SQUID_STOREFSCOSS_H */ diff --git a/src/fs/coss/async_io.h b/src/fs/coss/async_io.h index b09f428de4..fcc67827ff 100644 --- a/src/fs/coss/async_io.h +++ b/src/fs/coss/async_io.h @@ -1,5 +1,6 @@ #ifndef __ASYNC_IO_H__ #define __ASYNC_IO_H__ +#include #define MAX_ASYNCOP 128 diff --git a/src/fs/coss/store_coss.h b/src/fs/coss/store_coss.h index 776e08af47..e8c4ea0c94 100644 --- a/src/fs/coss/store_coss.h +++ b/src/fs/coss/store_coss.h @@ -2,6 +2,7 @@ #define __COSS_H__ #include "SwapDir.h" +#include "async_io.h" #ifndef COSS_MEMBUF_SZ #define COSS_MEMBUF_SZ 1048576 diff --git a/src/fs/coss/store_dir_coss.cc b/src/fs/coss/store_dir_coss.cc index ae112af7d8..3a5bbc8f9c 100644 --- a/src/fs/coss/store_dir_coss.cc +++ b/src/fs/coss/store_dir_coss.cc @@ -1,6 +1,6 @@ /* - * $Id: store_dir_coss.cc,v 1.45 2003/07/15 11:33:23 robertc Exp $ + * $Id: store_dir_coss.cc,v 1.46 2003/07/22 15:23:10 robertc Exp $ * * DEBUG: section 47 Store COSS Directory Routines * AUTHOR: Eric Stern @@ -35,9 +35,7 @@ #include "squid.h" #include "Store.h" -#include -#include "async_io.h" #include "store_coss.h" #include "fde.h" #include "SwapDir.h" @@ -47,7 +45,6 @@ int n_coss_dirs = 0; /* static int last_coss_pick_index = -1; */ -int coss_initialised = 0; MemPool *coss_index_pool = NULL; typedef struct _RebuildState RebuildState; @@ -87,9 +84,6 @@ static void storeCossDirRebuild(CossSwapDir * sd); static void storeCossDirCloseTmpSwapLog(CossSwapDir * sd); static FILE *storeCossDirOpenTmpSwapLog(CossSwapDir *, int *, int *); -/* The "only" externally visible function */ -STSETUP storeFsSetup_coss; - static char * storeCossDirSwapLogFile(SwapDir * sd, const char *ext) { @@ -828,7 +822,7 @@ CossSwapDir::parse(int anIndex, char *aPath) max_size = size; - parse_cachedir_options(this, NULL, 0); + parseOptions(0); /* Enforce maxobjsize being set to something */ if (max_objsize == -1) @@ -855,7 +849,7 @@ CossSwapDir::reconfigure(int index, char *path) max_size = size; } - parse_cachedir_options(this, NULL, 1); + parseOptions(1); /* Enforce maxobjsize being set to something */ if (max_objsize == -1) @@ -865,9 +859,8 @@ CossSwapDir::reconfigure(int index, char *path) void CossSwapDir::dump(StoreEntry &entry)const { - storeAppendPrintf(&entry, " %d", - max_size >> 20); - dump_cachedir_options(&entry, NULL, this); + storeAppendPrintf(&entry, " %d", max_size >> 20); + dumpOptions(&entry); } #if OLD_UNUSED_CODE @@ -916,25 +909,7 @@ storeCossDirPick(void) } #endif - -/* - * initial setup/done code - */ -static void -storeCossDirDone(void) -{ - /* 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) +CossSwapDir::CossSwapDir() : SwapDir ("coss"), fd (-1), swaplog_fd(-1), count(0), current_membuf (NULL), current_offset(0), numcollisions(0) { membufs.head = NULL; membufs.tail = NULL; @@ -942,13 +917,3 @@ CossSwapDir::CossSwapDir() : fd (-1), swaplog_fd(-1), count(0), current_membuf ( cossindex.tail = NULL; } -void -storeFsSetup_coss(storefs_entry_t * storefs) -{ - assert(!coss_initialised); - - storefs->donefunc = storeCossDirDone; - storefs->newfunc = storeCossNew; - coss_index_pool = memPoolCreate("COSS index data", sizeof(CossIndexNode)); - coss_initialised = 1; -} diff --git a/src/fs/diskd/StoreFSdiskd.cc b/src/fs/diskd/StoreFSdiskd.cc new file mode 100644 index 0000000000..63ff45cc8b --- /dev/null +++ b/src/fs/diskd/StoreFSdiskd.cc @@ -0,0 +1,42 @@ + +/* + * $Id: StoreFSdiskd.cc,v 1.1 2003/07/22 15:23:11 robertc Exp $ + * + * DEBUG: section 47 Store Directory Routines + * 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. + * + * Copyright (c) 2003, Robert Collins + */ + + +#include "StoreFileSystem.h" +#include "fs/ufs/StoreFSufs.h" +#include "fs/diskd/store_diskd.h" + +static StoreFSufs DiskdInstance(DiskdIOModule::GetInstance(), "diskd"); diff --git a/src/fs/diskd/store_dir_diskd.cc b/src/fs/diskd/store_dir_diskd.cc deleted file mode 100644 index adacce486f..0000000000 --- a/src/fs/diskd/store_dir_diskd.cc +++ /dev/null @@ -1,402 +0,0 @@ - -/* - * $Id: store_dir_diskd.cc,v 1.76 2003/02/21 22:50:40 robertc Exp $ - * - * DEBUG: section 47 Store Directory Routines - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "Store.h" - -#include -#include -#include - -#include "store_diskd.h" - -#include "ufscommon.h" - -#include "SwapDir.h" - -diskd_stats_t diskd_stats; - -static int diskd_initialised = 0; - -static void storeDiskdStats(StoreEntry * sentry); - -/* The only externally visible interface */ -STSETUP storeFsSetup_diskd; - - - -void -DiskdSwapDir::init() -{ - int x; - int rfd; - int ikey; - const char *args[5]; - char skey1[32]; - char skey2[32]; - char skey3[32]; - DiskdIO *DIO = dynamic_cast(IO); - - ikey = (getpid() << 10) + (index << 2); - ikey &= 0x7fffffff; - DIO->smsgid = msgget((key_t) ikey, 0700 | IPC_CREAT); - - if (DIO->smsgid < 0) { - debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror()); - fatal("msgget failed"); - } - - 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"); - } - - DIO->shm.init(ikey, DIO->magic2); - snprintf(skey1, 32, "%d", ikey); - snprintf(skey2, 32, "%d", ikey + 1); - snprintf(skey3, 32, "%d", ikey + 2); - args[0] = "diskd"; - args[1] = skey1; - args[2] = skey2; - args[3] = skey3; - args[4] = NULL; - x = ipcCreate(IPC_STREAM, - Config.Program.diskd, - args, - "diskd", - &rfd, - &DIO->wfd); - - if (x < 0) - fatalf("execl: %s", Config.Program.diskd); - - if (rfd != DIO->wfd) - comm_close(rfd); - - fd_note(DIO->wfd, "squid -> diskd"); - - commSetTimeout(DIO->wfd, -1, NULL, NULL); - - commSetNonBlocking(DIO->wfd); - - UFSSwapDir::init(); - - comm_quick_poll_required(); -} - - -static void -storeDiskdStats(StoreEntry * sentry) -{ - storeAppendPrintf(sentry, "sent_count: %d\n", diskd_stats.sent_count); - storeAppendPrintf(sentry, "recv_count: %d\n", diskd_stats.recv_count); - storeAppendPrintf(sentry, "max_away: %d\n", diskd_stats.max_away); - storeAppendPrintf(sentry, "max_shmuse: %d\n", diskd_stats.max_shmuse); - storeAppendPrintf(sentry, "open_fail_queue_len: %d\n", diskd_stats.open_fail_queue_len); - storeAppendPrintf(sentry, "block_queue_len: %d\n", diskd_stats.block_queue_len); - diskd_stats.max_away = diskd_stats.max_shmuse = 0; - storeAppendPrintf(sentry, "\n OPS SUCCESS FAIL\n"); - storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "open", diskd_stats.open.ops, diskd_stats.open.success, diskd_stats.open.fail); - storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "create", diskd_stats.create.ops, diskd_stats.create.success, diskd_stats.create.fail); - storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "close", diskd_stats.close.ops, diskd_stats.close.success, diskd_stats.close.fail); - storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "unlink", diskd_stats.unlink.ops, diskd_stats.unlink.success, diskd_stats.unlink.fail); - storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "read", diskd_stats.read.ops, diskd_stats.read.success, diskd_stats.read.fail); - storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", - "write", diskd_stats.write.ops, diskd_stats.write.success, diskd_stats.write.fail); -} - -/* - * storeDiskdDirSync - * - * Sync any pending data. We just sit around and read the queue - * until the data has finished writing. - */ -void -DiskdSwapDir::sync() -{ - static time_t lastmsg = 0; - DiskdIO *DIO = dynamic_cast(IO); - - while (DIO->away > 0) { - if (squid_curtime > lastmsg) { - debug(47, 1) ("storeDiskdDirSync: %d messages away\n", - DIO->away); - lastmsg = squid_curtime; - } - - callback(); - } -} - - -/* - * storeDiskdDirCallback - * - * Handle callbacks. If we have more than magic2 requests away, we block - * until the queue is below magic2. Otherwise, we simply return when we - * don't get a message. - */ -int -DiskdSwapDir::callback() -{ - diomsg M; - int x; - int retval = 0; - - DiskdIO *DIO = dynamic_cast(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.. */ - } - - if (diskd_stats.sent_count - diskd_stats.recv_count > - diskd_stats.max_away) { - diskd_stats.max_away = diskd_stats.sent_count - diskd_stats.recv_count; - } - - while (1) { -#ifdef ALWAYS_ZERO_BUFFERS - memset(&M, '\0', sizeof(M)); -#endif - - x = msgrcv(DIO->rmsgid, &M, msg_snd_rcv_sz, 0, IPC_NOWAIT); - - if (x < 0) - break; - else if (x != msg_snd_rcv_sz) { - debug(47, 1) ("storeDiskdDirCallback: msgget returns %d\n", - x); - break; - } - - diskd_stats.recv_count++; - --DIO->away; - storeDiskdHandle(&M); - retval = 1; /* Return that we've actually done some work */ - - if (M.shm_offset > -1) - DIO->shm.put ((off_t) M.shm_offset); - } - - return retval; -} - -/* - * storeDiskdDirCheckObj - * - * This routine is called by storeDirSelectSwapDir to see if the given - * object is able to be stored on this filesystem. DISKD filesystems will - * happily store anything as long as the LRU time isn't too small. - */ -int -DiskdSwapDir::canStore(StoreEntry const &e)const -{ - if (IO->shedLoad()) - return -1; - - return IO->load(); -} - -void -DiskdSwapDir::unlinkFile(char const *path) -{ -#if USE_UNLINKD - unlinkdUnlink(path); -#elif USE_TRUNCATE - - truncate(path, 0); -#else - - unlink(path); -#endif - -} - -/* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */ - -void -DiskdSwapDir::statfs(StoreEntry & sentry)const -{ - UFSSwapDir::statfs (sentry); - DiskdIO *DIO = dynamic_cast(IO); - storeAppendPrintf(&sentry, "Pending operations: %d\n", DIO->away); -} - -static void -storeDiskdDirParseQ1(SwapDir * sd, const char *name, const char *value, int reconfiguring) -{ - DiskdIO *IO = dynamic_cast(((DiskdSwapDir *)sd)->IO); - int old_magic1 = IO->magic1; - IO->magic1 = atoi(value); - - if (!reconfiguring) - return; - - 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 - * beyond their initial values because then we might have - * more "Q2 messages" than shared memory chunks, and this - * will cause an assertion in storeDiskdShmGet(). - */ - debug(3, 1) ("WARNING: cannot increase cache_dir '%s' Q1 value while Squid is running.\n", sd->path); - IO->magic1 = old_magic1; - return; - } - - if (old_magic1 != IO->magic1) - debug(3, 1) ("cache_dir '%s' new Q1 value '%d'\n", - sd->path, IO->magic1); -} - -static void -storeDiskdDirDumpQ1(StoreEntry * e, const char *option, SwapDir const * sd) -{ - DiskdIO *IO = dynamic_cast(((DiskdSwapDir *)sd)->IO); - storeAppendPrintf(e, " Q1=%d", IO->magic1); -} - -static void -storeDiskdDirParseQ2(SwapDir * sd, const char *name, const char *value, int reconfiguring) -{ - DiskdIO *IO = dynamic_cast(((DiskdSwapDir *)sd)->IO); - assert (IO); - int old_magic2 = IO->magic2; - IO->magic2 = atoi(value); - - if (!reconfiguring) - return; - - 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); - IO->magic2 = old_magic2; - return; - } - - if (old_magic2 != IO->magic2) - debug(3, 1) ("cache_dir '%s' new Q2 value '%d'\n", - sd->path, IO->magic2); -} - -static void -storeDiskdDirDumpQ2(StoreEntry * e, const char *option, SwapDir const * sd) -{ - DiskdIO *IO = dynamic_cast(((DiskdSwapDir *)sd)->IO); - storeAppendPrintf(e, " Q2=%d", IO->magic2); -} - -struct cache_dir_option options[] = - { -#if NOT_YET - {"L1", storeDiskdDirParseL1, storeDiskdDirDumpL1}, - {"L2", storeDiskdDirParseL2, storeDiskdDirDumpL2}, -#endif - {"Q1", storeDiskdDirParseQ1, storeDiskdDirDumpQ1}, - {"Q2", storeDiskdDirParseQ2, storeDiskdDirDumpQ2}, - {NULL, NULL} - }; - -/* - * storeDiskdDirReconfigure - * - * This routine is called when the given swapdir needs reconfiguring - */ -void -DiskdSwapDir::reconfigure(int anIndex, char *aPath) -{ - UFSSwapDir::reconfigure (anIndex, aPath); - - parse_cachedir_options(this, options, 1); -} - -void -DiskdSwapDir::dump(StoreEntry & entry)const -{ - UFSSwapDir::dump (entry); - dump_cachedir_options(&entry, options, this); -} - -/* - * storeDiskdDirParse - * - * Called when a *new* fs is being setup. - */ -void -DiskdSwapDir::parse(int anIndex, char *aPath) -{ - UFSSwapDir::parse(anIndex, aPath); - - parse_cachedir_options(this, options, 0); -} - -/* - * Initial setup / end destruction - */ -static void -storeDiskdDirDone(void) -{ - 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->donefunc = storeDiskdDirDone; - storefs->newfunc = storeDiskdNew; - memset(&diskd_stats, '\0', sizeof(diskd_stats)); - cachemgrRegister("diskd", "DISKD Stats", storeDiskdStats, 0, 1); - debug(47, 1) ("diskd started\n"); - diskd_initialised = 1; -} diff --git a/src/fs/diskd/store_diskd.h b/src/fs/diskd/store_diskd.h index 7420767724..166d258c99 100644 --- a/src/fs/diskd/store_diskd.h +++ b/src/fs/diskd/store_diskd.h @@ -37,6 +37,7 @@ public: virtual void close (); virtual bool error() const; virtual bool canRead() const; + virtual bool ioInProgress()const; /* Temporary */ int getID() const {return id;} @@ -58,6 +59,9 @@ private: int mode; void notifyClient(); bool canNotifyClient() const; + void ioAway(); + void ioCompleted(); + size_t inProgressIOs; }; class SharedMemory @@ -80,29 +84,6 @@ public: int id; }; -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); -}; - #include "dio.h" struct _diskd_stats @@ -128,29 +109,29 @@ struct _diskd_stats typedef struct _diskd_stats diskd_stats_t; -extern void storeDiskdHandle(diomsg * M); +class SwapDir; +#define SHMBUF_BLKSZ SM_PAGE_SIZE + +extern diskd_stats_t diskd_stats; -#include "SwapDir.h" +#include "fs/ufs/IOModule.h" -class DiskdSwapDir : public UFSSwapDir +class DiskdIOModule : public IOModule { public: + static DiskdIOModule &GetInstance(); + DiskdIOModule(); 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 *); -}; + virtual void shutdown(); + virtual UFSStrategy *createSwapDirIOStrategy(); -#define SHMBUF_BLKSZ SM_PAGE_SIZE +private: + static DiskdIOModule *Instance; + bool initialised; +}; -extern diskd_stats_t diskd_stats; +/* Per SwapDir instance */ class DiskdIO : public UFSStrategy { @@ -163,6 +144,13 @@ public: virtual int load(); virtual StoreIOState::Pointer createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const; virtual DiskFile::Pointer newFile (char const *path); + virtual SwapDirOption *getOptionTree() const; + virtual void unlinkFile (char const *); + void storeDiskdHandle(diomsg * M); + virtual void init(); + virtual int callback(); + virtual void sync(); + virtual void statfs(StoreEntry & sentry)const; int away; int magic1; int magic2; @@ -170,6 +158,18 @@ public: int rmsgid; int wfd; SharedMemory shm; + +private: + static size_t newInstance(); + bool optionQ1Parse(char const *option, const char *value, int reconfiguring); + void optionQ1Dump(StoreEntry * e) const; + bool optionQ2Parse(char const *option, const char *value, int reconfiguring); + void optionQ2Dump(StoreEntry * e) const; + void unlinkDone(diomsg * M); + static size_t nextInstanceID; + size_t instanceID; }; +extern void storeDiskdStats(StoreEntry * sentry); + #endif diff --git a/src/fs/diskd/store_io_diskd.cc b/src/fs/diskd/store_io_diskd.cc index 7426827886..8808c19356 100644 --- a/src/fs/diskd/store_io_diskd.cc +++ b/src/fs/diskd/store_io_diskd.cc @@ -1,6 +1,6 @@ /* - * $Id: store_io_diskd.cc,v 1.33 2003/02/21 22:50:40 robertc Exp $ + * $Id: store_io_diskd.cc,v 1.34 2003/07/22 15:23:11 robertc Exp $ * * DEBUG: section 79 Squid-side DISKD I/O functions. * AUTHOR: Duane Wessels @@ -44,13 +44,21 @@ #include "store_diskd.h" #include "SwapDir.h" +size_t DiskdIO::nextInstanceID (0); + 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) +DiskdIO::DiskdIO() : away (0), magic1(64), magic2(72), instanceID(newInstance()) {} +size_t +DiskdIO::newInstance() +{ + return ++nextInstanceID; +} + bool DiskdIO::shedLoad() { @@ -90,7 +98,7 @@ DiskdIO::openFailed() StoreIOState::Pointer DiskdIO::createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const { - return new diskdstate_t (SD, e, callback, callback_data); + return new UFSStoreState (SD, e, callback, callback_data); } DiskFile::Pointer @@ -100,6 +108,54 @@ DiskdIO::newFile (char const *path) } +void +DiskdIO::unlinkFile(char const *path) +{ + if (shedLoad()) { + /* Damn, we need to issue a sync unlink here :( */ + debug(79, 2) ("storeDiskUnlink: Out of queue space, sync unlink\n"); +#if USE_UNLINKD + + unlinkdUnlink(path); +#elif USE_TRUNCATE + + truncate(path, 0); +#else + + unlink(path); +#endif + + return; + } + + /* We can attempt a diskd unlink */ + int x; + + off_t shm_offset; + + char *buf; + + buf = (char *)shm.get(&shm_offset); + + xstrncpy(buf, path, SHMBUF_BLKSZ); + + x = storeDiskdSend(_MQD_UNLINK, + this, + 0, + (StoreIOState::Pointer )NULL, + 0, + 0, + shm_offset); + + if (x < 0) { + debug(79, 1) ("storeDiskdSend UNLINK: %s\n", xstrerror()); + ::unlink(buf); /* XXX EWW! */ + shm.put (shm_offset); + } + + diskd_stats.unlink.ops++; +} + /* * SHM manipulation routines */ @@ -203,7 +259,8 @@ DiskdFile::operator delete (void *address) void DiskdFile::deleteSelf() const {delete this;} -DiskdFile::DiskdFile (char const *aPath, DiskdIO *anIO) : errorOccured (false), IO(anIO) +DiskdFile::DiskdFile (char const *aPath, DiskdIO *anIO) : errorOccured (false), IO(anIO), + inProgressIOs (0) { assert (aPath); debug (79,3)("DiskdFile::DiskdFile: %s\n", aPath); @@ -213,6 +270,7 @@ DiskdFile::DiskdFile (char const *aPath, DiskdIO *anIO) : errorOccured (false), DiskdFile::~DiskdFile() { + assert (inProgressIOs == 0); safe_free (path_); } @@ -227,6 +285,7 @@ DiskdFile::open (int flags, mode_t aMode, IORequestor::Pointer callback) off_t shm_offset; char *buf = (char *)IO->shm.get(&shm_offset); xstrncpy(buf, path_, SHMBUF_BLKSZ); + ioAway(); int x = storeDiskdSend(_MQD_OPEN, IO, id, @@ -236,6 +295,7 @@ DiskdFile::open (int flags, mode_t aMode, IORequestor::Pointer callback) shm_offset); if (x < 0) { + ioCompleted(); errorOccured = true; IO->shm.put (shm_offset); ioRequestor->ioCompletedNotification(); @@ -256,6 +316,7 @@ DiskdFile::create (int flags, mode_t aMode, IORequestor::Pointer callback) off_t shm_offset; char *buf = (char *)IO->shm.get(&shm_offset); xstrncpy(buf, path_, SHMBUF_BLKSZ); + ioAway(); int x = storeDiskdSend(_MQD_CREATE, IO, id, @@ -265,6 +326,7 @@ DiskdFile::create (int flags, mode_t aMode, IORequestor::Pointer callback) shm_offset); if (x < 0) { + ioCompleted(); errorOccured = true; IO->shm.put (shm_offset); debug(79, 1) ("storeDiskdSend CREATE: %s\n", xstrerror()); @@ -283,6 +345,7 @@ DiskdFile::read(char *buf, off_t offset, size_t size) off_t shm_offset; char *rbuf = (char *)IO->shm.get(&shm_offset); assert(rbuf); + ioAway(); int x = storeDiskdSend(_MQD_READ, IO, id, @@ -292,6 +355,7 @@ DiskdFile::read(char *buf, off_t offset, size_t size) shm_offset); if (x < 0) { + ioCompleted(); errorOccured = true; IO->shm.put (shm_offset); debug(79, 1) ("storeDiskdSend READ: %s\n", xstrerror()); @@ -308,6 +372,7 @@ DiskdFile::close() { debug (79,3)("DiskdFile::close: %p closing for %p\n", this, ioRequestor.getRaw()); assert (ioRequestor.getRaw()); + ioAway(); int x = storeDiskdSend(_MQD_CLOSE, IO, id, @@ -317,6 +382,7 @@ DiskdFile::close() -1); if (x < 0) { + ioCompleted(); errorOccured = true; debug(79, 1) ("storeDiskdSend CLOSE: %s\n", xstrerror()); notifyClient(); @@ -411,6 +477,7 @@ DiskdFile::openDone(diomsg *M) diskd_stats.open.success++; } + ioCompleted(); notifyClient(); } @@ -427,111 +494,14 @@ DiskdFile::createDone(diomsg *M) diskd_stats.create.success++; } + ioCompleted(); notifyClient(); } -CBDATA_CLASS_INIT(diskdstate_t); - -void * -diskdstate_t::operator new (size_t) -{ - 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 (79,3)("diskdstate with base %p allocating\n", result); - return result; -} - -void -diskdstate_t::operator delete (void *address) -{ - debug (79,3)("diskdstate with base %p deleting\n",address); - diskdstate_t *t = static_cast(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; - } - - 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) { + debug(79, 3) ("DiskdFile::write: this %p , buf %p, off %ld, len %d\n", this, buf, offset, size); off_t shm_offset; char *sbuf = (char *)IO->shm.get(&shm_offset); xmemcpy(sbuf, buf, size); @@ -539,6 +509,8 @@ DiskdFile::write(char const *buf, size_t size, off_t offset, FREE *free_func) if (free_func) free_func(const_cast(buf)); + ioAway(); + int x = storeDiskdSend(_MQD_WRITE, IO, id, @@ -548,6 +520,7 @@ DiskdFile::write(char const *buf, size_t size, off_t offset, FREE *free_func) shm_offset); if (x < 0) { + ioCompleted(); errorOccured = true; debug(79, 1) ("storeDiskdSend WRITE: %s\n", xstrerror()); IO->shm.put (shm_offset); @@ -559,55 +532,26 @@ DiskdFile::write(char const *buf, size_t size, off_t offset, FREE *free_func) diskd_stats.write.ops++; } -void -DiskdSwapDir::unlink(StoreEntry & e) -{ - int x; - off_t shm_offset; - char *buf; - - 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"); - UFSSwapDir::unlinkFile(e.swap_filen); - return; - } - - /* We can attempt a diskd unlink */ - buf = (char *)((DiskdIO *)IO)->shm.get(&shm_offset); - - xstrncpy(buf, fullPath(e.swap_filen, NULL), SHMBUF_BLKSZ); - x = storeDiskdSend(_MQD_UNLINK, - (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! */ - ((DiskdIO *)IO)->shm.put (shm_offset); - } +/* === STATIC =========================================================== */ - diskd_stats.unlink.ops++; +void +DiskdFile::ioAway() +{ + ++inProgressIOs; } - -/* === STATIC =========================================================== */ +void +DiskdFile::ioCompleted() +{ + --inProgressIOs; +} void DiskdFile::closeDone(diomsg * M) { statCounter.syscalls.disk.closes++; - debug(79, 3) ("storeDiskdCloseDone: status %d\n", M->status); + debug(79, 3) ("DiskdFile::closeDone: status %d\n", M->status); if (M->status < 0) { diskd_stats.close.fail++; @@ -616,6 +560,8 @@ DiskdFile::closeDone(diomsg * M) diskd_stats.close.success++; } + ioCompleted(); + if (canNotifyClient()) ioRequestor->closeCompleted(); @@ -630,6 +576,7 @@ DiskdFile::readDone(diomsg * M) if (M->status < 0) { diskd_stats.read.fail++; + ioCompleted(); errorOccured = true; ioRequestor->readCompleted(NULL, -1, DISK_ERROR); return; @@ -637,55 +584,10 @@ DiskdFile::readDone(diomsg * M) diskd_stats.read.success++; + ioCompleted(); 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); - - 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 - */ - - if (len > 0 && read_buf != buf) - memcpy(read_buf, buf, len); - - callback(cbdata, read_buf, len); - } -} - -void -diskdstate_t::writeCompleted(int errflag, size_t len) -{ - writing = false; - debug(79, 3) ("storeDiskdWriteDone: dirno %d, fileno %08x status %d\n", - swap_dirn, swap_filen, len); - offset_ += len; - - if (errflag) - doCallback(DISK_ERROR); -} - void DiskdFile::writeDone(diomsg *M) { @@ -695,19 +597,27 @@ DiskdFile::writeDone(diomsg *M) if (M->status < 0) { errorOccured = true; diskd_stats.write.fail++; + ioCompleted(); ioRequestor->writeCompleted (DISK_ERROR,0); return; } diskd_stats.write.success++; + ioCompleted(); ioRequestor->writeCompleted (DISK_OK,M->status); } -static void -storeDiskdUnlinkDone(diomsg * M) +bool +DiskdFile::ioInProgress()const +{ + return inProgressIOs != 0; +} + +void +DiskdIO::unlinkDone(diomsg * M) { - debug(79, 3) ("storeDiskdUnlinkDone: fileno %08x status %d\n", - M->id, M->status); + debug(79, 3) ("storeDiskdUnlinkDone: file %s status %d\n",shm.buf + M->shm_offset, + M->status); statCounter.syscalls.disk.unlinks++; if (M->status < 0) @@ -717,7 +627,7 @@ storeDiskdUnlinkDone(diomsg * M) } void -storeDiskdHandle(diomsg * M) +DiskdIO::storeDiskdHandle(diomsg * M) { if (!cbdataReferenceValid (M->callback_data)) { debug(79, 3) ("storeDiskdHandle: Invalid callback_data %p\n", @@ -746,7 +656,7 @@ storeDiskdHandle(diomsg * M) break; case _MQD_UNLINK: - storeDiskdUnlinkDone(M); + unlinkDone(M); break; default: @@ -757,23 +667,6 @@ storeDiskdHandle(diomsg * M) cbdataReferenceDone (M->callback_data); } -void -diskdstate_t::doCallback(int errflag) -{ - if (!this || !cbdataReferenceValid(this)) { - debug (79, 0) ("storeDiskdIOCallback: invalid siocb %p\n",this); - return; - } - - void *cbdata; - STIOCB *theCallback = callback; - debug(79, 3) ("storeUfsIOCallback: errflag=%d\n", errflag); - callback = NULL; - - if (cbdataReferenceValidDone(callback_data, &cbdata) && theCallback) - theCallback(cbdata, errflag, this); -} - int storeDiskdSend(int mtype, DiskdIO *IO, int id, DiskdFile *theFile, int size, int offset, off_t shm_offset) { @@ -893,4 +786,291 @@ storeDiskdSend(int mtype, DiskdIO *IO, int id, StoreIOState::Pointer sio, int si return x; } +SwapDirOption * +DiskdIO::getOptionTree() const +{ + SwapDirOptionVector *result = new SwapDirOptionVector; + result->options.push_back(new SwapDirOptionAdapter(*const_cast(this), &DiskdIO::optionQ1Parse, &DiskdIO::optionQ1Dump)); + result->options.push_back(new SwapDirOptionAdapter(*const_cast(this), &DiskdIO::optionQ2Parse, &DiskdIO::optionQ2Dump)); + return result; +} + +bool +DiskdIO::optionQ1Parse(const char *name, const char *value, int reconfiguring) +{ + if (strcmp(name, "Q1") != 0) + return false; + + int old_magic1 = magic1; + + magic1 = atoi(value); + + if (!reconfiguring) + return true; + + if (old_magic1 < magic1) { + /* + * This is because shm.nbufs is computed at startup, when + * we call shmget(). We can't increase the Q1/Q2 parameters + * beyond their initial values because then we might have + * more "Q2 messages" than shared memory chunks, and this + * will cause an assertion in storeDiskdShmGet(). + */ + /* TODO: have DiskdIO hold a link to the swapdir, to allow detailed reporting again */ + debug(3, 1) ("WARNING: cannot increase cache_dir Q1 value while Squid is running.\n"); + magic1 = old_magic1; + return true; + } + + if (old_magic1 != magic1) + debug(3, 1) ("cache_dir new Q1 value '%d'\n", + magic1); + + return true; +} + +void +DiskdIO::optionQ1Dump(StoreEntry * e) const +{ + storeAppendPrintf(e, " Q1=%d", magic1); +} + +bool +DiskdIO::optionQ2Parse(const char *name, const char *value, int reconfiguring) +{ + if (strcmp(name, "Q2") != 0) + return false; + + int old_magic2 = magic2; + + magic2 = atoi(value); + + if (!reconfiguring) + return true; + + if (old_magic2 < magic2) { + /* See comments in Q1 function above */ + debug(3, 1) ("WARNING: cannot increase cache_dir Q2 value while Squid is running.\n"); + magic2 = old_magic2; + return true; + } + + if (old_magic2 != magic2) + debug(3, 1) ("cache_dir new Q2 value '%d'\n", + magic2); + + return true; +} + +void +DiskdIO::optionQ2Dump(StoreEntry * e) const +{ + storeAppendPrintf(e, " Q2=%d", magic2); +} + +void +DiskdIO::init() +{ + int x; + int rfd; + int ikey; + const char *args[5]; + char skey1[32]; + char skey2[32]; + char skey3[32]; + + ikey = (getpid() << 10) + (instanceID << 2); + ikey &= 0x7fffffff; + smsgid = msgget((key_t) ikey, 0700 | IPC_CREAT); + + if (smsgid < 0) { + debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror()); + fatal("msgget failed"); + } + + rmsgid = msgget((key_t) (ikey + 1), 0700 | IPC_CREAT); + + if (rmsgid < 0) { + debug(50, 0) ("storeDiskdInit: msgget: %s\n", xstrerror()); + fatal("msgget failed"); + } + + shm.init(ikey, magic2); + snprintf(skey1, 32, "%d", ikey); + snprintf(skey2, 32, "%d", ikey + 1); + snprintf(skey3, 32, "%d", ikey + 2); + args[0] = "diskd"; + args[1] = skey1; + args[2] = skey2; + args[3] = skey3; + args[4] = NULL; + x = ipcCreate(IPC_STREAM, + Config.Program.diskd, + args, + "diskd", + &rfd, + &wfd); + if (x < 0) + fatalf("execl: %s", Config.Program.diskd); + + if (rfd != wfd) + comm_close(rfd); + + fd_note(wfd, "squid -> diskd"); + + commSetTimeout(wfd, -1, NULL, NULL); + + commSetNonBlocking(wfd); + + comm_quick_poll_required(); +} + +/* + * Sync any pending data. We just sit around and read the queue + * until the data has finished writing. + */ +void +DiskdIO::sync() +{ + static time_t lastmsg = 0; + + while (away > 0) { + if (squid_curtime > lastmsg) { + debug(47, 1) ("storeDiskdDirSync: %d messages away\n", + away); + lastmsg = squid_curtime; + } + + callback(); + } +} + + +/* + * Handle callbacks. If we have more than magic2 requests away, we block + * until the queue is below magic2. Otherwise, we simply return when we + * don't get a message. + */ +int +DiskdIO::callback() +{ + diomsg M; + int x; + int retval = 0; + + DiskdIO *DIO = this;//dynamic_cast(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.. */ + } + + if (diskd_stats.sent_count - diskd_stats.recv_count > + diskd_stats.max_away) { + diskd_stats.max_away = diskd_stats.sent_count - diskd_stats.recv_count; + } + + while (1) { +#ifdef ALWAYS_ZERO_BUFFERS + memset(&M, '\0', sizeof(M)); +#endif + + x = msgrcv(DIO->rmsgid, &M, msg_snd_rcv_sz, 0, IPC_NOWAIT); + + if (x < 0) + break; + else if (x != msg_snd_rcv_sz) { + debug(47, 1) ("storeDiskdDirCallback: msgget returns %d\n", + x); + break; + } + + diskd_stats.recv_count++; + --DIO->away; + DIO->storeDiskdHandle(&M); + retval = 1; /* Return that we've actually done some work */ + + if (M.shm_offset > -1) + DIO->shm.put ((off_t) M.shm_offset); + } + + return retval; +} + +void +DiskdIO::statfs(StoreEntry & sentry)const +{ + storeAppendPrintf(&sentry, "Pending operations: %d\n", away); +} + +DiskdIOModule::DiskdIOModule() : initialised(false) {} + +DiskdIOModule & +DiskdIOModule::GetInstance() +{ + if (!Instance) + Instance = new DiskdIOModule; + + return *Instance; +} + +void +DiskdIOModule::init() +{ + /* We may be reused - for instance in coss - eventually. + * When we do, we either need per-using-module stats ( + * no singleton pattern), or we need to refcount the + * initialisation level and handle multiple clients. + * RBC - 20030718. + */ + assert(!initialised); + memset(&diskd_stats, '\0', sizeof(diskd_stats)); + cachemgrRegister("diskd", "DISKD Stats", storeDiskdStats, 0, 1); + + debug(47, 1) ("diskd started\n"); + initialised = true; +} + +void +DiskdIOModule::shutdown() +{ + initialised = false; +} + +UFSStrategy * +DiskdIOModule::createSwapDirIOStrategy() +{ + return new DiskdIO; +} + +DiskdIOModule *DiskdIOModule::Instance = NULL; + +diskd_stats_t diskd_stats; + +void +storeDiskdStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "sent_count: %d\n", diskd_stats.sent_count); + storeAppendPrintf(sentry, "recv_count: %d\n", diskd_stats.recv_count); + storeAppendPrintf(sentry, "max_away: %d\n", diskd_stats.max_away); + storeAppendPrintf(sentry, "max_shmuse: %d\n", diskd_stats.max_shmuse); + storeAppendPrintf(sentry, "open_fail_queue_len: %d\n", diskd_stats.open_fail_queue_len); + storeAppendPrintf(sentry, "block_queue_len: %d\n", diskd_stats.block_queue_len); + diskd_stats.max_away = diskd_stats.max_shmuse = 0; + storeAppendPrintf(sentry, "\n OPS SUCCESS FAIL\n"); + storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", + "open", diskd_stats.open.ops, diskd_stats.open.success, diskd_stats.open.fail); + storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", + "create", diskd_stats.create.ops, diskd_stats.create.success, diskd_stats.create.fail); + storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", + "close", diskd_stats.close.ops, diskd_stats.close.success, diskd_stats.close.fail); + storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", + "unlink", diskd_stats.unlink.ops, diskd_stats.unlink.success, diskd_stats.unlink.fail); + storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", + "read", diskd_stats.read.ops, diskd_stats.read.success, diskd_stats.read.fail); + storeAppendPrintf(sentry, "%7s %7d %7d %7d\n", + "write", diskd_stats.write.ops, diskd_stats.write.success, diskd_stats.write.fail); +} diff --git a/src/fs/null/StoreFSnull.cc b/src/fs/null/StoreFSnull.cc new file mode 100644 index 0000000000..6f172b98f7 --- /dev/null +++ b/src/fs/null/StoreFSnull.cc @@ -0,0 +1,79 @@ + + +/* + * $Id: StoreFSnull.cc,v 1.1 2003/07/22 15:23:14 robertc Exp $ + * + * DEBUG: section 47 Store Directory Routines + * 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. + * + * Copyright (c) 2003, Robert Collins + */ + + +#include "StoreFileSystem.h" +#include "fs/null/StoreFSnull.h" +#include "fs/null/store_null.h" + +StoreFSnull StoreFSnull::_instance; + +StoreFileSystem & +StoreFSnull::GetInstance() +{ + return _instance; +} + +StoreFSnull::StoreFSnull() +{ + FsAdd(*this); +} + +char const * +StoreFSnull::type() const +{ + return "null"; +} + +void +StoreFSnull::done() +{ + initialised = false; +} + +SwapDir * +StoreFSnull::createSwapDir() +{ + return new NullSwapDir; +} + +void +StoreFSnull::setup() +{ + assert(!initialised); + initialised = true; +} diff --git a/src/fs/null/StoreFSnull.h b/src/fs/null/StoreFSnull.h new file mode 100644 index 0000000000..d53d9ba8de --- /dev/null +++ b/src/fs/null/StoreFSnull.h @@ -0,0 +1,59 @@ + +/* + * $Id: StoreFSnull.h,v 1.1 2003/07/22 15:23:14 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. + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef SQUID_STOREFSNULL_H +#define SQUID_STOREFSNULL_H + +#include "squid.h" + +class StoreFSnull : public StoreFileSystem +{ + +public: + static StoreFileSystem &GetInstance(); + StoreFSnull(); + virtual ~StoreFSnull() {} + + virtual char const *type() const; + virtual SwapDir *createSwapDir(); + virtual void done(); + virtual void setup(); + /* Not implemented */ + StoreFSnull (StoreFSnull const &); + StoreFSnull &operator=(StoreFSnull const &); + +private: + static StoreFSnull _instance; +}; + +#endif /* SQUID_STOREFSNULL_H */ diff --git a/src/fs/null/store_null.cc b/src/fs/null/store_null.cc index 0b88411dc0..79a2d562ee 100644 --- a/src/fs/null/store_null.cc +++ b/src/fs/null/store_null.cc @@ -1,6 +1,6 @@ /* - * $Id: store_null.cc,v 1.6 2003/02/21 22:50:44 robertc Exp $ + * $Id: store_null.cc,v 1.7 2003/07/22 15:23:14 robertc Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels @@ -39,26 +39,11 @@ #include #endif #endif -#include "SwapDir.h" #include "Store.h" +#include "fs/null/store_null.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 EVH storeNullDirRebuildComplete; - -/* The only externally visible interface */ -STSETUP storeFsSetup_null; +NullSwapDir::NullSwapDir() : SwapDir ("null") {} void NullSwapDir::reconfigure(int index, char *path) @@ -66,18 +51,6 @@ NullSwapDir::reconfigure(int index, char *path) (void) 0; } -static void -storeNullDirDone(void) -{ - null_initialised = 0; -} - -static SwapDir * -storeNullNew(void) -{ - SwapDir *result = new NullSwapDir; - return result; -} void NullSwapDir::init() @@ -122,16 +95,6 @@ NullSwapDir::parse(int anIndex, char *aPath) { index = anIndex; path = xstrdup(aPath); - parse_cachedir_options(this, NULL, 0); + parseOptions(0); } -/* Setup and register the store module */ - -void -storeFsSetup_null(storefs_entry_t * storefs) -{ - assert(!null_initialised); - storefs->donefunc = storeNullDirDone; - storefs->newfunc = storeNullNew; - null_initialised = 1; -} diff --git a/src/fs/null/store_null.h b/src/fs/null/store_null.h new file mode 100644 index 0000000000..521f6828e2 --- /dev/null +++ b/src/fs/null/store_null.h @@ -0,0 +1,53 @@ + +/* + * $Id: store_null.h,v 1.1 2003/07/22 15:23:14 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. + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef SQUID_STORE_NULL_H +#define SQUID_STORE_NULL_H + +#include "squid.h" +#include "SwapDir.h" + +class NullSwapDir : public SwapDir +{ + +public: + NullSwapDir(); + 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 *); +}; + +#endif /* SQUID_STORE_NULL_H */ diff --git a/src/fs/ufs/IOModule.h b/src/fs/ufs/IOModule.h new file mode 100644 index 0000000000..87ccc12575 --- /dev/null +++ b/src/fs/ufs/IOModule.h @@ -0,0 +1,53 @@ + +/* + * $Id: IOModule.h,v 1.1 2003/07/22 15:23:14 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. + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef SQUID_IOMODULE_H +#define SQUID_IOMODULE_H + +#include "squid.h" + +class UFSStrategy; + +class IOModule +{ + +public: + virtual ~IOModule(){} + + virtual void init() = 0; + virtual void shutdown() = 0; + virtual UFSStrategy *createSwapDirIOStrategy() = 0; +}; + + +#endif /* SQUID_IOMODULE_H */ diff --git a/src/fs/ufs/StoreFSufs.cc b/src/fs/ufs/StoreFSufs.cc new file mode 100644 index 0000000000..ab74d6ff62 --- /dev/null +++ b/src/fs/ufs/StoreFSufs.cc @@ -0,0 +1,44 @@ + + +/* + * $Id: StoreFSufs.cc,v 1.1 2003/07/22 15:23:14 robertc Exp $ + * + * DEBUG: section 47 Store Directory Routines + * 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. + * + * Copyright (c) 2003, Robert Collins + */ + + +#include "StoreFileSystem.h" +#include "fs/ufs/StoreFSufs.h" +#include "fs/ufs/store_ufs.h" + +static StoreFSufs UfsInstance(UfsIOModule::GetInstance(), "ufs"); + diff --git a/src/fs/ufs/StoreFSufs.h b/src/fs/ufs/StoreFSufs.h new file mode 100644 index 0000000000..947fad1029 --- /dev/null +++ b/src/fs/ufs/StoreFSufs.h @@ -0,0 +1,103 @@ + +/* + * $Id: StoreFSufs.h,v 1.1 2003/07/22 15:23:14 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. + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef SQUID_STOREFSUFS_H +#define SQUID_STOREFSUFS_H + +#include "squid.h" + +class IOModule; + +template + +class StoreFSufs : public StoreFileSystem +{ + +public: + static StoreFileSystem &GetInstance(); + StoreFSufs(IOModule &, char const *label); + virtual ~StoreFSufs() {} + + virtual char const *type() const; + virtual SwapDir *createSwapDir(); + virtual void done(); + virtual void setup(); + /* Not implemented */ + StoreFSufs (StoreFSufs const &); + StoreFSufs &operator=(StoreFSufs const &); + +protected: + IOModule &IO; + char const *label; +}; + +template +StoreFSufs::StoreFSufs(IOModule &anIO, char const *aLabel) : IO(anIO), label(aLabel) +{ + FsAdd(*this); +} + +template +char const * +StoreFSufs::type() const +{ + return label; +} + +template +SwapDir * +StoreFSufs::createSwapDir() +{ + C *result = new C(type()); + result->IO = IO.createSwapDirIOStrategy(); + return result; +} + +template +void +StoreFSufs::done() +{ + IO.shutdown(); + initialised = false; +} + +template +void +StoreFSufs::setup() +{ + assert(!initialised); + initialised = true; + IO.init(); +} + +#endif /* SQUID_STOREFSUFS_H */ diff --git a/src/fs/ufs/store_dir_ufs.cc b/src/fs/ufs/store_dir_ufs.cc index 813c7bd221..fe0ff71aca 100644 --- a/src/fs/ufs/store_dir_ufs.cc +++ b/src/fs/ufs/store_dir_ufs.cc @@ -1,6 +1,6 @@ /* - * $Id: store_dir_ufs.cc,v 1.59 2003/07/15 11:33:23 robertc Exp $ + * $Id: store_dir_ufs.cc,v 1.60 2003/07/22 15:23:14 robertc Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels @@ -41,13 +41,9 @@ #include "StoreSwapLogData.h" #include "SwapDir.h" -static int ufs_initialised = 0; - int UFSSwapDir::NumberOfUFSDirs = 0; int *UFSSwapDir::UFSDirToGlobalDirMapping = NULL; -STSETUP storeFsSetup_ufs; - /* * storeUfsDirCheckObj * @@ -56,51 +52,19 @@ STSETUP storeFsSetup_ufs; * happily store anything as long as the LRU time isn't too small. */ int -UfsSwapDir::canStore(StoreEntry const &e)const +UFSSwapDir::canStore(StoreEntry const &e)const { - /* Return 999 (99.9%) constant load */ - return 999; -} - -void -UfsSwapDir::unlinkFile(char const *path) -{ -#if USE_UNLINKD - unlinkdUnlink(path); -#elif USE_TRUNCATE - - truncate(path, 0); -#else + if (IO->shedLoad()) + return -1; - ::unlink(path); -#endif + return IO->load(); } -/* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */ - -static struct cache_dir_option options[] = - { -#if NOT_YET_DONE - {"L1", storeUfsDirParseL1, storeUfsDirDumpL1}, - {"L2", storeUfsDirParseL2, storeUfsDirDumpL2}, -#endif - {NULL, NULL} - }; -/* - * storeUfsDirReconfigure - * - * This routine is called when the given swapdir needs reconfiguring - */ -void -UfsSwapDir::reconfigure(int anIndex, char *aPath) -{ - UFSSwapDir::reconfigure (anIndex, aPath); - parse_cachedir_options(this, options, 1); -} +/* ========== LOCAL FUNCTIONS ABOVE, GLOBAL FUNCTIONS BELOW ========== */ void -UFSSwapDir::reconfigure(int index, char *path) +UFSSwapDir::parseSizeL1L2() { int i; int size; @@ -109,17 +73,7 @@ UFSSwapDir::reconfigure(int index, char *path) size = i << 10; /* Mbytes to kbytes */ if (size <= 0) - fatal("storeDiskdDirReconfigure: invalid size value"); - - l1 = GetInteger(); - - if (l1 <= 0) - fatal("storeDiskdDirReconfigure: invalid level 1 directories value"); - - l2 = GetInteger(); - - if (l2 <= 0) - fatal("storeDiskdDirReconfigure: invalid level 2 directories value"); + fatal("UFSSwapDir::parseSizeL1L2: invalid size value"); /* just reconfigure it */ if (size == max_size) @@ -130,13 +84,29 @@ UFSSwapDir::reconfigure(int index, char *path) path, size); max_size = size; + + l1 = GetInteger(); + + if (l1 <= 0) + fatal("UFSSwapDir::parseSizeL1L2: invalid level 1 directories value"); + + l2 = GetInteger(); + + if (l2 <= 0) + fatal("UFSSwapDir::parseSizeL1L2: invalid level 2 directories value"); } +/* + * storeUfsDirReconfigure + * + * This routine is called when the given swapdir needs reconfiguring + */ + void -UfsSwapDir::dump(StoreEntry & entry)const +UFSSwapDir::reconfigure(int index, char *path) { - UFSSwapDir::dump (entry); - dump_cachedir_options(&entry, options, this); + parseSizeL1L2(); + parseOptions(1); } /* @@ -145,37 +115,36 @@ UfsSwapDir::dump(StoreEntry & entry)const * Called when a *new* fs is being setup. */ void -UfsSwapDir::parse(int anIndex, char *aPath) +UFSSwapDir::parse (int anIndex, char *aPath) { - UFSSwapDir::parse (anIndex, aPath); + parseSizeL1L2(); - parse_cachedir_options(this, options, 1); -} + index = anIndex; -void -UFSSwapDir::parse (int anIndex, char *aPath) -{ - max_size = GetInteger() << 10; /* Mbytes to kbytes */ + path = xstrdup(aPath); - if (max_size <= 0) - fatal("storeAufsDirParse: invalid size value"); + /* Initialise replacement policy stuff */ + repl = createRemovalPolicy(Config.replPolicy); - l1 = GetInteger(); + parseOptions(0); +} - if (l1 <= 0) - fatal("storeAufsDirParse: invalid level 1 directories value"); +SwapDirOption * +UFSSwapDir::getOptionTree() const +{ + SwapDirOption *parentResult = SwapDir::getOptionTree(); + SwapDirOption *ioOptions = IO->getOptionTree(); - l2 = GetInteger(); + if (!ioOptions) + return parentResult; - if (l2 <= 0) - fatal("storeAufsDirParse: invalid level 2 directories value"); + SwapDirOptionVector *result = new SwapDirOptionVector(); - index = anIndex; + result->options.push_back(parentResult); - path = xstrdup(aPath); + result->options.push_back(ioOptions); - /* Initialise replacement policy stuff */ - repl = createRemovalPolicy(Config.replPolicy); + return result; } /* @@ -189,6 +158,7 @@ UFSSwapDir::init() "\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."; + IO->init(); initBitmap(); if (verifyCacheDirs()) @@ -214,7 +184,7 @@ UFSSwapDir::newFileSystem() createSwapSubDirs(); } -UFSSwapDir::UFSSwapDir() : IO(NULL), map(NULL), suggest(0), swaplog_fd (-1) {} +UFSSwapDir::UFSSwapDir(char const *aType) : SwapDir(aType), IO(NULL), map(NULL), suggest(0), swaplog_fd (-1) {} UFSSwapDir::~UFSSwapDir() { @@ -231,29 +201,6 @@ UFSSwapDir::~UFSSwapDir() IO = NULL; } -static void -storeUfsDirDone(void) -{ - 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->donefunc = storeUfsDirDone; - storefs->newfunc = storeUfsNew; - ufs_initialised = 1; -} - void UFSSwapDir::dumpEntry(StoreEntry &e) const { @@ -330,6 +277,8 @@ UFSSwapDir::statfs(StoreEntry & sentry) const storeAppendPrintf(&sentry, " READ-ONLY"); storeAppendPrintf(&sentry, "\n"); + + IO->statfs(sentry); } void @@ -569,13 +518,13 @@ UFSSwapDir::verifyCacheDirs() void UFSSwapDir::createSwapSubDirs() { - int i, k; - int should_exist; LOCAL_ARRAY(char, name, MAXPATHLEN); - for (i = 0; i < l1; i++) { + for (int i = 0; i < l1; i++) { snprintf(name, MAXPATHLEN, "%s/%02X", path, i); + int should_exist; + if (createDirectory(name, 0)) should_exist = 0; else @@ -583,7 +532,7 @@ UFSSwapDir::createSwapSubDirs() debug(47, 1) ("Making directories in %s\n", name); - for (k = 0; k < l2; k++) { + for (int k = 0; k < l2; k++) { snprintf(name, MAXPATHLEN, "%s/%02X/%02X", path, i, k); createDirectory(name, should_exist); } @@ -664,7 +613,7 @@ UFSSwapDir::closeLog() swaplog_fd = -1; - NumberOfUFSDirs--; + --NumberOfUFSDirs; assert(NumberOfUFSDirs >= 0); @@ -882,16 +831,16 @@ public: #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) {} +/* + * 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 UFSSwapDir::writeCleanStart() { @@ -1308,6 +1257,8 @@ UFSSwapDir::validFileno(sfileno filn, int flag) const return 1; } + + /* * UFSSwapDir::unlinkFile * @@ -1318,9 +1269,18 @@ UFSSwapDir::validFileno(sfileno filn, int flag) const void UFSSwapDir::unlinkFile(sfileno f) { - debug(79, 3) ("UFSSwapDir::unlinkFile: unlinking fileno %08X\n", f); + debug(79, 3) ("UFSSwapDir::unlinkFile: unlinking fileno %08X '%s'\n", f, fullPath(f,NULL)); /* commonUfsDirMapBitReset(this, f); */ - unlinkFile(fullPath(f, NULL)); + IO->unlinkFile(fullPath(f,NULL)); +} + +void +UFSSwapDir::unlink(StoreEntry & e) +{ + debug(79, 3) ("storeUfsUnlink: dirno %d, fileno %08X\n", index, e.swap_filen); + replacementRemove(&e); + mapBitReset(e.swap_filen); + UFSSwapDir::unlinkFile(e.swap_filen); } /* @@ -1362,6 +1322,7 @@ UFSSwapDir::dump(StoreEntry & entry) const max_size >> 10, l1, l2); + dumpOptions(&entry); } char * @@ -1384,3 +1345,15 @@ UFSSwapDir::fullPath(sfileno filn, char *fullpath) const return fullpath; } + +int +UFSSwapDir::callback() +{ + return IO->callback(); +} + +void +UFSSwapDir::sync() +{ + IO->sync(); +} diff --git a/src/fs/ufs/store_io_ufs.cc b/src/fs/ufs/store_io_ufs.cc index 9923d22d1e..a875c1563b 100644 --- a/src/fs/ufs/store_io_ufs.cc +++ b/src/fs/ufs/store_io_ufs.cc @@ -1,6 +1,6 @@ /* - * $Id: store_io_ufs.cc,v 1.19 2003/07/15 23:12:02 robertc Exp $ + * $Id: store_io_ufs.cc,v 1.20 2003/07/22 15:23:15 robertc Exp $ * * DEBUG: section 79 Storage Manager UFS Interface * AUTHOR: Duane Wessels @@ -47,6 +47,13 @@ UfsIO::shedLoad() return false; } +int +UfsIO::load() +{ + /* Return 999 (99.9%) constant load */ + return 999; +} + void UfsIO::deleteSelf() const { @@ -56,7 +63,7 @@ UfsIO::deleteSelf() const StoreIOState::Pointer UfsIO::createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const { - return new ufsstate_t (SD, e, callback, callback_data); + return new UFSStoreState (SD, e, callback, callback_data); } DiskFile::Pointer @@ -65,36 +72,33 @@ UfsIO::newFile (char const *path) return new UFSFile (path); } -CBDATA_CLASS_INIT(ufsstate_t); +void +UfsIO::unlinkFile(char const *path) +{ +#if USE_UNLINKD + unlinkdUnlink(path); +#elif USE_TRUNCATE + + truncate(path, 0); +#else + + ::unlink(path); +#endif +} + +CBDATA_CLASS_INIT(UFSStoreState); void * -ufsstate_t::operator new (size_t) +UFSStoreState::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; + CBDATA_INIT_TYPE(UFSStoreState); + return cbdataAlloc(UFSStoreState); } void -ufsstate_t::operator delete (void *address) +UFSStoreState::operator delete (void *address) { - ufsstate_t *t = static_cast(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; } CBDATA_CLASS_INIT(UFSFile); @@ -121,7 +125,7 @@ UFSFile::operator delete (void *address) void UFSFile::deleteSelf() const {delete this;} -UFSFile::UFSFile (char const *aPath) : fd (-1) +UFSFile::UFSFile (char const *aPath) : fd (-1), closed (true) { assert (aPath); debug (79,3)("UFSFile::UFSFile: %s\n", aPath); @@ -144,6 +148,7 @@ UFSFile::open (int flags, mode_t mode, IORequestor::Pointer callback) if (fd < 0) { debug(79, 3) ("UFSFile::open: got failure (%d)\n", errno); } else { + closed = false; store_open_disk_fd++; debug(79, 3) ("UFSFile::open: opened FD %d\n", fd); } @@ -162,6 +167,7 @@ UFSFile::create (int flags, mode_t mode, IORequestor::Pointer callback) void UFSFile::doClose() { if (fd > -1) { + closed = true; file_close(fd); store_open_disk_fd--; fd = -1; @@ -186,45 +192,87 @@ UFSFile::canRead() const bool UFSFile::error() const { - if (fd < 0) + if (fd < 0 && !closed) return true; return false; } void -ufsstate_t::ioCompletedNotification() +UFSStoreState::ioCompletedNotification() { if (opening) { opening = false; - /* There is no 'opened' callback */ + debug(79, 3) ("storeDiskdOpenDone: dirno %d, fileno %08x status %d\n", + swap_dirn, swap_filen, theFile->error()); + assert (FILE_MODE(mode) == O_RDONLY); + openDone(); + return; } if (creating) { creating = false; + debug(79, 3) ("storeDiskdCreateDone: dirno %d, fileno %08x status %d\n", + swap_dirn, swap_filen, theFile->error()); + openDone(); + return; } - assert(0); + assert (!(closing ||opening)); + 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 -ufsstate_t::closeCompleted() +UFSStoreState::openDone() { - doCallback(theFile->error() ? 0 : -1); + if (theFile->error()) { + doCallback(DISK_ERROR); + return; + } + + if (FILE_MODE(mode) == O_WRONLY) { + if (kickWriteQueue()) + return; + } else if ((FILE_MODE(mode) == O_RDONLY) && !closing) { + if (kickReadQueue()) + return; + } + + if (closing && !theFile->ioInProgress()) + doCallback(theFile->error() ? -1 : 0); + + debug(79, 3) ("squidaiostate_t::openDone: exiting\n"); } void -ufsstate_t::close() +UFSStoreState::closeCompleted() { - debug(79, 3) ("storeUfsClose: dirno %d, fileno %08X\n", - swap_dirn, swap_filen); - closing = true; + assert (closing); + debug(79, 3) ("UFSStoreState::closeCompleted: dirno %d, fileno %08x status %d\n", + swap_dirn, swap_filen, theFile->error()); - if (!(reading || writing)) { - ((UFSFile *)theFile.getRaw())->close(); - } + if (theFile->error()) + doCallback(DISK_ERROR); + else + doCallback(DISK_OK); + + closing = false; +} + +/* Close */ +void +UFSStoreState::close() +{ + debug(79, 3) ("UFSStoreState::close: dirno %d, fileno %08X\n", swap_dirn, + swap_filen); + /* mark the object to be closed on the next io that completes */ + closing = true; + theFile->close(); } void @@ -286,7 +334,7 @@ UFSStoreState::write(char const *buf, size_t size, off_t offset, FREE * free_fun { debug(79, 3) ("UFSStoreState::write: dirn %d, fileno %08X\n", swap_dirn, swap_filen); - if (!theFile->canWrite() || writing) { + if (!theFile->canWrite()) { assert(creating || writing); queueWrite(buf, size, offset, free_func); return; @@ -296,13 +344,11 @@ UFSStoreState::write(char const *buf, size_t size, off_t offset, FREE * free_fun theFile->write(buf,size,offset,free_func); } -void -UfsSwapDir::unlink(StoreEntry & e) +bool +UFSFile::ioInProgress()const { - debug(79, 3) ("storeUfsUnlink: fileno %08X\n", e.swap_filen); - replacementRemove(&e); - mapBitReset(e.swap_filen); - UFSSwapDir::unlinkFile(e.swap_filen); + /* IO is never pending with UFS */ + return false; } /* === STATIC =========================================================== */ @@ -329,11 +375,10 @@ UFSFile::readDone(int rvfd, const char *buf, int len, int errflag) } void -ufsstate_t::readCompleted(const char *buf, int len, int errflag) +UFSStoreState::readCompleted(const char *buf, int len, int errflag) { - reading = false; - debug(79, 3) ("storeUfsReadDone: dirno %d, fileno %08X, len %d\n", + debug(79, 3) ("storeDiskdReadDone: dirno %d, fileno %08x len %d\n", swap_dirn, swap_filen, len); if (len > 0) @@ -347,13 +392,25 @@ ufsstate_t::readCompleted(const char *buf, int len, int errflag) void *cbdata; + /* A note: + * diskd IO queues closes via the diskd queue. So close callbacks + * occur strictly after reads and writes. + * ufs doesn't queue, it simply completes, so close callbacks occur + * strictly after reads and writes. + * aufs performs closes syncronously, so close events must be managed + * to force strict ordering. + * The below does this: + * closing is set when close() is called, and close only triggers + * when no io's are pending. + * writeCompleted likewise. + */ if (!closing && cbdataReferenceValidDone(read.callback_data, &cbdata)) { if (len > 0 && read_buf != buf) memcpy(read_buf, buf, len); callback(cbdata, read_buf, len); - } else if (closing) - fatal("Sync ufs doesn't support overlapped close and read calls\n"); + } else if (closing && theFile.getRaw()!= NULL && !theFile->ioInProgress()) + doCallback(errflag); } void @@ -381,47 +438,66 @@ UFSFile::writeDone(int rvfd, int errflag, size_t len) } void -ufsstate_t::writeCompleted(int errflag, size_t len) +UFSStoreState::writeCompleted(int errflag, size_t len) { debug(79, 3) ("storeUfsWriteDone: dirno %d, fileno %08X, len %ld\n", swap_dirn, swap_filen, (long int) len); writing = false; - if (theFile->error()) + offset_ += len; + + if (theFile->error()) { doCallback(DISK_ERROR); + return; + } - offset_ += len; + if (closing && !theFile->ioInProgress()) { + theFile->close(); + return; + } + + if (!flags.write_kicking) { + flags.write_kicking = true; + /* While we start and complete syncronously io's. */ + + while (kickWriteQueue() && !theFile->ioInProgress()) - if (closing) - ((UFSFile *)theFile.getRaw())->close(); + ; + flags.write_kicking = false; + + if (!theFile->ioInProgress() && closing) + doCallback(errflag); + } } void -ufsstate_t::doCallback(int errflag) +UFSStoreState::doCallback(int errflag) { debug(79, 3) ("storeUfsIOCallback: errflag=%d\n", errflag); - /* We are finished with the file */ + /* We are finished with the file as this is on close or error only.*/ theFile = NULL; - void *cbdata; - - if (cbdataReferenceValidDone(callback_data, &cbdata)) - callback(cbdata, errflag, this); + STIOCB *theCallback = callback; callback = NULL; -} - - -/* - * Clean up any references from the SIO before it get's released. - */ -ufsstate_t::~ufsstate_t() -{} + void *cbdata; + if (cbdataReferenceValidDone(callback_data, &cbdata) && theCallback) + theCallback(cbdata, errflag, this); +} /* ============= THE REAL UFS CODE ================ */ -UFSStoreState::UFSStoreState() : opening (false), creating (false), closing (false), reading(false), writing(false), pending_reads(NULL), pending_writes (NULL){} +UFSStoreState::UFSStoreState(SwapDir * SD, StoreEntry * anEntry, STIOCB * callback_, void *callback_data_) : opening (false), creating (false), closing (false), reading(false), writing(false), pending_reads(NULL), pending_writes (NULL) +{ + swap_filen = anEntry->swap_filen; + swap_dirn = SD->index; + mode = O_BINARY; + callback = callback_; + callback_data = cbdataReference(callback_data_); + e = anEntry; + flags.write_kicking = false; +} UFSStoreState::~UFSStoreState() { @@ -545,7 +621,7 @@ StoreIOState::Pointer UFSStrategy::open(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data) { - assert (((UfsSwapDir *)SD)->IO == this); + assert (((UFSSwapDir *)SD)->IO == this); debug(79, 3) ("UFSStrategy::open: fileno %08X\n", e->swap_filen); if (shedLoad()) { @@ -582,7 +658,7 @@ StoreIOState::Pointer UFSStrategy::create(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data) { - assert (((UfsSwapDir *)SD)->IO == this); + assert (((UFSSwapDir *)SD)->IO == this); /* Allocate a number */ sfileno filn = ((UFSSwapDir *)SD)->mapBitAllocate(); debug(79, 3) ("UFSStrategy::create: fileno %08X\n", filn); @@ -625,3 +701,28 @@ UFSStrategy::create(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, return sio; } + +UfsIOModule & +UfsIOModule::GetInstance() +{ + if (!Instance) + Instance = new UfsIOModule; + + return *Instance; +} + +void +UfsIOModule::init() +{} + +void +UfsIOModule::shutdown() +{} + +UFSStrategy * +UfsIOModule::createSwapDirIOStrategy() +{ + return new InstanceToSingletonAdapter(&UfsIO::Instance); +} + +UfsIOModule *UfsIOModule::Instance = NULL; diff --git a/src/fs/ufs/store_ufs.h b/src/fs/ufs/store_ufs.h index d2f09e7aec..c30ce25d03 100644 --- a/src/fs/ufs/store_ufs.h +++ b/src/fs/ufs/store_ufs.h @@ -27,12 +27,14 @@ public: virtual int getFD() const { return fd;} virtual bool canRead() const; + virtual bool ioInProgress()const; private: static DRCB ReadDone; static DWCB WriteDone; CBDATA_CLASS(UFSFile); int fd; + bool closed; char const *path_; IORequestor::Pointer ioRequestor; void doClose(); @@ -40,53 +42,38 @@ private: void writeDone(int fd, int errflag, size_t len); }; -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); -}; - - #include "SwapDir.h" /* * Store IO stuff */ /* 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 int load(); 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); + virtual void unlinkFile (char const *); static UfsIO Instance; }; +#include "fs/ufs/IOModule.h" + +class UfsIOModule : public IOModule +{ + +public: + static UfsIOModule &GetInstance(); + virtual void init(); + virtual void shutdown(); + virtual UFSStrategy *createSwapDirIOStrategy(); + +private: + static UfsIOModule *Instance; +}; + #endif diff --git a/src/globals.h b/src/globals.h index 028b9485fb..1144a29a79 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1,6 +1,6 @@ /* - * $Id: globals.h,v 1.125 2003/07/09 14:14:58 hno Exp $ + * $Id: globals.h,v 1.126 2003/07/22 15:23:02 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -148,7 +148,6 @@ extern int refresh_nocache_hack; /* 0 */ extern int store_open_disk_fd; /* 0 */ extern const char *SwapDirType[]; extern authscheme_entry_t *authscheme_list; /* NULL */ -extern storefs_entry_t *storefs_list; /* NULL */ extern storerepl_entry_t *storerepl_list; /* NULL */ extern int store_swap_low; /* 0 */ extern int store_swap_high; /* 0 */ diff --git a/src/main.cc b/src/main.cc index b87552a1e9..a4f7793fd4 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,6 @@ /* - * $Id: main.cc,v 1.384 2003/07/15 06:50:42 robertc Exp $ + * $Id: main.cc,v 1.385 2003/07/22 15:23:02 robertc Exp $ * * DEBUG: section 1 Startup and Main Loop * AUTHOR: Harvest Derived @@ -42,6 +42,7 @@ #include "ACLASN.h" #include "ACL.h" #include "htcp.h" +#include "StoreFileSystem.h" #if USE_WIN32_SERVICE @@ -982,6 +983,9 @@ main(int argc, char **argv) storeFsInit(); /* required for config parsing */ + /* Shouldn't be needed for config parsing, but have not audited for such */ + StoreFileSystem::SetupAllFs(); + authenticateSchemeInit(); /* required for config parsign */ parse_err = parseConfigFile(ConfigFile); @@ -1485,7 +1489,7 @@ SquidShutdown(void *unused) #endif storeDirSync(); /* Flush log close */ - storeFsDone(); + StoreFileSystem::FreeAllFs(); #if PURIFY || XMALLOC_TRACE configFreeMemory(); diff --git a/src/protos.h b/src/protos.h index 055a3b70de..5b596951a8 100644 --- a/src/protos.h +++ b/src/protos.h @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.484 2003/07/15 11:33:22 robertc Exp $ + * $Id: protos.h,v 1.485 2003/07/22 15:23:02 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -69,6 +69,8 @@ SQUIDCEXTERN void allocate_new_swapdir(cacheSwap *); SQUIDCEXTERN void self_destruct(void); SQUIDCEXTERN int GetInteger(void); SQUIDCEXTERN void add_http_port(char *portspec); +extern int xatoi(const char *token); +extern long xatol(const char *token); /* extra functions from cache_cf.c useful for lib modules */ @@ -79,9 +81,6 @@ SQUIDCEXTERN void parse_wordlist(wordlist ** list); 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 const * sd); SQUIDCEXTERN void parse_sockaddr_in_list_token(sockaddr_in_list **, char *); @@ -733,9 +732,6 @@ SQUIDCEXTERN int memPoolsTotalAllocated(void); /* ----------------------------------------------------------------- */ -/* store_modules.c */ -SQUIDCEXTERN void storeFsSetup(void); - /* repl_modules.c */ SQUIDCEXTERN void storeReplSetup(void); diff --git a/src/store.cc b/src/store.cc index f2e270eb4e..63f75390ef 100644 --- a/src/store.cc +++ b/src/store.cc @@ -1,6 +1,6 @@ /* - * $Id: store.cc,v 1.571 2003/07/14 10:36:42 robertc Exp $ + * $Id: store.cc,v 1.572 2003/07/22 15:23:02 robertc Exp $ * * DEBUG: section 20 Storage Manager * AUTHOR: Harvest Derived @@ -1684,48 +1684,6 @@ void storeFsInit(void) { storeReplSetup(); - storeFsSetup(); -} - - -/* - * similar to above, but is called when a graceful shutdown is to occur - * of each fs module. - */ -void -storeFsDone(void) -{ - int i = 0; - - while (storefs_list[i].typestr != NULL) { - storefs_list[i].donefunc(); - i++; - } -} - -/* - * called to add another store fs module - * RBC: doesn't belong here. Move IT. - */ -void -StoreEntry::FsAdd(const char *type, STSETUP * setup) -{ - int i; - /* find the number of currently known storefs types */ - - for (i = 0; storefs_list && storefs_list[i].typestr; i++) { - assert(strcmp(storefs_list[i].typestr, type) != 0); - } - - /* add the new type */ - storefs_list = static_cast(xrealloc(storefs_list, (i + 2) * sizeof(storefs_entry_t))); - - memset(&storefs_list[i + 1], 0, sizeof(storefs_entry_t)); - - storefs_list[i].typestr = type; - - /* Call the FS to set up capabilities and initialize the FS driver */ - setup(&storefs_list[i]); } /* diff --git a/src/store_dir.cc b/src/store_dir.cc index 0edb6d46f0..cdb7257d25 100644 --- a/src/store_dir.cc +++ b/src/store_dir.cc @@ -1,6 +1,6 @@ /* - * $Id: store_dir.cc,v 1.147 2003/07/17 15:40:27 wessels Exp $ + * $Id: store_dir.cc,v 1.148 2003/07/22 15:23:02 robertc Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels @@ -362,7 +362,7 @@ storeDirStats(StoreEntry * sentry) for (i = 0; i < Config.cacheSwap.n_configured; i++) { storeAppendPrintf(sentry, "\n"); SD = INDEXSD(i); - storeAppendPrintf(sentry, "Store Directory #%d (%s): %s\n", i, SD->type, + storeAppendPrintf(sentry, "Store Directory #%d (%s): %s\n", i, SD->type(), storeSwapDir(i)); storeAppendPrintf(sentry, "FS Block Size %d Bytes\n", SD->fs.blksize); @@ -545,6 +545,9 @@ storeDirCallback(void) ++ndir; j += SD->callback(); + + if (j > 100) + fatal ("too much io\n"); } } while (j > 0); diff --git a/src/store_modules.sh b/src/store_modules.sh deleted file mode 100644 index 0f8a781b4c..0000000000 --- a/src/store_modules.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -echo "/* automatically generated by $0 $*" -echo " * do not edit" -echo " */" -echo "#include \"squid.h\"" -echo "#include \"Store.h\"" -echo "" -for module in "$@"; do - echo "extern STSETUP storeFsSetup_${module};" -done -echo "void storeFsSetup(void)" -echo "{" -for module in "$@"; do - echo " StoreEntry::FsAdd(\"$module\", storeFsSetup_${module});" -done -echo "}" diff --git a/src/structs.h b/src/structs.h index 489933621f..ed6ab210b8 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.475 2003/07/17 22:22:53 wessels Exp $ + * $Id: structs.h,v 1.476 2003/07/22 15:23:02 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -2172,17 +2172,6 @@ struct _store_rebuild_data int zero_object_sz; }; -/* - * This defines an fs type - */ - -struct _storefs_entry -{ - const char *typestr; - STFSSHUTDOWN *donefunc; - STFSNEW *newfunc; -}; - /* * This defines an repl type */ diff --git a/src/typedefs.h b/src/typedefs.h index 4d38215c50..422d91367a 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.167 2003/07/15 11:33:22 robertc Exp $ + * $Id: typedefs.h,v 1.168 2003/07/22 15:23:02 robertc Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -251,8 +251,6 @@ class storeIOState; typedef struct _link_list link_list; -typedef struct _storefs_entry storefs_entry_t; - typedef struct _storerepl_entry storerepl_entry_t; typedef struct _diskd_queue diskd_queue; @@ -332,9 +330,6 @@ typedef void HLPSONEQ(void *); typedef void HLPCMDOPTS(int *argc, char **argv); typedef void IDNSCB(void *, rfc1035_rr *, int); -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); diff --git a/src/ufscommon.h b/src/ufscommon.h index 8b471cc6d4..df45019510 100644 --- a/src/ufscommon.h +++ b/src/ufscommon.h @@ -1,6 +1,6 @@ /* - * $Id: ufscommon.h,v 1.6 2003/07/15 11:33:22 robertc Exp $ + * $Id: ufscommon.h,v 1.7 2003/07/22 15:23:03 robertc Exp $ * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- @@ -52,16 +52,16 @@ public: static int DirClean(int swap_index); static int FilenoBelongsHere(int fn, int F0, int F1, int F2); - UFSSwapDir(); + UFSSwapDir(char const *aType); virtual void init(); virtual void newFileSystem(); virtual void dump(StoreEntry &) const; ~UFSSwapDir(); virtual bool doubleCheck(StoreEntry &); - virtual void unlink(StoreEntry &) = 0; + virtual void unlink(StoreEntry &); virtual void statfs(StoreEntry &)const; virtual void maintainfs(); - virtual int canStore(StoreEntry const &)const = 0; + virtual int canStore(StoreEntry const &)const; virtual void reference(StoreEntry &); virtual void dereference(StoreEntry &); virtual StoreIOState::Pointer createStoreIO(StoreEntry &, STFNCB *, STIOCB *, void *); @@ -73,9 +73,10 @@ public: virtual void logEntry(const StoreEntry & e, int op) const; virtual void parse(int index, char *path); virtual void reconfigure(int, char *); + virtual int callback(); + virtual void sync(); void unlinkFile(sfileno f); - virtual void unlinkFile (char const *) = 0; // move down when unlink is a virtual method //protected: UFSStrategy *IO; @@ -99,6 +100,8 @@ public: int clean); int validFileno(sfileno filn, int flag) const; int mapBitAllocate(); + virtual SwapDirOption *getOptionTree() const; + void *fsdata; bool validL2(int) const; @@ -114,6 +117,7 @@ protected: int l2; private: + void parseSizeL1L2(); static int NumberOfUFSDirs; static int * UFSDirToGlobalDirMapping; bool pathIsDirectory(const char *path)const; @@ -152,6 +156,7 @@ public: 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 void close () = 0; virtual bool canRead() const = 0; virtual bool canWrite() const {return true;} @@ -159,6 +164,9 @@ public: virtual int getFD() const {return -1;} virtual bool error() const = 0; + + /* Inform callers if there is IO in progress */ + virtual bool ioInProgress() const = 0; }; /* UFS dir specific IO calls */ @@ -182,6 +190,80 @@ public: STIOCB *, void *); /* virtual void strategyStats(StoreEntry *sentry) const = 0; */ /* virtual void dumpCacheDirParams(StoreEntry * e, const char *option) const = 0; */ + virtual SwapDirOption *getOptionTree() const { return NULL;} + + virtual void unlinkFile (char const *) = 0; + virtual void sync() {} + + virtual int callback() { return 0; } + + /* Init per-instance logic */ + virtual void init() {} + + /* cachemgr output on the IO instance stats */ + virtual void statfs(StoreEntry & sentry)const {}} + +; + +class IOStrategy +{ + +public: + virtual ~IOStrategy(){} + + /* Can the IO Strategy handle more requests ? */ + virtual bool shedLoad() = 0; + /* What is the current load? 999 = 99.9% */ + virtual int load() = 0; + /* Return a handle for performing IO operations */ + virtual DiskFile::Pointer newFile (char const *path) = 0; + /* flush all IO operations */ + virtual void sync() {} + + /* perform any pending callbacks */ + virtual int callback() { return 0; } + + /* Init per-instance logic */ + virtual void init() {} + + /* cachemgr output on the IO instance stats */ + virtual void statfs(StoreEntry & sentry)const {}} + +; + +/* RBC 20030718 - use this to provide instance expecting classes a pointer to a + * singleton + */ + +template + +class InstanceToSingletonAdapter : public C +{ + +public: + void *operator new (size_t byteCount) { return ::operator new (byteCount);} + + void operator delete (void *address) { ::operator delete (address);} + + InstanceToSingletonAdapter(C const *instance) : theInstance (instance) {} + + C const * operator-> () const {return theInstance; } + + C * operator-> () {return const_cast(theInstance); } + + C const & operator * () const {return *theInstance; } + + C & operator * () {return *const_cast(theInstance); } + + operator C const * () const {return theInstance;} + + operator C *() {return const_cast(theInstance);} + + // This will go when we remove the deleteSelf idiom + virtual void deleteSelf() const {delete const_cast(this);} + +private: + C const *theInstance; }; /* Common ufs-store-dir logic */ @@ -190,10 +272,18 @@ class UFSStoreState : public storeIOState, public IORequestor { public: - virtual void deleteSelf() const = 0; - UFSStoreState(); + virtual void deleteSelf() const {delete this;} + + void * operator new (size_t); + void operator delete (void *); + UFSStoreState(SwapDir * SD, StoreEntry * anEntry, STIOCB * callback_, void *callback_data_); ~UFSStoreState(); + virtual void close(); + virtual void closeCompleted(); // protected: + virtual void ioCompletedNotification(); + virtual void readCompleted(const char *buf, int len, int errflag); + virtual void writeCompleted(int errflag, size_t len); DiskFile::Pointer theFile; bool opening; bool creating; @@ -204,6 +294,7 @@ public: void write(char const *buf, size_t size, off_t offset, FREE * free_func); protected: + virtual void doCallback (int errflag); class _queued_read { @@ -236,6 +327,14 @@ protected: static MemPool *Pool; }; + /* These should be in the IO strategy */ + + struct + { + bool write_kicking; + } + + flags; link_list *pending_reads; link_list *pending_writes; void queueRead(char *, size_t, off_t, STRCB *, void *); @@ -243,6 +342,10 @@ protected: bool kickReadQueue(); bool kickWriteQueue(); char *read_buf; + +private: + CBDATA_CLASS(UFSStoreState); + void openDone(); }; class RebuildState : public RefCountable