]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Modular policy implementation. See programmers guide for API details.
authorhno <>
Fri, 9 Jun 2000 00:05:30 +0000 (00:05 +0000)
committerhno <>
Fri, 9 Jun 2000 00:05:30 +0000 (00:05 +0000)
This also includes Adrians improved store I/O callback handler model.

32 files changed:
configure.in
doc/Programming-Guide/prog-guide.sgml
doc/debug-sections.txt
src/Makefile.in
src/cache_cf.cc
src/cf.data.pre
src/fs/aufs/async_io.cc
src/fs/aufs/store_asyncufs.h
src/fs/aufs/store_dir_aufs.cc
src/fs/aufs/store_io_aufs.cc
src/fs/coss/store_coss.h
src/fs/coss/store_dir_coss.cc
src/fs/coss/store_io_coss.cc
src/fs/diskd/store_dir_diskd.cc
src/fs/diskd/store_diskd.h
src/fs/ufs/store_dir_ufs.cc
src/globals.h
src/protos.h
src/repl/Makefile.in [new file with mode: 0644]
src/repl/heap/Makefile.in [new file with mode: 0644]
src/repl/heap/store_heap_replacement.cc [new file with mode: 0644]
src/repl/heap/store_heap_replacement.h [new file with mode: 0644]
src/repl/heap/store_repl_heap.cc [new file with mode: 0644]
src/repl/lru/Makefile.in [new file with mode: 0644]
src/repl/lru/store_repl_lru.cc [new file with mode: 0644]
src/squid.h
src/store.cc
src/store_digest.cc
src/store_dir.cc
src/store_log.cc
src/structs.h
src/typedefs.h

index 7f2aaa91fb29222b07c26a31d082afdcbfc9b0e9..f8b0fad3c35869846007e7b62d6c642f571671b1 100644 (file)
@@ -3,13 +3,13 @@ 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.192 2000/05/31 08:57:08 hno Exp $
+dnl  $Id: configure.in,v 1.193 2000/06/08 18:05:30 hno Exp $
 dnl
 dnl
 dnl
 AC_INIT(src/main.c)
 AC_CONFIG_HEADER(include/autoconf.h)
-AC_REVISION($Revision: 1.192 $)dnl
+AC_REVISION($Revision: 1.193 $)dnl
 AC_PREFIX_DEFAULT(/usr/local/squid)
 AC_CONFIG_AUX_DIR(cfgaux)
 
@@ -322,6 +322,49 @@ AC_SUBST(STORE_MODULES)
 STORE_OBJS="fs/`echo $STORE_MODULES|sed -e's% %.a fs/%g'`.a"
 AC_SUBST(STORE_OBJS)
 
+dnl --enable-heap-replacement compability option
+AC_ARG_ENABLE(heap-replacement,
+[  --enable-heap-replacement
+                          Backwards compability option. Please use the
+                         new --enable-removal-policies directive instead.],
+[ if test "$enableval" = "yes" ; then
+    echo "--enable-heap-replacement is obsolete. please use the new"
+    echo "--enable-removal-policies directive instead"
+    sleep 5
+    REPL_POLICIES="heap"
+  fi
+])
+
+AC_ARG_ENABLE(removal_policies,
+[  --enable-removal-policies=\"list of policies\"
+                          Build support for the list of removal policies.
+                          The default is only to build the "lru" module.
+                          See src/repl for a list of available modules, or
+                          Programmers Guide section 9.9 for details on how
+                         to build your custom policy],
+[ case $enableval in
+  yes)
+       for module in $srcdir/src/repl/*; do
+           if test -f $module/Makefile.in; then
+               REPL_POLICIES="$REPL_POLICIES `basename $module`"
+           fi
+       done
+       ;;
+  no)
+       ;;
+  *)   REPL_POLICIES="`echo $enableval| sed -e 's/,/ /g;s/  */ /g'`"
+       ;;
+  esac
+],
+[ if test -z "$REPL_POLICIES"; then
+    REPL_POLICIES="lru"
+  fi
+])
+echo "Store modules built: $REPL_POLICIES"
+AC_SUBST(REPL_POLICIES)
+REPL_OBJS="repl/`echo $REPL_POLICIES|sed -e's% %.a repl/%g'`.a"
+AC_SUBST(REPL_OBJS)
+
 OPT_PINGER_EXE=''
 AC_ARG_ENABLE(icmp,
 [  --enable-icmp           Enable ICMP pinging],
@@ -609,18 +652,6 @@ AC_ARG_ENABLE(underscores,
   fi
 ])
 
-dnl Enable HEAP_REPLACEMENT
-AC_ARG_ENABLE(heap-replacement,
-[  --enable-heap-replacement
-                          This option allows you to use various cache
-                          replacement algorithms, instead of the standard
-                          LRU algorithm.],
-[ if test "$enableval" = "yes" ; then
-    echo "Enabling HEAP_REPLACEMENT"
-    AC_DEFINE(HEAP_REPLACEMENT, 1)
-  fi
-])
-
 dnl Select auth modules to build
 AUTH_MODULES=
 AC_ARG_ENABLE(auth-modules,
@@ -1618,6 +1649,9 @@ AC_OUTPUT(\
        ./src/fs/ufs/Makefile \
        ./src/fs/aufs/Makefile \
        ./src/fs/coss/Makefile \
+       ./src/repl/Makefile \
+       ./src/repl/lru/Makefile \
+       ./src/repl/heap/Makefile \
        ./src/fs/diskd/Makefile \
        ./contrib/Makefile \
        $SNMP_MAKEFILE \
index fd90426900255c7b5c590a2d43336ddc152daca0..092bc4fdc78644238ce27e10dfc0574e66a22ea7 100644 (file)
@@ -2,7 +2,7 @@
 <article>
 <title>Squid Programmers Guide</title>
 <author>Duane Wessels, Squid Developers
-<date>$Id: prog-guide.sgml,v 1.27 2000/05/03 17:15:40 adrian Exp $</date>
+<date>$Id: prog-guide.sgml,v 1.28 2000/06/08 18:05:33 hno Exp $</date>
 
 <abstract>
 Squid is a WWW Cache application developed by the National Laboratory
@@ -1492,16 +1492,16 @@ Squid consists of the following major components
        This feature may not be required by some storage systems
        and can be implemented as a null-function (no-op).
 
-<sect2><tt/log.clean.open()/
+<sect2><tt/log.clean.start()/
 
        <P>
 <verb>
        int
-       STLOGCLEANOPEN(SwapDir *);
+       STLOGCLEANSTART(SwapDir *);
 </verb>
 
        <P>
-       The <tt/log.clean.open/ function, of type <em/STLOGCLEANOPEN/,
+       The <tt/log.clean.start/ function, of type <em/STLOGCLEANSTART/,
        is used for the process of writing "clean" state-holding
        log files.  The clean-writing procedure is initiated by
        the <em/squid -k rotate/ command.  This is a special case
@@ -1514,24 +1514,45 @@ Squid consists of the following major components
        keep state information for the clean-writing process, but
        should not be accessed by upper layers.
 
+<sect2><tt/log.clean.nextentry()/
+
+       <P>
+<verb>
+       StoreEntry *
+       STLOGCLEANNEXTENTRY(SwapDir *);
+</verb>
+
+       <P>
+       Gets the next entry that is a candidate for the clean log.
+
+       <P>
+       Returns NULL when there is no more objects to log
+
 <sect2><tt/log.clean.write()/
 
        <P>
 <verb>
        void
-       STLOGCLEANWRITE(const StoreEntry *, SwapDir *);
+       STLOGCLEANWRITE(SwapDir *, const StoreEntry *);
 </verb>
 
        <P>
        The <tt/log.clean.write/ function, of type <em/STLOGCLEANWRITE/,
        writes an entry to the clean log file (if any).
 
+<sect2><tt/log.clean.done()/
+
        <P>
-       A NULL <em/StoreEntry/ argument indicates the end of
-       the clean-writing process and signals the storage
-       system to close the clean log, and rename or move them
-       to become the official state-holding log.
+<verb>
+       void
+       STLOGCLEANDONE(SwapDir *);
+</verb>
 
+       <P>
+       Indicates the end of the clean-writing process and signals
+       the storage system to close the clean log, and rename or
+       move them to become the official state-holding log ready
+       to be opened.
 
 <sect1>Replacement policy implementation
 
@@ -1545,10 +1566,7 @@ replacement policy. Cyclic filesystems such as COSS require this tight
 coupling between the storage layer and the replacement policy.
 
 
-<sect1>Future removal policy
-
-       <P>
-       (replaces the above Replace policy)
+<sect1>Removal policy API
 
        <P>
        The removal policy is responsible for determining in which order
@@ -1625,10 +1643,26 @@ coupling between the storage layer and the replacement policy.
 </verb>
 
        <P>
-       Tells the policy that a StoreEntry has been referenced.
+       Tells the policy that a StoreEntry is going to be referenced. Called
+       whenever a entry gets locked.
 
        <P>
-       datap is a pointer to where policy specific data is stored
+       node is a pointer to where policy specific data is stored
+       for the store entry, currently the size of one (void *) pointer.
+
+<sect3>policy.Dereferenced()
+
+<P>
+<verb>
+       policy-&gt;Dereferenced(RemovalPolicy *policy, const StoreEntry *, RemovalPolicyNode *node)
+</verb>
+
+       <P>
+       Tells the policy that a StoreEntry has been referenced. Called when
+       an access to the entry has finished.
+
+       <P>
+       node is a pointer to where policy specific data is stored
        for the store entry, currently the size of one (void *) pointer.
 
 <sect3>policy.WalkInit()
@@ -1822,6 +1856,32 @@ coupling between the storage layer and the replacement policy.
        Prior to returning the created instance must be registered as
        callback-data by calling cbdataAdd().
 
+<sect2>Design notes/bugs
+
+<P>
+       The RemovalPolicyNode design is incomplete/insufficient. The intention
+       was to abstract the location of the index pointers from the policy
+       implementation to allow the policy to work on both on-disk and memory
+       caches, but unfortunately the purge method for HEAP based policies
+       needs to update this, and it is also preferable if the purge method
+       in general knows how to clear the information. I think the agreement
+       was that the current design of thightly coupling the two together
+       on one StoreEntry is not the best design possible.
+
+<P>
+       It is debated if the design in having the policy index control the
+       clean index writes is the correct approach. Perhaps not. Perhaps a
+       more appropriate design is probably to do the store indexing
+       completely outside the policy implementation (i.e. using the hash
+       index), and only ask the policy to dump it's state somehow.
+
+<P>
+       The Referenced/Dereferenced() calls is today mapped to lock/unlock
+       which is an approximation of when they are intended to be called.
+       However, the real intention is to have Referenced() called whenever
+       an object is referenced, and Dereferenced() only called when the
+       object has actually been used for anything good.
+
 <!-- %%%% Chapter : FORWARDING SELECTION %%%% -->
 <sect>Forwarding Selection
 
index 15bf1ad1a5d5274dc1785c0f9b359cb8e7f5df37..1b35dbc6bcebf07b20d79f2007bcdfbc7824c247 100644 (file)
@@ -85,3 +85,4 @@ section 77    Delay Pools
 section 78    HTTP Connection Header
 section 79    HTTP Meter Header
 section 80    WCCP
+section 81    Store Removal/Replacement policy
index 2d209d5cef8587704d8191ed268d5ecf515f05bb..6dcd6c7b034fb15b9c839193cbb8b592ee02d497 100644 (file)
@@ -1,7 +1,7 @@
 #
 #  Makefile for the Squid Object Cache server
 #
-#  $Id: Makefile.in,v 1.188 2000/05/31 08:57:08 hno Exp $
+#  $Id: Makefile.in,v 1.189 2000/06/08 18:05:34 hno Exp $
 #
 #  Uncomment and customize the following to suit your needs:
 #
@@ -18,7 +18,7 @@ localstatedir   = @localstatedir@
 srcdir         = @srcdir@
 VPATH          = @srcdir@
 
-SUBDIRS                = fs
+SUBDIRS                = fs repl
 
 # Gotta love the DOS legacy
 #
@@ -67,6 +67,8 @@ XTRA_LIBS     = @XTRA_LIBS@
 XTRA_OBJS      = @XTRA_OBJS@
 STORE_OBJS     = @STORE_OBJS@
 STORE_MODULES  = @STORE_MODULES@
+REPL_OBJS      = @REPL_OBJS@
+REPL_POLICIES  = @REPL_POLICIES@
 MV             = @MV@
 RM             = @RM@
 SHELL          = /bin/sh
@@ -149,6 +151,7 @@ OBJS                = \
                pump.o \
                redirect.o \
                refresh.o \
+               repl_modules.o \
                send-announce.o \
                @SNMP_OBJS@ \
                ssl.o \
@@ -168,7 +171,6 @@ OBJS                = \
                store_swapin.o \
                store_swapmeta.o \
                store_swapout.o \
-               store_heap_replacement.o \
                string_arrays.o \
                tools.o \
                @UNLINKD_OBJS@ \
@@ -194,14 +196,14 @@ LEAKFINDER_OBJS   = \
 DEFAULTS        = \
        -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\"
 
-all:    squid.conf store_modules $(PROGS) $(UTILS) $(SUID_UTILS) $(CGIPROGS)
+all:    squid.conf store_modules repl_modules $(PROGS) $(UTILS) $(SUID_UTILS) $(CGIPROGS)
 
 $(OBJS): $(top_srcdir)/include/version.h ../include/autoconf.h
 
 $(SNMP_OBJS): ../snmplib/libsnmp.a $(top_srcdir)/include/cache_snmp.h
 
-$(SQUID_EXE): $(OBJS) $(STORE_OBJS)
-       $(CC) -o $@ $(LDFLAGS) $(OBJS) $(STORE_OBJS) $(SQUID_LIBS)
+$(SQUID_EXE): $(OBJS) $(STORE_OBJS) $(REPL_OBJS)
+       $(CC) -o $@ $(LDFLAGS) $(OBJS) $(STORE_OBJS) $(REPL_OBJS) $(SQUID_LIBS)
 
 globals.o: globals.c Makefile
        $(CC) -c globals.c $(CFLAGS) -I$(srcdir) $(DEFAULTS)
@@ -267,7 +269,7 @@ cf.data: cf.data.pre Makefile
        < $(srcdir)/cf.data.pre >$@
 
 store_modules.c: store_modules.sh Makefile 
-       @sh $(srcdir)/store_modules.sh $(STORE_MODULES) >store_modules.c
+       sh $(srcdir)/store_modules.sh $(STORE_MODULES) >store_modules.c
 
 store_modules.o: store_modules.c
        $(CC) -c store_modules.c $(CFLAGS) -I$(srcdir)
@@ -277,6 +279,17 @@ $(STORE_OBJS): fs/stamp
 store_modules fs/stamp:
        @sh -c "cd fs && $(MAKE) all"
 
+repl_modules.c: repl_modules.sh Makefile 
+       sh $(srcdir)/repl_modules.sh $(REPL_POLICIES) >repl_modules.c
+
+repl_modules.o: repl_modules.c
+       $(CC) -c repl_modules.c $(CFLAGS) -I$(srcdir)
+
+$(REPL_OBJS): repl/stamp
+
+repl_modules repl/stamp:
+       @sh -c "cd repl && $(MAKE) all"
+
 install-mkdirs:
        -@if test ! -d $(prefix); then \
                echo "mkdir $(prefix)"; \
index 83106cb84075c1f9ef73de0fefde6b484a2fdbcc..90016c1db5110ee5a95fc1cf61469b030dec8dee 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: cache_cf.cc,v 1.349 2000/05/31 07:01:41 hno Exp $
+ * $Id: cache_cf.cc,v 1.350 2000/06/08 18:05:34 hno Exp $
  *
  * DEBUG: section 3     Configuration File Parsing
  * AUTHOR: Harvest Derived
@@ -348,14 +348,6 @@ configDoConfigure(void)
        debug(3, 0) ("WARNING: resetting 'maximum_single_addr_tries to 1\n");
        Config.retry.maxtries = 1;
     }
-#if HEAP_REPLACEMENT
-    /* The non-LRU policies do not use referenceAge */
-#else
-    if (Config.referenceAge < 300) {
-       debug(3, 0) ("WARNING: resetting 'reference_age' to 1 week\n");
-       Config.referenceAge = 86400 * 7;
-    }
-#endif
     requirePathnameExists("MIME Config Table", Config.mimeTablePathname);
 #if USE_DNSSERVERS
     requirePathnameExists("cache_dns_program", Config.Program.dnsserver);
@@ -1732,6 +1724,40 @@ dump_uri_whitespace(StoreEntry * entry, const char *name, int var)
     storeAppendPrintf(entry, "%s %s\n", name, s);
 }
 
+static void
+free_removalpolicy(RemovalPolicySettings **settings)
+{
+    if (!*settings)
+       return;
+    free_string(&(*settings)->type);
+    free_wordlist(&(*settings)->args);
+    xfree(*settings);
+    *settings = NULL;
+}
+
+static void
+parse_removalpolicy(RemovalPolicySettings **settings)
+{
+    if (*settings)
+       free_removalpolicy(settings);
+    *settings = xcalloc(1, sizeof(**settings));
+    parse_string(&(*settings)->type);
+    parse_wordlist(&(*settings)->args);
+}
+
+static void
+dump_removalpolicy(StoreEntry * entry, const char *name, RemovalPolicySettings *settings)
+{
+    wordlist *args;
+    storeAppendPrintf(entry, "%s %s", name, settings->type);
+    args = settings->args;
+    while (args) {
+       storeAppendPrintf(entry, " %s", args->key);
+       args = args->next;
+    }
+}
+    
+
 #include "cf_parser.c"
 
 peer_t
@@ -1833,3 +1859,5 @@ requirePathnameExists(const char *name, const char *path)
     if (stat(path, &sb) < 0)
        fatalf("%s: %s", path, xstrerror());
 }
+
+
index b80383eceded976eb431a2aa2fdde933c387c8a3..3488e763ec535ce34d174094944b788402706be7 100644 (file)
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.187 2000/05/31 07:01:42 hno Exp $
+# $Id: cf.data.pre,v 1.188 2000/06/08 18:05:35 hno Exp $
 #
 #
 # SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -590,6 +590,58 @@ DOC_START
        Maximum number of FQDN cache entries.
 DOC_END
 
+NAME: cache_replacement_policy
+TYPE: removalpolicy
+LOC: Config.replPolicy
+DEFAULT: lru
+DOC_START
+       The cache replacement policy parameter determines which
+       objects are evicted (replaced) when disk space is needed.
+
+           lru       : Squid's original list based LRU policy
+           heap GDSF : Greedy-Dual Size Frequency
+           heap LFUDA: Least Frequently Used with Dynamic Aging
+           heap LRU  : LRU policy implemented using a heap
+
+       Applies to any cache_dir lines listed below this.
+
+       The LRU policies keeps recently referenced objects.
+
+       The heap GDSF policy optimizes object hit rate by keeping smaller
+       popular objects in cache so it has a better chance of getting a
+       hit.  It achieves a lower byte hit rate than LFUDA though since
+       it evicts larger (possibly popular) objects.
+
+       The heap LFUDA policy keeps popular objects in cache regardless of
+       their size and thus optimizes byte hit rate at the expense of
+       hit rate since one large, popular object will prevent many
+       smaller, slightly less popular objects from being cached.
+
+       Both policies utilize a dynamic aging mechanism that prevents
+       cache pollution that can otherwise occur with frequency-based
+       replacement policies.
+
+       NOTE: if using the LFUDA replacement policy you should increase
+       the value of maximum_object_size above its default of 4096 KB to
+       to maximize the potential byte hit rate improvement of LFUDA.  
+
+       For more information about the GDSF and LFUDA cache replacement
+       policies see http://www.hpl.hp.com/techreports/1999/HPL-1999-69.html
+       and http://fog.hpl.external.hp.com/techreports/98/HPL-98-173.html.
+DOC_END
+
+NAME: memory_replacement_policy
+TYPE: removalpolicy
+LOC: Config.memPolicy
+DEFAULT: lru
+DOC_START
+       The memory replacement policy parameter determines which
+       objects are purged from memory when memory space is needed.
+
+       See cache_replacement_policy for details.
+DOC_END
+
+
 COMMENT_START
  LOGFILE PATHNAMES AND CACHE DIRECTORIES
  -----------------------------------------------------------------------------
@@ -1227,49 +1279,6 @@ DOC_START
        used.
 DOC_END
 
-
-NAME: replacement_policy
-TYPE: string
-LOC: Config.replPolicy
-DEFAULT: LFUDA
-IFDEF: HEAP_REPLACEMENT
-DOC_START
-       The cache replacement policy parameter determines which
-       objects are evicted (replaced) when disk space is needed.
-       Squid used to have only a single replacement policy, LRU.
-       But when built with -DHEAP_REPLACEMENT you can choose
-       between two new, enhanced policies:
-
-                  GDSF: Greedy-Dual Size Frequency
-                  LFUDA: Least Frequently Used with Dynamic Aging
-
-       Both of these policies are frequency based rather than recency
-       based, and perform better than LRU.
-
-       The GDSF policy optimizes object hit rate by keeping smaller
-       popular objects in cache so it has a better chance of getting a
-       hit.  It achieves a lower byte hit rate than LFUDA though since
-       it evicts larger (possibly popular) objects.
-
-       The LFUDA policy keeps popular objects in cache regardless of
-       their size and thus optimizes byte hit rate at the expense of
-       hit rate since one large, popular object will prevent many
-       smaller, slightly less popular objects from being cached.
-
-       Both policies utilize a dynamic aging mechanism that prevents
-       cache pollution that can otherwise occur with frequency-based
-       replacement policies.
-
-       NOTE: if using the LFUDA replacement policy you should increase
-       the value of maximum_object_size above its default of 4096 KB to
-       to maximize the potential byte hit rate improvement of LFUDA.  
-
-       For more information about these cache replacement policies see
-       http://www.hpl.hp.com/techreports/1999/HPL-1999-69.html and
-       http://fog.hpl.external.hp.com/techreports/98/HPL-98-173.html.
-DOC_END
-
-
 NAME: reference_age
 TYPE: time_t
 LOC: Config.referenceAge
