📄 indexnode.java
字号:
// You can redistribute this software and/or modify it under the terms of// the Ozone Core License version 1 published by ozone-db.org.//// Copyright (C) 2003-@year@, Leo Mekenkamp. All rights reserved.//// $Id: IndexNode.java,v 1.4 2004/02/01 20:55:47 leomekenkamp Exp $package org.ozoneDB.core.storage.gammaStore;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.util.logging.Level;import java.util.logging.Logger;import org.ozoneDB.OzoneInternalException;import org.ozoneDB.core.storage.Cache;/** * <p>Index nodes are the nodes that make up the tree used for storing * information on where objects can be found (cluster + location). Because * memory is limited, it is impossible to have all index nodes in memory under * all circumstances. Therefor there are no hard references to other index nodes * but only ids are stored.</p> * * <p>There is not much logic here, most logic is in <code>IndexManager</code>. * </p> * * @author <a href="mailto:leoATmekenkampD0Tcom">Leo Mekenkamp (mind the anti sp@m)</a> * @version $Id: IndexNode.java,v 1.4 2004/02/01 20:55:47 leomekenkamp Exp $ */public abstract class IndexNode implements Storable { private static final long serialVersionUID = 0L; protected static final Logger log = Logger.getLogger(IndexNode.class.getName()); static {// log.setLevel(Level.ALL); } /** * alternative <code>null</code> value */ public static final long LONGNULL = Long.MIN_VALUE; public static final long MINOBJECTID = Long.MIN_VALUE + 1; public static final long MAXOBJECTID = Long.MAX_VALUE; /** * used for <code>StorageFactory</code> instances */ private static final String INDEXNODENAMESUFFIX = ".idxnode"; /** * <p>Used to name indexfiles. We could take any value from 2 to * <code>Character.MAX_RADIX</code> (36) here, but we settle for 16 because * it looks nice and nerdy. 36 would look less nice because that would * inevitably lead to filenames with very nasty words in them, like * <code>fuck.idxnode</code> and <code>microsoft.idxnode</code>.</p> * <p>Before you know it, someone sues you for trademark infringement.</p> * <p>Insiders joke: CAFEBABE is not a trademark, is she?</p> */ private static final int NAMECONVERTRADIX = 10; // 16; /** * Read buffer for instantiating new index nodes from storage. */ private static ThreadLocal readBufHolder = new ThreadLocal() { protected synchronized Object initialValue() { return new byte[1024]; } }; /** * our id */ private long nodeId = LONGNULL; /** * parent in the tree */ private long parentNodeId = LONGNULL; /** * maximum number of subnodes or object entries */ private int maxSize; /** * indicates a change which requires a write to storage when finalized */ private transient boolean dirty; /** * sibling node in the tree */ private long prevNodeId = LONGNULL; /** * sibling node in the tree */ private long nextNodeId = LONGNULL; /** * Index manager this instance is in. Set by constructor * and/or <code>read()</code> factory method. */ private transient IndexManager indexManager; private transient int invoked; /** * Constructor for an index node. Extending classes should place themselves * in its index managers cache. * * @param indexManager manages this instance */ protected IndexNode(IndexManager indexManager) { startInvoke(); nodeId = indexManager.nextNodeId(); } /** * Returns the index manager that is 'managing' this tree. * * @return IndexManager manager this instance is in */ protected IndexManager getIndexManager() { return indexManager; } /** * Sets the index manager that is 'managing' this tree. Also deletes image * from storage if necessary. * * @param indexManager manager this instance is in */ protected void setIndexManager(IndexManager indexManager) { Long id = new Long(getNodeId()); if (this.indexManager != null) { this.indexManager.removeFromCaches(this); this.indexManager.getNodeSerializer().remove(id); this.indexManager.getDeleter().delete(this, this.indexManager.getStorageFactory()); } this.indexManager = indexManager; setDirty(); if (this.indexManager != null) { this.indexManager.putInCaches(this); } } public String toString() { return "id:" + getNodeId() + "; parent:" + ((getParentNodeId() == LONGNULL) ? "null" : Long.toString(getParentNodeId())) +// "; prev:" + // ((getPrevNodeId() == LONGNULL) ? "null" : Long.toString(getPrevNodeId())) // + "; next:" + // ((getNextNodeId() == LONGNULL) ? "null" : Long.toString(getNextNodeId())) + "; dirty:" + isDirty() + "; minObjectId:" + getMinObjectId() + "; maxObjectId:" + getMaxObjectId() + "; size:" + size() + "; invoked: " + invoked; } /** * Indicates if this node has changed since last call to <code>write()</code>. */ final boolean isDirty() { return dirty; } final void setDirty(boolean dirty) { if (log.isLoggable(Level.FINEST)) log.finest(getNodeId() + " dirty: " + dirty); boolean changed = this.dirty != dirty; this.dirty = dirty; if (changed) { getIndexManager().nodeBecameDirty(this); } } final void setDirty() { setDirty(true); } /** * Converts a node id to corresponding (file)name for a node. */ static String nodeIdToStorageName(long nodeId) { return Long.toString(nodeId, NAMECONVERTRADIX) + INDEXNODENAMESUFFIX; } /** * Converts an index (file)name to its corresponding node id */ static long storageNameToNodeId(String indexFilename) { String num = indexFilename.substring(0, indexFilename.length() - 1 - INDEXNODENAMESUFFIX.length()); return Long.parseLong(num, NAMECONVERTRADIX); } /** Returnes the filename that this node can be saved to, or to be more * precise: the name that can be used by a <code>StorageFactory</code> to * create a unique <code>Storable</code>. */ public String getStorageName() { return nodeIdToStorageName(getNodeId()); } /** Factory method to create a node by reading it from the storage used * for index nodes by the specified index manager. * * @param indexManager index manager that manages this instance * @param nodeId id of the node to be read */ static IndexNode read(IndexManager indexManager, long nodeId) throws IOException { if (log.isLoggable(Level.FINE)) log.fine("about to read indexnode " + nodeId); String nodeName = nodeIdToStorageName(nodeId); IndexNode result; Storage storage = null; try { storage = indexManager.getStorageFactory().createStorage(nodeName); try { byte[] b = (byte[]) readBufHolder.get(); int numBytesToRead = (int) storage.length(); if (b.length < numBytesToRead) { b = new byte[numBytesToRead]; readBufHolder.set(b); } storage.readFully(b, 0, numBytesToRead); StreamFactory streamFactory = indexManager.getStreamFactory(); ObjectInputStream objIn; if (streamFactory == null) { objIn = new ObjectInputStream(new ByteArrayInputStream(b)); } else { objIn = new ObjectInputStream(streamFactory.createInputStream(new ByteArrayInputStream(b))); } result = (IndexNode) objIn.readObject(); result.startInvoke(); result.setIndexManager(indexManager); } catch (ClassNotFoundException e) { throw new OzoneInternalException("\"Ford, you are turning into a penguin. Stop it.\"", e); } } finally { if (storage != null) { storage.close(); } }//if (nodeId == 8 || nodeId == 6) log.severe("read " + result);if (result instanceof IndexLeafNode) { if (result.getParentNodeId() == LONGNULL) { log.severe("no parent for " + result.getNodeId()); throw new RuntimeException(); }} return result; } /** * Returns the number of elements in this node. * @return number of elements in this node */ protected abstract int size(); /** * Returns <code>true</code> if there is no more room for new elements, * <code>false</code> otherwise * @return <code>true</code> if this node is full, <code>false</code> * otherwise */ protected final boolean isFull() { return isFull(0); } /** * Returns <code>true</code> if there is no more room for new elements after * the specified number of elements were added, * <code>false</code> otherwise * @return <code>true</code> if this node (+ specified extra) is full, * <code>false</code> otherwise */ protected final boolean isFull(int withExtraElements) { return size() + withExtraElements >= getMaxSize(); } /** * Returns the relative size of this node, on a scale of [0 .. 1] */ final float relSize() { return (float) size() / (float) getMaxSize(); } /** * @throws IllegalStateException when called for the second time */ protected final void setMaxSize(int maxSize) { if (this.maxSize != 0) { throw new IllegalStateException("cannot change max size"); } this.maxSize = maxSize; } final int getMaxSize() { return maxSize; } /** * Returns the minimum object id that can be found be in this node */ abstract long getMinObjectId(); /** * Returns the maximum object id that can be found be in this node */ abstract long getMaxObjectId(); final long getNodeId() { return nodeId; } final long getParentNodeId() { return parentNodeId; } final void setParentNodeId(long parentNodeId) { this.parentNodeId = parentNodeId; setDirty(); } /** * Only ment to be called from IndexBranchNode.putChildNode(IndexNode). */ final void setParentNode(IndexBranchNode parent) { if (parent == null) { setParentNodeId(LONGNULL); } else { setParentNodeId(parent.getNodeId()); } } final IndexBranchNode getParentNode() { return (IndexBranchNode) getIndexManager().getNode(getParentNodeId()); } final long getPrevNodeId() { return prevNodeId; } final IndexNode getPrevNode() { return getIndexManager().getNode(getPrevNodeId()); } final void setPrevNodeId(long prevNodeId) { this.prevNodeId = prevNodeId; setDirty(); } final void setPrevNode(IndexNode prev) { if (prev == null) { setPrevNodeId(LONGNULL); } else { setPrevNodeId(prev.getNodeId()); } } final long getNextNodeId() { return nextNodeId; } final IndexNode getNextNode() { return getIndexManager().getNode(getNextNodeId()); } final void setNextNodeId(long nextNodeId) { this.nextNodeId = nextNodeId; setDirty(); } final void setNextNode(IndexNode next) { if (next == null) { setNextNodeId(LONGNULL); } else { setNextNodeId(next.getNodeId()); } } final void startInvoke() { invoked++; if (invoked > 3) throw new OzoneInternalException("pretty big invoke for node: " + getNodeId()); } final void endInvoke() { invoked--; if (invoked < 0) throw new OzoneInternalException("pretty small invoke for node: " + getNodeId()); } final boolean isInvoked() { return invoked > 0; } protected void finalize() throws Throwable { if (isDirty()) { log.severe("how can I (" + getNodeId() + ") be dirty on finalize()?"); } super.finalize(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -