001: /*
002: * $Id: DiskTTree.java,v 1.1 2005/06/30 01:14:44 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2005 Axion Development Team. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.ext.indexes.ttree;
042:
043: import java.io.File;
044: import java.io.IOException;
045: import java.io.ObjectInputStream;
046: import java.lang.ref.SoftReference;
047: import java.util.Comparator;
048:
049: import org.axiondb.AxionException;
050:
051: /**
052: * Disk T-Tree implemenation.
053: *
054: * @version $Revision: 1.1 $ $Date: 2005/06/30 01:14:44 $
055: * @author Pavels Andrejevs
056: */
057: public class DiskTTree extends TTree {
058:
059: private class TTreeNode extends AbstractTTreeNode {
060:
061: private SoftReference _keysRef;
062: private SoftReference _valuesRef;
063:
064: public TTreeNode(TTree tree) throws AxionException {
065: this (tree, 0);
066: }
067:
068: public TTreeNode(TTree tree, int fileId) throws AxionException {
069: super (tree, fileId);
070: }
071:
072: public void addKeyValue(Object key, int value)
073: throws AxionException {
074: setKey(_nodeSize, key);
075: setValue(_nodeSize, value);
076: _nodeSize++;
077: }
078:
079: public void copyKeysValues(int from, int to, int length)
080: throws AxionException {
081: markDirty();
082: copyKeys(from, to, length);
083: copyValues(from, to, length);
084: }
085:
086: public void insertKeyValue(int index, Object key, int value)
087: throws AxionException {
088: markDirty();
089: insertKey(index, key);
090: insertValue(index, value);
091: _nodeSize++;
092: }
093:
094: public void removeKeyValue(int index) throws AxionException {
095: markDirty();
096: removeKey(index);
097: removeValue(index);
098: _nodeSize--;
099: }
100:
101: public void setKeyValue(int index, Object key, int value)
102: throws AxionException {
103: setKey(index, key);
104: setValue(index, value);
105: }
106:
107: protected void copyKeys(int from, int to, int length)
108: throws AxionException {
109: Object[] keys = getKeys();
110: System.arraycopy(keys, from, keys, to, length);
111: }
112:
113: protected final void copyValues(int from, int to, int length)
114: throws AxionException {
115: int[] values = getValues();
116: System.arraycopy(values, from, values, to, length);
117: }
118:
119: protected Object[] createKeys() {
120: Object[] keys = _keysRef == null ? null
121: : (Object[]) _keysRef.get();
122: if (keys == null) {
123: keys = new Object[_tree.getMaxNodeSize()];
124: _keysRef = new SoftReference(keys);
125: }
126: return keys;
127: }
128:
129: protected final int[] createValues() {
130: int[] values = _valuesRef == null ? null
131: : (int[]) _valuesRef.get();
132: if (values == null) {
133: values = new int[_tree.getMaxNodeSize()];
134: _valuesRef = new SoftReference(values);
135: }
136: return values;
137: }
138:
139: protected void destroyKeys() {
140: _keysRef = null;
141: }
142:
143: protected final void destroyValues() {
144: _valuesRef = null;
145: }
146:
147: protected Object getKey(int index) throws AxionException {
148: return getKeys()[index];
149: }
150:
151: protected Object[] getKeys() throws AxionException {
152: loadOnNeed();
153: return (Object[]) _keysRef.get();
154: }
155:
156: protected final int getValue(int index) throws AxionException {
157: return getValues()[index];
158: }
159:
160: protected final int[] getValues() throws AxionException {
161: loadOnNeed();
162: return (int[]) _valuesRef.get();
163: }
164:
165: protected void insertKey(int index, Object key)
166: throws AxionException {
167: Object[] keys = getKeys();
168: System.arraycopy(keys, index, keys, index + 1, _nodeSize
169: - index);
170: keys[index] = key;
171: }
172:
173: protected final void insertValue(int index, int value)
174: throws AxionException {
175: int[] values = getValues();
176: System.arraycopy(values, index, values, index + 1,
177: _nodeSize - index);
178: values[index] = value;
179: }
180:
181: protected final void loadOnNeed() throws AxionException {
182: boolean needKeys = needKeys();
183: boolean needValues = needValues();
184: if (needKeys || needValues) {
185: Object[] keys = null;
186: int[] values = null;
187: if (needKeys) {
188: keys = createKeys();
189: }
190: if (needValues) {
191: values = createValues();
192: }
193: // Then check whether the file exists so it can be filled
194: File file = _tree.getMetaData().getFileById(_fileId);
195: if (file.exists()) {
196: // If it's not, this is a totally new node: nothing to load
197: // then.
198: ObjectInputStream in = null;
199: try {
200: in = FS.openObjectInputSteam(file);
201: int readNodeSize = in.readInt();
202: if (_nodeSize != readNodeSize) {
203: // Sanity check.
204: throw new AxionException(
205: "Node size in memory "
206: + "doesn't match that on disk");
207: }
208: if (needKeys && needValues) {
209: for (int i = 0; i < _nodeSize; i++) {
210: Object key = in.readObject();
211: int value = in.readInt();
212: keys[i] = key;
213: values[i] = value;
214: }
215: } else if (needKeys) {
216: for (int i = 0; i < _nodeSize; i++) {
217: Object key = in.readObject();
218: in.readInt();
219: keys[i] = key;
220: }
221: } else {
222: for (int i = 0; i < _nodeSize; i++) {
223: in.readObject();
224: int value = in.readInt();
225: values[i] = value;
226: }
227: }
228: } catch (ClassNotFoundException e) {
229: throw new AxionException(e);
230: } catch (IOException e) {
231: throw new AxionException(e);
232: } finally {
233: FS.closeInputStream(in);
234: }
235: }
236: }
237: }
238:
239: // ---------------------------------------------------------------------
240:
241: protected boolean needKeys() {
242: Object[] keys = _keysRef == null ? null
243: : (Object[]) _keysRef.get();
244: return keys == null;
245: }
246:
247: protected boolean needValues() {
248: int[] values = _valuesRef == null ? null
249: : (int[]) _valuesRef.get();
250: return values == null;
251: }
252:
253: protected void removeKey(int index) throws AxionException {
254: Object[] keys = getKeys();
255: System.arraycopy(keys, index + 1, keys, index, _nodeSize
256: - index - 1);
257: }
258:
259: protected final void removeValue(int index)
260: throws AxionException {
261: int[] values = getValues();
262: System.arraycopy(values, index + 1, values, index,
263: _nodeSize - index - 1);
264: }
265:
266: protected void setKey(int index, Object key)
267: throws AxionException {
268: markDirty();
269: getKeys()[index] = key;
270: }
271:
272: protected final void setValue(int index, int value)
273: throws AxionException {
274: markDirty();
275: getValues()[index] = value;
276: }
277: }
278:
279: public DiskTTree(int maxNodeSize, Comparator comparator,
280: TTreeMetaData metaData) throws AxionException {
281: super (maxNodeSize, comparator, metaData);
282: }
283:
284: public AbstractTTreeNode newNode() throws AxionException {
285: return new TTreeNode(this );
286: }
287:
288: public AbstractTTreeNode newNode(int fileId) throws AxionException {
289: return new TTreeNode(this, fileId);
290: }
291:
292: }
|