index 263976eac6d26000466879f3835beb365cc0cc0a..036f238e54fc997b814636bee5c6519963490a64 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: async_io.cc,v 1.3 2000/05/29 21:06:28 hno Exp $
+ * $Id: async_io.cc,v 1.4 2000/06/08 18:05:37 hno Exp $
  *
  * DEBUG: section 32    Asynchronous Disk I/O
  * AUTHOR: Pete Bentley <pete@demon.net>
@@ -335,7 +335,8 @@ aioUnlink(const char *pathname, AIOCB * callback, void *callback_data)
     cbdataLock(callback_data);
     if (aio_unlink(path, &ctrlp->result) < 0) {
        int ret = unlink(path);
-       (callback) (ctrlp->fd, callback_data, ret, errno);
+        if (callback)
+           (callback) (ctrlp->fd, callback_data, ret, errno);
        cbdataUnlock(callback_data);
        memPoolFree(aio_ctrl_pool, ctrlp);
        xfree(path);
@@ -347,7 +348,7 @@ aioUnlink(const char *pathname, AIOCB * callback, void *callback_data)
 }                              /* aioUnlink */
 
 
-void
+int
 aioCheckCallbacks(SwapDir * SD)
 {
     aio_result_t *resultp;
@@ -355,7 +356,8 @@ aioCheckCallbacks(SwapDir * SD)
     aio_ctrl_t *prev;
     AIOCB *done_handler;
     void *their_data;
-
+    int retval = 0;
+   
     assert(initialised);
     aio_counts.check_callback++;
     for (;;) {
@@ -376,6 +378,7 @@ aioCheckCallbacks(SwapDir * SD)
            ctrlp->done_handler = NULL;
            ctrlp->done_handler_data = NULL;
            if (cbdataValid(their_data))
+                retval = 1; /* Return that we've actually done some work */
                done_handler(ctrlp->fd, their_data,
                    ctrlp->result.aio_return, ctrlp->result.aio_errno);
            cbdataUnlock(their_data);
@@ -384,6 +387,7 @@ aioCheckCallbacks(SwapDir * SD)
            aioFDWasClosed(ctrlp->fd);
        memPoolFree(aio_ctrl_pool, ctrlp);
     }
+    return retval;
 }
 
 void
index 0757e965057131067fb97917fefffb1b6413b319..2385ba5af76d65da7e5924981f7a0a3e5baf5a08 100644 (file)
@@ -47,7 +47,7 @@ void aioWrite(int, int offset, char *, int size, AIOCB *, void *, FREE *);
 void aioRead(int, int offset, char *, int size, AIOCB *, void *);
 void aioStat(char *, struct stat *, AIOCB *, void *);
 void aioUnlink(const char *, AIOCB *, void *);
-void aioCheckCallbacks(SwapDir *);
+int aioCheckCallbacks(SwapDir *);
 void aioSync(SwapDir *);
 int aioQueueSize(void);
 
index ec983233306142c6a17de9a475c6e22f7a28f465..dd96090c9dde8a6c18eb0d399e34299b6c9bb9d7 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_dir_aufs.cc,v 1.3 2000/05/29 21:06:28 hno Exp $
+ * $Id: store_dir_aufs.cc,v 1.4 2000/06/08 18:05:37 hno Exp $
  *
  * DEBUG: section 47    Store Directory Routines
  * AUTHOR: Duane Wessels
@@ -99,9 +99,10 @@ static FILE *storeAufsDirOpenTmpSwapLog(SwapDir *, int *, int *);
 static STLOGOPEN storeAufsDirOpenSwapLog;
 static STINIT storeAufsDirInit;
 static STFREE storeAufsDirFree;
-static STLOGCLEANOPEN storeAufsDirWriteCleanOpen;
-static void storeAufsDirWriteCleanClose(SwapDir * sd);
+static STLOGCLEANSTART storeAufsDirWriteCleanStart;
+static STLOGCLEANNEXTENTRY storeAufsDirCleanLogNextEntry;
 static STLOGCLEANWRITE storeAufsDirWriteCleanEntry;
+static STLOGCLEANDONE storeAufsDirWriteCleanDone;
 static STLOGCLOSE storeAufsDirCloseSwapLog;
 static STLOGWRITE storeAufsDirSwapLog;
 static STNEWFS storeAufsDirNewfs;
@@ -119,10 +120,6 @@ static int storeAufsCleanupDoubleCheck(SwapDir *, StoreEntry *);
 static void storeAufsDirStats(SwapDir *, StoreEntry *);
 static void storeAufsDirInitBitmap(SwapDir *);
 static int storeAufsDirValidFileno(SwapDir *, sfileno, int);
-static int storeAufsDirCheckExpired(SwapDir *, StoreEntry *);
-#if !HEAP_REPLACEMENT
-static time_t storeAufsDirExpiredReferenceAge(SwapDir *);
-#endif
 
 /*
  * These functions were ripped straight out of the heart of store_dir.c.
@@ -351,9 +348,9 @@ storeAufsDirInit(SwapDir * sd)
 {
     static int started_clean_event = 0;
     static const char *errmsg =
-    "\tFailed to verify one of the swap directories, Check cache.log\n"
-    "\tfor details.  Run 'squid -z' to create swap directories\n"
-    "\tif needed, or if running Squid for the first time.";
+       "\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.";
     storeAufsDirInitBitmap(sd);
     if (storeAufsDirVerifyCacheDirs(sd) < 0)
        fatal(errmsg);
@@ -612,10 +609,7 @@ storeAufsDirRebuildFromSwapLog(void *data)
                e->lastmod = s.lastmod;
                e->flags = s.flags;
                e->refcount += s.refcount;
-#if HEAP_REPLACEMENT
-               storeHeapPositionUpdate(e, SD);
                storeAufsDirUnrefObj(SD, e);
-#endif
            } else {
                debug_trap("storeAufsDirRebuildFromSwapLog: bad condition");
                debug(20, 1) ("\tSee %s:%d\n", __FILE__, __LINE__);
@@ -795,9 +789,6 @@ storeAufsDirAddDiskRestore(SwapDir * SD, const cache_key * key,
     e->swap_dirn = SD->index;
     e->swap_file_sz = swap_file_sz;
     e->lock_count = 0;
-#if !HEAP_REPLACEMENT
-    e->refcount = 0;
-#endif
     e->lastref = lastref;
     e->timestamp = timestamp;
     e->expires = expires;
@@ -934,6 +925,7 @@ struct _clean_state {
     char *outbuf;
     off_t outbuf_offset;
     int fd;
+    RemovalPolicyWalker *walker;
 };
 
 #define CLEAN_BUF_SZ 16384
@@ -943,7 +935,7 @@ struct _clean_state {
  * we succeed, and assign the 'func' and 'data' return pointers.
  */
 static int
-storeAufsDirWriteCleanOpen(SwapDir * sd)
+storeAufsDirWriteCleanStart(SwapDir * sd)
 {
     struct _clean_state *state = xcalloc(1, sizeof(*state));
     struct stat sb;
@@ -954,6 +946,7 @@ storeAufsDirWriteCleanOpen(SwapDir * sd)
     state->cln = xstrdup(storeAufsDirSwapLogFile(sd, ".last-clean"));
     state->outbuf = xcalloc(CLEAN_BUF_SZ, 1);
     state->outbuf_offset = 0;
+    state->walker = sd->repl->WalkInit(sd->repl);
     unlink(state->new);
     unlink(state->cln);
     state->fd = file_open(state->new, O_WRONLY | O_CREAT | O_TRUNC);
@@ -970,19 +963,28 @@ storeAufsDirWriteCleanOpen(SwapDir * sd)
     return 0;
 }
 
+/*
+ * Get the next entry that is a candidate for clean log writing
+ */
+const StoreEntry *
+storeAufsDirCleanLogNextEntry(SwapDir * sd)
+{
+    const StoreEntry *entry = NULL;
+    struct _clean_state *state = sd->log.clean.state;
+    if (state->walker)
+       entry = state->walker->Next(state->walker);
+    return entry;
+}
+
 /*
  * "write" an entry to the clean log file.
  */
 static void
-storeAufsDirWriteCleanEntry(const StoreEntry * e, SwapDir * sd)
+storeAufsDirWriteCleanEntry(SwapDir * sd, const StoreEntry * e)
 {
     storeSwapLogData s;
     static size_t ss = sizeof(storeSwapLogData);
     struct _clean_state *state = sd->log.clean.state;
-    if (NULL == e) {
-       storeAufsDirWriteCleanClose(sd);
-       return;
-    }
     memset(&s, '\0', ss);
     s.op = (char) SWAP_LOG_ADD;
     s.swap_filen = e->swap_filen;
@@ -1014,11 +1016,12 @@ storeAufsDirWriteCleanEntry(const StoreEntry * e, SwapDir * sd)
 }
 
 static void
-storeAufsDirWriteCleanClose(SwapDir * sd)
+storeAufsDirWriteCleanDone(SwapDir * sd)
 {
     struct _clean_state *state = sd->log.clean.state;
     if (state->fd < 0)
        return;
+    state->walker->Done(state->walker);
     if (write(state->fd, state->outbuf, state->outbuf_offset) < 0) {
        debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
            state->new, xstrerror());
@@ -1276,30 +1279,18 @@ void
 storeAufsDirMaintain(SwapDir * SD)
 {
     StoreEntry *e = NULL;
-    int scanned = 0;
-    int locked = 0;
-    int expired = 0;
+    int removed = 0;
     int max_scan;
     int max_remove;
     double f;
-    static time_t last_warn_time = 0;
-#if !HEAP_REPLACEMENT
-    dlink_node *m;
-    dlink_node *prev = NULL;
-#else
-    heap_key age;
-    heap_key min_age = 0.0;
-    link_list *locked_entries = NULL;
-#if HEAP_REPLACEMENT_DEBUG
-    if (!verify_heap_property(SD->repl.heap.heap)) {
-       debug(20, 1) ("Heap property violated!\n");
-    }
-#endif
-#endif
+    RemovalPurgeWalker *walker;
     /* We can't delete objects while rebuilding swap */
     if (store_dirs_rebuilding) {
        return;
     } else {
+       /* XXX FixMe: This should use the cache_dir hig/low values, not the
+        * global ones
+        */
        f = (double) (store_swap_size - store_swap_low) / (store_swap_high - store_swap_low);
        f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f;
        max_scan = (int) (f * 400.0 + 100.0);
@@ -1307,120 +1298,26 @@ storeAufsDirMaintain(SwapDir * SD)
        /*
         * This is kinda cheap, but so we need this priority hack?
         */
-#if 0
-       eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0 - f, 1);
-#endif
     }
-    debug(20, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n", f, max_scan, max_remove);
-#if HEAP_REPLACEMENT
-    while (heap_nodes(SD->repl.heap.heap) > 0) {
-       if (store_swap_size < store_swap_low)
-           break;
-       if (expired >= max_remove)
-           break;
-       if (scanned >= max_scan)
-           break;
-       age = heap_peepminkey(SD->repl.heap.heap);
-       e = heap_extractmin(SD->repl.heap.heap);
-       e->repl.node = NULL;    /* no longer in the heap */
-       scanned++;
-       if (storeEntryLocked(e)) {
-           /*
-            * Entry is in use ... put it in a linked list to ignore it.
-            */
-           if (!EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-               /*
-                * If this was a "SPECIAL" do not add it back into the heap.
-                * It will always be "SPECIAL" and therefore never removed.
-                */
-               debug(20, 4) ("storeAufsDirMaintain: locked url %s\n",
-                   (e->mem_obj && e->mem_obj->url) ? e->mem_obj->url : storeKeyText(e->
-                       key));
-               linklistPush(&locked_entries, e);
-           }
-           locked++;
-           continue;
-       } else if (storeAufsDirCheckExpired(SD, e)) {
-           /*
-            * Note: This will not check the reference age ifdef
-            * HEAP_REPLACEMENT, but it does some other useful
-            * checks...
-            */
-           expired++;
-           debug(20, 3) ("Released store object age %f size %d refs %d key %s\n",
-               age, e->swap_file_sz, e->refcount, storeKeyText(e->key));
-           min_age = age;
-           storeRelease(e);
-       } else {
-           /*
-            * Did not expire the object so we need to add it back
-            * into the heap!
-            */
-           debug(20, 5) ("storeMaintainSwapSpace: non-expired %s\n",
-               storeKeyText(e->key));
-           linklistPush(&locked_entries, e);
-           continue;
-       }
+    debug(20, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n",
+       f, max_scan, max_remove);
+    walker = SD->repl->PurgeInit(SD->repl, max_scan);
+    while (1) {
+       /* XXX FixMe: This should use the cache_dir hig/low values, not the
+        * global ones
+        */
        if (store_swap_size < store_swap_low)
            break;
-       else if (expired >= max_remove)
-           break;
-       else if (scanned >= max_scan)
+       if (removed >= max_remove)
            break;
+       e = walker->Next(walker);
+       if (!e)
+           break;              /* no more objects */
+       removed++;
+       storeRelease(e);
     }
-    /*
-     * Bump the heap age factor.
-     */
-    if (min_age > 0.0)
-       SD->repl.heap.heap->age = min_age;
-    /*
-     * Reinsert all bumped locked entries back into heap...
-     */
-    while ((e = linklistShift(&locked_entries)))
-       e->repl.node = heap_insert(SD->repl.heap.heap, e);
-#else
-    for (m = SD->repl.lru.list.tail; m; m = prev) {
-       prev = m->prev;
-       e = m->data;
-       scanned++;
-       if (storeEntryLocked(e)) {
-           /*
-            * If there is a locked entry at the tail of the LRU list,
-            * move it to the beginning to get it out of the way.
-            * Theoretically, we might have all locked objects at the
-            * tail, and then we'll never remove anything here and the
-            * LRU age will go to zero.
-            */
-           if (memInUse(MEM_STOREENTRY) > max_scan) {
-               dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
-               dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
-           }
-           locked++;
-
-       } else if (storeAufsDirCheckExpired(SD, e)) {
-           expired++;
-           storeRelease(e);
-       }
-       if (expired >= max_remove)
-           break;
-       if (scanned >= max_scan)
-           break;
-    }
-#endif
-    debug(20, (expired ? 2 : 3)) ("storeMaintainSwapSpace: scanned %d/%d removed %d/%d locked %d f=%.03f\n",
-       scanned, max_scan, expired, max_remove, locked, f);
-    debug(20, 3) ("storeMaintainSwapSpace stats:\n");
-    debug(20, 3) ("  %6d objects\n", memInUse(MEM_STOREENTRY));
-    debug(20, 3) ("  %6d were scanned\n", scanned);
-    debug(20, 3) ("  %6d were locked\n", locked);
-    debug(20, 3) ("  %6d were expired\n", expired);
-    if (store_swap_size < Config.Swap.maxSize)
-       return;
-    if (squid_curtime - last_warn_time < 10)
-       return;
-    debug(20, 0) ("WARNING: Disk space over limit: %d KB > %d KB\n",
-       store_swap_size, Config.Swap.maxSize);
-    last_warn_time = squid_curtime;
+    debug(20, (removed ? 2 : 3)) ("storeUfsDirMaintain: %s removed %d/%d f=%.03f max_scan=%d\n",
+       SD->path, removed, max_remove, f, max_scan);
 }
 
 /*
@@ -1436,7 +1333,7 @@ storeAufsDirCheckObj(SwapDir * SD, const StoreEntry * e)
     int loadav;
     int ql;
 
-#if !HEAP_REPLACEMENT
+#if OLD_UNUSED_CODE
     if (storeAufsDirExpiredReferenceAge(SD) < 300) {
        debug(20, 3) ("storeAufsDirCheckObj: NO: LRU Age = %d\n",
            storeAufsDirExpiredReferenceAge(SD));
@@ -1465,16 +1362,8 @@ storeAufsDirRefObj(SwapDir * SD, StoreEntry * e)
 {
     debug(1, 3) ("storeAufsDirRefObj: referencing %p %d/%d\n", e, e->swap_dirn,
        e->swap_filen);
-#if HEAP_REPLACEMENT
-    /* Nothing to do here */
-#else
-    /* Reference the object */
-    if (!EBIT_TEST(e->flags, RELEASE_REQUEST) &&
-       !EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-       dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
-       dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
-    }
-#endif
+    if (SD->repl->Referenced)
+       SD->repl->Referenced(SD->repl, e, &e->repl);
 }
 
 /*
@@ -1487,10 +1376,8 @@ storeAufsDirUnrefObj(SwapDir * SD, StoreEntry * e)
 {
     debug(1, 3) ("storeAufsDirUnrefObj: referencing %p %d/%d\n", e, e->swap_dirn,
        e->swap_filen);
-#if HEAP_REPLACEMENT
-    if (e->repl.node)
-       heap_update(SD->repl.heap.heap, e->repl.node, e);
-#endif
+    if (SD->repl->Dereferenced)
+       SD->repl->Dereferenced(SD->repl, e, &e->repl);
 }
 
 /*
@@ -1504,80 +1391,10 @@ void
 storeAufsDirUnlinkFile(SwapDir * SD, sfileno f)
 {
     debug(79, 3) ("storeAufsDirUnlinkFile: unlinking fileno %08X\n", f);
-    storeAufsDirMapBitReset(SD, f);
+    /* storeAufsDirMapBitReset(SD, f); */
     aioUnlink(storeAufsDirFullPath(SD, f, NULL), NULL, NULL);
 }
 
-#if !HEAP_REPLACEMENT
-/*
- * storeAufsDirExpiredReferenceAge
- *
- * The LRU age is scaled exponentially between 1 minute and
- * Config.referenceAge , when store_swap_low < store_swap_size <
- * store_swap_high.  This keeps store_swap_size within the low and high
- * water marks.  If the cache is very busy then store_swap_size stays
- * closer to the low water mark, if it is not busy, then it will stay
- * near the high water mark.  The LRU age value can be examined on the
- * cachemgr 'info' page.
- */
-static time_t
-storeAufsDirExpiredReferenceAge(SwapDir * SD)
-{
-    double x;
-    double z;
-    time_t age;
-    long store_high, store_low;
-
-    store_high = (long) (((float) SD->max_size *
-           (float) Config.Swap.highWaterMark) / (float) 100);
-    store_low = (long) (((float) SD->max_size *
-           (float) Config.Swap.lowWaterMark) / (float) 100);
-    debug(20, 20) ("RA: Dir %s, hi=%d, lo=%d, cur=%d\n", SD->path, store_high, store_low, SD->cur_size);
-
-    x = (double) (store_high - SD->cur_size) /
-       (store_high - store_low);
-    x = x < 0.0 ? 0.0 : x > 1.0 ? 1.0 : x;
-    z = pow((double) (Config.referenceAge / 60), x);
-    age = (time_t) (z * 60.0);
-    if (age < 60)
-       age = 60;
-    else if (age > Config.referenceAge)
-       age = Config.referenceAge;
-    return age;
-}
-#endif
-
-/*
- * storeAufsDirCheckExpired
- *
- * Check whether the given object is expired or not
- * It breaks layering a little by calling the upper layers to find
- * out whether the object is locked or not, but we can't help this
- * right now.
- */
-static int
-storeAufsDirCheckExpired(SwapDir * SD, StoreEntry * e)
-{
-    if (storeEntryLocked(e))
-       return 0;
-    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
-       return 1;
-    if (EBIT_TEST(e->flags, ENTRY_NEGCACHED) && squid_curtime >= e->expires)
-       return 1;
-
-#if HEAP_REPLACEMENT
-    /*
-     * with HEAP_REPLACEMENT we are not using the LRU reference age, the heap
-     * controls the replacement of objects.
-     */
-    return 1;
-#else
-    if (squid_curtime - e->lastref > storeAufsDirExpiredReferenceAge(SD))
-       return 1;
-    return 0;
-#endif
-}
-
 /*
  * Add and remove the given StoreEntry from the replacement policy in
  * use.
@@ -1588,17 +1405,7 @@ storeAufsDirReplAdd(SwapDir * SD, StoreEntry * e)
 {
     debug(20, 4) ("storeAufsDirReplAdd: added node %p to dir %d\n", e,
        SD->index);
-#if HEAP_REPLACEMENT
-    if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-       (void) 0;
-    } else {
-       e->repl.node = heap_insert(SD->repl.heap.heap, e);
-       debug(20, 4) ("storeAufsDirReplAdd: inserted node 0x%x\n", e->repl.node);
-    }
-#else
-    /* Shouldn't we not throw special objects into the lru ? */
-    dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
-#endif
+    SD->repl->Add(SD->repl, e, &e->repl);
 }
 
 
@@ -1608,17 +1415,7 @@ storeAufsDirReplRemove(StoreEntry * e)
     SwapDir *SD = INDEXSD(e->swap_dirn);
     debug(20, 4) ("storeAufsDirReplRemove: remove node %p from dir %d\n", e,
        SD->index);
-#if HEAP_REPLACEMENT
-    /* And now, release the object from the replacement policy */
-    if (e->repl.node) {
-       debug(20, 4) ("storeAufsDirReplRemove: deleting node 0x%x\n",
-           e->repl.node);
-       heap_delete(SD->repl.heap.heap, e->repl.node);
-       e->repl.node = NULL;
-    }
-#else
-    dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
-#endif
+    SD->repl->Remove(SD->repl, e, &e->repl);
 }
 
 
@@ -1662,15 +1459,15 @@ storeAufsDirStats(SwapDir * SD, StoreEntry * sentry)
     if (SD->flags.read_only)
        storeAppendPrintf(sentry, " READ-ONLY");
     storeAppendPrintf(sentry, "\n");
+#if OLD_UNUSED_CODE
 #if !HEAP_REPLACEMENT
     storeAppendPrintf(sentry, "LRU Expiration Age: %6.2f days\n",
        (double) storeAufsDirExpiredReferenceAge(SD) / 86400.0);
 #else
-#if 0
     storeAppendPrintf(sentry, "Storage Replacement Threshold:\t%f\n",
        heap_peepminkey(sd.repl.heap.heap));
 #endif
-#endif
+#endif /* OLD_UNUSED_CODE */
 }
 
 /*
@@ -1746,7 +1543,6 @@ storeAufsDirFree(SwapDir * s)
     filemapFreeMemory(aioinfo->map);
     xfree(aioinfo);
     s->fsdata = NULL;          /* Will aid debugging... */
-
 }
 
 char *
@@ -1865,41 +1661,12 @@ storeAufsDirParse(SwapDir * sd, int index, char *path)
     sd->log.open = storeAufsDirOpenSwapLog;
     sd->log.close = storeAufsDirCloseSwapLog;
     sd->log.write = storeAufsDirSwapLog;
