001: // SimpleCacheSweeper.java
002: // $Id: SimpleCacheSweeper.java,v 1.21 2000/08/16 21:38:04 ylafon Exp $
003: // (c) COPYRIGHT MIT, INRIA and Keio, 1999.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.www.protocol.http.cache;
007:
008: import java.util.Enumeration;
009:
010: import java.io.PrintStream;
011:
012: public class SimpleCacheSweeper extends CacheSweeper {
013: // usual debug flag
014: private static final boolean debug = false;
015: // the default waiting times
016: private static final int WAIT_MIN = 5000;
017: private static final int WAIT_MAX = 60000;
018: // the current state
019: protected int state = STATE_CLEAN_STORED;
020: // our father
021: private CacheFilter filter = null;
022: // used to signal an action required
023: private boolean signal = false;
024: // the wating time between two sweeper calls
025: private long wait_time = 60000;
026:
027: /**
028: * Used to trigger a signal
029: */
030: public synchronized void signal() {
031: signal = true;
032: notifyAll();
033: }
034:
035: public synchronized void waitSignal() {
036: // Use to trigger cache sync to disk:
037: long sync_time = 0;
038: long gencomp_time = 0;
039: signal = false;
040: wait_time = WAIT_MIN;
041: while (!signal) {
042: // Wait for something to happen:
043: try {
044: wait(wait_time);
045: } catch (InterruptedException ex) {
046: continue;
047: }
048: // What was signaled ?
049: if (signal)
050: // Trigger a garbage collection
051: break;
052: // Update generation if needed:
053: if (debug) {
054: System.out.println("# Sweeper waited for " + wait_time);
055: }
056: // regulary check for removed files
057: try {
058: collectStored();
059: } catch (Exception ex) {
060: }
061: // Recompute our wait_time value in any case
062: CacheStore store = filter.getStore();
063: wait_time = (long) (WAIT_MAX * (1 - store
064: .getMRUGenerationRatio()))
065: / state;
066: wait_time = Math.max(WAIT_MIN, Math
067: .min(wait_time, WAIT_MAX));
068: if (debug) {
069: System.out.println("# Sweeper will wait for "
070: + wait_time);
071: System.out.println("# Sweeper sync time " + sync_time);
072: switch (state) {
073: case STATE_CLEAN_STORED:
074: System.out.println("State: STATE_CLEAN_STORED");
075: break;
076: case STATE_FORCE_CLEAN_STORED:
077: System.out
078: .println("State: STATE_FORCE_CLEAN_STORED");
079: break;
080: case STATE_CLEAN_GENERATIONS:
081: System.out
082: .println("State: STATE_CLEAN_GENERATIONS");
083: break;
084: case STATE_FORCE_CLEAN_GENERATIONS:
085: System.out
086: .println("State: STATE_FORCE_CLEAN_GENERATIONS");
087: break;
088: }
089: System.out.println(store.toString());
090: store.checkState();
091: }
092: sync_time += wait_time;
093: gencomp_time += wait_time;
094: // compact everything if possible FIXME time for that
095: if (gencomp_time >= store.getCompactGenerationDelay()) {
096: gencomp_time = 0;
097: store.compactGenerations();
098: }
099: // Sync if possible:
100: if (sync_time >= store.getSyncDelay()) {
101: sync_time = 0;
102: store.sync();
103: }
104: }
105: // Do the work:
106: signal = false;
107: }
108:
109: public void run() {
110: while (true) {
111: try {
112: waitSignal();
113: garbageCollect();
114: } catch (Exception ex) {
115: ex.printStackTrace();
116: }
117: }
118: }
119:
120: /**
121: * Run the garbage collector.
122: */
123: public void garbageCollect() {
124: long to_save;
125: switch (state) {
126: case CacheSweeper.STATE_CLEAN_STORED:
127: try {
128: collectStored();
129: } catch (Exception ex) {
130: // probably thrown due to the lack of synchronization
131: }
132: ;
133: break;
134: case CacheSweeper.STATE_FORCE_CLEAN_STORED:
135: // force the cleaning by syncrhonizing the call
136: synchronized (filter.getStore()) {
137: collectStored();
138: }
139: break;
140: case CacheSweeper.STATE_CLEAN_GENERATIONS:
141: to_save = filter.getStore().getRequiredByteNumber();
142: try {
143: // get the info from the store about bytes
144: to_save -= collectCached(to_save, true);
145: to_save -= collectCached(to_save, false);
146: // and erase them
147: collectStored();
148: } catch (Exception ex) {
149: // sync pb, don't worry about this one
150: }
151: break;
152: case CacheSweeper.STATE_FORCE_CLEAN_GENERATIONS:
153: synchronized (filter.getStore()) {
154: to_save = filter.getStore().getRequiredByteNumber();
155: // get the info from the store about bytes
156: to_save -= collectCached(to_save, true);
157: to_save -= collectCached(to_save, false);
158: // and erase them
159: collectStored();
160: }
161: break;
162: }
163: // try to upgrade the priority level according to the store
164: // usage
165: filter.getStore().updateSweeperPriority();
166: }
167:
168: /**
169: * change the state of the Sweeper
170: * @param an integer, setting the new cache state
171: */
172: protected synchronized void setState(int state) {
173: this .state = state;
174: }
175:
176: /**
177: * collect the still stored resources
178: * @param generation, the CacheGeneration to clean
179: */
180: protected void collectStored(CacheGeneration generation) {
181: Enumeration e = generation.getDeletedResources();
182: CachedResource cr;
183: while (e.hasMoreElements()) {
184: cr = (CachedResource) e.nextElement();
185: generation.deleteStored(cr);
186: }
187: }
188:
189: /**
190: * collect the still stored resources
191: * in the whole cache
192: * It will NOT block the cache during the process
193: */
194: protected void collectStored() {
195: if (debug)
196: System.out.println("*** Sweeper: collect stored");
197: CacheGeneration gen;
198: gen = (CacheGeneration) filter.getStore().getLRUGeneration();
199: while (gen != null) {
200: collectStored(gen);
201: gen = filter.getStore().getPrevGeneration(gen);
202: }
203: }
204:
205: /**
206: * collect the existing resources
207: * @param generation, the CacheGeneration to clean
208: * @param bytes, a long. The number of bytes to collect
209: * @param check, a boolean. If true, then only the stale resources
210: * will be removed
211: */
212: protected long collectCached(CacheGeneration generation,
213: long bytes, boolean check) {
214: if (bytes > 0) {
215: return generation.collectSpace(bytes, check);
216: }
217: return 0;
218: }
219:
220: /**
221: * collect the existing resources
222: * @param bytes, a long. The number of bytes to collect
223: * @param check, a boolean. If true, then only the stale resources
224: * will be removed
225: * @return a long, the number of collected bytes
226: */
227: protected long collectCached(long bytes, boolean check) {
228: CacheGeneration gen, next;
229: long collected = 0;
230: CacheStore store = filter.getStore();
231: gen = (CacheGeneration) store.getLRUGeneration();
232: while (gen != null) {
233: next = filter.getStore().getPrevGeneration(gen);
234: collected += gen.collectSpace(bytes - collected, check);
235: if (collected >= bytes) {
236: break;
237: }
238: gen = next;
239: }
240: return collected;
241: }
242:
243: /**
244: * initialize the sweeper
245: */
246: public void initialize(CacheFilter filter) {
247: this .filter = filter;
248: this .setDaemon(true);
249: this .setPriority(3);
250: this .setName("CacheSweeper");
251: }
252: }
|