View Javadoc
1 /* Reattore HTTP Server 2 3 Copyright (C) 2002 Michael Hope <michaelh@juju.net.nz> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 19 $Id: CachingInterceptor.java,v 1.8 2003/03/05 04:31:57 michaelh Exp $ 20 */ 21 22 package juju.reattore.server.intercept.impl; 23 24 import java.util.*; 25 import java.io.*; 26 27 import juju.reattore.protocol.http.*; 28 import juju.reattore.server.intercept.Interceptor; 29 import juju.reattore.util.GaugeStat; 30 import juju.reattore.util.CounterStat; 31 import juju.reattore.io.*; 32 33 /*** Interceptor that may cache the response from a lower level 34 interceptor. 35 36 @see Cache 37 @see CachableSource 38 39 @tag cache 40 @group Interceptor 41 @children Interceptor 42 43 @todo Lacks tests. 44 */ 45 public class CachingInterceptor 46 implements Interceptor, Cache { 47 48 private static GaugeStat allocStat = new GaugeStat(CachingInterceptor.class, "Alloc"); 49 private static CounterStat hitsStat = new CounterStat(CachingInterceptor.class, "Hits"); 50 private static CounterStat missesStat = new CounterStat(CachingInterceptor.class, "Misses"); 51 52 /*** Request path to List of CachableSource */ 53 private final Map cache = new HashMap(); 54 /*** CachableSource to List of CachableSource */ 55 private final Map outstanding = new HashMap(); 56 57 private Interceptor child; 58 59 /*** Set the child to cache. 60 61 @param child The child tree to wrap. 62 */ 63 public void addChild(Interceptor child) { 64 this.child = child; 65 } 66 67 private List getRow(String req) { 68 List li; 69 70 if ((li = (List)cache.get(req)) == null) { 71 li = new LinkedList(); 72 cache.put(req, li); 73 } 74 75 return li; 76 } 77 78 private CachableSource tryGet(String req) { 79 /* Look it up in the cache */ 80 List li = getRow(req); 81 82 if (li.size() > 0) { 83 CachableSource ret = (CachableSource)li.remove(0); 84 if (ret.isExpired()) { 85 ret.release(); 86 allocStat.dec(); 87 88 return null; 89 } 90 else { 91 /* Have one in the cache. Use it. */ 92 ret.rewind(); 93 return ret; 94 } 95 } 96 else { 97 return null; 98 } 99 } 100 101 /*** @see Cache */ 102 public boolean onClose(CachableSource so) { 103 List li = (List)outstanding.get(so); 104 105 li.add(so); 106 107 return false; 108 } 109 110 private boolean subProcess(HttpRequest req, HttpResponse resp) { 111 if (child.process(req, resp)) { 112 /* Child served it - perhaps cache */ 113 if (resp.getStatus() == HttpResponse.SC_OK) { 114 115 CachableSource source = (CachableSource)resp.getBody(); 116 source.setCacheCallback(this); 117 outstanding.put(source, getRow(req.getPath())); 118 allocStat.inc(); 119 120 return true; 121 } 122 else { 123 return true; 124 } 125 } 126 else { 127 return false; 128 } 129 } 130 131 /*** @see Interceptor */ 132 public boolean process(HttpRequest req, HttpResponse resp) { 133 String path = req.getPath(); 134 135 List row = getRow(path); 136 CachableSource source; 137 138 if ((source = tryGet(path)) != null) { 139 140 resp.setBody((ByteSource)source); 141 resp.setStatus(HttpResponse.SC_OK); 142 143 hitsStat.inc(); 144 return true; 145 } 146 else { 147 /* Not in the cache - ask the child and cache. */ 148 missesStat.inc(); 149 return subProcess(req, resp); 150 } 151 } 152 }

This page was automatically generated by Maven