-    sd->log.clean.open = storeAufsDirWriteCleanOpen;
+    sd->log.clean.start = storeAufsDirWriteCleanStart;
+    sd->log.clean.nextentry = storeAufsDirCleanLogNextEntry;
+    sd->log.clean.done = storeAufsDirWriteCleanDone;
 
     /* Initialise replacement policy stuff */
-#if HEAP_REPLACEMENT
-    /*
-     * Create new heaps with cache replacement policies attached to them.
-     * The cache replacement policy is specified as either GDSF or LFUDA in
-     * the squid.conf configuration file.  Note that the replacement policy
-     * applies only to the disk replacement algorithm.  Memory replacement
-     * always uses GDSF since we want to maximize object hit rate.
-     */
-    if (Config.replPolicy) {
-       if (tolower(Config.replPolicy[0]) == 'g') {
-           debug(20, 1) ("Using GDSF disk replacement policy\n");
-           sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_GDSF);
-       } else if (tolower(Config.replPolicy[0]) == 'l') {
-           if (tolower(Config.replPolicy[1]) == 'f') {
-               debug(20, 1) ("Using LFUDA disk replacement policy\n");
-               sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_LFUDA);
-           } else if (tolower(Config.replPolicy[1]) == 'r') {
-               debug(20, 1) ("Using LRU heap disk replacement policy\n");
-               sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_LRU);
-           }
-       } else {
-           debug(20, 1) ("Unrecognized replacement_policy; using GDSF\n");
-           sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_GDSF);
-       }
-    } else {
-       debug(20, 1) ("Using default disk replacement policy (GDSF)\n");
-       sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_GDSF);
-    }
-#else
-    sd->repl.lru.list.head = NULL;
-    sd->repl.lru.list.tail = NULL;
-#endif
+    sd->repl = createRemovalPolicy(Config.replPolicy);
 }
 
 /*
index 38e7a10ee87ea43a929914ff2d8d815de811c7fc..3d7e6147b0f879302391f2cea8586bafc8432627 100644 (file)
@@ -204,6 +204,7 @@ storeAufsUnlink(SwapDir * SD, StoreEntry * e)
 {
     debug(78, 3) ("storeAufsUnlink: dirno %d, fileno %08X\n", SD->index, e->swap_filen);
     storeAufsDirReplRemove(e);
+    storeAufsDirMapBitReset(SD, e->swap_filen);
     storeAufsDirUnlinkFile(SD, e->swap_filen);
 }
 
index 1b9fa4b3ae74f25cdd4a8318474610abd12148f9..9699fd89e075aefbadc6e146029cf47f05821a4c 100644 (file)
@@ -31,6 +31,16 @@ struct _cossinfo {
     int fd;
     int swaplog_fd;
     int numcollisions;
+    dlink_list index;
+    int count;
+    dlink_node *walk_current;
+};
+
+struct _cossindex {
+    /* Note: the dlink_node MUST be the first member of the structure.
+     * This member is later pointer typecasted to coss_index_node *.
+     */
+    dlink_node node;
 };
 
 
@@ -50,12 +60,13 @@ struct _cossstate {
 typedef struct _cossmembuf CossMemBuf;
 typedef struct _cossinfo CossInfo;
 typedef struct _cossstate CossState;
+typedef struct _cossindex CossIndexNode;
 
 /* Whether the coss system has been setup or not */
 extern int coss_initialised;
 extern MemPool *coss_membuf_pool;
 extern MemPool *coss_state_pool;
-
+extern MemPool *coss_index_pool;
 
 /*
  * Store IO stuff
@@ -66,17 +77,11 @@ extern STOBJCLOSE storeCossClose;
 extern STOBJREAD storeCossRead;
 extern STOBJWRITE storeCossWrite;
 extern STOBJUNLINK storeCossUnlink;
+extern STSYNC storeCossSync;
 
 extern off_t storeCossAllocate(SwapDir * SD, const StoreEntry * e, int which);
-extern void storeCossFree(StoreEntry * e);
-extern void storeCossMaintainSwapSpace(SwapDir * SD);
-extern void storeCossDirStats(SwapDir *, StoreEntry *);
-extern void storeCossDirDump(StoreEntry * entry, const char *name, SwapDir * s);
-extern void storeCossDirFree(SwapDir *);
-extern SwapDir *storeCossDirPick(void);
-
-void storeFsSetup_ufs(storefs_entry_t *);
-
-
+extern void storeCossAdd(SwapDir *, StoreEntry *);
+extern void storeCossRemove(SwapDir *, StoreEntry *);
+extern void storeCossStartMembuf(SwapDir *SD);
 
 #endif
index 60e444f42b0caee1395ffd27f873da71333ba21f..5b85c9663174565aef7509551727aba26b684f24 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_dir_coss.cc,v 1.2 2000/05/12 00:29:19 wessels Exp $
+ * $Id: store_dir_coss.cc,v 1.3 2000/06/08 18:05:38 hno Exp $
  *
  * DEBUG: section 81    Store COSS Directory Routines
  * AUTHOR: Eric Stern
 
 #define STORE_META_BUFSZ 4096
 
-extern void storeCossFlushMemBufs(SwapDir * SD);
-
 int n_coss_dirs = 0;
 /* static int last_coss_pick_index = -1; */
 int coss_initialised = 0;
 MemPool *coss_membuf_pool = NULL;
 MemPool *coss_state_pool = NULL;
+MemPool *coss_index_pool = NULL;
 
 typedef struct _RebuildState RebuildState;
 struct _RebuildState {
@@ -87,16 +86,18 @@ static void storeCossDirCloseTmpSwapLog(SwapDir * sd);
 static FILE *storeCossDirOpenTmpSwapLog(SwapDir *, int *, int *);
 static STLOGOPEN storeCossDirOpenSwapLog;
 static STINIT storeCossDirInit;
-static STLOGCLEANOPEN storeCossDirWriteCleanOpen;
-static void storeCossDirWriteCleanClose(SwapDir * sd);
+static STLOGCLEANSTART storeCossDirWriteCleanStart;
+static STLOGCLEANNEXTENTRY storeCossDirCleanLogNextEntry;
 static STLOGCLEANWRITE storeCossDirWriteCleanEntry;
+static STLOGCLEANDONE storeCossDirWriteCleanDone;
 static STLOGCLOSE storeCossDirCloseSwapLog;
 static STLOGWRITE storeCossDirSwapLog;
 static STNEWFS storeCossDirNewfs;
 static STCHECKOBJ storeCossDirCheckObj;
-static void storeCossDirShutdown(SwapDir * sd);
-static void storeCossDirParse(SwapDir *, int, char *);
-static void storeCossDirReconfigure(SwapDir *, int, char *);
+static STFREE storeCossDirShutdown;
+static STFSPARSE storeCossDirParse;
+static STFSRECONFIGURE storeCossDirReconfigure;
+static STDUMP storeCossDirDump;
 
 static char *
 storeCossDirSwapLogFile(SwapDir * sd, const char *ext)
@@ -165,10 +166,45 @@ storeCossDirInit(SwapDir * sd)
     n_coss_dirs++;
 }
 
+void
+storeCossRemove(SwapDir *sd, StoreEntry *e)
+{
+    CossInfo *cs = (CossInfo *) sd->fsdata;
+    CossIndexNode *coss_node = e->repl.data;
+    e->repl.data = NULL;
+    dlinkDelete(&coss_node->node, &cs->index);
+    memPoolFree(coss_index_pool, coss_node);
+    cs->count -= 1;
+}
+
+void
+storeCossAdd(SwapDir *sd, StoreEntry *e)
+{
+    CossInfo *cs = (CossInfo *) sd->fsdata;
+    CossIndexNode *coss_node = memPoolAlloc(coss_index_pool);
+    assert(!e->repl.data);
+    e->repl.data = coss_node;
+    dlinkAdd(e, &coss_node->node, &cs->index);
+    cs->count += 1;
+}
+
+static void
+storeCossRebuildComplete(void *data)
+{
+    RebuildState *rb = data;
+    SwapDir *sd = rb->sd;
+    storeCossStartMembuf(sd);
+    store_dirs_rebuilding--;
+    storeCossDirCloseTmpSwapLog(rb->sd);
+    storeRebuildComplete(&rb->counts);
+    cbdataFree(rb);
+}
+
 static void
 storeCossRebuildFromSwapLog(void *data)
 {
     RebuildState *rb = data;
+    SwapDir *sd = rb->sd;
     StoreEntry *e = NULL;
     storeSwapLogData s;
     size_t ss = sizeof(storeSwapLogData);
@@ -182,10 +218,7 @@ storeCossRebuildFromSwapLog(void *data)
                rb->sd->path, rb->n_read);
            fclose(rb->log);
            rb->log = NULL;
-           store_dirs_rebuilding--;
-           storeCossDirCloseTmpSwapLog(rb->sd);
-           storeRebuildComplete(&rb->counts);
-           cbdataFree(rb);
+           storeCossRebuildComplete(rb);
            return;
        }
        rb->n_read++;
@@ -215,7 +248,7 @@ storeCossRebuildFromSwapLog(void *data)
                }
                storeRelease(e);
                /* Fake an unlink here, this is a bad hack :( */
-               dlinkDelete(&e->repl.lru, &rb->sd->repl.lru.list);
+               storeCossRemove(sd, e);
                rb->counts.objcount--;
                rb->counts.cancelcount++;
            }
@@ -285,9 +318,6 @@ storeCossAddDiskRestore(SwapDir * SD, const cache_key * key,
     e->swap_filen = file_number;
     e->swap_file_sz = swap_file_sz;
     e->lock_count = 0;
-#if !HEAP_REPLACEMENT
-    e->refcount = 0;
-#endif
     e->lastref = lastref;
     e->timestamp = timestamp;
     e->expires = expires;
@@ -300,7 +330,7 @@ storeCossAddDiskRestore(SwapDir * SD, const cache_key * key,
     e->ping_status = PING_NONE;
     EBIT_CLR(e->flags, ENTRY_VALIDATED);
     storeHashInsert(e, key);   /* do it after we clear KEY_PRIVATE */
-    dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
+    storeCossAdd(SD, e);
     e->swap_filen = storeCossAllocate(SD, e, COSS_ALLOC_NOTIFY);
     return e;
 }
@@ -313,8 +343,11 @@ storeCossDirRebuild(SwapDir * sd)
     int zero = 0;
     FILE *fp;
     EVH *func = NULL;
+    cbdataAdd(rb, cbdataXfree, 0);
     rb->sd = sd;
     rb->speed = opt_foreground_rebuild ? 1 << 30 : 50;
+    func = storeCossRebuildFromSwapLog;
+    rb->flags.clean = (unsigned int) clean;
     /*
      * If the swap.state file exists in the cache_dir, then
      * we'll use storeCossRebuildFromSwapLog().
@@ -322,6 +355,8 @@ storeCossDirRebuild(SwapDir * sd)
     fp = storeCossDirOpenTmpSwapLog(sd, &clean, &zero);
     debug(20, 1) ("Rebuilding COSS storage in %s (%s)\n",
        sd->path, clean ? "CLEAN" : "DIRTY");
+    rb->log = fp;
+    store_dirs_rebuilding++;
     if (!clean || fp == NULL) {
        /* COSS cannot yet rebuild from a dirty state. If the log
         * is dirty then the COSS contents is thrown away.
@@ -330,24 +365,15 @@ storeCossDirRebuild(SwapDir * sd)
         */
        if (fp != NULL)
            fclose(fp);
-       storeCossDirCloseTmpSwapLog(rb->sd);
        /*
         * XXX Make sure we don't trigger an assertion if this is the first
         * storedir, since if we are, this call will cause storeRebuildComplete
         * to prematurely complete the rebuild process, and then some other
         * storedir will try to rebuild and eventually die.
         */
-       store_dirs_rebuilding++;
-       storeRebuildComplete(&rb->counts);
-       store_dirs_rebuilding--;
-       xfree(rb);
+       eventAdd("storeCossRebuildComplete", storeCossRebuildComplete, rb, 0.0, 0);
        return;
     }
-    func = storeCossRebuildFromSwapLog;
-    rb->log = fp;
-    rb->flags.clean = (unsigned int) clean;
-    store_dirs_rebuilding++;
-    cbdataAdd(rb, cbdataXfree, 0);
     eventAdd("storeCossRebuild", func, rb, 0.0, 1);
 }
 
@@ -435,6 +461,7 @@ struct _clean_state {
     char *outbuf;
     off_t outbuf_offset;
     int fd;
+    dlink_node *current;
 };
 
 #define CLEAN_BUF_SZ 16384
@@ -444,8 +471,9 @@ struct _clean_state {
  * we succeed, and assign the 'func' and 'data' return pointers.
  */
 static int
-storeCossDirWriteCleanOpen(SwapDir * sd)
+storeCossDirWriteCleanStart(SwapDir * sd)
 {
+    CossInfo *cs = (CossInfo *) sd->fsdata;
     struct _clean_state *state = xcalloc(1, sizeof(*state));
     struct stat sb;
     sd->log.clean.write = NULL;
@@ -460,6 +488,7 @@ storeCossDirWriteCleanOpen(SwapDir * sd)
     state->fd = file_open(state->new, O_WRONLY | O_CREAT | O_TRUNC);
     if (state->fd < 0)
        return -1;
+    state->current = cs->index.tail;
     debug(20, 3) ("storeCOssDirWriteCleanLogs: opened %s, FD %d\n",
        state->new, state->fd);
 #if HAVE_FCHMOD
@@ -468,22 +497,33 @@ storeCossDirWriteCleanOpen(SwapDir * sd)
 #endif
     sd->log.clean.write = storeCossDirWriteCleanEntry;
     sd->log.clean.state = state;
+
     return 0;
 }
 
+static const StoreEntry *
+storeCossDirCleanLogNextEntry(SwapDir * sd)
+{
+    struct _clean_state *state = sd->log.clean.state;
+    const StoreEntry *entry;
+    if (!state)
+       return NULL;
+    if (!state->current)
+       return NULL;
+    entry = (const StoreEntry *)state->current->data;
+    state->current = state->current->prev;
+    return entry;
+}
+
 /*
  * "write" an entry to the clean log file.
  */
 static void
-storeCossDirWriteCleanEntry(const StoreEntry * e, SwapDir * sd)
+storeCossDirWriteCleanEntry(SwapDir *sd, const StoreEntry * e)
 {
     storeSwapLogData s;
     static size_t ss = sizeof(storeSwapLogData);
     struct _clean_state *state = sd->log.clean.state;
-    if (NULL == e) {
-       storeCossDirWriteCleanClose(sd);
-       return;
-    }
     memset(&s, '\0', ss);
     s.op = (char) SWAP_LOG_ADD;
     s.swap_filen = e->swap_filen;
@@ -515,7 +555,7 @@ storeCossDirWriteCleanEntry(const StoreEntry * e, SwapDir * sd)
 }
 
 static void
-storeCossDirWriteCleanClose(SwapDir * sd)
+storeCossDirWriteCleanDone(SwapDir * sd)
 {
     struct _clean_state *state = sd->log.clean.state;
     if (state->fd < 0)
@@ -600,13 +640,9 @@ static void
 storeCossDirShutdown(SwapDir * SD)
 {
     CossInfo *cs = (CossInfo *) SD->fsdata;
-    CossMemBuf *t;
 
-    /* we need to do this synchronously! */
-    for (t = cs->membufs; t; t = t->next) {
-       lseek(cs->fd, t->diskstart, SEEK_SET);
-       write(cs->fd, t->buffer, COSS_MEMBUF_SZ);
-    }
+    storeCossSync(SD);
+
     file_close(cs->fd);
     cs->fd = -1;
 
@@ -705,7 +741,7 @@ storeCossDirParse(SwapDir * sd, int index, char *path)
     sd->refobj = NULL;         /* LRU is done in storeCossRead */
     sd->unrefobj = NULL;
     sd->callback = NULL;
-    sd->sync = NULL;           /* should we make it call the coss sync? */
+    sd->sync = storeCossSync;
 
     sd->obj.create = storeCossCreate;
     sd->obj.open = storeCossOpen;
@@ -717,25 +753,19 @@ storeCossDirParse(SwapDir * sd, int index, char *path)
     sd->log.open = storeCossDirOpenSwapLog;
     sd->log.close = storeCossDirCloseSwapLog;
     sd->log.write = storeCossDirSwapLog;
-    sd->log.clean.open = storeCossDirWriteCleanOpen;
+    sd->log.clean.start = storeCossDirWriteCleanStart;
     sd->log.clean.write = storeCossDirWriteCleanEntry;
+    sd->log.clean.nextentry = storeCossDirCleanLogNextEntry;
+    sd->log.clean.done = storeCossDirWriteCleanDone;
 
     cs->current_offset = 0;
     cs->fd = -1;
     cs->swaplog_fd = -1;
     cs->numcollisions = 0;
-    cs->membufs = memPoolAlloc(coss_membuf_pool);
-    cs->membufs->diskstart = 0;
-    cs->membufs->diskend = COSS_MEMBUF_SZ;
-    cs->membufs->lockcount = 0;
-    cs->membufs->flags.full = 0;
-    cs->membufs->flags.writing = 0;
-    cs->membufs->next = NULL;
-    cs->membufs->SD = sd;
+    cs->membufs = NULL; /* set when the rebuild completes */
     cs->current_membuf = cs->membufs;
-
-    sd->repl.lru.list.head = NULL;
-    sd->repl.lru.list.tail = NULL;
+    cs->index.head = NULL;
+    cs->index.tail = NULL;
 }
 
 
@@ -778,7 +808,7 @@ storeCossDirDump(StoreEntry * entry, const char *name, SwapDir * s)
        s->max_size >> 20);
 }
 
-#if 0
+#if OLD_UNUSED_CODE
 SwapDir *
 storeCossDirPick(void)
 {
@@ -840,5 +870,6 @@ storeFsSetup_coss(storefs_entry_t * storefs)
     storefs->donefunc = storeCossDirDone;
     coss_membuf_pool = memPoolCreate("COSS Membuf data", sizeof(CossMemBuf));
     coss_state_pool = memPoolCreate("COSS IO State data", sizeof(CossState));
+    coss_index_pool = memPoolCreate("COSS index data", sizeof(CossIndexNode));
     coss_initialised = 1;
 }
index d361a269a5dd96aafc3faeac53e7fbe2f95d4e88..64b5ad888b00cfba378ae7f112e7a69d35ed9161 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_io_coss.cc,v 1.3 2000/05/16 07:09:36 wessels Exp $
+ * $Id: store_io_coss.cc,v 1.4 2000/06/08 18:05:38 hno Exp $
  *
  * DEBUG: section 81    Storage Manager COSS Interface
  * AUTHOR: Eric Stern
@@ -74,7 +74,7 @@ storeCossAllocate(SwapDir * SD, const StoreEntry * e, int which)
     else
        checkf = -1;
 
-    retofs = e->swap_filen;    /* Just for defaults */
+    retofs = e->swap_filen;    /* Just for defaults, or while rebuilding */
 
     if (e->swap_file_sz > 0)
        allocsize = e->swap_file_sz;
