001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.sail.nativerdf.datastore;
007:
008: import java.io.File;
009: import java.io.IOException;
010:
011: import info.aduna.io.ByteArrayUtil;
012:
013: import org.openrdf.sail.nativerdf.btree.BTree;
014: import org.openrdf.sail.nativerdf.btree.RecordIterator;
015: import org.openrdf.sail.nativerdf.btree.DefaultRecordComparator;
016:
017: /**
018: * A file-based hash table based on B-Trees.
019: *
020: * @author Arjohn Kampman
021: */
022: public class HashIndex {
023:
024: /*-----------*
025: * Constants *
026: *-----------*/
027:
028: // Records consist of 8 bytes:
029: // byte 0-3 : hash code
030: // byte 4-7 : ID
031: private static final int RECORD_LENGTH = 8;
032:
033: private static final int HASH_IDX = 0;
034:
035: private static final int ID_IDX = 4;
036:
037: private static final byte[] SEARCH_MASK = new byte[RECORD_LENGTH];
038:
039: static {
040: ByteArrayUtil.putInt(0xffffffff, SEARCH_MASK, HASH_IDX);
041: }
042:
043: /*-----------*
044: * Variables *
045: *-----------*/
046:
047: /**
048: * The file that is used to store the hash index.
049: */
050: private File file;
051:
052: /**
053: * The BTree that is used to store the hash code records.
054: */
055: private BTree btree;
056:
057: /*--------------*
058: * Constructors *
059: *--------------*/
060:
061: public HashIndex(File file) throws IOException {
062: this .file = file;
063: btree = new BTree(file, 4096, RECORD_LENGTH,
064: new DefaultRecordComparator());
065: }
066:
067: /*---------*
068: * Methods *
069: *---------*/
070:
071: public File getFile() {
072: return file;
073: }
074:
075: /**
076: * Gets an iterator that iterates over the IDs with hash codes that match the
077: * specified hash code.
078: */
079: public IDIterator getIDIterator(int hash) throws IOException {
080: return new IDIterator(hash);
081: }
082:
083: /**
084: * Stores an ID under the specified hash code in this hash index.
085: */
086: public void storeID(int hash, int id) throws IOException {
087: btree.insert(getData(hash, id));
088: }
089:
090: /**
091: * Removes the specified ID from this hash index.
092: */
093: public void removeID(int hash, int id) throws IOException {
094: btree.remove(getData(hash, id));
095: }
096:
097: public void sync() throws IOException {
098: btree.sync();
099: }
100:
101: public void clear() throws IOException {
102: btree.clear();
103: }
104:
105: public void close() throws IOException {
106: btree.close();
107: }
108:
109: private byte[] getData(int hash, int id) {
110: byte[] data = new byte[RECORD_LENGTH];
111: ByteArrayUtil.putInt(hash, data, HASH_IDX);
112: ByteArrayUtil.putInt(id, data, ID_IDX);
113: return data;
114: }
115:
116: private byte[] getMinValue(int hash) {
117: byte[] minValue = new byte[RECORD_LENGTH];
118: ByteArrayUtil.putInt(hash, minValue, HASH_IDX);
119: return minValue;
120: }
121:
122: private byte[] getMaxValue(int hash) {
123: byte[] maxValue = new byte[RECORD_LENGTH];
124: ByteArrayUtil.putInt(hash, maxValue, HASH_IDX);
125: ByteArrayUtil.putInt(0xffffffff, maxValue, ID_IDX);
126: return maxValue;
127: }
128:
129: /*------------------------*
130: * Inner class IDIterator *
131: *------------------------*/
132:
133: public class IDIterator {
134:
135: private RecordIterator btreeIter;
136:
137: private IDIterator(int hash) throws IOException {
138: byte[] minValue = getMinValue(hash);
139: byte[] maxValue = getMaxValue(hash);
140:
141: btreeIter = btree.iterateRange(minValue, maxValue);
142: }
143:
144: /**
145: * Returns the next ID that has been mapped to the specified hash code, or
146: * <tt>-1</tt> if no more IDs were found.
147: */
148: public int next() throws IOException {
149: byte[] result = btreeIter.next();
150:
151: if (result == null) {
152: return -1;
153: }
154:
155: return ByteArrayUtil.getInt(result, ID_IDX);
156: }
157:
158: public void close() throws IOException {
159: btreeIter.close();
160: }
161: } // End inner class IDIterator
162: }
|