KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > jdbc > RowCache


1 /**
2  * com.mckoi.database.jdbc.RowCache 03 Aug 2000
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database.jdbc;
26
27 import com.mckoi.util.Cache;
28 import com.mckoi.database.global.ObjectTransfer;
29 import java.util.Vector JavaDoc;
30 import java.io.*;
31 import java.sql.SQLException JavaDoc;
32
33 /**
34  * A Cache that stores rows retrieved from the server in result set's. This
35  * provides various mechanisms for determining the best rows to pick out that
36  * haven't been cached, etc.
37  *
38  * @author Tobias Downer
39  */

40
41 final class RowCache {
42
43   /**
44    * The actual cache that stores the rows.
45    */

46   private Cache row_cache;
47
48   /**
49    * Constructs the cache.
50    *
51    * @param cache_size the number of elements in the row cache.
52    * @param max_size the maximum size of the combined total of all items in
53    * the cache.
54    */

55   RowCache(int cache_size, int max_size) {
56     row_cache = new Cache(cache_size, cache_size, 20);
57   }
58
59   /**
60    * Requests a block of parts. If the block can be completely retrieved from
61    * the cache then it is done so. Otherwise, it forwards the request for the
62    * rows onto the connection object.
63    */

64   synchronized Vector JavaDoc getResultPart(Vector JavaDoc result_block,
65          MConnection connection, int result_id, int row_index, int row_count,
66          int col_count, int total_row_count) throws IOException, SQLException JavaDoc {
67
68     // What was requested....
69
int orig_row_index = row_index;
70     int orig_row_count = row_count;
71
72     Vector JavaDoc rows = new Vector JavaDoc();
73
74     // The top row that isn't found in the cache.
75
boolean found_notcached = false;
76     // Look for the top row in the block that hasn't been cached
77
for (int r = 0; r < row_count && !found_notcached; ++r) {
78       int da_row = row_index + r;
79       // Is the row in the cache?
80
RowRef row_ref = new RowRef(result_id, da_row);
81       // Not in cache so mark this as top row not in cache...
82
CachedRow row = (CachedRow) row_cache.get(row_ref);
83       if (row == null) {
84         row_index = da_row;
85         if (row_index + row_count > total_row_count) {
86           row_count = total_row_count - row_index;
87         }
88         found_notcached = true;
89       }
90       else {
91         rows.addElement(row);
92       }
93     }
94
95     Vector JavaDoc rows2 = new Vector JavaDoc();
96     if (found_notcached) {
97
98       // Now work up from the bottom and find row that isn't in cache....
99
found_notcached = false;
100       // Look for the bottom row in the block that hasn't been cached
101
for (int r = row_count - 1; r >= 0 && !found_notcached; --r) {
102         int da_row = row_index + r;
103         // Is the row in the cache?
104
RowRef row_ref = new RowRef(result_id, da_row);
105         // Not in cache so mark this as top row not in cache...
106
CachedRow row = (CachedRow) row_cache.get(row_ref);
107         if (row == null) {
108           if (row_index == orig_row_index) {
109             row_index = row_index - (row_count - (r + 1));
110             if (row_index < 0) {
111               row_count = row_count + row_index;
112               row_index = 0;
113             }
114           }
115           else {
116             row_count = r + 1;
117           }
118           found_notcached = true;
119         }
120         else {
121           rows2.insertElementAt(row, 0);
122         }
123       }
124
125     }
126
127     // Some of it not in the cache...
128
if (found_notcached) {
129 // System.out.println("REQUESTING: " + row_index + " - " + row_count);
130
// Request a part of a result from the server (blocks)
131
ResultPart block = connection.requestResultPart(result_id,
132                                                       row_index, row_count);
133
134       int block_index = 0;
135       for (int r = 0; r < row_count; ++r) {
136         Object JavaDoc[] arr = new Object JavaDoc[col_count];
137         int da_row = (row_index + r);
138         int col_size = 0;
139         for (int c = 0; c < col_count; ++c) {
140           Object JavaDoc ob = block.elementAt(block_index);
141           ++block_index;
142           arr[c] = ob;
143           col_size += ObjectTransfer.size(ob);
144         }
145
146         CachedRow cached_row = new CachedRow();
147         cached_row.row = da_row;
148         cached_row.row_data = arr;
149
150         // Don't cache if it's over a certain size,
151
if (col_size <= 3200) {
152           row_cache.put(new RowRef(result_id, da_row), cached_row);
153         }
154         rows.addElement(cached_row);
155       }
156
157     }
158
159     // At this point, the cached rows should be completely in the cache so
160
// retrieve it from the cache.
161
result_block.removeAllElements();
162     int low = orig_row_index;
163     int high = orig_row_index + orig_row_count;
164     for (int r = 0; r < rows.size(); ++r) {
165       CachedRow row = (CachedRow) rows.elementAt(r);
166       // Put into the result block
167
if (row.row >= low && row.row < high) {
168         for (int c = 0; c < col_count; ++c) {
169           result_block.addElement(row.row_data[c]);
170         }
171       }
172     }
173     for (int r = 0; r < rows2.size(); ++r) {
174       CachedRow row = (CachedRow) rows2.elementAt(r);
175       // Put into the result block
176
if (row.row >= low && row.row < high) {
177         for (int c = 0; c < col_count; ++c) {
178           result_block.addElement(row.row_data[c]);
179         }
180       }
181     }
182
183     // And return the result (phew!)
184
return result_block;
185   }
186
187   /**
188    * Flushes the complete contents of the cache.
189    */

190   synchronized void clear() {
191     row_cache.removeAll();
192   }
193
194
195
196
197
198   // ---------- Inner classes ----------
199

200   /**
201    * Used for the hash key in the cache.
202    */

203   private final static class RowRef {
204     int table_id;
205     int row;
206
207     RowRef(int table_id, int row) {
208       this.table_id = table_id;
209       this.row = row;
210     }
211
212     public int hashCode() {
213       return (int) table_id + (row * 35331);
214     }
215
216     public boolean equals(Object JavaDoc ob) {
217       RowRef dest = (RowRef) ob;
218       return (row == dest.row && table_id == dest.table_id);
219     }
220   }
221
222   /**
223    * A cached row.
224    */

225   private final static class CachedRow {
226     int row;
227     Object JavaDoc[] row_data;
228   }
229
230 }
231
Popular Tags