KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > sql > file > Cache


1 package com.quadcap.sql.file;
2
3 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved.
4  *
5  * This software is distributed under the Quadcap Free Software License.
6  * This software may be used or modified for any purpose, personal or
7  * commercial. Open Source redistributions are permitted. Commercial
8  * redistribution of larger works derived from, or works which bundle
9  * this software requires a "Commercial Redistribution License"; see
10  * http://www.quadcap.com/purchase.
11  *
12  * Redistributions qualify as "Open Source" under one of the following terms:
13  *
14  * Redistributions are made at no charge beyond the reasonable cost of
15  * materials and delivery.
16  *
17  * Redistributions are accompanied by a copy of the Source Code or by an
18  * irrevocable offer to provide a copy of the Source Code for up to three
19  * years at the cost of materials and delivery. Such redistributions
20  * must allow further use, modification, and redistribution of the Source
21  * Code under substantially the same terms as this license.
22  *
23  * Redistributions of source code must retain the copyright notices as they
24  * appear in each source code file, these license terms, and the
25  * disclaimer/limitation of liability set forth as paragraph 6 below.
26  *
27  * Redistributions in binary form must reproduce this Copyright Notice,
28  * these license terms, and the disclaimer/limitation of liability set
29  * forth as paragraph 6 below, in the documentation and/or other materials
30  * provided with the distribution.
31  *
32  * The Software is provided on an "AS IS" basis. No warranty is
33  * provided that the Software is free of defects, or fit for a
34  * particular purpose.
35  *
36  * Limitation of Liability. Quadcap Software shall not be liable
37  * for any damages suffered by the Licensee or any third party resulting
38  * from use of the Software.
39  */

40
41 import java.io.IOException JavaDoc;
42 import java.io.PrintWriter JavaDoc;
43
44 import java.util.Enumeration JavaDoc;
45 import java.util.Iterator JavaDoc;
46 import java.util.Hashtable JavaDoc;
47
48 import com.quadcap.util.Debug;
49 import com.quadcap.util.DList;
50 import com.quadcap.util.DListItem;
51 import com.quadcap.util.ListException;
52
53 import com.quadcap.util.collections.LongMap;
54
55 /**
56  * This class manages a number of buffers on an underlying store.
57  * <p>
58  *
59  * What about write-through policies?
60  *
61  * @author Stan Bailes
62  */

