1 8 package org.ozoneDB.core.storage.gammaStore; 9 10 import java.io.ByteArrayInputStream ; 11 import java.io.IOException ; 12 import java.io.ObjectInputStream ; 13 import java.util.logging.Level ; 14 import java.util.logging.Logger ; 15 import org.ozoneDB.OzoneInternalException; 16 import org.ozoneDB.core.storage.Cache; 17 18 31 public abstract class IndexNode implements Storable { 32 33 private static final long serialVersionUID = 0L; 34 35 protected static final Logger log = Logger.getLogger(IndexNode.class.getName()); 36 37 static { 38 } 40 41 44 public static final long LONGNULL = Long.MIN_VALUE; 45 46 public static final long MINOBJECTID = Long.MIN_VALUE + 1; 47 48 public static final long MAXOBJECTID = Long.MAX_VALUE; 49 50 53 private static final String INDEXNODENAMESUFFIX = ".idxnode"; 54 55 64 private static final int NAMECONVERTRADIX = 10; 66 69 private static ThreadLocal readBufHolder = new ThreadLocal () { 70 protected synchronized Object initialValue() { 71 return new byte[1024]; 72 } 73 }; 74 75 78 private long nodeId = LONGNULL; 79 80 83 private long parentNodeId = LONGNULL; 84 85 88 private int maxSize; 89 90 93 private transient boolean dirty; 94 95 98 private long prevNodeId = LONGNULL; 99 100 103 private long nextNodeId = LONGNULL; 104 105 109 private transient IndexManager indexManager; 110 111 private transient int invoked; 112 113 119 protected IndexNode(IndexManager indexManager) { 120 startInvoke(); 121 nodeId = indexManager.nextNodeId(); 122 } 123 124 129 protected IndexManager getIndexManager() { 130 return indexManager; 131 } 132 133 139 protected void setIndexManager(IndexManager indexManager) { 140 Long id = new Long (getNodeId()); 141 if (this.indexManager != null) { 142 this.indexManager.removeFromCaches(this); 143 this.indexManager.getNodeSerializer().remove(id); 144 this.indexManager.getDeleter().delete(this, this.indexManager.getStorageFactory()); 145 } 146 this.indexManager = indexManager; 147 setDirty(); 148 if (this.indexManager != null) { 149 this.indexManager.putInCaches(this); 150 } 151 } 152 153 public String toString() { 154 return "id:" + getNodeId() + "; parent:" + 155 ((getParentNodeId() == LONGNULL) ? "null" : Long.toString(getParentNodeId())) + 156 "; dirty:" + isDirty() + "; minObjectId:" + getMinObjectId() + 161 "; maxObjectId:" + getMaxObjectId() + "; size:" + size() + "; invoked: " + invoked; 162 } 163 164 167 final boolean isDirty() { 168 return dirty; 169 } 170 171 final void setDirty(boolean dirty) { 172 if (log.isLoggable(Level.FINEST)) log.finest(getNodeId() + " dirty: " + dirty); 173 174 boolean changed = this.dirty != dirty; 175 this.dirty = dirty; 176 if (changed) { 177 getIndexManager().nodeBecameDirty(this); 178 } 179 } 180 181 final void setDirty() { 182 setDirty(true); 183 } 184 185 188 static String nodeIdToStorageName(long nodeId) { 189 return Long.toString(nodeId, NAMECONVERTRADIX) + INDEXNODENAMESUFFIX; 190 } 191 192 195 static long storageNameToNodeId(String indexFilename) { 196 String num = indexFilename.substring(0, indexFilename.length() - 1 - INDEXNODENAMESUFFIX.length()); 197 return Long.parseLong(num, NAMECONVERTRADIX); 198 } 199 200 204 public String getStorageName() { 205 return nodeIdToStorageName(getNodeId()); 206 } 207 208 214 static IndexNode read(IndexManager indexManager, long nodeId) throws IOException { 215 if (log.isLoggable(Level.FINE)) log.fine("about to read indexnode " + nodeId); 216 String nodeName = nodeIdToStorageName(nodeId); 217 IndexNode result; 218 Storage storage = null; 219 try { 220 storage = indexManager.getStorageFactory().createStorage(nodeName); 221 try { 222 byte[] b = (byte[]) readBufHolder.get(); 223 int numBytesToRead = (int) storage.length(); 224 if (b.length < numBytesToRead) { 225 b = new byte[numBytesToRead]; 226 readBufHolder.set(b); 227 } 228 storage.readFully(b, 0, numBytesToRead); 229 StreamFactory streamFactory = indexManager.getStreamFactory(); 230 ObjectInputStream objIn; 231 if (streamFactory == null) { 232 objIn = new ObjectInputStream (new ByteArrayInputStream (b)); 233 } else { 234 objIn = new ObjectInputStream (streamFactory.createInputStream(new ByteArrayInputStream (b))); 235 } 236 result = (IndexNode) objIn.readObject(); 237 result.startInvoke(); 238 result.setIndexManager(indexManager); 239 } catch (ClassNotFoundException e) { 240 throw new OzoneInternalException("\"Ford, you are turning into a penguin. Stop it.\"", e); 241 } 242 } finally { 243 if (storage != null) { 244 storage.close(); 245 } 246 } 247 if (result instanceof IndexLeafNode) { 249 if (result.getParentNodeId() == LONGNULL) { 250 log.severe("no parent for " + result.getNodeId()); 251 throw new RuntimeException (); 252 } 253 } 254 return result; 255 } 256 257 261 protected abstract int size(); 262 263 269 protected final boolean isFull() { 270 return isFull(0); 271 } 272 273 280 protected final boolean isFull(int withExtraElements) { 281 return size() + withExtraElements >= getMaxSize(); 282 } 283 284 287 final float relSize() { 288 return (float) size() / (float) getMaxSize(); 289 } 290 291 294 protected final void setMaxSize(int maxSize) { 295 if (this.maxSize != 0) { 296 throw new IllegalStateException ("cannot change max size"); 297 } 298 this.maxSize = maxSize; 299 } 300 301 final int getMaxSize() { 302 return maxSize; 303 } 304 305 308 abstract long getMinObjectId(); 309 310 313 abstract long getMaxObjectId(); 314 315 final long getNodeId() { 316 return nodeId; 317 } 318 319 final long getParentNodeId() { 320 return parentNodeId; 321 } 322 323 final void setParentNodeId(long parentNodeId) { 324 this.parentNodeId = parentNodeId; 325 setDirty(); 326 } 327 328 331 final void setParentNode(IndexBranchNode parent) { 332 if (parent == null) { 333 setParentNodeId(LONGNULL); 334 } else { 335 setParentNodeId(parent.getNodeId()); 336 } 337 } 338 339 final IndexBranchNode getParentNode() { 340 return (IndexBranchNode) getIndexManager().getNode(getParentNodeId()); 341 } 342 343 final long getPrevNodeId() { 344 return prevNodeId; 345 } 346 347 final IndexNode getPrevNode() { 348 return getIndexManager().getNode(getPrevNodeId()); 349 } 350 351 final void setPrevNodeId(long prevNodeId) { 352 this.prevNodeId = prevNodeId; 353 setDirty(); 354 } 355 356 final void setPrevNode(IndexNode prev) { 357 if (prev == null) { 358 setPrevNodeId(LONGNULL); 359 } else { 360 setPrevNodeId(prev.getNodeId()); 361 } 362 } 363 364 final long getNextNodeId() { 365 return nextNodeId; 366 } 367 368 final IndexNode getNextNode() { 369 return getIndexManager().getNode(getNextNodeId()); 370 } 371 372 final void setNextNodeId(long nextNodeId) { 373 this.nextNodeId = nextNodeId; 374 setDirty(); 375 } 376 377 final void setNextNode(IndexNode next) { 378 if (next == null) { 379 setNextNodeId(LONGNULL); 380 } else { 381 setNextNodeId(next.getNodeId()); 382 } 383 } 384 385 final void startInvoke() { 386 invoked++; 387 if (invoked > 3) throw new OzoneInternalException("pretty big invoke for node: " + getNodeId()); 388 } 389 390 final void endInvoke() { 391 invoked--; 392 if (invoked < 0) throw new OzoneInternalException("pretty small invoke for node: " + getNodeId()); 393 } 394 395 final boolean isInvoked() { 396 return invoked > 0; 397 } 398 399 protected void finalize() throws Throwable { 400 if (isDirty()) { 401 log.severe("how can I (" + getNodeId() + ") be dirty on finalize()?"); 402 } 403 super.finalize(); 404 } 405 } 406 | Popular Tags |