@@ -107,7 +107,7 @@ storeCossAllocate(SwapDir * SD, const StoreEntry * e, int which)
        }
     }
     if (coll == 0) {
-       cs->current_offset += allocsize;
+       cs->current_offset = retofs + allocsize;
        return retofs;
     } else {
        return -1;
@@ -118,7 +118,7 @@ void
 storeCossUnlink(SwapDir * SD, StoreEntry * e)
 {
     debug(81, 3) ("storeCossUnlink: offset %d\n", e->swap_filen);
-    dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
+    storeCossRemove(SD, e);
 }
 
 
@@ -148,15 +148,14 @@ storeCossCreate(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * c
     sio->callback_data = callback_data;
     cbdataLock(callback_data);
     sio->e = (StoreEntry *) e;
-    sio->st_size = -1;         /* we won't know this until we read the metadata */
 
     cstate->flags.writing = 0;
     cstate->flags.reading = 0;
     cstate->readbuffer = NULL;
     cstate->reqdiskoffset = -1;
 
-    /* Now add it into the LRU */
-    dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
+    /* Now add it into the index list */
+    storeCossAdd(SD, e);
 
     storeCossMemBufLock(SD, sio);
     return sio;
@@ -231,10 +230,10 @@ storeCossOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback,
        storeCossMemBufLock(SD, sio);
 
        /*
-        * Do the LRU magic to keep the disk and memory LRUs identical
+        * Do the index magic to keep the disk and memory LRUs identical
         */
-       dlinkDelete(&sio->e->repl.lru, &SD->repl.lru.list);
-       dlinkAdd(sio->e, &sio->e->repl.lru, &SD->repl.lru.list);
+       storeCossRemove(SD, e);
+       storeCossAdd(SD, e);
 
        /*
         * Since we've reallocated a spot for this object, we need to
@@ -410,6 +409,22 @@ storeCossMemBufUnlock(SwapDir * SD, storeIOState * e)
     }
 }
 
+void
+storeCossSync(SwapDir * SD)
+{
+    CossInfo *cs = (CossInfo *) SD->fsdata;
+    CossMemBuf *t;
+    int end;
+    if (!cs->membufs)
+       return;
+    for (t=cs->membufs; t; t = t->next) {
+       if (t->flags.writing)
+           sleep(5);
+       lseek(cs->fd, t->diskstart, SEEK_SET);
+       end = (t == cs->current_membuf) ? cs->current_offset : t->diskend;
+       write(cs->fd, t->buffer, end - t->diskstart);
+    }
+}
 
 static void
 storeCossWriteMemBuf(SwapDir * SD, CossMemBuf * t)
@@ -418,9 +433,9 @@ storeCossWriteMemBuf(SwapDir * SD, CossMemBuf * t)
     debug(81, 3) ("storeCossWriteMemBuf: offset %d, len %d\n",
        t->diskstart, t->diskend - t->diskstart);
     cbdataAdd(t, storeCossMembufFree, 0);
+    t->flags.writing = 1;
     file_write(cs->fd, t->diskstart, &t->buffer,
        t->diskend - t->diskstart, storeCossWriteMemBufDone, t, NULL);
-    t->flags.writing = 1;
 }
 
 
@@ -472,15 +487,16 @@ storeCossCreateMemBuf(SwapDir * SD, size_t start,
     newmb->flags.writing = 0;
     newmb->lockcount = 0;
     newmb->SD = SD;
+    /* XXX This should be reversed, with the new buffer last in the chain */
     newmb->next = cs->membufs;
     cs->membufs = newmb;
     for (t = cs->membufs; t; t = t->next)
        debug(81, 3) ("storeCossCreateMemBuf: membuflist %d lockcount %d\n", t->diskstart, t->lockcount);
 
     /*
-     * XXX more evil LRU specific code. This needs to be replaced.
+     * Kill objects from the tail to make space for a new chunk
      */
-    for (m = SD->repl.lru.list.tail; m; m = prev) {
+    for (m = cs->index.tail; m; m = prev) {
        prev = m->prev;
        e = m->data;
        if (curfn == e->swap_filen)
@@ -497,6 +513,18 @@ storeCossCreateMemBuf(SwapDir * SD, size_t start,
     return newmb;
 }
 
+/*
+ * Creates the initial membuf after rebuild
+ */
+void
+storeCossStartMembuf(SwapDir *sd)
+{
+    CossInfo *cs = (CossInfo *) sd->fsdata;
+    CossMemBuf *newmb = storeCossCreateMemBuf(sd, cs->current_offset, -1, NULL);
+    assert(!cs->current_membuf);
+    cs->current_membuf = newmb;
+}
+
 /*
  * We can't pass memFree() as a free function here, because we need to free
  * the fsstate variable ..
index 6e737d7a9b637bab95c88ebac096fd8658f5fe17..1b62da48ab1b4cea8cace33a892ee39b315ab6a7 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_dir_diskd.cc,v 1.10 2000/05/29 03:10:39 wessels Exp $
+ * $Id: store_dir_diskd.cc,v 1.11 2000/06/08 18:05:38 hno Exp $
  *
  * DEBUG: section 47    Store Directory Routines
  * AUTHOR: Duane Wessels
@@ -109,9 +109,10 @@ static FILE *storeDiskdDirOpenTmpSwapLog(SwapDir *, int *, int *);
 static STLOGOPEN storeDiskdDirOpenSwapLog;
 static STINIT storeDiskdDirInit;
 static STFREE storeDiskdDirFree;
-static STLOGCLEANOPEN storeDiskdDirWriteCleanOpen;
-static void storeDiskdDirWriteCleanClose(SwapDir * sd);
+static STLOGCLEANSTART storeDiskdDirWriteCleanStart;
+static STLOGCLEANNEXTENTRY storeDiskdDirCleanLogNextEntry;
 static STLOGCLEANWRITE storeDiskdDirWriteCleanEntry;
+static STLOGCLEANDONE storeDiskdDirWriteCleanDone;
 static STLOGCLOSE storeDiskdDirCloseSwapLog;
 static STLOGWRITE storeDiskdDirSwapLog;
 static STNEWFS storeDiskdDirNewfs;
@@ -129,10 +130,6 @@ static int storeDiskdCleanupDoubleCheck(SwapDir *, StoreEntry *);
 static void storeDiskdDirStats(SwapDir *, StoreEntry *);
 static void storeDiskdDirInitBitmap(SwapDir *);
 static int storeDiskdDirValidFileno(SwapDir *, sfileno, int);
-static int storeDiskdDirCheckExpired(SwapDir *, StoreEntry *);
-#if !HEAP_REPLACEMENT
-static time_t storeDiskdDirExpiredReferenceAge(SwapDir *);
-#endif
 static void storeDiskdStats(StoreEntry * sentry);
 static void storeDiskdDirSync(SwapDir *);
 
@@ -475,31 +472,31 @@ storeDiskdDirSync(SwapDir * SD)
  * until the queue is below magic2. Otherwise, we simply return when we
  * don't get a message.
  */
-void
+int
 storeDiskdDirCallback(SwapDir * SD)
 {
     diomsg M;
     int x;
     diskdinfo_t *diskdinfo = SD->fsdata;
+    int retval = 0;
 
-    if (diskdinfo->away >= diskdinfo->magic2)
+    if (diskdinfo->away >= diskdinfo->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;
        diskd_stats.max_shmuse = diskd_stats.shmbuf_count;
     }
-    /* if we are above magic2, we do not break under any reason */
     while (1) {
        memset(&M, '\0', sizeof(M));
        x = msgrcv(diskdinfo->rmsgid, &M, msg_snd_rcv_sz, 0, IPC_NOWAIT);
-       if (x < 0) {
-           if (diskdinfo->away >= diskdinfo->magic2)
-               continue;
-           else
+       if (x < 0)
                break;
-       else if (x != msg_snd_rcv_sz) {
+       else if (x != msg_snd_rcv_sz) {
            debug(81, 1) ("storeDiskdDirCallback: msgget returns %d\n",
                x);
            break;
@@ -507,9 +504,11 @@ storeDiskdDirCallback(SwapDir * SD)
        diskd_stats.recv_count++;
        diskdinfo->away--;
        storeDiskdHandle(&M);
+        retval = 1; /* Return that we've actually done some work */
        if (M.shm_offset > -1)
            storeDiskdShmPut(SD, M.shm_offset);
     }
+    return retval;
 }
 
 
@@ -761,10 +760,7 @@ storeDiskdDirRebuildFromSwapLog(void *data)
                e->lastmod = s.lastmod;
                e->flags = s.flags;
                e->refcount += s.refcount;
-#if HEAP_REPLACEMENT
-               storeHeapPositionUpdate(e, SD);
                storeDiskdDirUnrefObj(SD, e);
-#endif
            } else {
                debug_trap("storeDiskdDirRebuildFromSwapLog: bad condition");
                debug(20, 1) ("\tSee %s:%d\n", __FILE__, __LINE__);
@@ -944,9 +940,6 @@ storeDiskdDirAddDiskRestore(SwapDir * SD, const cache_key * key,
     e->swap_dirn = SD->index;
     e->swap_file_sz = swap_file_sz;
     e->lock_count = 0;
-#if !HEAP_REPLACEMENT
-    e->refcount = 0;
-#endif
     e->lastref = lastref;
     e->timestamp = timestamp;
     e->expires = expires;
@@ -1083,6 +1076,7 @@ struct _clean_state {
     char *outbuf;
     off_t outbuf_offset;
     int fd;
+    RemovalPolicyWalker *walker;
 };
 
 #define CLEAN_BUF_SZ 16384
@@ -1092,7 +1086,7 @@ struct _clean_state {
  * we succeed, and assign the 'func' and 'data' return pointers.
  */
 static int
-storeDiskdDirWriteCleanOpen(SwapDir * sd)
+storeDiskdDirWriteCleanStart(SwapDir * sd)
 {
     struct _clean_state *state = xcalloc(1, sizeof(*state));
     struct stat sb;
@@ -1103,6 +1097,7 @@ storeDiskdDirWriteCleanOpen(SwapDir * sd)
     state->cln = xstrdup(storeDiskdDirSwapLogFile(sd, ".last-clean"));
     state->outbuf = xcalloc(CLEAN_BUF_SZ, 1);
     state->outbuf_offset = 0;
+    state->walker = sd->repl->WalkInit(sd->repl);
     unlink(state->new);
     unlink(state->cln);
     state->fd = file_open(state->new, O_WRONLY | O_CREAT | O_TRUNC);
@@ -1119,19 +1114,28 @@ storeDiskdDirWriteCleanOpen(SwapDir * sd)
     return 0;
 }
 
+/*
+ * Get the next entry that is a candidate for clean log writing
+ */
+const StoreEntry *
+storeDiskdDirCleanLogNextEntry(SwapDir * sd)
+{
+    const StoreEntry *entry = NULL;
+    struct _clean_state *state = sd->log.clean.state;
+    if (state->walker)
+       entry = state->walker->Next(state->walker);
+    return entry;
+}
+
 /*
  * "write" an entry to the clean log file.
  */
 static void
-storeDiskdDirWriteCleanEntry(const StoreEntry * e, SwapDir * sd)
+storeDiskdDirWriteCleanEntry(SwapDir *sd, const StoreEntry * e)
 {
     storeSwapLogData s;
     static size_t ss = sizeof(storeSwapLogData);
     struct _clean_state *state = sd->log.clean.state;
-    if (NULL == e) {
-       storeDiskdDirWriteCleanClose(sd);
-       return;
-    }
     memset(&s, '\0', ss);
     s.op = (char) SWAP_LOG_ADD;
     s.swap_filen = e->swap_filen;
@@ -1163,11 +1167,12 @@ storeDiskdDirWriteCleanEntry(const StoreEntry * e, SwapDir * sd)
 }
 
 static void
-storeDiskdDirWriteCleanClose(SwapDir * sd)
+storeDiskdDirWriteCleanDone(SwapDir * sd)
 {
     struct _clean_state *state = sd->log.clean.state;
     if (state->fd < 0)
        return;
+    state->walker->Done(state->walker);
     if (write(state->fd, state->outbuf, state->outbuf_offset) < 0) {
        debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
            state->new, xstrerror());
@@ -1425,30 +1430,18 @@ void
 storeDiskdDirMaintain(SwapDir * SD)
 {
     StoreEntry *e = NULL;
-    int scanned = 0;
-    int locked = 0;
-    int expired = 0;
+    int removed = 0;
     int max_scan;
     int max_remove;
     double f;
-    static time_t last_warn_time = 0;
-#if !HEAP_REPLACEMENT
-    dlink_node *m;
-    dlink_node *prev = NULL;
-#else
-    heap_key age;
-    heap_key min_age = 0.0;
-    link_list *locked_entries = NULL;
-#if HEAP_REPLACEMENT_DEBUG
-    if (!verify_heap_property(SD->repl.heap.heap)) {
-       debug(20, 1) ("Heap property violated!\n");
-    }
-#endif
-#endif
+    RemovalPurgeWalker *walker;
     /* We can't delete objects while rebuilding swap */
     if (store_dirs_rebuilding) {
        return;
     } else {
+       /* XXX FixMe: This should use the cache_dir hig/low values, not the
+        * global ones
+        */
        f = (double) (store_swap_size - store_swap_low) / (store_swap_high - store_swap_low);
        f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f;
        max_scan = (int) (f * 400.0 + 100.0);
@@ -1456,120 +1449,26 @@ storeDiskdDirMaintain(SwapDir * SD)
        /*
         * This is kinda cheap, but so we need this priority hack?
         */
-#if 0
-       eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0 - f, 1);
-#endif
     }
     debug(20, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n", f, max_scan, max_remove);
-#if HEAP_REPLACEMENT
-    while (heap_nodes(SD->repl.heap.heap) > 0) {
-       if (store_swap_size < store_swap_low)
-           break;
-       if (expired >= max_remove)
-           break;
-       if (scanned >= max_scan)
-           break;
-       age = heap_peepminkey(SD->repl.heap.heap);
-       e = heap_extractmin(SD->repl.heap.heap);
-       e->repl.node = NULL;    /* no longer in the heap */
-       scanned++;
-       if (storeEntryLocked(e)) {
-           /*
-            * Entry is in use ... put it in a linked list to ignore it.
-            */
-           if (!EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-               /*
-                * If this was a "SPECIAL" do not add it back into the heap.
-                * It will always be "SPECIAL" and therefore never removed.
-                */
-               debug(20, 4) ("storeDiskdDirMaintain: locked url %s\n",
-                   (e->mem_obj && e->mem_obj->url) ? e->mem_obj->url : storeKeyText(e->
-                       key));
-               linklistPush(&locked_entries, e);
-           }
-           locked++;
-           continue;
-       } else if (storeDiskdDirCheckExpired(SD, e)) {
-           /*
-            * Note: This will not check the reference age ifdef
-            * HEAP_REPLACEMENT, but it does some other useful
-            * checks...
-            */
-           expired++;
-           debug(20, 3) ("Released store object age %f size %d refs %d key %s\n",
-               age, e->swap_file_sz, e->refcount, storeKeyText(e->key));
-           min_age = age;
-           storeRelease(e);
-       } else {
-           /*
-            * Did not expire the object so we need to add it back
-            * into the heap!
-            */
-           debug(20, 5) ("storeMaintainSwapSpace: non-expired %s\n",
-               storeKeyText(e->key));
-           linklistPush(&locked_entries, e);
-           continue;
-       }
+    walker = SD->repl->PurgeInit(SD->repl, max_scan);
+    while (1) {
+       /* XXX FixMe: This should use the cache_dir hig/low values, not the
+        * global ones
+        */
        if (store_swap_size < store_swap_low)
            break;
-       else if (expired >= max_remove)
-           break;
-       else if (scanned >= max_scan)
+       if (removed >= max_remove)
            break;
+       e = walker->Next(walker);
+       if (!e)
+           break;              /* no more objects */
+       removed++;
+       storeRelease(e);
     }
-    /*
-     * Bump the heap age factor.
-     */
-    if (min_age > 0.0)
-       SD->repl.heap.heap->age = min_age;
-    /*
-     * Reinsert all bumped locked entries back into heap...
-     */
-    while ((e = linklistShift(&locked_entries)))
-       e->repl.node = heap_insert(SD->repl.heap.heap, e);
-#else
-    for (m = SD->repl.lru.list.tail; m; m = prev) {
-       prev = m->prev;
-       e = m->data;
-       scanned++;
-       if (storeEntryLocked(e)) {
-           /*
-            * If there is a locked entry at the tail of the LRU list,
-            * move it to the beginning to get it out of the way.
-            * Theoretically, we might have all locked objects at the
-            * tail, and then we'll never remove anything here and the
-            * LRU age will go to zero.
-            */
-           if (memInUse(MEM_STOREENTRY) > max_scan) {
-               dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
-               dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
-           }
-           locked++;
-
-       } else if (storeDiskdDirCheckExpired(SD, e)) {
-           expired++;
-           storeRelease(e);
-       }
-       if (expired >= max_remove)
-           break;
-       if (scanned >= max_scan)
-           break;
-    }
-#endif
-    debug(20, (expired ? 2 : 3)) ("storeMaintainSwapSpace: scanned %d/%d removed %d/%d locked %d f=%.03f\n",
-       scanned, max_scan, expired, max_remove, locked, f);
-    debug(20, 3) ("storeMaintainSwapSpace stats:\n");
-    debug(20, 3) ("  %6d objects\n", memInUse(MEM_STOREENTRY));
-    debug(20, 3) ("  %6d were scanned\n", scanned);
-    debug(20, 3) ("  %6d were locked\n", locked);
-    debug(20, 3) ("  %6d were expired\n", expired);
-    if (store_swap_size < Config.Swap.maxSize)
-       return;
-    if (squid_curtime - last_warn_time < 10)
-       return;
-    debug(20, 0) ("WARNING: Disk space over limit: %d KB > %d KB\n",
-       store_swap_size, Config.Swap.maxSize);
-    last_warn_time = squid_curtime;
+    walker->Done(walker);
+    debug(20, (removed ? 2 : 3)) ("storeDiskdDirMaintain: %s removed %d/%d f=%.03f max_scan=%d\n",
+       SD->path, removed, max_remove, f, max_scan);
 }
 
 /*
@@ -1585,7 +1484,7 @@ storeDiskdDirCheckObj(SwapDir * SD, const StoreEntry * e)
     int loadav;
 
     diskdinfo_t *diskdinfo = SD->fsdata;
-#if !HEAP_REPLACEMENT
+#if OLD_UNUSED_CODE
     if (storeDiskdDirExpiredReferenceAge(SD) < 300) {
        debug(20, 3) ("storeDiskdDirCheckObj: NO: LRU Age = %d\n",
            storeDiskdDirExpiredReferenceAge(SD));
@@ -1617,16 +1516,8 @@ storeDiskdDirRefObj(SwapDir * SD, StoreEntry * e)
 {
     debug(1, 3) ("storeDiskdDirRefObj: referencing %p %d/%d\n", e, e->swap_dirn,
        e->swap_filen);
-#if HEAP_REPLACEMENT
-    /* Nothing to do here */
-#else
-    /* Reference the object */
-    if (!EBIT_TEST(e->flags, RELEASE_REQUEST) &&
-       !EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-       dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
-       dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
-    }
-#endif
+    if (SD->repl->Referenced)
+       SD->repl->Referenced(SD->repl, e, &e->repl);
 }
 
 /*
@@ -1639,10 +1530,8 @@ storeDiskdDirUnrefObj(SwapDir * SD, StoreEntry * e)
 {
     debug(1, 3) ("storeDiskdDirUnrefObj: referencing %p %d/%d\n", e,
        e->swap_dirn, e->swap_filen);
-#if HEAP_REPLACEMENT
-    if (e->repl.node)
-       heap_update(SD->repl.heap.heap, e->repl.node, e);
-#endif
+    if (SD->repl->Dereferenced)
+       SD->repl->Dereferenced(SD->repl, e, &e->repl);
 }
 
 /*
@@ -1656,80 +1545,10 @@ void
 storeDiskdDirUnlinkFile(SwapDir * SD, sfileno f)
 {
     debug(79, 3) ("storeDiskdDirUnlinkFile: unlinking fileno %08X\n", f);
-    storeDiskdDirMapBitReset(SD, f);
+    /* storeDiskdDirMapBitReset(SD, f); */
     unlinkdUnlink(storeDiskdDirFullPath(SD, f, NULL));
 }
 
-#if !HEAP_REPLACEMENT
-/*
- * storeDiskdDirExpiredReferenceAge
- *
- * The LRU age is scaled exponentially between 1 minute and
- * Config.referenceAge , when store_swap_low < store_swap_size <
- * store_swap_high.  This keeps store_swap_size within the low and high
- * water marks.  If the cache is very busy then store_swap_size stays
- * closer to the low water mark, if it is not busy, then it will stay
- * near the high water mark.  The LRU age value can be examined on the
- * cachemgr 'info' page.
- */
-static time_t
-storeDiskdDirExpiredReferenceAge(SwapDir * SD)
-{
-    double x;
-    double z;
-    time_t age;
-    long store_high, store_low;
-
-    store_high = (long) (((float) SD->max_size *
-           (float) Config.Swap.highWaterMark) / (float) 100);
-    store_low = (long) (((float) SD->max_size *
-           (float) Config.Swap.lowWaterMark) / (float) 100);
-    debug(20, 20) ("RA: Dir %s, hi=%d, lo=%d, cur=%d\n", SD->path, store_high, store_low, SD->cur_size);
-
-    x = (double) (store_high - SD->cur_size) /
-       (store_high - store_low);
-    x = x < 0.0 ? 0.0 : x > 1.0 ? 1.0 : x;
-    z = pow((double) (Config.referenceAge / 60), x);
-    age = (time_t) (z * 60.0);
-    if (age < 60)
-       age = 60;
-    else if (age > Config.referenceAge)
-       age = Config.referenceAge;
-    return age;
-}
-#endif
-
-/*
- * storeDiskdDirCheckExpired
- *
- * Check whether the given object is expired or not
- * It breaks layering a little by calling the upper layers to find
- * out whether the object is locked or not, but we can't help this
- * right now.
- */
-static int
-storeDiskdDirCheckExpired(SwapDir * SD, StoreEntry * e)
-{
-    if (storeEntryLocked(e))
-       return 0;
-    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
-       return 1;
-    if (EBIT_TEST(e->flags, ENTRY_NEGCACHED) && squid_curtime >= e->expires)
-       return 1;
-
-#if HEAP_REPLACEMENT
-    /*
-     * with HEAP_REPLACEMENT we are not using the LRU reference age, the heap
-     * controls the replacement of objects.
-     */
-    return 1;
-#else
-    if (squid_curtime - e->lastref > storeDiskdDirExpiredReferenceAge(SD))
-       return 1;
-    return 0;
-#endif
-}
-
 /*
  * Add and remove the given StoreEntry from the replacement policy in
  * use.
@@ -1740,17 +1559,7 @@ storeDiskdDirReplAdd(SwapDir * SD, StoreEntry * e)
 {
     debug(20, 4) ("storeDiskdDirReplAdd: added node %p to dir %d\n", e,
        SD->index);
-#if HEAP_REPLACEMENT
-    if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-       (void) 0;
-    } else {
-       e->repl.node = heap_insert(SD->repl.heap.heap, e);
-       debug(20, 4) ("storeDiskdDirReplAdd: inserted node 0x%x\n", e->repl.node);
-    }
-#else
-    /* Shouldn't we not throw special objects into the lru ? */
-    dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
-#endif
+    SD->repl->Add(SD->repl, e, &e->repl);
 }
 
 
@@ -1760,17 +1569,7 @@ storeDiskdDirReplRemove(StoreEntry * e)
     SwapDir *SD = INDEXSD(e->swap_dirn);
     debug(20, 4) ("storeDiskdDirReplRemove: remove node %p from dir %d\n", e,
        SD->index);
-#if HEAP_REPLACEMENT
-    /* And now, release the object from the replacement policy */
-    if (e->repl.node) {
-       debug(20, 4) ("storeDiskdDirReplRemove: deleting node 0x%x\n",
-           e->repl.node);
-       heap_delete(SD->repl.heap.heap, e->repl.node);
-       e->repl.node = NULL;
-    }
-#else
-    dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
-#endif
+    SD->repl->Remove(SD->repl, e, &e->repl);
 }
 
 
@@ -1846,15 +1645,15 @@ storeDiskdDirStats(SwapDir * SD, StoreEntry * sentry)
     if (SD->flags.read_only)
        storeAppendPrintf(sentry, " READ-ONLY");
     storeAppendPrintf(sentry, "\n");
+#if OLD_UNUSED_CODE
 #if !HEAP_REPLACEMENT
     storeAppendPrintf(sentry, "LRU Expiration Age: %6.2f days\n",
        (double) storeDiskdDirExpiredReferenceAge(SD) / 86400.0);
 #else
-#if 0
     storeAppendPrintf(sentry, "Storage Replacement Threshold:\t%f\n",
        heap_peepminkey(sd.repl.heap.heap));
 #endif
-#endif
+#endif /* OLD_UNUSED_CODE */
     storeAppendPrintf(sentry, "Pending operations: %d\n", diskdinfo->away);
 }
 
@@ -2072,41 +1871,12 @@ storeDiskdDirParse(SwapDir * sd, int index, char *path)
     sd->log.open = storeDiskdDirOpenSwapLog;
     sd->log.close = storeDiskdDirCloseSwapLog;
     sd->log.write = storeDiskdDirSwapLog;
-    sd->log.clean.open = storeDiskdDirWriteCleanOpen;
+    sd->log.clean.start = storeDiskdDirWriteCleanStart;
+    sd->log.clean.nextentry = storeDiskdDirCleanLogNextEntry;
+    sd->log.clean.done = storeDiskdDirWriteCleanDone;
 
     /* Initialise replacement policy stuff */
-#if HEAP_REPLACEMENT
-    /*
-     * Create new heaps with cache replacement policies attached to them.
-     * The cache replacement policy is specified as either GDSF or LFUDA in
-     * the squid.conf configuration file.  Note that the replacement policy
-     * applies only to the disk replacement algorithm.  Memory replacement
-     * always uses GDSF since we want to maximize object hit rate.
-     */
-    if (Config.replPolicy) {
-       if (tolower(Config.replPolicy[0]) == 'g') {
-           debug(20, 1) ("Using GDSF disk replacement policy\n");
-           sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_GDSF);
-       } else if (tolower(Config.replPolicy[0]) == 'l') {
-           if (tolower(Config.replPolicy[1]) == 'f') {
-               debug(20, 1) ("Using LFUDA disk replacement policy\n");
-               sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_LFUDA);
-           } else if (tolower(Config.replPolicy[1]) == 'r') {
-               debug(20, 1) ("Using LRU heap disk replacement policy\n");
-               sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_LRU);
-           }
-       } else {
-           debug(20, 1) ("Unrecognized replacement_policy; using GDSF\n");
-           sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_GDSF);
-       }
-    } else {
-       debug(20, 1) ("Using default disk replacement policy (GDSF)\n");
-       sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_GDSF);
-    }
-#else
-    sd->repl.lru.list.head = NULL;
-    sd->repl.lru.list.tail = NULL;
-#endif
+    sd->repl = createRemovalPolicy(Config.replPolicy);
 }
 
 /*
index 0ee2d89149dfb20159a1152fbd20d8a94cce951b..4c410d09a065eb3515aee6cf15c945af439796e0 100644 (file)
@@ -93,7 +93,7 @@ extern void storeDiskdDirReplRemove(StoreEntry *);
 extern void storeDiskdShmPut(SwapDir *, int);
 extern void *storeDiskdShmGet(SwapDir *, int *);
 extern void storeDiskdHandle(diomsg * M);
-extern void storeDiskdDirCallback(SwapDir *);
+extern int storeDiskdDirCallback(SwapDir *);
 
 
 /*
index 659528f5e7960eaa0c904a90b66b9c713043bc92..df51ca615efa175b70c1bb2b90021e13b0cf6c3c 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_dir_ufs.cc,v 1.4 2000/05/29 03:10:42 wessels Exp $
+ * $Id: store_dir_ufs.cc,v 1.5 2000/06/08 18:05:39 hno Exp $
  *
  * DEBUG: section 47    Store Directory Routines
  * AUTHOR: Duane Wessels
@@ -99,9 +99,10 @@ static FILE *storeUfsDirOpenTmpSwapLog(SwapDir *, int *, int *);
 static STLOGOPEN storeUfsDirOpenSwapLog;
 static STINIT storeUfsDirInit;
 static STFREE storeUfsDirFree;
-static STLOGCLEANOPEN storeUfsDirWriteCleanOpen;
-static void storeUfsDirWriteCleanClose(SwapDir * sd);
+static STLOGCLEANSTART storeUfsDirWriteCleanStart;
+static STLOGCLEANNEXTENTRY storeUfsDirCleanLogNextEntry;
 static STLOGCLEANWRITE storeUfsDirWriteCleanEntry;
+static STLOGCLEANDONE storeUfsDirWriteCleanDone;
 static STLOGCLOSE storeUfsDirCloseSwapLog;
 static STLOGWRITE storeUfsDirSwapLog;
 static STNEWFS storeUfsDirNewfs;
@@ -119,10 +120,6 @@ static int storeUfsCleanupDoubleCheck(SwapDir *, StoreEntry *);
 static void storeUfsDirStats(SwapDir *, StoreEntry *);
 static void storeUfsDirInitBitmap(SwapDir *);
 static int storeUfsDirValidFileno(SwapDir *, sfileno, int);
-static int storeUfsDirCheckExpired(SwapDir *, StoreEntry *);
-#if !HEAP_REPLACEMENT
-static time_t storeUfsDirExpiredReferenceAge(SwapDir *);
-#endif
 
 /*
  * These functions were ripped straight out of the heart of store_dir.c.
@@ -351,9 +348,9 @@ storeUfsDirInit(SwapDir * sd)
 {
     static int started_clean_event = 0;
     static const char *errmsg =
-    "\tFailed to verify one of the swap directories, Check cache.log\n"
-    "\tfor details.  Run 'squid -z' to create swap directories\n"
-    "\tif needed, or if running Squid for the first time.";
+       "\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.";
     storeUfsDirInitBitmap(sd);
     if (storeUfsDirVerifyCacheDirs(sd) < 0)
        fatal(errmsg);
@@ -612,10 +609,7 @@ storeUfsDirRebuildFromSwapLog(void *data)
                e->lastmod = s.lastmod;
                e->flags = s.flags;
                e->refcount += s.refcount;
-#if HEAP_REPLACEMENT
-               storeHeapPositionUpdate(e, SD);
                storeUfsDirUnrefObj(SD, e);
-#endif
            } else {
                debug_trap("storeUfsDirRebuildFromSwapLog: bad condition");
                debug(20, 1) ("\tSee %s:%d\n", __FILE__, __LINE__);
@@ -693,8 +687,7 @@ storeUfsDirGetNextFile(RebuildState * rb, int *sfileno, int *size)
     debug(20, 3) ("storeUfsDirGetNextFile: flag=%d, %d: /%02X/%02X\n",
        rb->flags.init,
        rb->sd->index,
-       rb->curlvl1,
-       rb->curlvl2);
+       rb->curlvl1, rb->curlvl2);
     if (rb->done)
        return -2;
     while (fd < 0 && rb->done == 0) {
@@ -710,7 +703,8 @@ storeUfsDirGetNextFile(RebuildState * rb, int *sfileno, int *size)
        if (0 == rb->in_dir) {  /* we need to read in a new directory */
            snprintf(rb->fullpath, SQUID_MAXPATHLEN, "%s/%02X/%02X",
                rb->sd->path,
-               rb->curlvl1, rb->curlvl2);
+               rb->curlvl1,
+               rb->curlvl2);
            if (rb->flags.init && rb->td != NULL)
                closedir(rb->td);
            rb->td = NULL;
@@ -795,9 +789,6 @@ storeUfsDirAddDiskRestore(SwapDir * SD, const cache_key * key,
     e->swap_dirn = SD->index;
     e->swap_file_sz = swap_file_sz;
     e->lock_count = 0;
-#if !HEAP_REPLACEMENT
-    e->refcount = 0;
-#endif
     e->lastref = lastref;
     e->timestamp = timestamp;
     e->expires = expires;
@@ -934,6 +925,7 @@ struct _clean_state {
     char *outbuf;
     off_t outbuf_offset;
     int fd;
+    RemovalPolicyWalker *walker;
 };
 
 #define CLEAN_BUF_SZ 16384
@@ -943,7 +935,7 @@ struct _clean_state {
  * we succeed, and assign the 'func' and 'data' return pointers.
  */
 static int
-storeUfsDirWriteCleanOpen(SwapDir * sd)
+storeUfsDirWriteCleanStart(SwapDir * sd)
 {
     struct _clean_state *state = xcalloc(1, sizeof(*state));
     struct stat sb;
@@ -954,6 +946,7 @@ storeUfsDirWriteCleanOpen(SwapDir * sd)
     state->cln = xstrdup(storeUfsDirSwapLogFile(sd, ".last-clean"));
     state->outbuf = xcalloc(CLEAN_BUF_SZ, 1);
     state->outbuf_offset = 0;
+    state->walker = sd->repl->WalkInit(sd->repl);
     unlink(state->new);
     unlink(state->cln);
     state->fd = file_open(state->new, O_WRONLY | O_CREAT | O_TRUNC);
@@ -970,19 +963,28 @@ storeUfsDirWriteCleanOpen(SwapDir * sd)
     return 0;
 }
 
+/*
+ * Get the next entry that is a candidate for clean log writing
+ */
+const StoreEntry *
+storeUfsDirCleanLogNextEntry(SwapDir * sd)
+{
+    const StoreEntry *entry = NULL;
+    struct _clean_state *state = sd->log.clean.state;
+    if (state->walker)
+       entry = state->walker->Next(state->walker);
+    return entry;
+}
+
 /*
  * "write" an entry to the clean log file.
  */
 static void
-storeUfsDirWriteCleanEntry(const StoreEntry * e, SwapDir * sd)
+storeUfsDirWriteCleanEntry(SwapDir * sd, const StoreEntry * e)
 {
     storeSwapLogData s;
     static size_t ss = sizeof(storeSwapLogData);
     struct _clean_state *state = sd->log.clean.state;
-    if (NULL == e) {
-       storeUfsDirWriteCleanClose(sd);
-       return;
-    }
     memset(&s, '\0', ss);
     s.op = (char) SWAP_LOG_ADD;
     s.swap_filen = e->swap_filen;
@@ -1014,11 +1016,12 @@ storeUfsDirWriteCleanEntry(const StoreEntry * e, SwapDir * sd)
 }
 
 static void
-storeUfsDirWriteCleanClose(SwapDir * sd)
+storeUfsDirWriteCleanDone(SwapDir * sd)
 {
     struct _clean_state *state = sd->log.clean.state;
     if (state->fd < 0)
        return;
+    state->walker->Done(state->walker);
     if (write(state->fd, state->outbuf, state->outbuf_offset) < 0) {
        debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
            state->new, xstrerror());
@@ -1276,30 +1279,18 @@ void
 storeUfsDirMaintain(SwapDir * SD)
 {
     StoreEntry *e = NULL;
-    int scanned = 0;
-    int locked = 0;
-    int expired = 0;
+    int removed = 0;
     int max_scan;
     int max_remove;
     double f;
-    static time_t last_warn_time = 0;
-#if !HEAP_REPLACEMENT
-    dlink_node *m;
-    dlink_node *prev = NULL;
-#else
-    heap_key age;
-    heap_key min_age = 0.0;
-    link_list *locked_entries = NULL;
-#if HEAP_REPLACEMENT_DEBUG
-    if (!verify_heap_property(SD->repl.heap.heap)) {
-       debug(20, 1) ("Heap property violated!\n");
-    }
-#endif
-#endif
+    RemovalPurgeWalker *walker;
     /* We can't delete objects while rebuilding swap */
     if (store_dirs_rebuilding) {
        return;
     } else {
+       /* XXX FixMe: This should use the cache_dir hig/low values, not the
+        * global ones
+        */
        f = (double) (store_swap_size - store_swap_low) / (store_swap_high - store_swap_low);
        f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f;
        max_scan = (int) (f * 400.0 + 100.0);
@@ -1307,120 +1298,26 @@ storeUfsDirMaintain(SwapDir * SD)
        /*
         * This is kinda cheap, but so we need this priority hack?
         */
-#if 0
-       eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0 - f, 1);
-#endif
     }
     debug(20, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n", f, max_scan, max_remove);
-#if HEAP_REPLACEMENT
-    while (heap_nodes(SD->repl.heap.heap) > 0) {
-       if (store_swap_size < store_swap_low)
-           break;
-       if (expired >= max_remove)
-           break;
-       if (scanned >= max_scan)
-           break;
-       age = heap_peepminkey(SD->repl.heap.heap);
-       e = heap_extractmin(SD->repl.heap.heap);
-       e->repl.node = NULL;    /* no longer in the heap */
-       scanned++;
-       if (storeEntryLocked(e)) {
-           /*
-            * Entry is in use ... put it in a linked list to ignore it.
-            */
-           if (!EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-               /*
-                * If this was a "SPECIAL" do not add it back into the heap.
-                * It will always be "SPECIAL" and therefore never removed.
-                */
-               debug(20, 4) ("storeUfsDirMaintain: locked url %s\n",
-                   (e->mem_obj && e->mem_obj->url) ? e->mem_obj->url : storeKeyText(e->
-                       key));
-               linklistPush(&locked_entries, e);
-           }
-           locked++;
-           continue;
-       } else if (storeUfsDirCheckExpired(SD, e)) {
-           /*
-            * Note: This will not check the reference age ifdef
-            * HEAP_REPLACEMENT, but it does some other useful
-            * checks...
-            */
-           expired++;
-           debug(20, 3) ("Released store object age %f size %d refs %d key %s\n",
-               age, e->swap_file_sz, e->refcount, storeKeyText(e->key));
-           min_age = age;
-           storeRelease(e);
-       } else {
-           /*
-            * Did not expire the object so we need to add it back
-            * into the heap!
-            */
-           debug(20, 5) ("storeMaintainSwapSpace: non-expired %s\n",
-               storeKeyText(e->key));
-           linklistPush(&locked_entries, e);
-           continue;
-       }
+    walker = SD->repl->PurgeInit(SD->repl, max_scan);
+    while (1) {
+       /* XXX FixMe: This should use the cache_dir hig/low values, not the
+        * global ones
+        */
        if (store_swap_size < store_swap_low)
            break;
-       else if (expired >= max_remove)
-           break;
-       else if (scanned >= max_scan)
+       if (removed >= max_remove)
            break;
+       e = walker->Next(walker);
+       if (!e)
+           break;              /* no more objects */
+       removed++;
+       storeRelease(e);
     }
-    /*
-     * Bump the heap age factor.
-     */
-    if (min_age > 0.0)
-       SD->repl.heap.heap->age = min_age;
-    /*
-     * Reinsert all bumped locked entries back into heap...
-     */
-    while ((e = linklistShift(&locked_entries)))
-       e->repl.node = heap_insert(SD->repl.heap.heap, e);
-#else
-    for (m = SD->repl.lru.list.tail; m; m = prev) {
-       prev = m->prev;
-       e = m->data;
-       scanned++;
-       if (storeEntryLocked(e)) {
-           /*
-            * If there is a locked entry at the tail of the LRU list,
-            * move it to the beginning to get it out of the way.
-            * Theoretically, we might have all locked objects at the
-            * tail, and then we'll never remove anything here and the
-            * LRU age will go to zero.
-            */
-           if (memInUse(MEM_STOREENTRY) > max_scan) {
-               dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
-               dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
-           }
-           locked++;
-
-       } else if (storeUfsDirCheckExpired(SD, e)) {
-           expired++;
-           storeRelease(e);
-       }
-       if (expired >= max_remove)
-           break;
-       if (scanned >= max_scan)
-           break;
-    }
-#endif
-    debug(20, (expired ? 2 : 3)) ("storeMaintainSwapSpace: scanned %d/%d removed %d/%d locked %d f=%.03f\n",
-       scanned, max_scan, expired, max_remove, locked, f);
-    debug(20, 3) ("storeMaintainSwapSpace stats:\n");
-    debug(20, 3) ("  %6d objects\n", memInUse(MEM_STOREENTRY));
-    debug(20, 3) ("  %6d were scanned\n", scanned);
-    debug(20, 3) ("  %6d were locked\n", locked);
-    debug(20, 3) ("  %6d were expired\n", expired);
-    if (store_swap_size < Config.Swap.maxSize)
-       return;
-    if (squid_curtime - last_warn_time < 10)
-       return;
-    debug(20, 0) ("WARNING: Disk space over limit: %d KB > %d KB\n",
-       store_swap_size, Config.Swap.maxSize);
-    last_warn_time = squid_curtime;
+    walker->Done(walker);
+    debug(20, (removed ? 2 : 3)) ("storeUfsDirMaintain: %s removed %d/%d f=%.03f max_scan=%d\n",
+       SD->path, removed, max_remove, f, max_scan);
 }
 
 /*
@@ -1433,7 +1330,7 @@ storeUfsDirMaintain(SwapDir * SD)
 int
 storeUfsDirCheckObj(SwapDir * SD, const StoreEntry * e)
 {
-#if !HEAP_REPLACEMENT
+#if OLD_UNUSED_CODE
     if (storeUfsDirExpiredReferenceAge(SD) < 300) {
        debug(20, 3) ("storeUfsDirCheckObj: NO: LRU Age = %d\n",
            storeUfsDirExpiredReferenceAge(SD));
@@ -1456,16 +1353,8 @@ storeUfsDirRefObj(SwapDir * SD, StoreEntry * e)
 {
     debug(1, 3) ("storeUfsDirRefObj: referencing %p %d/%d\n", e, e->swap_dirn,
        e->swap_filen);
-#if HEAP_REPLACEMENT
-    /* Nothing to do here */
-#else
-    /* Reference the object */
-    if (!EBIT_TEST(e->flags, RELEASE_REQUEST) &&
-       !EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-       dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
-       dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
-    }
-#endif
+    if (SD->repl->Referenced)
+       SD->repl->Referenced(SD->repl, e, &e->repl);
 }
 
 /*
@@ -1478,10 +1367,8 @@ storeUfsDirUnrefObj(SwapDir * SD, StoreEntry * e)
 {
     debug(1, 3) ("storeUfsDirUnrefObj: referencing %p %d/%d\n", e, e->swap_dirn,
        e->swap_filen);
-#if HEAP_REPLACEMENT
-    if (e->repl.node)
-       heap_update(SD->repl.heap.heap, e->repl.node, e);
-#endif
+    if (SD->repl->Dereferenced)
+       SD->repl->Dereferenced(SD->repl, e, &e->repl);
 }
 
 /*
@@ -1495,80 +1382,10 @@ void
 storeUfsDirUnlinkFile(SwapDir * SD, sfileno f)
 {
     debug(79, 3) ("storeUfsDirUnlinkFile: unlinking fileno %08X\n", f);
-    storeUfsDirMapBitReset(SD, f);
+    /* storeUfsDirMapBitReset(SD, f); */
     unlinkdUnlink(storeUfsDirFullPath(SD, f, NULL));
 }
 
-#if !HEAP_REPLACEMENT
-/*
- * storeUfsDirExpiredReferenceAge
- *
- * The LRU age is scaled exponentially between 1 minute and
- * Config.referenceAge , when store_swap_low < store_swap_size <
- * store_swap_high.  This keeps store_swap_size within the low and high
- * water marks.  If the cache is very busy then store_swap_size stays
- * closer to the low water mark, if it is not busy, then it will stay
- * near the high water mark.  The LRU age value can be examined on the
- * cachemgr 'info' page.
- */
-static time_t
-storeUfsDirExpiredReferenceAge(SwapDir * SD)
-{
-    double x;
-    double z;
-    time_t age;
-    long store_high, store_low;
-
-    store_high = (long) (((float) SD->max_size *
-           (float) Config.Swap.highWaterMark) / (float) 100);
-    store_low = (long) (((float) SD->max_size *
-           (float) Config.Swap.lowWaterMark) / (float) 100);
-    debug(20, 20) ("RA: Dir %s, hi=%d, lo=%d, cur=%d\n", SD->path, store_high, store_low, SD->cur_size);
-
-    x = (double) (store_high - SD->cur_size) /
-       (store_high - store_low);
-    x = x < 0.0 ? 0.0 : x > 1.0 ? 1.0 : x;
-    z = pow((double) (Config.referenceAge / 60), x);
-    age = (time_t) (z * 60.0);
-    if (age < 60)
-       age = 60;
-    else if (age > Config.referenceAge)
-       age = Config.referenceAge;
-    return age;
-}
-#endif
-
-/*
- * storeUfsDirCheckExpired
- *
- * Check whether the given object is expired or not
- * It breaks layering a little by calling the upper layers to find
- * out whether the object is locked or not, but we can't help this
- * right now.
- */
-static int
-storeUfsDirCheckExpired(SwapDir * SD, StoreEntry * e)
-{
-    if (storeEntryLocked(e))
-       return 0;
-    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
-       return 1;
-    if (EBIT_TEST(e->flags, ENTRY_NEGCACHED) && squid_curtime >= e->expires)
-       return 1;
-
-#if HEAP_REPLACEMENT
-    /*
-     * with HEAP_REPLACEMENT we are not using the LRU reference age, the heap
-     * controls the replacement of objects.
-     */
-    return 1;
-#else
-    if (squid_curtime - e->lastref > storeUfsDirExpiredReferenceAge(SD))
-       return 1;
-    return 0;
-#endif
-}
-
 /*
  * Add and remove the given StoreEntry from the replacement policy in
  * use.
@@ -1579,17 +1396,7 @@ storeUfsDirReplAdd(SwapDir * SD, StoreEntry * e)
 {
     debug(20, 4) ("storeUfsDirReplAdd: added node %p to dir %d\n", e,
        SD->index);
-#if HEAP_REPLACEMENT
-    if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-       (void) 0;
-    } else {
-       e->repl.node = heap_insert(SD->repl.heap.heap, e);
-       debug(20, 4) ("storeUfsDirReplAdd: inserted node 0x%x\n", e->repl.node);
-    }
-#else
-    /* Shouldn't we not throw special objects into the lru ? */
-    dlinkAdd(e, &e->repl.lru, &SD->repl.lru.list);
-#endif
+    SD->repl->Add(SD->repl, e, &e->repl);
 }
 
 
@@ -1599,17 +1406,7 @@ storeUfsDirReplRemove(StoreEntry * e)
     SwapDir *SD = INDEXSD(e->swap_dirn);
     debug(20, 4) ("storeUfsDirReplRemove: remove node %p from dir %d\n", e,
        SD->index);
-#if HEAP_REPLACEMENT
-    /* And now, release the object from the replacement policy */
-    if (e->repl.node) {
-       debug(20, 4) ("storeUfsDirReplRemove: deleting node 0x%x\n",
-           e->repl.node);
-       heap_delete(SD->repl.heap.heap, e->repl.node);
-       e->repl.node = NULL;
-    }
-#else
-    dlinkDelete(&e->repl.lru, &SD->repl.lru.list);
-#endif
+    SD->repl->Remove(SD->repl, e, &e->repl);
 }
 
 
@@ -1653,15 +1450,15 @@ storeUfsDirStats(SwapDir * SD, StoreEntry * sentry)
     if (SD->flags.read_only)
        storeAppendPrintf(sentry, " READ-ONLY");
     storeAppendPrintf(sentry, "\n");
