1 19 package org.netbeans.mdr.persistence.btreeimpl.btreestorage; 20 21 import org.netbeans.mdr.persistence.btreeimpl.btreeindex.*; 22 import org.netbeans.mdr.persistence.*; 23 import java.io.*; 24 import java.text.*; 25 import java.util.*; 26 27 35 36 public class BtreeFileSource extends Object 37 implements BtreePageSource, FileCache.NotifyOnCommit { 38 39 55 static final int MAGIC = 123456789; 56 static final int VERSION = 1; 57 static final int NO_PAGEID = -1; 58 static final int NEXTFREE_OFFSET = FileHeader.HEADER_SIZE + 8; 59 static final int CACHE_SIZE = 5; 60 61 62 private FileCache fileCache; private int fileId; private int pageSize; 66 private EntryTypeInfo pageIdInfo; 67 private byte[] noPageId; 68 private boolean metaChanged; 69 private int nextFree; private BtreeStorage storage; 71 72 private Hashtable btreeCache; private IntrusiveList lruList; 75 private MofidGenerator gen; 76 77 private static class CacheEntry extends IntrusiveList.Member { 78 BtreePage page; 79 CachedPage fcp; int pinned; boolean needsStore; } 83 84 93 public BtreeFileSource(int fileId, FileCache fileCache, int pageSize, 94 boolean isNew, MofidGenerator mGen, BtreeStorage storage) 95 throws StorageException { 96 97 CachedPage metaFCP; 98 byte[] metadata; 99 int offset; 100 101 this.fileId = fileId; 102 this.fileCache = fileCache; 103 this.pageSize = pageSize; 104 this.storage = storage; 105 gen = mGen; 106 107 pageIdInfo = EntryTypeInfo.getEntryTypeInfo(Storage.EntryType.INT, null); 108 noPageId = pageIdInfo.toBuffer(new Integer (NO_PAGEID)); 109 btreeCache = new Hashtable(10); 110 lruList = new IntrusiveList(); 111 112 metaChanged = false; 113 114 metaFCP = fileCache.getPage(fileId, 0); 115 metadata = metaFCP.contents; 116 offset = FileHeader.HEADER_SIZE; 117 118 if (isNew) { 119 offset = Converter.writeInt(metadata, offset, MAGIC); 121 offset = Converter.writeInt(metadata, offset, VERSION); 122 nextFree = 1; 123 offset = Converter.writeInt(metadata, offset, nextFree); 124 fileCache.setWritable(metaFCP); 125 } else { 126 int magic, version; 128 magic = Converter.readInt(metadata, offset); 129 offset += 4; 130 version = Converter.readInt(metadata, offset); 131 offset += 4; 132 nextFree = Converter.readInt(metadata, offset); 133 134 if (magic != MAGIC) { 135 throw new StorageBadRequestException( 136 MessageFormat.format( 137 "Index file has bad magic number ", 138 new Object [] {new Integer (magic) } )); 139 } 140 if (version != VERSION) { 141 throw new StorageBadRequestException( 142 MessageFormat.format( 143 "Index file has incorrect version number. {0} expected, {1} found", 144 new Object [] { 145 new Integer (VERSION), 146 new Integer (version) } )); 147 } 148 } 149 150 fileCache.unpin(metaFCP); 151 152 fileCache.addNotifier(this); 153 } 154 155 public EntryTypeInfo getPageIdInfo() { 156 return new IntInfo(); 157 } 158 159 162 public void setNoPage(byte[] pageId) { 163 164 System.arraycopy(noPageId, 0, pageId, 0, pageId.length); 165 } 166 167 170 public boolean isNoPage(byte[] pageId) { 171 172 for (int i = 0; i < pageId.length; i++) { 173 if (pageId[i] != noPageId[i]) { 174 return false; 175 } 176 } 177 return true; 178 } 179 180 183 public synchronized void prepareToCommit() throws StorageException { 184 185 Enumeration entries; 186 CacheEntry entry; 187 CachedPage metaFCP; 188 189 entries = btreeCache.elements(); 190 191 while (entries.hasMoreElements()) { 192 entry = (CacheEntry) entries.nextElement(); 193 if (entry.needsStore) { 194 entry.page.store(); 195 } 196 } 197 198 199 if (metaChanged) { 200 metaFCP = fileCache.getPage(fileId, 0); 201 fileCache.setWritable(metaFCP); 202 Converter.writeInt(metaFCP.contents, NEXTFREE_OFFSET, nextFree); 203 fileCache.unpin(metaFCP); 204 } 205 metaChanged = false; 206 } 207 208 213 public BtreePage getRootPage(Btree btree) throws StorageException { 214 215 if (nextFree > 1) { 216 return getPage(pageIdInfo.toBuffer(new Integer (1)), btree); 217 } else { 218 return newPage(btree); 219 } 220 } 221 222 231 public synchronized BtreePage getPage(byte[] pageId, Btree btree) 232 throws StorageException { 233 Integer pageNum; 234 CacheEntry entry; 235 236 pageNum = (Integer ) pageIdInfo.fromBuffer(pageId); 237 entry = (CacheEntry) btreeCache.get(pageNum); 238 if (entry == null) { 239 entry = addToBtreeCache(pageId, pageNum, false, btree); 240 } else if (entry.pinned == 0) { 241 lruList.remove((IntrusiveList.Member)entry); 242 } 243 entry.pinned++; 244 return entry.page; 245 } 246 247 private CacheEntry addToBtreeCache(byte[] pageId, 248 Integer pageNum, boolean isNew, Btree btree) 249 throws StorageException { 250 251 CacheEntry entry; 252 253 entry = getCacheEntry(); 254 entry.fcp = fileCache.getPage(fileId, pageNum.intValue()); 255 if (entry.page == null) { 256 entry.page = btree.pageFactory(); 257 } else { 258 entry.page.uninit(); 259 } 260 entry.page.init(btree, pageId, entry.fcp.contents, isNew); 261 btreeCache.put(pageNum, entry); 262 return entry; 263 } 264 265 private CacheEntry getCacheEntry() throws StorageException { 266 267 CacheEntry entry = null; 268 Integer pageNum; 269 270 if (btreeCache.size() >= CACHE_SIZE) { 271 272 entry = (CacheEntry) lruList.removeFirst(); 273 } 274 if (entry != null) { 275 pageNum = (Integer ) pageIdInfo.fromBuffer(entry.page.pageId); 276 btreeCache.remove(pageNum); 277 if (entry.needsStore) { 278 entry.page.store(); 279 entry.needsStore = false; 280 } 281 fileCache.unpin(entry.fcp); 282 } else { 283 entry = new CacheEntry(); 284 } 285 return entry; 286 } 287 288 295 public synchronized BtreePage newPage(Btree btree) throws StorageException { 296 297 CacheEntry entry; 298 Integer pageNum; 299 byte[] pageId; 300 301 pageNum = new Integer (nextFree); 302 nextFree++; 303 metaChanged = true; 304 pageId = pageIdInfo.toBuffer(pageNum); 305 entry = addToBtreeCache(pageId, pageNum, true, btree); 306 entry.pinned++; 307 dirtyPage(entry.page); 308 return entry.page; 309 } 310 311 315 public synchronized BigKeyPage newBigKeyPage(Btree btree) 316 throws StorageException { 317 CacheEntry entry; 318 Integer pageNum; 319 byte[] pageId; 320 321 pageNum = new Integer (nextFree); 322 nextFree++; 323 metaChanged = true; 324 pageId = pageIdInfo.toBuffer(pageNum); 325 entry = new CacheEntry(); 326 entry.fcp = fileCache.getPage(fileId, pageNum.intValue()); 327 entry.page = new BigKeyPage(); 328 entry.page.init(btree, pageId, entry.fcp.contents, true); 329 btreeCache.put(pageNum, entry); 330 entry.pinned++; 331 dirtyPage(entry.page); 332 return (BigKeyPage)entry.page; 333 } 334 335 343 public synchronized void unpinPage(BtreePage page) { 344 345 CacheEntry entry; 346 347 entry = (CacheEntry) btreeCache.get(pageIdInfo.fromBuffer(page.pageId)); 348 if (--entry.pinned == 0) { 349 lruList.addLast((IntrusiveList.Member)entry); 350 } 351 } 352 353 public synchronized void unpinPage(BigKeyPage page) throws StorageException { 354 355 CacheEntry entry; 356 Integer pageNum; 357 358 entry = (CacheEntry) btreeCache.get(pageIdInfo.fromBuffer(page.pageId)); 359 if (--entry.pinned == 0) { 360 pageNum = (Integer ) pageIdInfo.fromBuffer(entry.page.pageId); 361 btreeCache.remove(pageNum); 362 if (entry.needsStore) { 363 entry.page.store(); 364 entry.needsStore = false; 365 } 366 fileCache.unpin(entry.fcp); 367 } 368 } 369 370 376 public synchronized void dirtyPage(BtreePage page) throws StorageException { 377 378 CacheEntry entry; 379 380 entry = (CacheEntry) btreeCache.get(pageIdInfo.fromBuffer(page.pageId)); 381 entry.needsStore = true; 382 fileCache.setWritable(entry.fcp); 383 } 384 385 public int getPageIdLength() { 386 return pageIdInfo.getLength(); 387 } 388 389 public int getPageSize() { 390 return pageSize; 391 } 392 393 public long getNextMofid() { 394 if (gen != null) 395 return gen.getNextMofid(); 396 throw new RuntimeException ("Not implemented"); 397 } 398 399 public String getMofidPrefix() { 400 if (gen != null) 401 return gen.getMofidPrefix(); 402 throw new RuntimeException ("Not implemented"); 403 } 404 405 public BtreeStorage getStorage () { 406 return storage; 407 } 408 409 } 410 | Popular Tags |