package org.exist.storage;
import java.io.EOFException;
import java.io.IOException;
import org.exist.dom.persistent.NodeHandle;
import org.exist.storage.io.VariableByteInput;
import org.exist.storage.io.VariableByteOutputStream;
/**
* Represents a (virtual) storage address in the paged file, consisting
* of page number, tuple id and type indicator.
*
* The format of a storage address is as follows:
*
* <pre>
* | page | type | tid |
* | 1 2 3 4 | 5 6 | 7 8 |
* </pre>
*/
public class StorageAddress {
/**
* Create virtual address from page number and offset (tid)
*
*@param page Page number
*@param tid Tuple identifier
*@return Virtual address of the tuple
*/
public final static long createPointer(int page, short tid) {
return tid | (((long)page) & 0xFFFFFFFFL) << 32;
}
public final static long createPointer(int page, short tid, short flags) {
return tid | (((long)flags) & 0xFFFFL) << 16 | (((long)page) & 0xFFFFFFFFL) << 32;
}
/**
* Get the tuple identifier from a virtual address.
*
*@param pointer The address
*@return The tuple ID at this address
*/
public final static short tidFromPointer(long pointer) {
return (short) (pointer & 0xFFFFL);
}
/**
* Get the page number from a virtual address.
*
*@param pointer The address
*@return The page number
*/
public final static int pageFromPointer(long pointer) {
return (int) ((pointer >>> 32) & 0xFFFFFFFFL);
}
/**
* Get the type indicator from a virtual address.
*
* Returns a short corresponding to the type constants defined
* in {@link org.exist.xquery.value.Type}.
*
* @param pointer The address
* @return The type indicator
*/
public final static short indexTypeFromPointer(long pointer) {
return (short) ((pointer >>> 16) & 0xFFFFL);
}
public final static long setIndexType(long pointer, short type) {
return pointer | ((long)(type << 16) & 0xFFFF0000L);
}
public final static boolean hasAddress(long pointer) {
return (pointer & 0xFFFFFFFF0000FFFFL) > 0;
}
/**
* Returns <code>true</code> if the page number and the tuple ID of the two storage
* addresses are equal. The type indicator is ignored.
*
* @param p0 The first storage address
* @param p1 The second storage address
* @return <code>true</code> if the page number and the tuple ID
* of the two storage addresses are equal
*/
public final static boolean equals(long p0, long p1) {
return ((p0 & 0xFFFFFFFF0000FFFFL) == (p1 & 0xFFFFFFFF0000FFFFL));
}
public final static boolean equals(NodeHandle n0, NodeHandle n1) {
return equals(n0.getInternalAddress(), n1.getInternalAddress());
}
public final static void write(long pointer, VariableByteOutputStream os) {
os.writeInt(pageFromPointer(pointer));
os.writeShort(tidFromPointer(pointer));
os.writeShort(indexTypeFromPointer(pointer));
}
public final static long read(VariableByteInput is) throws IOException, EOFException {
return createPointer(is.readInt(), is.readShort(), is.readShort());
}
public final static String toString(long pointer) {
return pageFromPointer(pointer) + ":" + tidFromPointer(pointer);
}
public final static String toString(NodeHandle nodeHandle) {
return toString(nodeHandle.getInternalAddress());
}
}