+#if OLD_UNUSED_CODE
 #if !HEAP_REPLACEMENT
     storeAppendPrintf(sentry, "LRU Expiration Age: %6.2f days\n",
        (double) storeUfsDirExpiredReferenceAge(SD) / 86400.0);
 #else
-#if 0
     storeAppendPrintf(sentry, "Storage Replacement Threshold:\t%f\n",
        heap_peepminkey(sd.repl.heap.heap));
 #endif
-#endif
+#endif /* OLD_UNUSED_CODE */
 }
 
 /*
@@ -1856,41 +1653,12 @@ storeUfsDirParse(SwapDir * sd, int index, char *path)
     sd->log.open = storeUfsDirOpenSwapLog;
     sd->log.close = storeUfsDirCloseSwapLog;
     sd->log.write = storeUfsDirSwapLog;
-    sd->log.clean.open = storeUfsDirWriteCleanOpen;
+    sd->log.clean.start = storeUfsDirWriteCleanStart;
+    sd->log.clean.nextentry = storeUfsDirCleanLogNextEntry;
+    sd->log.clean.done = storeUfsDirWriteCleanDone;
 
     /* Initialise replacement policy stuff */
-#if HEAP_REPLACEMENT
-    /*
-     * Create new heaps with cache replacement policies attached to them.
-     * The cache replacement policy is specified as either GDSF or LFUDA in
-     * the squid.conf configuration file.  Note that the replacement policy
-     * applies only to the disk replacement algorithm.  Memory replacement
-     * always uses GDSF since we want to maximize object hit rate.
-     */
-    if (Config.replPolicy) {
-       if (tolower(Config.replPolicy[0]) == 'g') {
-           debug(20, 1) ("Using GDSF disk replacement policy\n");
-           sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_GDSF);
-       } else if (tolower(Config.replPolicy[0]) == 'l') {
-           if (tolower(Config.replPolicy[1]) == 'f') {
-               debug(20, 1) ("Using LFUDA disk replacement policy\n");
-               sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_LFUDA);
-           } else if (tolower(Config.replPolicy[1]) == 'r') {
-               debug(20, 1) ("Using LRU heap disk replacement policy\n");
-               sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_LRU);
-           }
-       } else {
-           debug(20, 1) ("Unrecognized replacement_policy; using GDSF\n");
-           sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_GDSF);
-       }
-    } else {
-       debug(20, 1) ("Using default disk replacement policy (GDSF)\n");
-       sd->repl.heap.heap = new_heap(10000, HeapKeyGen_StoreEntry_GDSF);
-    }
-#else
-    sd->repl.lru.list.head = NULL;
-    sd->repl.lru.list.tail = NULL;
-#endif
+    sd->repl = createRemovalPolicy(Config.replPolicy);
 }
 
 /*
index da90d7c0474ea255c9c08ceff676cb54a70c994b..884c91ff80c2afd9eb28e9a30adbd8ac60d94943 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: globals.h,v 1.91 2000/05/31 04:26:32 wessels Exp $
+ * $Id: globals.h,v 1.92 2000/06/08 18:05:35 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -125,10 +125,6 @@ extern double request_failure_ratio;       /* 0.0 */
 extern double current_dtime;
 extern int store_hash_buckets; /* 0 */
 extern hash_table *store_table;        /* NULL */
-#if HEAP_REPLACEMENT
-extern heap *inmem_heap;
-#else
-#endif
 extern dlink_list ClientActiveRequests;
 extern const String StringNull;        /* { 0, 0, NULL } */
 extern const MemBuf MemBufNull;        /* MemBufNULL */
@@ -154,3 +150,4 @@ extern int store_swap_low;  /* 0 */
 extern int store_swap_high;    /* 0 */
 extern int store_pages_max;    /* 0 */
 extern ssize_t store_maxobjsize; /* -1 */
+extern RemovalPolicy *mem_policy;
index e7e213aca3244deb3b54cdd3ac72d76a71cd8836..4e4fdb3652bdb1e97d05c1ca214db4a41ec0d10b 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.369 2000/05/31 07:01:42 hno Exp $
+ * $Id: protos.h,v 1.370 2000/06/08 18:05:35 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -849,13 +849,6 @@ extern void storeFsInit(void);
 extern void storeFsDone(void);
 extern void storeFsAdd(char *, STSETUP *);
 
-/* store_heap_replacement.c */
-#ifdef HEAP_REPLACEMENT
-extern heap_key HeapKeyGen_StoreEntry_LFUDA(void *, double);
-extern heap_key HeapKeyGen_StoreEntry_GDSF(void *, double);
-extern heap_key HeapKeyGen_StoreEntry_LRU(void *, double);
-#endif
-
 /* store_modules.c */
 extern void storeFsSetup(void);
 
@@ -1185,6 +1178,10 @@ extern void logfilePrintf(Logfile * lf, const char *fmt,...);
 extern void logfilePrintf(va_alist);
 #endif
 
+/* Removal Policies */
+RemovalPolicy *
+createRemovalPolicy(RemovalPolicySettings *settings);
+
 /*
  * prototypes for system functions missing from system includes
  */
