1 18 package net.sf.mybatchfwk.history; 19 20 import java.io.File ; 21 import java.io.IOException ; 22 import java.io.RandomAccessFile ; 23 24 31 public class KeysFileIndexer { 32 33 36 private RandomAccessFile reader; 37 38 41 static final int DEFAULT_INITIAL_CAPACITY = 16; 42 43 48 static final int MAXIMUM_CAPACITY = 1 << 30; 49 50 53 static final float DEFAULT_LOAD_FACTOR = 0.75f; 54 55 58 transient Entry[] table; 59 60 63 transient int size; 64 65 69 int threshold; 70 71 76 final float loadFactor; 77 78 85 transient volatile int modCount; 86 87 92 public KeysFileIndexer(File keysFile, String mode) throws IOException { 93 94 this.loadFactor = DEFAULT_LOAD_FACTOR; 95 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); 96 table = new Entry[DEFAULT_INITIAL_CAPACITY]; 97 98 reader = new RandomAccessFile (keysFile, mode); 99 buildIndex(); 100 } 101 102 106 protected void buildIndex() throws IOException { 107 String key = null; 108 long pointer = 0; 109 while ((key = reader.readLine()) != null) { 110 if (key.length() == 0) { 111 pointer = reader.getFilePointer(); 112 continue; 113 } 114 115 putKey(pointer, key); 116 117 pointer = reader.getFilePointer(); 118 } 119 } 120 121 125 public void closeReader() throws IOException { 126 reader.close(); 127 } 128 129 139 static int hash(Object x) { 140 int h = x.hashCode(); 141 142 h += ~(h << 9); 143 h ^= (h >>> 14); 144 h += (h << 4); 145 h ^= (h >>> 10); 146 return h; 147 } 148 149 152 static int indexFor(int h, int length) { 153 return h & (length-1); 154 } 155 156 161 public int size() { 162 return size; 163 } 164 165 170 public boolean isEmpty() { 171 return size == 0; 172 } 173 174 179 public void addKey(String key) throws IOException { 180 reader.seek(reader.length()); 181 long pointer = reader.getFilePointer(); 182 reader.write(key.getBytes()); 183 reader.write("\n".getBytes()); 184 putKey(pointer, key); 185 } 186 187 192 protected void putKey(long pointer, String key) { 193 int hash = hash(key); 194 int i = indexFor(hash, table.length); 195 196 for (Entry e = table[i]; e != null; e = e.next) { 197 if (e.hash == hash && (pointer == e.pointer)) { 198 return; 199 } 200 } 201 202 modCount++; 203 addEntry(hash, pointer, i); 204 return; 205 } 206 207 216 public boolean containsKey(String key) throws IOException { 217 int hash = hash(key); 218 int i = indexFor(hash, table.length); 219 Entry e = table[i]; 220 while (e != null) { 221 if (e.hash == hash) { 222 reader.seek(e.pointer); 223 if (key.equals(reader.readLine())) { 224 return true; 225 } 226 } 227 e = e.next; 228 } 229 return false; 230 } 231 232 246 void resize(int newCapacity) { 247 Entry[] oldTable = table; 248 int oldCapacity = oldTable.length; 249 if (oldCapacity == MAXIMUM_CAPACITY) { 250 threshold = Integer.MAX_VALUE; 251 return; 252 } 253 254 Entry[] newTable = new Entry[newCapacity]; 255 transfer(newTable); 256 table = newTable; 257 threshold = (int)(newCapacity * loadFactor); 258 } 259 260 263 void transfer(Entry[] newTable) { 264 Entry[] src = table; 265 int newCapacity = newTable.length; 266 for (int j = 0; j < src.length; j++) { 267 Entry e = src[j]; 268 if (e != null) { 269 src[j] = null; 270 do { 271 Entry next = e.next; 272 int i = indexFor(e.hash, newCapacity); 273 e.next = newTable[i]; 274 newTable[i] = e; 275 e = next; 276 } while (e != null); 277 } 278 } 279 } 280 281 284 static class Entry { 285 final int hash; 286 final long pointer; 287 Entry next; 288 289 292 Entry(int hash, long pointer, Entry next) { 293 this.next = next; 294 this.pointer = pointer; 295 this.hash = hash; 296 } 297 298 public long getPointer() { 299 return pointer; 300 } 301 } 302 303 310 void addEntry(int hash, long pointer, int bucketIndex) { 311 Entry e = table[bucketIndex]; 312 table[bucketIndex] = new Entry(hash, pointer, e); 313 if (size++ >= threshold) 314 resize(2 * table.length); 315 } 316 } 317 | Popular Tags |