KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > persist > Cache


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb.persist;
33
34 import java.io.IOException JavaDoc;
35
36 import org.hsqldb.Trace;
37 import org.hsqldb.lib.Iterator;
38 import org.hsqldb.lib.ObjectComparator;
39 import org.hsqldb.lib.Sort;
40 import org.hsqldb.lib.StopWatch;
41 import org.hsqldb.store.ObjectCacheHashMap;
42
43 /**
44  * New implementation of row caching for CACHED tables.<p>
45  *
46  * Manages memory for the cache map and its contents based on least recently
47  * used clearup.<p>
48  * Also provides services for selecting rows to be saved and passing them
49  * to DataFileCache.<p>
50  *
51  * @author fredt@users
52  * @version 1.8.0
53  */

54 public class Cache {
55
56     final DataFileCache dataFileCache;
57     private int capacity; // number of Rows
58
private long bytesCapacity; // number of bytes
59
private final CachedObjectComparator rowComparator;
60
61 //
62
private CachedObject[] rowTable;
63
64 //
65
private final ObjectCacheHashMap cacheMap;
66     long cacheBytesLength;
67
68     // for testing
69
StopWatch saveAllTimer = new StopWatch(false);
70     StopWatch makeRowTimer = new StopWatch(false);
71     StopWatch sortTimer = new StopWatch(false);
72     int makeRowCount = 0;
73     int saveRowCount = 0;
74
75     Cache(DataFileCache dfc) {
76
77         dataFileCache = dfc;
78         capacity = dfc.capacity();
79         bytesCapacity = dfc.bytesCapacity();
80         rowComparator = new CachedObjectComparator();
81         rowTable = new CachedObject[capacity];
82         cacheMap = new ObjectCacheHashMap(capacity);
83         cacheBytesLength = 0;
84     }
85
86     /**
87      * Structural initialisations take place here. This allows the Cache to
88      * be resized while the database is in operation.
89      */

90     void init(int capacity, long bytesCapacity) {}
91
92     int size() {
93         return cacheMap.size();
94     }
95
96     long getTotalCachedBlockSize() {
97         return cacheBytesLength;
98     }
99
100     /**
101      * Returns a row if in memory cache.
102      */

103     synchronized CachedObject get(int pos) {
104         return (CachedObject) cacheMap.get(pos);
105     }
106
107     /**
108      * Adds a row to the cache.
109      */

110     synchronized void put(int key,
111                                  CachedObject row) throws IOException JavaDoc {
112
113         int storageSize = row.getStorageSize();
114
115         if (cacheMap.size() >= capacity
116                 || storageSize + cacheBytesLength > bytesCapacity) {
117             cleanUp();
118         }
119
120         cacheMap.put(key, row);
121
122         cacheBytesLength += storageSize;
123     }
124
125     /**
126      * Removes an object from memory cache. Does not release the file storage.
127      */

128     synchronized CachedObject release(int i) {
129
130         CachedObject r = (CachedObject) cacheMap.remove(i);
131
132         if (r == null) {
133             return null;
134         }
135
136         cacheBytesLength -= r.getStorageSize();
137
138         return r;
139     }
140
141     /**
142      * Reduces the number of rows held in this Cache object. <p>
143      *
144      * Cleanup is done by checking the accessCount of the Rows and removing
145      * the rows with the lowest access count.
146      *
147      * Index operations require that up to 5 recently accessed rows remain
148      * in the cache.
149      *
150      */

151     private synchronized void cleanUp() throws IOException JavaDoc {
152
153         int removeCount = cacheMap.size() / 2;
154         int accessTarget = cacheMap.getAccessCountCeiling(removeCount,
155             removeCount / 8);
156         ObjectCacheHashMap.ObjectCacheIterator it = cacheMap.iterator();
157         int savecount = 0;
158
159         for (; it.hasNext(); ) {
160             CachedObject r = (CachedObject) it.next();
161
162             if (it.getAccessCount() <= accessTarget) {
163                 if (!r.isKeepInMemory()) {
164                     if (r.hasChanged()) {
165                         rowTable[savecount++] = r;
166                     }
167
168                     it.remove();
169
170                     cacheBytesLength -= r.getStorageSize();
171                 }
172             }
173         }
174
175         cacheMap.setAccessCountFloor(accessTarget);
176         saveRows(savecount);
177     }
178
179     private synchronized void saveRows(int count) throws IOException JavaDoc {
180
181         if (count == 0) {
182             return;
183         }
184
185         rowComparator.setType(rowComparator.COMPARE_POSITION);
186         sortTimer.start();
187         Sort.sort(rowTable, rowComparator, 0, count - 1);
188         sortTimer.stop();
189         saveAllTimer.start();
190         dataFileCache.saveRows(rowTable, 0, count);
191
192         saveRowCount += count;
193
194         /*
195                 // not necessary if the full storage size of each object is written out
196                 try {
197                     dataFile.file.seek(fileFreePosition);
198                 } catch (IOException e){}
199         */

200         saveAllTimer.stop();
201     }
202
203     /**
204      * Writes out all modified cached Rows.
205      */

206     synchronized void saveAll() throws IOException JavaDoc {
207
208         Iterator it = cacheMap.iterator();
209         int savecount = 0;
210
211         for (; it.hasNext(); ) {
212             CachedObject r = (CachedObject) it.next();
213
214             if (r.hasChanged()) {
215                 rowTable[savecount++] = r;
216             }
217         }
218
219         saveRows(savecount);
220         Trace.printSystemOut(
221             saveAllTimer.elapsedTimeToMessage(
222                 "Cache.saveRow() total row save time"));
223         Trace.printSystemOut("Cache.saveRow() total row save count = "
224                              + saveRowCount);
225         Trace.printSystemOut(
226             makeRowTimer.elapsedTimeToMessage(
227                 "Cache.makeRow() total row load time"));
228         Trace.printSystemOut("Cache.makeRow() total row load count = "
229                              + makeRowCount);
230         Trace.printSystemOut(
231             sortTimer.elapsedTimeToMessage("Cache.sort() total time"));
232     }
233
234     /**
235      * clears out the memory cache
236      */

237     synchronized void clear() {
238
239         cacheMap.clear();
240
241         cacheBytesLength = 0;
242     }
243
244     static class CachedObjectComparator implements ObjectComparator {
245
246         static final int COMPARE_LAST_ACCESS = 0;
247         static final int COMPARE_POSITION = 1;
248         static final int COMPARE_SIZE = 2;
249         private int compareType;
250
251         CachedObjectComparator() {}
252
253         void setType(int type) {
254             compareType = type;
255         }
256
257         public int compare(Object JavaDoc a, Object JavaDoc b) {
258
259             switch (compareType) {
260
261                 case COMPARE_POSITION :
262                     return ((CachedObject) a).getPos()
263                            - ((CachedObject) b).getPos();
264
265                 case COMPARE_SIZE :
266                     return ((CachedObject) a).getStorageSize()
267                            - ((CachedObject) b).getStorageSize();
268
269                 default :
270                     return 0;
271             }
272         }
273     }
274 }
275
Popular Tags