diff --git a/src/repl/Makefile.in b/src/repl/Makefile.in
new file mode 100644 (file)
index 0000000..c4589ed
--- /dev/null
@@ -0,0 +1,35 @@
+#  Makefile for storage modules in the Squid Object Cache server
+#
+#  $Id: Makefile.in,v 1.1 2000/06/08 18:05:39 hno Exp $
+#
+
+SUBDIRS                = @REPL_POLICIES@
+
+all:
+       @test -z "$(SUBDIRS)" || for dir in $(SUBDIRS); do \
+          sh -c "cd $$dir && $(MAKE) all" || exit 1; \
+       done; \
+       if [ ! -f stamp ]; then \
+          touch stamp; \
+       fi
+
+clean:
+       -rm -f *.a stamp
+       -for dir in *; do \
+           if [ -f $$dir/Makefile ]; then \
+              sh -c "cd $$dir && $(MAKE) $@" || exit 1;\
+           fi; \
+       done
+
+distclean:
+       -rm -f *.a Makefile
+       -for dir in *; do \
+           if [ -f $$dir/Makefile ]; then \
+               sh -c "cd $$dir && $(MAKE) distclean"; \
+           fi; \
+       done
+
+.DEFAULT:
+       @test -z "$(SUBDIRS)" || for dir in $(SUBDIRS); do \
+          sh -c "cd $$dir && $(MAKE) $@" || exit 1; \
+       done
diff --git a/src/repl/heap/Makefile.in b/src/repl/heap/Makefile.in
new file mode 100644 (file)
index 0000000..a2e56b6
--- /dev/null
@@ -0,0 +1,55 @@
+#
+#  Makefile for the UFS storage driver for the Squid Object Cache server
+#
+#  $Id: Makefile.in,v 1.1 2000/06/08 18:05:40 hno Exp $
+#
+
+REPL           = heap
+
+top_srcdir     = @top_srcdir@
+VPATH          = @srcdir@
+
+CC             = @CC@
+MAKEDEPEND     = @MAKEDEPEND@
+AR_R           = @AR_R@
+RANLIB         = @RANLIB@
+AC_CFLAGS      = @CFLAGS@
+SHELL          = /bin/sh
+
+INCLUDE                = -I../../../include -I$(top_srcdir)/include -I$(top_srcdir)/src/
+CFLAGS                 = $(AC_CFLAGS) $(INCLUDE) $(DEFINES)
+
+OUT            = ../$(REPL).a
+
+OBJS           = \
+               store_repl_$(REPL).o \
+               store_heap_replacement.o
+
+all: $(OUT)
+
+$(OUT): $(OBJS)
+       @rm -f ../stamp
+       $(AR_R) $(OUT) $(OBJS)
+       $(RANLIB) $(OUT)
+
+$(OBJS): $(top_srcdir)/include/version.h ../../../include/autoconf.h
+
+.c.o:
+       @rm -f ../stamp
+       $(CC) $(CFLAGS) -c $<
+
+clean: 
+       -rm -rf *.o *pure_* core ../$(FS).a
+
+distclean:     clean
+       -rm -f Makefile
+       -rm -f Makefile.bak
+       -rm -f tags
+
+install:
+
+tags:
+       ctags *.[ch] $(top_srcdir)/src/*.[ch] $(top_srcdir)/include/*.h $(top_srcdir)/lib/*.[ch]
+
+depend:
+       $(MAKEDEPEND) $(INCLUDE) -fMakefile *.c
diff --git a/src/repl/heap/store_heap_replacement.cc b/src/repl/heap/store_heap_replacement.cc
new file mode 100644 (file)
index 0000000..e04d459
--- /dev/null
@@ -0,0 +1,138 @@
+
+/*
+ * $Id: store_heap_replacement.cc,v 1.1 2000/06/08 18:05:40 hno Exp $
+ *
+ * DEBUG: section 20    Storage Manager Heap-based replacement
+ * AUTHOR: John Dilley
+ *
+ * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from the
+ *  Internet community.  Development is led by Duane Wessels of the
+ *  National Laboratory for Applied Network Research and funded by the
+ *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
+ *  the Regents of the University of California.  Please see the
+ *  COPYRIGHT file for full details.  Squid incorporates software
+ *  developed and/or copyrighted by other sources.  Please 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.
+ *
+ */
+
+/*
+ * The code in this file is Copyrighted (C) 1999 by Hewlett Packard.
+ * 
+ *
+ * For a description of these cache replacement policies see --
+ *  http://www.hpl.hp.com/techreports/1999/HPL-1999-69.html
+ */
+
+#include "squid.h"
+#include "heap.h"
+
+/*
+ * Key generation function to implement the LFU-DA policy (Least
+ * Frequently Used with Dynamic Aging).  Similar to classical LFU
+ * but with aging to handle turnover of the popular document set.
+ * Maximizes byte hit rate by keeping more currently popular objects
+ * in cache regardless of size.  Achieves lower hit rate than GDS
+ * because there are more large objects in cache (so less room for
+ * smaller popular objects).
+ * 
+ * This version implements a tie-breaker based upon recency
+ * (e->lastref): for objects that have the same reference count
+ * the most recent object wins (gets a higher key value).
+ *
+ * Note: this does not properly handle when the aging factor
+ * gets so huge that the added value is outside of the
+ * precision of double. However, Squid has to stay up
+ * for quite a extended period of time (number of requests)
+ * for this to become a problem. (estimation is 10^8 cache
+ * turnarounds)
+ */
+heap_key HeapKeyGen_StoreEntry_LFUDA(void *entry, double age)
+{
+    StoreEntry *e = entry;
+    heap_key key;
+    double tie;
+    if (e->lastref <= 0)
+       tie = 0.0;
+    else if (squid_curtime <= e->lastref)
+       tie = 0.0;
+    else
+       tie = 1.0 - exp((double) (e->lastref - squid_curtime) / 86400.0);
+    key = age + (double) e->refcount - tie;
+    debug(81, 3) ("HeapKeyGen_StoreEntry_LFUDA: %s refcnt=%ld lastref=%ld age=%f tie=%f -> %f\n",
+           storeKeyText(e->key), e->refcount, e->lastref, age, tie, key);
+    if (e->mem_obj && e->mem_obj->url)
+       debug(81, 3) ("HeapKeyGen_StoreEntry_LFUDA: url=%s\n",
+           e->mem_obj->url);
+    return (double)key;
+}
+
+
+/*
+ * Key generation function to implement the GDS-Frequency policy.
+ * Similar to Greedy Dual-Size Hits policy, but adds aging of
+ * documents to prevent pollution.  Maximizes object hit rate by
+ * keeping more small, popular objects in cache.  Achieves lower
+ * byte hit rate than LFUDA because there are fewer large objects
+ * in cache.
+ * 
+ * This version implements a tie-breaker based upon recency
+ * (e->lastref): for objects that have the same reference count
+ * the most recent object wins (gets a higher key value).
+ *
+ * Note: this does not properly handle when the aging factor
+ * gets so huge that the added value is outside of the
+ * precision of double. However, Squid has to stay up
+ * for quite a extended period of time (number of requests)
+ * for this to become a problem. (estimation is 10^8 cache
+ * turnarounds)
+ */
+heap_key HeapKeyGen_StoreEntry_GDSF(void *entry, double age)
+{
+    StoreEntry *e = entry;
+    heap_key key;
+    double size = e->swap_file_sz ? (double) e->swap_file_sz : 1.0;
+    double tie = (e->lastref > 1) ? (1.0 / e->lastref) : 1.0;
+    key = age + ((double) e->refcount / size) - tie;
+    debug(81, 3) ("HeapKeyGen_StoreEntry_GDSF: %s size=%f refcnt=%ld lastref=%ld age=%f tie=%f -> %f\n",
+           storeKeyText(e->key), size, e->refcount, e->lastref, age, tie, key);
+    if (e->mem_obj && e->mem_obj->url)
+       debug(81, 3) ("HeapKeyGen_StoreEntry_GDSF: url=%s\n",
+           e->mem_obj->url);
+    return key;
+}
+
+/* 
+ * Key generation function to implement the LRU policy.  Normally
+ * one would not do this with a heap -- use the linked list instead.
+ * For testing and performance characterization it was useful.
+ * Don't use it unless you are trying to compare performance among
+ * heap-based replacement policies...
+ */
+heap_key HeapKeyGen_StoreEntry_LRU(void *entry, double age)
+{
+    StoreEntry *e = entry;
+    debug(81, 3) ("HeapKeyGen_StoreEntry_LRU: %s age=%f lastref=%f\n",
+           storeKeyText(e->key), age, (double)e->lastref);
+    if (e->mem_obj && e->mem_obj->url)
+       debug(81, 3) ("HeapKeyGen_StoreEntry_LRU: url=%s\n",
+           e->mem_obj->url);
+    return (heap_key) e->lastref;
+}
diff --git a/src/repl/heap/store_heap_replacement.h b/src/repl/heap/store_heap_replacement.h
new file mode 100644 (file)
index 0000000..f8084aa
--- /dev/null
@@ -0,0 +1,3 @@
+extern heap_key HeapKeyGen_StoreEntry_LFUDA(void *entry, double age);
+extern heap_key HeapKeyGen_StoreEntry_GDSF(void *entry, double age);
+extern heap_key HeapKeyGen_StoreEntry_LRU(void *entry, double age);
diff --git a/src/repl/heap/store_repl_heap.cc b/src/repl/heap/store_repl_heap.cc
new file mode 100644 (file)
index 0000000..5da654e
--- /dev/null
@@ -0,0 +1,310 @@
+
+/*
+ * $Id: store_repl_heap.cc,v 1.1 2000/06/08 18:05:40 hno Exp $
+ *
+ * DEBUG: section ?     HEAP based removal policies
+ * AUTHOR: Henrik Nordstrom
+ *
+ * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from the
+ *  Internet community.  Development is led by Duane Wessels of the
+ *  National Laboratory for Applied Network Research and funded by the
+ *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
+ *  Duane Wessels and the University of California San Diego.  Please
+ *  see the COPYRIGHT file for full details.  Squid incorporates
+ *  software developed and/or copyrighted by other sources.  Please 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 "heap.h"
+#include "store_heap_replacement.h"
+
+REMOVALPOLICYCREATE createRemovalPolicy_heap;
+
+static int nr_heap_policies = 0;
+
+typedef struct _HeapPolicyData HeapPolicyData;
+struct _HeapPolicyData {
+    RemovalPolicy *policy;
+    heap *heap;
+    heap_key_func *keyfunc;
+    int count;
+    int nwalkers;
+    enum heap_entry_type
+    { TYPE_UNKNOWN = 0, TYPE_STORE_ENTRY, TYPE_STORE_MEM }
+    type;
+};
+
+/* Hack to avoid having to remember the RemovalPolicyNode location.
+ * Needed by the purge walker.
+ */
+static enum heap_entry_type
+heap_guessType(StoreEntry * entry, RemovalPolicyNode * node)
+{
+    if (node == &entry->repl)
+       return TYPE_STORE_ENTRY;
+    if (entry->mem_obj && node == &entry->mem_obj->repl)
+       return TYPE_STORE_MEM;
+    fatal("Heap Replacement: Unknown StoreEntry node type");
+    return TYPE_UNKNOWN;
+}
+#define SET_POLICY_NODE(entry,value) \
+    switch(heap->type) { \
+    case TYPE_STORE_ENTRY: entry->repl.data = value; break ; \
+    case TYPE_STORE_MEM: entry->mem_obj->repl.data = value ; break ; \
+    default: break; \
+    }
+
+static void
+heap_add(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
+{
+    HeapPolicyData *heap = policy->_data;
+    assert(!node->data);
+    if (EBIT_TEST(entry->flags, ENTRY_SPECIAL))
+       return; /* We won't manage these.. they messes things up */
+    node->data = heap_insert(heap->heap, entry);
+    heap->count += 1;
+    if (!heap->type)
+       heap->type = heap_guessType(entry, node);
+    /* Add a little more variance to the aging factor */
+    heap->heap->age += heap->heap->age / 100000000;
+}
+
+static void
+heap_remove(RemovalPolicy * policy, StoreEntry * entry,
+    RemovalPolicyNode * node)
+{
+    HeapPolicyData *heap = policy->_data;
+    heap_node *hnode = node->data;
+    if (!hnode)
+       return;
+    heap_delete(heap->heap, hnode);
+    node->data = NULL;
+    heap->count -= 1;
+}
+
+static void
+heap_referenced(RemovalPolicy * policy, const StoreEntry * entry,
+    RemovalPolicyNode * node)
+{
+    HeapPolicyData *heap = policy->_data;
+    heap_node *hnode = node->data;
+    if (!hnode)
+       return;
+    heap_update(heap->heap, hnode, (StoreEntry *) entry);
+}
+
+/** RemovalPolicyWalker **/
+
+typedef struct _HeapWalkData HeapWalkData;
+struct _HeapWalkData
+{
+    int current;
+};
+
+const StoreEntry *
+heap_walkNext(RemovalPolicyWalker * walker)
+{
+    HeapWalkData *heap_walk = walker->_data;
+    RemovalPolicy *policy = walker->_policy;
+    HeapPolicyData *heap = policy->_data;
+    StoreEntry *entry;
+    if (heap_walk->current >= heap_nodes(heap->heap))
+       return NULL;            /* done */
+    entry = (StoreEntry *) heap_peep(heap->heap, heap_walk->current++);
+    return entry;
+}
+
+static void
+heap_walkDone(RemovalPolicyWalker * walker)
+{
+    RemovalPolicy *policy = walker->_policy;
+    HeapPolicyData *heap = policy->_data;
+    assert(strcmp(policy->_type, "heap") == 0);
+    assert(heap->nwalkers > 0);
+    heap->nwalkers -= 1;
+    safe_free(walker->_data);
+    cbdataFree(walker);
+}
+
+static RemovalPolicyWalker *
+heap_walkInit(RemovalPolicy * policy)
+{
+    HeapPolicyData *heap = policy->_data;
+    RemovalPolicyWalker *walker;
+    HeapWalkData *heap_walk;
+    heap->nwalkers += 1;
+    walker = xcalloc(1, sizeof(*walker));
+    heap_walk = xcalloc(1, sizeof(*heap_walk));
+    heap_walk->current = 0;
+    walker->_policy = policy;
+    walker->_data = heap_walk;
+    walker->Next = heap_walkNext;
+    walker->Done = heap_walkDone;
+    cbdataAdd(walker, cbdataXfree, 0);
+    return walker;
+}
+
+/** RemovalPurgeWalker **/
+
+typedef struct _HeapPurgeData HeapPurgeData;
+struct _HeapPurgeData
+{
+    link_list *locked_entries;
+    heap_key min_age;
+};
+
+static StoreEntry *
+heap_purgeNext(RemovalPurgeWalker * walker)
+{
+    HeapPurgeData *heap_walker = walker->_data;
+    RemovalPolicy *policy = walker->_policy;
+    HeapPolicyData *heap = policy->_data;
+    StoreEntry *entry;
+    heap_key age;
+  try_again:
+    if (!heap_nodes(heap->heap) > 0)
+       return NULL;            /* done */
+    age = heap_peepminkey(heap->heap);
+    entry = heap_extractmin(heap->heap);
+    if (storeEntryLocked(entry)) {
+       linklistPush(&heap_walker->locked_entries, entry);
+       goto try_again;
+    }
+    heap_walker->min_age = age;
+    SET_POLICY_NODE(entry, NULL);
+    return entry;
+}
+
+static void
+heap_purgeDone(RemovalPurgeWalker * walker)
+{
+    HeapPurgeData *heap_walker = walker->_data;
+    RemovalPolicy *policy = walker->_policy;
+    HeapPolicyData *heap = policy->_data;
+    StoreEntry *entry;
+    assert(strcmp(policy->_type, "heap") == 0);
+    assert(heap->nwalkers > 0);
+    heap->nwalkers -= 1;
+    if (heap_walker->min_age > 0) {
+       heap->heap->age = heap_walker->min_age;
+       debug (81, 3) ("heap_purgeDone: Heap age set to %f\n",
+               (double) heap->heap->age);
+    }
+    /*
+     * Reinsert the locked entries
+     */
+    while ((entry = linklistShift(&heap_walker->locked_entries))) {
+       heap_node *node = heap_insert(heap->heap, entry);
+       SET_POLICY_NODE(entry, node);
+    }
+    safe_free(walker->_data);
+    cbdataFree(walker);
+}
+
+static RemovalPurgeWalker *
+heap_purgeInit(RemovalPolicy * policy, int max_scan)
+{
+    HeapPolicyData *heap = policy->_data;
+    RemovalPurgeWalker *walker;
+    HeapPurgeData *heap_walk;
+    heap->nwalkers += 1;
+    walker = xcalloc(1, sizeof(*walker));
+    heap_walk = xcalloc(1, sizeof(*heap_walk));
+    heap_walk->min_age = 0.0;
+    heap_walk->locked_entries = NULL;
+    walker->_policy = policy;
+    walker->_data = heap_walk;
+    walker->max_scan = max_scan;
+    walker->Next = heap_purgeNext;
+    walker->Done = heap_purgeDone;
+    cbdataAdd(walker, cbdataXfree, 0);
+#if HEAP_REPLACEMENT_DEBUG
+    if (!verify_heap_property(heap->heap)) {
+       debug(81, 1) ("Heap property violated!\n");
+    }
+#endif
+    return walker;
+}
+
+static void
+heap_free(RemovalPolicy * policy)
+{
+    HeapPolicyData *heap = policy->_data;
+    /* Make some verification of the policy state */
+    assert(strcmp(policy->_type, "heap") == 0);
+    assert(heap->nwalkers);
+    assert(heap->count);
+    /* Ok, time to destroy this policy */
+    safe_free(policy->_data);
+    memset(policy, 0, sizeof(*policy));
+    cbdataFree(policy);
+}
+
+RemovalPolicy *
+createRemovalPolicy_heap(wordlist * args)
+{
+    RemovalPolicy *policy;
+    HeapPolicyData *heap_data;
+    char *keytype;
+    /* Allocate the needed structures */
+    policy = xcalloc(1, sizeof(*policy));
+    heap_data = xcalloc(1, sizeof(*heap_data));
+    /* cbdata register the policy */
+    cbdataAdd(policy, cbdataXfree, 0);
+    /* Initialize the policy data */
+    heap_data->policy = policy;
+    if (args) {
+       keytype = args->key;
+       args = args->next;
+    } else {
+       debug(81, 1) ("createRemovalPolicy_heap: No key type specified. Using LRU\n");
+       keytype = "LRU";
+    }
+    if (!strcmp(keytype, "GDSF"))
+       heap_data->keyfunc = HeapKeyGen_StoreEntry_GDSF;
+    else if (!strcmp(keytype, "LFUDA"))
+       heap_data->keyfunc = HeapKeyGen_StoreEntry_LFUDA;
+    else if (!strcmp(keytype, "LRU"))
+       heap_data->keyfunc = HeapKeyGen_StoreEntry_LRU;
+    else {
+       debug(81, 0) ("createRemovalPolicy_heap: Unknown key type \"%s\". Using LRU\n",
+           keytype);
+       heap_data->keyfunc = HeapKeyGen_StoreEntry_LRU;
+    }
+    /* No additional arguments expected */
+    assert(!args);
+    heap_data->heap = new_heap(1000, heap_data->keyfunc);
+    heap_data->heap->age = 1.0;
+    /* Populate the policy structure */
+    policy->_type = "heap";
+    policy->_data = heap_data;
+    policy->Free = heap_free;
+    policy->Add = heap_add;
+    policy->Remove = heap_remove;
+    policy->Referenced = NULL;
+    policy->Dereferenced = heap_referenced;
+    policy->WalkInit = heap_walkInit;
+    policy->PurgeInit = heap_purgeInit;
+    /* Increase policy usage count */
+    nr_heap_policies += 0;
+    return policy;
+}
diff --git a/src/repl/lru/Makefile.in b/src/repl/lru/Makefile.in
new file mode 100644 (file)
index 0000000..a89ebea
--- /dev/null
@@ -0,0 +1,54 @@
+#
+#  Makefile for the UFS storage driver for the Squid Object Cache server
+#
+#  $Id: Makefile.in,v 1.1 2000/06/08 18:05:40 hno Exp $
+#
+
+REPL           = lru
+
+top_srcdir     = @top_srcdir@
+VPATH          = @srcdir@
+
+CC             = @CC@
+MAKEDEPEND     = @MAKEDEPEND@
+AR_R           = @AR_R@
+RANLIB         = @RANLIB@
+AC_CFLAGS      = @CFLAGS@
+SHELL          = /bin/sh
+
+INCLUDE                = -I../../../include -I$(top_srcdir)/include -I$(top_srcdir)/src/
+CFLAGS                 = $(AC_CFLAGS) $(INCLUDE) $(DEFINES)
+
+OUT            = ../$(REPL).a
+
+OBJS           = \
+               store_repl_$(REPL).o
+
+all: $(OUT)
+
+$(OUT): $(OBJS)
+       @rm -f ../stamp
+       $(AR_R) $(OUT) $(OBJS)
+       $(RANLIB) $(OUT)
+
+$(OBJS): $(top_srcdir)/include/version.h ../../../include/autoconf.h
+
+.c.o:
+       @rm -f ../stamp
+       $(CC) $(CFLAGS) -c $<
+
+install:
+
+clean: 
+       -rm -rf *.o *pure_* core ../$(FS).a
+
+distclean:     clean
+       -rm -f Makefile
+       -rm -f Makefile.bak
+       -rm -f tags
+
+tags:
+       ctags *.[ch] $(top_srcdir)/src/*.[ch] $(top_srcdir)/include/*.h $(top_srcdir)/lib/*.[ch]
+
+depend:
+       $(MAKEDEPEND) $(INCLUDE) -fMakefile *.c
diff --git a/src/repl/lru/store_repl_lru.cc b/src/repl/lru/store_repl_lru.cc
new file mode 100644 (file)
index 0000000..2a6e82c
--- /dev/null
@@ -0,0 +1,358 @@
+
+/*
+ * $Id: store_repl_lru.cc,v 1.1 2000/06/08 18:05:40 hno Exp $
+ *
+ * DEBUG: section ?     LRU Removal policy
+ * AUTHOR: Henrik Nordstrom
+ *
+ * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from the
+ *  Internet community.  Development is led by Duane Wessels of the
+ *  National Laboratory for Applied Network Research and funded by the
+ *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
+ *  Duane Wessels and the University of California San Diego.  Please
+ *  see the COPYRIGHT file for full details.  Squid incorporates
+ *  software developed and/or copyrighted by other sources.  Please 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"
+
+REMOVALPOLICYCREATE createRemovalPolicy_lru;
+
+typedef struct _LruPolicyData LruPolicyData;
+struct _LruPolicyData {
+    RemovalPolicy *policy;
+    dlink_list list;
+    int count;
+    int nwalkers;
+    enum heap_entry_type
+    { TYPE_UNKNOWN = 0, TYPE_STORE_ENTRY, TYPE_STORE_MEM }
+    type;
+};
+
+/* Hack to avoid having to remember the RemovalPolicyNode location.
+ * Needed by the purge walker to clear the policy information
+ */
+static enum heap_entry_type
+repl_guessType(StoreEntry * entry, RemovalPolicyNode * node)
+{
+    if (node == &entry->repl)
+       return TYPE_STORE_ENTRY;
+    if (entry->mem_obj && node == &entry->mem_obj->repl)
+       return TYPE_STORE_MEM;
+    fatal("Heap Replacement: Unknown StoreEntry node type");
+    return TYPE_UNKNOWN;
+}
+#define SET_POLICY_NODE(entry,value) \
+    switch(lru->type) { \
+    case TYPE_STORE_ENTRY: entry->repl.data = value; break ; \
+    case TYPE_STORE_MEM: entry->mem_obj->repl.data = value ; break ; \
+    default: break; \
+    }
+
+typedef struct _LruNode LruNode;
+struct _LruNode
+{
+    /* Note: the dlink_node MUST be the first member of the LruNode
+     * structure. This member is later pointer typecasted to LruNode *.
+     */
+    dlink_node node;
+};
+
+static MemPool *lru_node_pool = NULL;
+static int nr_lru_policies = 0;
+
+static void
+lru_add(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
+{
+    LruPolicyData *lru = policy->_data;
+    LruNode *lru_node;
+    assert(!node->data);
+    node->data = lru_node = memPoolAlloc(lru_node_pool);
+    dlinkAddTail(entry, &lru_node->node, &lru->list);
+    lru->count += 1;
+    if (!lru->type)
+       lru->type = repl_guessType(entry, node);
+}
+
+static void
+lru_remove(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
+{
+    LruPolicyData *lru = policy->_data;
+    LruNode *lru_node = node->data;
+    if (!lru_node)
+       return;
+    assert(lru_node->node.data == entry);
+    node->data = NULL;
+    dlinkDelete(&lru_node->node, &lru->list);
+    memPoolFree(lru_node_pool, lru_node);
+    lru->count -= 1;
+}
+
+static void
+lru_referenced(RemovalPolicy * policy, const StoreEntry * entry,
+    RemovalPolicyNode * node)
+{
+    LruPolicyData *lru = policy->_data;
+    LruNode *lru_node = node->data;
+    if (!lru_node)
+       return;
+    dlinkDelete(&lru_node->node, &lru->list);
+    dlinkAddTail((void *) entry, &lru_node->node, &lru->list);
+}
+
+/** RemovalPolicyWalker **/
+
+typedef struct _LruWalkData LruWalkData;
+struct _LruWalkData
+{
+    LruNode *current;
+};
+
+const StoreEntry *
+lru_walkNext(RemovalPolicyWalker * walker)
+{
+    LruWalkData *lru_walk = walker->_data;
+    LruNode *lru_node = lru_walk->current;
+    if (!lru_node)
+       return NULL;
+    lru_walk->current = (LruNode *) lru_node->node.next;
+    return (StoreEntry *) lru_node->node.data;
+}
+
+static void
+lru_walkDone(RemovalPolicyWalker * walker)
+{
+    RemovalPolicy *policy = walker->_policy;
+    LruPolicyData *lru = policy->_data;
+    assert(strcmp(policy->_type, "lru") == 0);
+    assert(lru->nwalkers > 0);
+    lru->nwalkers -= 1;
+    safe_free(walker->_data);
+    cbdataFree(walker);
+}
+
+static RemovalPolicyWalker *
+lru_walkInit(RemovalPolicy * policy)
+{
+    LruPolicyData *lru = policy->_data;
+    RemovalPolicyWalker *walker;
+    LruWalkData *lru_walk;
+    lru->nwalkers += 1;
+    walker = xcalloc(1, sizeof(*walker));
+    lru_walk = xcalloc(1, sizeof(*lru_walk));
+    walker->_policy = policy;
+    walker->_data = lru_walk;
+    walker->Next = lru_walkNext;
+    walker->Done = lru_walkDone;
+    lru_walk->current = (LruNode *) lru->list.head;
+    cbdataAdd(walker, cbdataXfree, 0);
+    return walker;
+}
+
+/** RemovalPurgeWalker **/
+
+typedef struct _LruPurgeData LruPurgeData;
+struct _LruPurgeData
+{
+    LruNode *current;
+    LruNode *start;
+};
+
+static StoreEntry *
+lru_purgeNext(RemovalPurgeWalker * walker)
+{
+    LruPurgeData *lru_walker = walker->_data;
+    RemovalPolicy *policy = walker->_policy;
+    LruPolicyData *lru = policy->_data;
+    LruNode *lru_node;
+    StoreEntry *entry;
+  try_again:
+    lru_node = lru_walker->current;
+    if (!lru_node || walker->scanned >= walker->max_scan)
+       return NULL;
+    walker->scanned += 1;
+    lru_walker->current = (LruNode *) lru_node->node.next;
+    if (lru_walker->current == lru_walker->start) {
+       /* Last node found */
+       lru_walker->current = NULL;
+    }
+    entry = (StoreEntry *) lru_node->node.data;
+    dlinkDelete(&lru_node->node, &lru->list);
+    if (storeEntryLocked(entry)) {
+       /* Shit, it is locked. we can't return this one */
+       walker->locked++;
+       dlinkAddTail(entry, &lru_node->node, &lru->list);
+       goto try_again;
+    }
+    memPoolFree(lru_node_pool, lru_node);
+    lru->count -= 1;
+    SET_POLICY_NODE(entry, NULL);
+    return entry;
+}
+
+static void
+lru_purgeDone(RemovalPurgeWalker * walker)
+{
+    RemovalPolicy *policy = walker->_policy;
+    LruPolicyData *lru = policy->_data;
+    assert(strcmp(policy->_type, "lru") == 0);
+    assert(lru->nwalkers > 0);
+    lru->nwalkers -= 1;
+    safe_free(walker->_data);
+    cbdataFree(walker);
+}
+
+static RemovalPurgeWalker *
+lru_purgeInit(RemovalPolicy * policy, int max_scan)
+{
+    LruPolicyData *lru = policy->_data;
+    RemovalPurgeWalker *walker;
+    LruPurgeData *lru_walk;
+    lru->nwalkers += 1;
+    walker = xcalloc(1, sizeof(*walker));
+    lru_walk = xcalloc(1, sizeof(*lru_walk));
+    walker->_policy = policy;
+    walker->_data = lru_walk;
+    walker->max_scan = max_scan;
+    walker->Next = lru_purgeNext;
+    walker->Done = lru_purgeDone;
+    lru_walk->start = lru_walk->current = (LruNode *) lru->list.head;
+    cbdataAdd(walker, cbdataXfree, 0);
+    return walker;
+}
+
+static void
+lru_free(RemovalPolicy * policy)
+{
+    LruPolicyData *lru = policy->_data;
+    /* Make some verification of the policy state */
+    assert(strcmp(policy->_type, "lru") == 0);
+    assert(lru->nwalkers);
+    assert(lru->count);
+    /* Ok, time to destroy this policy */
+    safe_free(policy->_data);
+    memset(policy, 0, sizeof(*policy));
+    cbdataFree(policy);
+}
+
+RemovalPolicy *
+createRemovalPolicy_lru(wordlist *args)
+{
+    RemovalPolicy *policy;
+    LruPolicyData *lru_data;
+    /* no arguments expected or understood */
+    assert(!args);
+    /* Initialize */
+    if (!lru_node_pool)
+       lru_node_pool = memPoolCreate("LRU policy node", sizeof(LruNode));
+    /* Allocate the needed structures */
+    policy = xcalloc(1, sizeof(*policy));
+    lru_data = xcalloc(1, sizeof(*lru_data));
+    /* cbdata register the policy */
+    cbdataAdd(policy, cbdataXfree, 0);
+    /* Initialize the URL data */
+    lru_data->policy = policy;
+    /* Populate the policy structure */
+    policy->_type = "lru";
+    policy->_data = lru_data;
+    policy->Free = lru_free;
+    policy->Add = lru_add;
+    policy->Remove = lru_remove;
+    policy->Referenced = lru_referenced;
+    policy->Dereferenced = lru_referenced;
+    policy->WalkInit = lru_walkInit;
+    policy->PurgeInit = lru_purgeInit;
+    /* Increase policy usage count */
+    nr_lru_policies += 0;
+    return policy;
+}
+
+
+#if OLD_UNUSED_CODE
+/*
+ * storeUfsDirCheckExpired
+ *
+ * Check whether the given object is expired or not
+ * It breaks layering a little by calling the upper layers to find
+ * out whether the object is locked or not, but we can't help this
+ * right now.
+ */
+static int
+storeUfsDirCheckExpired(SwapDir * SD, StoreEntry * e)
+{
+    if (storeEntryLocked(e))
+       return 0;
+    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
+       return 1;
+    if (EBIT_TEST(e->flags, ENTRY_NEGCACHED) && squid_curtime >= e->expires)
+       return 1;
+
+#if HEAP_REPLACEMENT
+    /*
+     * with HEAP_REPLACEMENT we are not using the LRU reference age, the heap
+     * controls the replacement of objects.
+     */
+    return 1;
+#else
+    if (squid_curtime - e->lastref > storeUfsDirExpiredReferenceAge(SD))
+       return 1;
+    return 0;
+#endif
+}
+
+/*
+ * storeUfsDirExpiredReferenceAge
+ *
+ * The LRU age is scaled exponentially between 1 minute and
+ * Config.referenceAge , when store_swap_low < store_swap_size <
+ * store_swap_high.  This keeps store_swap_size within the low and high
+ * water marks.  If the cache is very busy then store_swap_size stays
+ * closer to the low water mark, if it is not busy, then it will stay
+ * near the high water mark.  The LRU age value can be examined on the
+ * cachemgr 'info' page.
+ */
+static time_t
+storeUfsDirExpiredReferenceAge(SwapDir * SD)
+{
+    double x;
+    double z;
+    time_t age;
+    long store_high, store_low;
+
+    store_high = (long) (((float) SD->max_size *
+           (float) Config.Swap.highWaterMark) / (float) 100);
+    store_low = (long) (((float) SD->max_size *
+           (float) Config.Swap.lowWaterMark) / (float) 100);
+    debug(81, 4) ("storeUfsDirExpiredReferenceAge: Dir %s, hi=%d, lo=%d, cur=%d\n", SD->path, store_high,
+       store_low, SD->cur_size);
+
+    x = (double) (store_high - SD->cur_size) / (store_high - store_low);
+    x = x < 0.0 ? 0.0 : x > 1.0 ? 1.0 : x;
+    z = pow((double) (Config.referenceAge / 60), x);
+    age = (time_t) (z * 60.0);
+    if (age < 60)
+       age = 60;
+    else if (age > Config.referenceAge)
+       age = Config.referenceAge;
+    return age;
+}
+#endif /* OLD_UNUSED_CODE */
index ee3c6fc752be4b24c4f667049a8b54b67e17245f..d237dcc890b58c4b1bc99e4686a41ed45cf3b74a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: squid.h,v 1.201 2000/05/03 17:15:42 adrian Exp $
+ * $Id: squid.h,v 1.202 2000/06/08 18:05:35 hno Exp $
  *
  * AUTHOR: Duane Wessels
  *
@@ -359,9 +359,6 @@ struct rusage {
 
 #include "hash.h"
 #include "rfc1035.h"
-#if HEAP_REPLACEMENT
-#include "heap.h"
-#endif
 
 #include "defines.h"
 #include "enums.h"
index 472bf2c49c4094359fa93197c4fc61580e075a13..6e1856b3e4815d5790719be0167a44f0318f0440 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store.cc,v 1.524 2000/05/28 17:00:13 wessels Exp $
+ * $Id: store.cc,v 1.525 2000/06/08 18:05:36 hno Exp $
  *
  * DEBUG: section 20    Storage Manager
  * AUTHOR: Harvest Derived
@@ -81,6 +81,8 @@ static MemObject *new_MemObject(const char *, const char *);
 static void destroy_MemObject(StoreEntry *);
 static FREE destroy_StoreEntry;
 static void storePurgeMem(StoreEntry *);
+static void storeEntryReferenced(StoreEntry *);
+static void storeEntryDereferenced(StoreEntry *);
 static int getKeyCounter(void);
 static int storeKeepInMemory(const StoreEntry *);
 static OBJH storeCheckCachableStats;
@@ -89,14 +91,6 @@ static EVH storeLateRelease;
 /*
  * local variables
  */
-#if HEAP_REPLACEMENT
-/*
- * The heap equivalent of inmem_list, inmem_heap, is in globals.c so other
- * modules can access it when updating object metadata (e.g., refcount)
- */
-#else
-static dlink_list inmem_list;
-#endif
 static Stack LateReleaseStack;
 
 #if URL_CHECKSUM_DEBUG
@@ -223,23 +217,50 @@ storePurgeMem(StoreEntry * e)
        storeRelease(e);
 }
 
-void
-storeLockObject(StoreEntry * e)
+static void
+storeEntryReferenced(StoreEntry *e)
 {
     SwapDir *SD;
 
-    if (e->swap_dirn > -1)
+    /* Notify the fs that we're referencing this object again */
+    if (e->swap_dirn > -1) {
        SD = INDEXSD(e->swap_dirn);
-    else
-       SD = NULL;
+       if (SD->refobj)
+           SD->refobj(SD, e);
+    }
+    /* Notify the memory cache that we're referencing this object again */
+    if(e->mem_obj) {
+       if (mem_policy->Referenced)
+           mem_policy->Referenced(mem_policy, e, &e->mem_obj->repl);
+    }
+}
 
+static void
+storeEntryDereferenced(StoreEntry *e)
+{
+    SwapDir *SD;
+
+    /* Notify the fs that we're not referencing this object any more */
+    if (e->swap_filen > -1) {
+        SD = INDEXSD(e->swap_dirn);
+       if (SD->unrefobj != NULL)
+           SD->unrefobj(SD, e);
+    }
+    /* Notify the memory cache that we're not referencing this object any more */
+    if(e->mem_obj) {
+       if (mem_policy->Dereferenced)
+           mem_policy->Dereferenced(mem_policy, e, &e->mem_obj->repl);
+    }
+}
+
+void
+storeLockObject(StoreEntry * e)
+{
     e->lock_count++;
     debug(20, 3) ("storeLockObject: key '%s' count=%d\n",
        storeKeyText(e->key), (int) e->lock_count);
     e->lastref = squid_curtime;
-    /* Notify the fs that we're referencing this object again */
-    if (SD != NULL && SD->refobj != NULL)
-       SD->refobj(SD, e);
+    storeEntryReferenced(e);
 }
 
 void
@@ -263,7 +284,6 @@ storeReleaseRequest(StoreEntry * e)
 int
 storeUnlockObject(StoreEntry * e)
 {
-    SwapDir *SD;
     e->lock_count--;
     debug(20, 3) ("storeUnlockObject: key '%s' count=%d\n",
        storeKeyText(e->key), e->lock_count);
@@ -272,30 +292,16 @@ storeUnlockObject(StoreEntry * e)
     if (e->store_status == STORE_PENDING)
        EBIT_SET(e->flags, RELEASE_REQUEST);
     assert(storePendingNClients(e) == 0);
-    /* Notify the fs that we're not referencing this object any more */
-    if (e->swap_filen > -1)
-       SD = INDEXSD(e->swap_dirn);
-    else
-       SD = NULL;
-    if (SD != NULL && SD->unrefobj != NULL)
-       SD->unrefobj(SD, e);
-#if HEAP_REPLACEMENT
-    storeHeapPositionUpdate(e, SD);
-#else
-#if 0
-    /* Note: From 2.4. Not sure how this relates to the unrefobj() call above */
-    storeDirLRUDelete(e);
-    storeDirLRUAdd(e);
-#endif
-#endif
     if (EBIT_TEST(e->flags, RELEASE_REQUEST))
        storeRelease(e);
     else if (storeKeepInMemory(e)) {
+       storeEntryDereferenced(e);
        storeSetMemStatus(e, IN_MEMORY);
        requestUnlink(e->mem_obj->request);
        e->mem_obj->request = NULL;
     } else {
        storePurgeMem(e);
+       storeEntryDereferenced(e);
        if (EBIT_TEST(e->flags, KEY_PRIVATE))
            debug(20, 1) ("WARNING: %s:%d: found KEY_PRIVATE\n", __FILE__, __LINE__);
     }
@@ -368,7 +374,7 @@ storeSetPublicKey(StoreEntry * e)
      * If RELEASE_REQUEST is set, then ENTRY_CACHABLE should not
      * be set, and storeSetPublicKey() should not be called.
      */
-#if HEAP_REPLACEMENT
+#if MORE_DEBUG_OUTPUT
     if (EBIT_TEST(e->flags, RELEASE_REQUEST))
        debug(20, 1) ("assertion failed: RELEASE key %s, url %s\n",
            e->key, mem->url);
@@ -698,16 +704,7 @@ storeGetMemSpace(int size)
     int released = 0;
     static time_t last_check = 0;
     int pages_needed;
-    int locked = 0;
-#if !HEAP_REPLACEMENT
-    dlink_node *head;
-    dlink_node *m;
-    dlink_node *prev = NULL;
-#else
-    heap_key age;
-    heap_key min_age = 0.0;
-    link_list *locked_entries = NULL;
-#endif
+    RemovalPurgeWalker *walker;
     if (squid_curtime == last_check)
        return;
     last_check = squid_curtime;
@@ -715,57 +712,15 @@ storeGetMemSpace(int size)
     if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max)
        return;
     debug(20, 2) ("storeGetMemSpace: Starting, need %d pages\n", pages_needed);
-#if HEAP_REPLACEMENT
-    while (heap_nodes(inmem_heap) > 0) {
-       age = heap_peepminkey(inmem_heap);
-       e = heap_extractmin(inmem_heap);
-       e->mem_obj->node = NULL;        /* no longer in the heap */
-       if (storeEntryLocked(e)) {
-           locked++;
-           debug(20, 5) ("storeGetMemSpace: locked key %s\n",
-               storeKeyText(e->key));
-           linklistPush(&locked_entries, e);
-           continue;
-       }
-       released++;
-       debug(20, 3) ("Released memory object with key %f size %d refs %d url %s\n",
-           age, e->swap_file_sz, e->refcount, e->mem_obj->url);
-       min_age = age;
+    /* XXX what to set as max_scan here? */
+    walker = mem_policy->PurgeInit(mem_policy, 100000);
+    while((e = walker->Next(walker))) {
        storePurgeMem(e);
-       if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max)
-           break;
-    }
-    /*
-     * Increase the heap age factor.
-     */
-    if (min_age > 0)
-       inmem_heap->age = min_age;
-    /*
-     * Reinsert all bumped locked entries back into heap...
-     */
-    while ((e = linklistShift(&locked_entries)))
-       e->mem_obj->node = heap_insert(inmem_heap, e);
-#else
-    head = inmem_list.head;
-    for (m = inmem_list.tail; m; m = prev) {
-       if (m == head)
-           break;
-       prev = m->prev;
-       e = m->data;
-       if (storeEntryLocked(e)) {
-           locked++;
-           dlinkDelete(m, &inmem_list);
-           dlinkAdd(e, m, &inmem_list);
-           continue;
-       }
        released++;
-       storePurgeMem(e);
        if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max)
            break;
     }
-#endif
-    debug(20, 3) ("storeGetMemSpace: released %d/%d locked %d\n",
-       released, hot_obj_count, locked);
+    walker->Done(walker);
     debug(20, 3) ("storeGetMemSpace stats:\n");
     debug(20, 3) ("  %6d HOT objects\n", hot_obj_count);
     debug(20, 3) ("  %6d were released\n", released);
@@ -787,15 +742,25 @@ storeMaintainSwapSpace(void *datanotused)
 {
     int i;
     SwapDir *SD;
+    static time_t last_warn_time = 0;
 
     /* walk each fs */
     for (i = 0; i < Config.cacheSwap.n_configured; i++) {
        /* call the maintain function .. */
-       SD = INDEXSD(i);
-       if (SD->maintainfs != NULL)
+       SD = INDEXSD(i); 
+       /* XXX FixMe: This should be done "in parallell" on the different
+        * cache_dirs, not one at a time.
+        */
+        if (SD->maintainfs != NULL)
            SD->maintainfs(SD);
     }
-
+    if (store_swap_size > Config.Swap.maxSize) {
+       if (squid_curtime - last_warn_time > 10) {
+           debug(20, 0) ("WARNING: Disk space over limit: %d KB > %d KB\n",
+               store_swap_size, Config.Swap.maxSize);
+           last_warn_time = squid_curtime;
+       }
+    }
     /* Reregister a maintain event .. */
     eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0, 1);
 }
@@ -960,11 +925,9 @@ storeInit(void)
     storeInitHashValues();
     store_table = hash_create(storeKeyHashCmp,
        store_hash_buckets, storeKeyHashHash);
+    mem_policy = createRemovalPolicy(Config.memPolicy);
     storeDigestInit();
     storeLogOpen();
-#if HEAP_REPLACEMENT
-    inmem_heap = new_heap(1000, HeapKeyGen_StoreEntry_GDSF);
-#endif
     stackInit(&LateReleaseStack);
     eventAdd("storeLateRelease", storeLateRelease, NULL, 1.0, 1);
     storeDirInit();
@@ -1148,35 +1111,24 @@ storeSetMemStatus(StoreEntry * e, int new_status)
     assert(mem != NULL);
     if (new_status == IN_MEMORY) {
        assert(mem->inmem_lo == 0);
-#if HEAP_REPLACEMENT
-       if (mem->node == NULL) {
-           if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
-               debug(20, 4) ("storeSetMemStatus: not inserting special %s\n",
-                   mem->url);
-           } else {
-               mem->node = heap_insert(inmem_heap, e);
-               debug(20, 4) ("storeSetMemStatus: inserted mem node %p\n",
-                   mem->node);
-           }
+       if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
+           debug(20, 4) ("storeSetMemStatus: not inserting special %s into policy\n",
+               mem->url);
+       } else {
+           mem_policy->Add(mem_policy, e, &mem->repl);
+           debug(20, 4) ("storeSetMemStatus: inserted mem node %s\n",
+               mem->url);
        }
-#else
-       dlinkAdd(e, &mem->lru, &inmem_list);
-#endif
        hot_obj_count++;
     } else {
-#if HEAP_REPLACEMENT
-       /*
-        * It's being removed from the memory heap; is it already gone?
-        */
-       if (mem->node) {
-           heap_delete(inmem_heap, mem->node);
-           debug(20, 4) ("storeSetMemStatus: deleted mem node %p\n",
-               mem->node);
-           mem->node = NULL;
+       if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
+               debug(20, 4) ("storeSetMemStatus: special entry %s\n",
+                   mem->url);
+       } else {
+           mem_policy->Remove(mem_policy, e, &mem->repl);
+           debug(20, 4) ("storeSetMemStatus: removed mem node %s\n",
+               mem->url);
        }
-#else
-       dlinkDelete(&mem->lru, &inmem_list);
-#endif
        hot_obj_count--;
     }
     e->mem_status = new_status;