63 public abstract class Cache {
64     Object JavaDoc store;
65     Object JavaDoc lock;
66     int size;
67     boolean readOnly;
68
69     /**
70      * Map long -> Cacheable
71      */

72     LongMap t;
73
74     /**
75      * LRU list of free cache items
76      */

77     DList lru = new DList();
78
79     /**
80      * Initialize the cache.
81      *
82      * @param s the underlying store
83      * @param size the size of the cache
84      */

85     public void init(Object JavaDoc store, int size) {
86     this.store = store;
87     this.size = size;
88     if (this.lock == null) this.lock = this;
89     lru.resize(size);
90     t = new LongMap(size);
91     }
92
93     /**
94      * Am I read only?
95      */

96     public boolean isReadOnly() { return readOnly; }
97
98     /**
99      * Set the 'read only' flag
100      */

101     public void setReadOnly(boolean v) { this.readOnly = v; }
102
103     /**
104      * Specify the lock-object to be used to synchronize access to the
105      * cache. If the lock isn't specified, it defaults to the cache
106      * object itself.
107      *
108      * @param lock the lock object
109      */

110     public void setLock(Object JavaDoc lock) {
111     this.lock = lock;
112     }
113
114     /**
115      * Search the cache for the specified key and return the associated
116      * cache item if one was found. Otherwise, find a free cache item
117      * and initialize it from the underlying store.
118      *
119      * @param key the search key
120      * @return the cache item associated with the specified key.
121      */

122     public Cacheable getCacheable(long key) throws IOException JavaDoc {
123     synchronized (lock) {
124         // ---- check the cache first.
125
Cacheable c = (Cacheable)t.get(key);
126         if (c == null) {
127         // ---- if not in the cache, find a free cache slot and
128
// ---- fill it with this object.
129
c = getCacheable();
130         c.init(store, key);
131         c.setReadOnly(readOnly);
132         t.put(key, c);
133         }
134
135         // ---- move this object to the front of the LRU list.
136
try {
137         lru.moveFront(c.getDListItem());
138         } catch (ListException e) {
139                 //#ifdef DEBUG
140
Debug.print(e);
141                 //#endif
142
}
143         c.incrRefCount();
144             if (lru.size() != size) throw new RuntimeException JavaDoc("cache size!");
145         //checkCache();
146
return c;
147     }
148     }
149
150     /**
151      * Get the specified object from the cache, if available; from the
152      * underlying store if not. In any case, the object (if found)
153      * should be in the cache after this call.<p>
154      *
155      * If the object isn't in the cache <b>OR</b> the underlying store,
156      * this method should return null, and the contents of both the cache
157      * and the underlying store should remain unchanged.<p>
158      *
159      * <b>This implementation doesn't change the underlying store, but
160      * the cache ends up holding a CacheItem with a null data component.</b>
161      * @param key the search key
162      * @param return the data associated with the key
163      */

164     public Object JavaDoc get(int key) throws IOException JavaDoc {
165     Object JavaDoc data = null;
166     synchronized (lock) {
167         Cacheable c = getCacheable(key);
168         try {
169         data = c.getData();
170         } finally {
171         c.decrRefCount();
172         }
173     }
174     return data;
175     }
176
177     /**
178      * Store the object in the cache. The object will be marked <i>dirty</i>,
179      * and will eventually be written back to the underlying store.
180      */

181     public void put(int key, Object JavaDoc val) throws IOException JavaDoc {
182     synchronized (lock) {
183         Cacheable c = getCacheable(key);
184         try {
185         c.setData(val);
186         } finally {
187         c.decrRefCount();
188         }
189     }
190     }
191
192     /**
193      * Factory to create an empty cache slot. Only a fixed number of
194      * cache slots should be created, and they should then be recycled,
195      * never destroyed.
196      */

197     abstract public Cacheable makeCacheable();
198
199     /**
200      * Find a free cache slot. If necessary, seize an existing cache
201      * slot, with preference for the "least recently used" item.
202      * This function should only be called if the lock on the cache is
203      * held by this thread.
204      */

205     private final Cacheable getCacheable() throws IOException JavaDoc {
206     Cacheable c = null;
207     DListItem d = lru.tail();
208         
209     while (d != null) {
210         c = (Cacheable)d.obj;
211         if (c != null && c.getRefCount() > 0) {
212         if (d == lru.head()) {
213             throw new RuntimeException JavaDoc("no free cache item: cache size = " + lru.size() + "(" + size + ")");
214         }
215         d = d.prev;
216         } else {
217         break; // 'c' contains the Cacheable we're looking for
218
}
219     }
220
221     if (c == null) {
222         d.obj = c = makeCacheable();
223         c.setDListItem(d);
224     } else {
225         long key = c.getKey();
226             t.remove(key);
227         if (c.isDirty()) c.flush();
228     }
229     return c;
230     }
231
232     /**
233      * Flush all modified items back to the underlying store.
234      */

235     public void flush() throws IOException JavaDoc {
236     synchronized (lock) {
237         boolean started = false;
238         for (DListItem d = lru.head(); !started || d != lru.head();
239          d = d.next) {
240         started = true;
241         Cacheable c = (Cacheable)d.obj;
242         if (c != null) {
243             c.flush();
244         }
245         }
246     }
247     }
248
249     public void revert() {
250         synchronized (lock) {
251             lru = new DList();
252             init(store, size);
253         }
254     }
255
256     public void show(PrintWriter JavaDoc os) {
257     synchronized (lock) {
258         lru.show(os, "\n");
259     }
260     }
261 }
262
Popular Tags