@@ -1255,18 +1207,6 @@ storeEntryReset(StoreEntry * e)
     e->expires = e->lastmod = e->timestamp = -1;
 }
 
-#if HEAP_REPLACEMENT
-/*
- * This routine only handles memory updates these days
- */
-void
-storeHeapPositionUpdate(StoreEntry * e, SwapDir * SD)
-{
-    if (e->mem_obj && e->mem_obj->node)
-       heap_update(inmem_heap, e->mem_obj->node, e);
-}
-#endif
-
 /*
  * storeFsInit
  *
index bab541c72328bbc981331e6a4451cbed50a6d932..e90ab0ee3012e9a3657111a95e7fe3ce891bd1bb 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_digest.cc,v 1.41 2000/06/06 19:34:31 hno Exp $
+ * $Id: store_digest.cc,v 1.42 2000/06/08 18:05:36 hno Exp $
  *
  * DEBUG: section 71    Store Digest Manager
  * AUTHOR: Alex Rousskov
@@ -231,11 +231,9 @@ storeDigestAddable(const StoreEntry * e)
      * idea: skip objects that are going to be purged before the next
      * update.
      */
-#if 0                          /* This code isn't applicable anymore, we can't fix it atm either :( */
-#if !HEAP_REPLACEMENT
+#if OLD_UNUSED_CODE            /* This code isn't applicable anymore, we can't fix it atm either :( */
     if ((squid_curtime + Config.digest.rebuild_period) - e->lastref > storeExpiredReferenceAge())
        return 0;
-#endif
 #endif
     return 1;
 }
index 976e74f11a6d97449512965da370cee2269ddbba..80811197941ba002f63a8b058edd8bb8d16ab027 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_dir.cc,v 1.110 2000/05/28 22:15:42 wessels Exp $
+ * $Id: store_dir.cc,v 1.111 2000/06/08 18:05:36 hno Exp $
  *
  * DEBUG: section 47    Store Directory Routines
  * AUTHOR: Duane Wessels
@@ -36,8 +36,6 @@
 #include "squid.h"
 
 static int storeDirValidSwapDirSize(int, ssize_t);
-static void storeDirLRUWalkInitHead(SwapDir * sd);
-static void *storeDirLRUWalkNext(SwapDir * sd);
 
 void
 storeDirInit(void)
@@ -365,15 +363,14 @@ storeDirCloseSwapLogs(void)
 int
 storeDirWriteCleanLogs(int reopen)
 {
-    StoreEntry *e = NULL;
+    const StoreEntry *e = NULL;
     int n = 0;
     struct timeval start;
     double dt;
     SwapDir *sd;
+    RemovalPolicyWalker **walkers;
     int dirn;
-#if HEAP_REPLACEMENT
-    int node;
-#endif
+    int notdone = 1;
     if (store_dirs_rebuilding) {
        debug(20, 1) ("Not currently OK to rewrite swap log.\n");
        debug(20, 1) ("storeDirWriteCleanLogs: Operation aborted.\n");
@@ -382,28 +379,24 @@ storeDirWriteCleanLogs(int reopen)
     debug(20, 1) ("storeDirWriteCleanLogs: Starting...\n");
     getCurrentTime();
     start = current_time;
+    walkers = xcalloc(Config.cacheSwap.n_configured, sizeof *walkers);
     for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
        sd = &Config.cacheSwap.swapDirs[dirn];
-       if (sd->log.clean.open(sd) < 0) {
-           debug(20, 1) ("log.clean.open() failed for dir #%d\n", sd->index);
+       if (sd->log.clean.start(sd) < 0) {
+           debug(20, 1) ("log.clean.start() failed for dir #%d\n", sd->index);
            continue;
        }
-       if (NULL == sd->log.clean.write)
-           continue;
-#if HEAP_REPLACEMENT
-       if (NULL == sd->repl.heap.heap)
-           continue;
-#endif
-#if HEAP_REPLACEMENT
-       for (node = 0; node < heap_nodes(sd->repl.heap.heap); node++)
-#else
-       storeDirLRUWalkInitHead(sd);
-       while ((e = storeDirLRUWalkNext(sd)) != NULL)
-#endif
-       {
-#if HEAP_REPLACEMENT
-           e = (StoreEntry *) heap_peep(sd->repl.heap.heap, node);
-#endif
+    }
+    while(notdone) {
+       notdone = 0;
+       for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
+           sd = &Config.cacheSwap.swapDirs[dirn];
+           if (NULL == sd->log.clean.write)
+               continue;
+           e = sd->log.clean.nextentry(sd);
+           if (!e)
+               continue;
+           notdone = 1;
            if (e->swap_filen < 0)
                continue;
            if (e->swap_status != SWAPOUT_DONE)
@@ -416,14 +409,17 @@ storeDirWriteCleanLogs(int reopen)
                continue;
            if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
                continue;
-           sd->log.clean.write(e, sd);
+           sd->log.clean.write(sd, e);
            if ((++n & 0xFFFF) == 0) {
                getCurrentTime();
                debug(20, 1) ("  %7d entries written so far.\n", n);
            }
        }
-       /* Flush */
-       sd->log.clean.write(NULL, sd);
+    }
+    /* Flush */
+    for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
+       sd = &Config.cacheSwap.swapDirs[dirn];
+        sd->log.clean.done(sd);
     }
     if (reopen)
        storeDirOpenSwapLogs();
@@ -458,51 +454,20 @@ storeDirSync(void)
 void
 storeDirCallback(void)
 {
-    int i;
+    int i, j;
     SwapDir *SD;
-
-    for (i = 0; i < Config.cacheSwap.n_configured; i++) {
-       SD = &Config.cacheSwap.swapDirs[i];
-       if (SD->callback != NULL)
-           SD->callback(SD);
-    }
-}
-
-#if 0                          /* from Squid-2.4.DEVEL3 */
-void
-storeDirLRUDelete(StoreEntry * e)
-{
-    SwapDir *sd;
-    if (e->swap_filen < 0)
-       return;
-    sd = &Config.cacheSwap.swapDirs[e->swap_dirn];
-    dlinkDelete(&e->lru, &sd->repl.lru.list);
-}
-
-void
-storeDirLRUAdd(StoreEntry * e)
-{
-    SwapDir *sd;
-    if (e->swap_file_number < 0)
-       return;
-    sd = &Config.cacheSwap.swapDirs[e->swap_dirn];
-    dlinkAdd(e, &e->lru, &sd->repl.lru.list);
-}
-#endif /* from Squid-2.4.DEVEL3 */
-
-static void
-storeDirLRUWalkInitHead(SwapDir * sd)
-{
-    sd->repl.lru.walker = sd->repl.lru.list.head;
+    static int ndir = 0;
+    do {
+        j = 0;
+        for (i = 0; i < Config.cacheSwap.n_configured; i++) {
+            if (ndir >= Config.cacheSwap.n_configured)
+                ndir = ndir % Config.cacheSwap.n_configured;
+            SD = &Config.cacheSwap.swapDirs[ndir++];
+            if (NULL == SD->callback)
+                continue;
+            j += SD->callback(SD);
+        }
+    } while (j > 0);
+    ndir++;
 }
 
-static void *
-storeDirLRUWalkNext(SwapDir * sd)
-{
-    void *p;
-    if (NULL == sd->repl.lru.walker)
-       return NULL;
-    p = sd->repl.lru.walker->data;
-    sd->repl.lru.walker = sd->repl.lru.walker->next;
-    return p;
-}
index 8bccb847d6216ea5efce30c05d2d87ea259203d5..afb059305fa9ed550ada2218c1abf514fdc3169e 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_log.cc,v 1.15 2000/05/29 23:30:46 hno Exp $
+ * $Id: store_log.cc,v 1.16 2000/06/08 18:05:36 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Logging Functions
  * AUTHOR: Duane Wessels
@@ -66,12 +66,13 @@ storeLog(int tag, const StoreEntry * e)
      * Because if we print it before the swap file number, it'll break
      * the existing log format.
      */
-    logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %4d %9d %9d %9d %s %d/%d %s %s\n",
+    logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s %4d %9d %9d %9d %s %d/%d %s %s\n",
        (int) current_time.tv_sec,
        (int) current_time.tv_usec / 1000,
        storeLogTags[tag],
        e->swap_dirn,
        e->swap_filen,
+       storeKeyText(e->key),
        reply->sline.status,
        (int) reply->date,
        (int) reply->last_modified,
@@ -83,7 +84,7 @@ storeLog(int tag, const StoreEntry * e)
        mem->log_url);
     } else {
        /* no mem object. Most RELEASE cases */
-       logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X    ?         ?         ?         ? ?/? ?/? ? %s\n",
+       logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s   ?         ?         ?         ? ?/? ?/? ? ?\n",
            (int) current_time.tv_sec,
            (int) current_time.tv_usec / 1000,
            storeLogTags[tag],
index 0963c9952d2a411ff86e36f53d23c806ab3ff2f4..8ae03d871095379480756cc5b79355cb960ae1ee 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.338 2000/05/31 07:01:42 hno Exp $
+ * $Id: structs.h,v 1.339 2000/06/08 18:05:36 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -210,6 +210,11 @@ struct _delayConfig {
 
 #endif
 
+struct _RemovalPolicySettings {
+    char *type;
+    wordlist *args;
+};
+
 struct _SquidConfig {
     struct {
        size_t maxSize;
@@ -227,14 +232,8 @@ struct _SquidConfig {
        int pct;
        size_t max;
     } quickAbort;
-#if HEAP_REPLACEMENT
-    char *replPolicy;
-#else
-    /* 
-     * Note: the non-LRU policies do not use referenceAge, but we cannot
-     * remove it until we find out how to implement #else for cf_parser.c
-     */
-#endif
+    RemovalPolicySettings *replPolicy;
+    RemovalPolicySettings *memPolicy;
     time_t referenceAge;
     time_t negativeTtl;
     time_t negativeDnsTtl;
@@ -1272,6 +1271,39 @@ struct _store_client {
 };
 
 
+/* Removal policies */
+
+struct _RemovalPolicyNode {
+    void *data;
+};
+
+struct _RemovalPolicy {
+    char *_type;
+    void *_data;
+    void (*Free)(RemovalPolicy *policy);
+    void (*Add)(RemovalPolicy *policy, StoreEntry *entry, RemovalPolicyNode *node);
+    void (*Remove)(RemovalPolicy *policy, StoreEntry *entry, RemovalPolicyNode *node);
+    void (*Referenced)(RemovalPolicy *policy, const StoreEntry *entry, RemovalPolicyNode *node);
+    void (*Dereferenced)(RemovalPolicy *policy, const StoreEntry *entry, RemovalPolicyNode *node);
+    RemovalPolicyWalker *(*WalkInit)(RemovalPolicy *policy);
+    RemovalPurgeWalker *(*PurgeInit)(RemovalPolicy *policy, int max_scan);
+};
+
+struct _RemovalPolicyWalker {
+    RemovalPolicy *_policy;
+    void *_data;
+    const StoreEntry *(*Next)(RemovalPolicyWalker *walker);
+    void (*Done)(RemovalPolicyWalker *walker);
+};
+
+struct _RemovalPurgeWalker {
+    RemovalPolicy *_policy;
+    void *_data;
+    int scanned, max_scan, locked;
+    StoreEntry *(*Next)(RemovalPurgeWalker *walker);
+    void (*Done)(RemovalPurgeWalker *walker);
+};
+
 /* This structure can be freed while object is purged out from memory */
 struct _MemObject {
     method_t method;
@@ -1297,14 +1329,7 @@ struct _MemObject {
        void *data;
     } abort;
     char *log_url;
-#if HEAP_REPLACEMENT
-    /* 
-     * A MemObject knows where it is in the in-memory heap.
-     */
-    heap_node *node;
-#else
-    dlink_node lru;
-#endif
+    RemovalPolicyNode repl;
     int id;
     ssize_t object_sz;
     size_t swap_hdr_sz;
@@ -1327,12 +1352,7 @@ struct _StoreEntry {
     u_short flags;
     sdirno swap_dirn;
     sfileno swap_filen;
-    union {
-#ifdef HEAP_REPLACEMENT
-       heap_node *node;
-#endif
-       dlink_node lru;
-    } repl;
+    RemovalPolicyNode repl;
     u_short lock_count;                /* Assume < 65536! */
     mem_status_t mem_status:3;
     ping_status_t ping_status:3;
@@ -1349,17 +1369,7 @@ struct _SwapDir {
     int index;                 /* This entry's index into the swapDirs array */
     int suggest;
     ssize_t max_objsize;
-    union {
-#ifdef HEAP_REPLACEMENT
-       struct {
-           heap *heap;
-       } heap;
-#endif
-       struct {
-           dlink_list list;
-           dlink_node *walker;
-       } lru;
-    } repl;
+    RemovalPolicy *repl;
     int removals;
     int scanned;
     struct {
@@ -1392,8 +1402,10 @@ struct _SwapDir {
        STLOGCLOSE *close;
        STLOGWRITE *write;
        struct {
-           STLOGCLEANOPEN *open;
+           STLOGCLEANSTART *start;
+           STLOGCLEANNEXTENTRY *nextentry;
            STLOGCLEANWRITE *write;
+           STLOGCLEANDONE *done;
            void *state;
        } clean;
     } log;
@@ -1897,3 +1909,4 @@ struct _Logfile {
     size_t bufsz;
     off_t offset;
 };
+
index 0cc45bcba4b614ead7510aa896bd45f71405c902..e0684479afb1ce5e88a790ce822b3caafb69302f 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.103 2000/05/12 00:29:09 wessels Exp $
+ * $Id: typedefs.h,v 1.104 2000/06/08 18:05:37 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -171,6 +171,11 @@ typedef struct _link_list link_list;
 typedef struct _storefs_entry storefs_entry_t;
 typedef struct _diskd_queue diskd_queue;
 typedef struct _Logfile Logfile;
+typedef struct _RemovalPolicy RemovalPolicy;
+typedef struct _RemovalPolicyWalker RemovalPolicyWalker;
+typedef struct _RemovalPurgeWalker RemovalPurgeWalker;
+typedef struct _RemovalPolicyNode RemovalPolicyNode;
+typedef struct _RemovalPolicySettings RemovalPolicySettings;
 
 #if SQUID_SNMP
 typedef variable_list *(oid_ParseFn) (variable_list *, snint *);
@@ -238,7 +243,7 @@ typedef void STREFOBJ(SwapDir *, StoreEntry *);
 typedef void STUNREFOBJ(SwapDir *, StoreEntry *);
 typedef void STSETUP(storefs_entry_t *);
 typedef void STDONE(void);
-typedef void STCALLBACK(SwapDir *);
+typedef int STCALLBACK(SwapDir *);
 typedef void STSYNC(SwapDir *);
 
 typedef storeIOState *STOBJCREATE(SwapDir *, StoreEntry *, STFNCB *, STIOCB *, void *);
@@ -251,8 +256,10 @@ typedef void STOBJUNLINK(SwapDir *, StoreEntry *);
 typedef void STLOGOPEN(SwapDir *);
 typedef void STLOGCLOSE(SwapDir *);
 typedef void STLOGWRITE(const SwapDir *, const StoreEntry *, int);
-typedef int STLOGCLEANOPEN(SwapDir *);
-typedef void STLOGCLEANWRITE(const StoreEntry *, SwapDir *);
+typedef int STLOGCLEANSTART(SwapDir *);
+typedef const StoreEntry *STLOGCLEANNEXTENTRY(SwapDir *);
+typedef void STLOGCLEANWRITE(SwapDir *, const StoreEntry *);
+typedef void STLOGCLEANDONE(SwapDir *);
 
 /* Store dir configuration routines */
 /* SwapDir *sd, char *path ( + char *opt later when the strtok mess is gone) */
@@ -301,4 +308,5 @@ typedef unsigned int delay_id;
 typedef struct _htcpReplyData htcpReplyData;
 #endif
 
+typedef RemovalPolicy *REMOVALPOLICYCREATE(wordlist *args);
 #endif /* _TYPEDEFS_H_ */