(null, null);
- browser = browse(key,true);
- if (browser.getNext(tuple)) {
- return tuple;
- } else {
- return null;
- }
- }
-
-
- /**
- * Get a browser initially positioned at the beginning of the BTree.
- *
- * WARNING: If you make structural modifications to the BTree during
- * browsing, you will get inconsistent browing results.
- *
- *
- * @return Browser positionned at the beginning of the BTree.
- */
- @SuppressWarnings("unchecked")
- public BTreeTupleBrowser browse()
- throws IOException {
- try {
- lock.readLock().lock();
- BTreeNode rootNode = getRoot();
- if (rootNode == null) {
- return EMPTY_BROWSER;
- }
- return rootNode.findFirst();
- } finally {
- lock.readLock().unlock();
- }
- }
-
-
- /**
- * Get a browser initially positioned just before the given key.
- *
- * WARNING: �If you make structural modifications to the BTree during
- * browsing, you will get inconsistent browing results.
- *
- *
- * @param key Key used to position the browser. If null, the browser
- * will be positionned after the last entry of the BTree.
- * (Null is considered to be an "infinite" key)
- * @return Browser positionned just before the given key.
- */
- @SuppressWarnings("unchecked")
- public BTreeTupleBrowser browse(final K key, final boolean inclusive)
- throws IOException {
- try {
- lock.readLock().lock();
- BTreeNode rootNode = getRoot();
- if (rootNode == null) {
- return EMPTY_BROWSER;
- }
- BTreeTupleBrowser browser = rootNode.find(_height, key, inclusive);
- return browser;
- } finally {
- lock.readLock().unlock();
- }
- }
-
-
- /**
- * Return the persistent record identifier of the BTree.
- */
- public long getRecid() {
- return _recid;
- }
-
-
- /**
- * Return the root BTreeNode, or null if it doesn't exist.
- */
- BTreeNode getRoot()
- throws IOException {
- if (_root == 0) {
- return null;
- }
- BTreeNode root = _db.fetch(_root, _nodeSerializer);
- if (root != null) {
- root._recid = _root;
- root._btree = this;
- }
- return root;
- }
-
-
- static BTree readExternal(DataInput in, Serialization ser)
- throws IOException, ClassNotFoundException {
- BTree tree = new BTree();
- tree._db = ser.db;
- tree._height = in.readInt();
- tree._recid = in.readLong();
- tree._root = in.readLong();
- tree._entries = in.readLong();
- tree.hasValues = in.readBoolean();
- tree._comparator = (Comparator) ser.deserialize(in);
- tree.keySerializer = (Serializer) ser.deserialize(in);
- tree.valueSerializer = (Serializer) ser.deserialize(in);
- return tree;
- }
-
-
- public void writeExternal(DataOutput out)
- throws IOException {
- out.writeInt(_height);
- out.writeLong(_recid);
- out.writeLong(_root);
- out.writeLong(_entries);
- out.writeBoolean(hasValues);
- _db.defaultSerializer().serialize(out, _comparator);
- _db.defaultSerializer().serialize(out, keySerializer);
- _db.defaultSerializer().serialize(out, valueSerializer);
- }
-
- /**
- * Copyes tree from one db to other, defragmenting it allong the way
- * @param recid
- * @param r1
- * @param r2
- * @throws IOException
- */
- public static void defrag(long recid, DBStore r1, DBStore r2) throws IOException {
- try {
- byte[] data = r1.fetchRaw(recid);
- r2.forceInsert(recid, data);
- DataInput in = new DataInputOutput(data);
- BTree t = (BTree) r1.defaultSerializer().deserialize(in);
- t.loadValues = false;
- t._db = r1;
- t._nodeSerializer = new BTreeNode(t, false);
-
-
- BTreeNode p = t.getRoot();
- if (p != null) {
- r2.forceInsert(t._root, r1.fetchRaw(t._root));
- p.defrag(r1, r2);
- }
-
- } catch (ClassNotFoundException e) {
- throw new IOError(e);
- }
- }
-
-
- /**
- * Browser returning no element.
- */
- private static final BTreeTupleBrowser EMPTY_BROWSER = new BTreeTupleBrowser() {
-
- public boolean getNext(BTreeTuple tuple) {
- return false;
- }
-
- public boolean getPrevious(BTreeTuple tuple) {
- return false;
- }
-
- public void remove(Object key) {
- throw new IndexOutOfBoundsException();
- }
- };
-
-
- /**
- * add RecordListener which is notified about record changes
- *
- * @param listener
- */
- public void addRecordListener(RecordListener listener) {
- recordListeners = Arrays.copyOf(recordListeners, recordListeners.length + 1);
- recordListeners[recordListeners.length - 1] = listener;
- }
-
- /**
- * remove RecordListener which is notified about record changes
- *
- * @param listener
- */
- public void removeRecordListener(RecordListener listener) {
- List l = Arrays.asList(recordListeners);
- l.remove(listener);
- recordListeners = (RecordListener[]) l.toArray(new RecordListener[1]);
- }
-
-
- public DBAbstract getRecordManager() {
- return _db;
- }
-
-
- public Comparator getComparator() {
- return _comparator;
- }
-
- /**
- * Deletes all BTreeNodes in this BTree
- */
- public void clear()
- throws IOException {
- try {
- lock.writeLock().lock();
- BTreeNode rootNode = getRoot();
- if (rootNode != null)
- rootNode.delete();
- _entries = 0;
- modCount++;
- } finally {
- lock.writeLock().unlock();
- }
- }
-
- /**
- * Used for debugging and testing only. Populates the 'out' list with
- * the recids of all child nodes in the BTree.
- *
- * @param out
- * @throws IOException
- */
- void dumpChildNodeRecIDs(List out) throws IOException {
- BTreeNode root = getRoot();
- if (root != null) {
- out.add(root._recid);
- root.dumpChildNodeRecIDs(out, _height);
- }
- }
-
- public boolean hasValues() {
- return hasValues;
- }
-
- /**
- * Browser to traverse a collection of tuples. The browser allows for
- * forward and reverse order traversal.
- *
- *
- */
- static interface BTreeTupleBrowser {
-
- /**
- * Get the next tuple.
- *
- * @param tuple Tuple into which values are copied.
- * @return True if values have been copied in tuple, or false if there is no next tuple.
- */
- boolean getNext(BTree.BTreeTuple tuple) throws IOException;
-
- /**
- * Get the previous tuple.
- *
- * @param tuple Tuple into which values are copied.
- * @return True if values have been copied in tuple, or false if there is no previous tuple.
- */
- boolean getPrevious(BTree.BTreeTuple tuple) throws IOException;
-
- /**
- * Remove an entry with given key, and increases browsers expectedModCount
- * This method is here to support 'ConcurrentModificationException' on Map interface.
- *
- * @param key
- */
- void remove(K key) throws IOException;
-
- }
-
- /**
- * Tuple consisting of a key-value pair.
- */
- static final class BTreeTuple {
-
- K key;
-
- V value;
-
- BTreeTuple() {
- // empty
- }
-
- BTreeTuple(K key, V value) {
- this.key = key;
- this.value = value;
- }
-
- }
-
-
-
-}
-
diff --git a/com.minres.scviewer.database.text/src/org/apache/jdbm/BTreeLazyRecord.java b/com.minres.scviewer.database.text/src/org/apache/jdbm/BTreeLazyRecord.java
deleted file mode 100644
index c0ce160..0000000
--- a/com.minres.scviewer.database.text/src/org/apache/jdbm/BTreeLazyRecord.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.apache.jdbm;
-
-import java.io.*;
-
-/**
- * An record lazily loaded from store.
- * This is used in BTree/HTree to store big records outside of index tree
- *
- * @author Jan Kotek
- */
-class BTreeLazyRecord {
-
- private E value = null;
- private DBAbstract db;
- private Serializer serializer;
- final long recid;
-
- BTreeLazyRecord(DBAbstract db, long recid, Serializer serializer) {
- this.db = db;
- this.recid = recid;
- this.serializer = serializer;
- }
-
-
- E get() {
- if (value != null) return value;
- try {
- value = db.fetch(recid, serializer);
- } catch (IOException e) {
- throw new IOError(e);
- }
- return value;
- }
-
- void delete() {
- try {
- db.delete(recid);
- } catch (IOException e) {
- throw new IOError(e);
- }
- value = null;
- serializer = null;
- db = null;
- }
-
- /**
- * Serialier used to insert already serialized data into store
- */
- static final Serializer FAKE_SERIALIZER = new Serializer() {
-
- public void serialize(DataOutput out, Object obj) throws IOException {
- byte[] data = (byte[]) obj;
- out.write(data);
- }
-
- public Object deserialize(DataInput in) throws IOException, ClassNotFoundException {
- throw new UnsupportedOperationException();
- }
- };
-
-
- static Object fastDeser(DataInputOutput in, Serializer serializer, int expectedSize) throws IOException, ClassNotFoundException {
- //we should propably copy data for deserialization into separate buffer and pass it to Serializer
- //but to make it faster, Serializer will operate directly on top of buffer.
- //and we check that it readed correct number of bytes.
- int origAvail = in.available();
- if (origAvail == 0)
- throw new InternalError(); //is backed up by byte[] buffer, so there should be always avail bytes
- Object ret = serializer.deserialize(in);
- //check than valueSerializer did not read more bytes, if yes it readed bytes from next record
- int readed = origAvail - in.available();
- if (readed > expectedSize)
- throw new IOException("Serializer readed more bytes than is record size.");
- else if (readed != expectedSize) {
- //deserializer did not readed all bytes, unussual but valid.
- //Skip some to get into correct position
- for (int ii = 0; ii < expectedSize - readed; ii++)
- in.readUnsignedByte();
- }
- return ret;
- }
-
-
- /**
- * if value in tree is serialized in more bytes, it is stored as separate record outside of tree
- * This value must be always smaller than 250
- */
- static final int MAX_INTREE_RECORD_SIZE = 32;
-
- static {
- if (MAX_INTREE_RECORD_SIZE > 250) throw new Error();
- }
-
- static final int NULL = 255;
- static final int LAZY_RECORD = 254;
-
-}
diff --git a/com.minres.scviewer.database.text/src/org/apache/jdbm/BTreeMap.java b/com.minres.scviewer.database.text/src/org/apache/jdbm/BTreeMap.java
deleted file mode 100644
index fba1bf2..0000000
--- a/com.minres.scviewer.database.text/src/org/apache/jdbm/BTreeMap.java
+++ /dev/null
@@ -1,611 +0,0 @@
-/*******************************************************************************
- * Copyright 2010 Cees De Groot, Alex Boisvert, Jan Kotek
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- ******************************************************************************/
-package org.apache.jdbm;
-
-import java.io.IOError;
-import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.ConcurrentNavigableMap;
-
-
-/**
- * Wrapper for BTree
which implements ConcurrentNavigableMap
interface
- *
- * @param key type
- * @param value type
- *
- * @author Jan Kotek
- */
-class BTreeMap extends AbstractMap implements ConcurrentNavigableMap {
-
- protected BTree tree;
-
- protected final K fromKey;
-
- protected final K toKey;
-
- protected final boolean readonly;
-
- protected NavigableSet keySet2;
- private final boolean toInclusive;
- private final boolean fromInclusive;
-
- public BTreeMap(BTree tree, boolean readonly) {
- this(tree, readonly, null, false, null, false);
- }
-
- protected BTreeMap(BTree tree, boolean readonly, K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
- this.tree = tree;
- this.fromKey = fromKey;
- this.fromInclusive = fromInclusive;
- this.toKey = toKey;
- this.toInclusive = toInclusive;
- this.readonly = readonly;
- }
-
- @Override
- public Set> entrySet() {
- return _entrySet;
- }
-
-
-
- private final Set> _entrySet = new AbstractSet>() {
-
- protected Entry newEntry(K k, V v) {
- return new SimpleEntry(k, v) {
- private static final long serialVersionUID = 978651696969194154L;
-
- public V setValue(V arg0) {
- BTreeMap.this.put(getKey(), arg0);
- return super.setValue(arg0);
- }
-
- };
- }
-
- public boolean add(java.util.Map.Entry e) {
- if (readonly)
- throw new UnsupportedOperationException("readonly");
-
- try {
- if (e.getKey() == null)
- throw new NullPointerException("Can not add null key");
- if (!inBounds(e.getKey()))
- throw new IllegalArgumentException("key outside of bounds");
- return tree.insert(e.getKey(), e.getValue(), true) == null;
- } catch (IOException e1) {
- throw new IOError(e1);
- }
- }
-
- @SuppressWarnings("unchecked")
- public boolean contains(Object o) {
-
- if (o instanceof Entry) {
- Entry e = (java.util.Map.Entry) o;
- try {
- if (!inBounds(e.getKey()))
- return false;
- if (e.getKey() != null && tree.get(e.getKey()) != null)
- return true;
- } catch (IOException e1) {
- throw new IOError(e1);
- }
- }
- return false;
- }
-
-
- public Iterator> iterator() {
- try {
- final BTree.BTreeTupleBrowser br = fromKey == null ?
- tree.browse() : tree.browse(fromKey, fromInclusive);
- return new Iterator>() {
-
- private Entry next;
- private K lastKey;
-
- void ensureNext() {
- try {
- BTree.BTreeTuple t = new BTree.BTreeTuple();
- if (br.getNext(t) && inBounds(t.key))
- next = newEntry(t.key, t.value);
- else
- next = null;
- } catch (IOException e1) {
- throw new IOError(e1);
- }
- }
-
- {
- ensureNext();
- }
-
-
- public boolean hasNext() {
- return next != null;
- }
-
- public java.util.Map.Entry next() {
- if (next == null)
- throw new NoSuchElementException();
- Entry ret = next;
- lastKey = ret.getKey();
- //move to next position
- ensureNext();
- return ret;
- }
-
- public void remove() {
- if (readonly)
- throw new UnsupportedOperationException("readonly");
-
- if (lastKey == null)
- throw new IllegalStateException();
- try {
- br.remove(lastKey);
- lastKey = null;
- } catch (IOException e1) {
- throw new IOError(e1);
- }
-
- }
- };
-
- } catch (IOException e) {
- throw new IOError(e);
- }
-
- }
-
- @SuppressWarnings("unchecked")
- public boolean remove(Object o) {
- if (readonly)
- throw new UnsupportedOperationException("readonly");
-
- if (o instanceof Entry) {
- Entry e = (java.util.Map.Entry) o;
- try {
- //check for nulls
- if (e.getKey() == null || e.getValue() == null)
- return false;
- if (!inBounds(e.getKey()))
- throw new IllegalArgumentException("out of bounds");
- //get old value, must be same as item in entry
- V v = get(e.getKey());
- if (v == null || !e.getValue().equals(v))
- return false;
- V v2 = tree.remove(e.getKey());
- return v2 != null;
- } catch (IOException e1) {
- throw new IOError(e1);
- }
- }
- return false;
-
- }
-
- public int size() {
- return BTreeMap.this.size();
- }
-
- public void clear(){
- if(fromKey!=null || toKey!=null)
- super.clear();
- else
- try {
- tree.clear();
- } catch (IOException e) {
- throw new IOError(e);
- }
- }
-
- };
-
-
- public boolean inBounds(K e) {
- if(fromKey == null && toKey == null)
- return true;
-
- Comparator comp = comparator();
- if (comp == null) comp = Utils.COMPARABLE_COMPARATOR;
-
- if(fromKey!=null){
- final int compare = comp.compare(e, fromKey);
- if(compare<0) return false;
- if(!fromInclusive && compare == 0) return false;
- }
- if(toKey!=null){
- final int compare = comp.compare(e, toKey);
- if(compare>0)return false;
- if(!toInclusive && compare == 0) return false;
- }
- return true;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V get(Object key) {
- try {
- if (key == null)
- return null;
- if (!inBounds((K) key))
- return null;
- return tree.get((K) key);
- } catch (ClassCastException e) {
- return null;
- } catch (IOException e) {
- throw new IOError(e);
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V remove(Object key) {
- if (readonly)
- throw new UnsupportedOperationException("readonly");
-
- try {
- if (key == null || tree.get((K) key) == null)
- return null;
- if (!inBounds((K) key))
- throw new IllegalArgumentException("out of bounds");
-
- return tree.remove((K) key);
- } catch (ClassCastException e) {
- return null;
- } catch (IOException e) {
- throw new IOError(e);
- }
- }
-
- public V put(K key, V value) {
- if (readonly)
- throw new UnsupportedOperationException("readonly");
-
- try {
- if (key == null || value == null)
- throw new NullPointerException("Null key or value");
- if (!inBounds(key))
- throw new IllegalArgumentException("out of bounds");
- return tree.insert(key, value, true);
- } catch (IOException e) {
- throw new IOError(e);
- }
- }
-
- public void clear(){
- entrySet().clear();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public boolean containsKey(Object key) {
- if (key == null)
- return false;
- try {
- if (!inBounds((K) key))
- return false;
- V v = tree.get((K) key);
- return v != null;
- } catch (IOException e) {
- throw new IOError(e);
- } catch (ClassCastException e) {
- return false;
- }
- }
-
- public Comparator super K> comparator() {
- return tree._comparator;
- }
-
- public K firstKey() {
- if (isEmpty())
- return null;
- try {
-
- BTree.BTreeTupleBrowser b = fromKey == null ? tree.browse() : tree.browse(fromKey,fromInclusive);
- BTree.BTreeTuple t = new BTree.BTreeTuple();
- b.getNext(t);
- return t.key;
- } catch (IOException e) {
- throw new IOError(e);
- }
- }
-
- public K lastKey() {
- if (isEmpty())
- return null;
- try {
- BTree.BTreeTupleBrowser b = toKey == null ? tree.browse(null,true) : tree.browse(toKey,false);
- BTree.BTreeTuple t = new BTree.BTreeTuple();
- b.getPrevious(t);
- if(!toInclusive && toKey!=null){
- //make sure we wont return last key
- Comparator c = comparator();
- if(c==null) c=Utils.COMPARABLE_COMPARATOR;
- if(c.compare(t.key,toKey)==0)
- b.getPrevious(t);
- }
- return t.key;
- } catch (IOException e) {
- throw new IOError(e);
- }
- }
-
- public ConcurrentNavigableMap headMap(K toKey2, boolean inclusive) {
- K toKey3 = Utils.min(this.toKey,toKey2,comparator());
- boolean inclusive2 = toKey3 == toKey? toInclusive : inclusive;
- return new BTreeMap(tree, readonly, this.fromKey, this.fromInclusive, toKey3, inclusive2);
- }
-
-
- public ConcurrentNavigableMap headMap(K toKey) {
- return headMap(toKey,false);
- }
-
-
- public Entry lowerEntry(K key) {
- K k = lowerKey(key);
- return k==null? null : new SimpleEntry(k,get(k));
- }
-
- public K lowerKey(K key) {
- if (isEmpty())
- return null;
- K key2 = Utils.min(key,toKey,comparator());
- try {
- BTree.BTreeTupleBrowser b = tree.browse(key2,true) ;
- BTree.BTreeTuple t = new BTree.BTreeTuple();
- b.getPrevious(t);
-
- return t.key;
-
- } catch (IOException e) {
- throw new IOError(e);
- }
-
- }
-
- public Entry floorEntry(K key) {
- K k = floorKey(key);
- return k==null? null : new SimpleEntry(k,get(k));
-
- }
-
- public K floorKey(K key) {
- if (isEmpty())
- return null;
-
- K key2 = Utils.max(key,fromKey,comparator());
- try {
- BTree.BTreeTupleBrowser b = tree.browse(key2,true) ;
- BTree.BTreeTuple t = new BTree.BTreeTuple();
- b.getNext(t);
- Comparator comp = comparator();
- if (comp == null) comp = Utils.COMPARABLE_COMPARATOR;
- if(comp.compare(t.key,key2) == 0)
- return t.key;
-
- b.getPrevious(t);
- b.getPrevious(t);
- return t.key;
-
- } catch (IOException e) {
- throw new IOError(e);
- }
- }
-
- public Entry ceilingEntry(K key) {
- K k = ceilingKey(key);
- return k==null? null : new SimpleEntry(k,get(k));
- }
-
- public K ceilingKey(K key) {
- if (isEmpty())
- return null;
- K key2 = Utils.min(key,toKey,comparator());
-
- try {
- BTree.BTreeTupleBrowser b = tree.browse(key2,true) ;
- BTree.BTreeTuple t = new BTree.BTreeTuple();
- b.getNext(t);
- return t.key;
-
- } catch (IOException e) {
- throw new IOError(e);
- }
- }
-
- public Entry higherEntry(K key) {
- K k = higherKey(key);
- return k==null? null : new SimpleEntry(k,get(k));
- }
-
- public K higherKey(K key) {
- if (isEmpty())
- return null;
-
- K key2 = Utils.max(key,fromKey,comparator());
-
- try {
- BTree.BTreeTupleBrowser b = tree.browse(key2,false) ;
- BTree.BTreeTuple t = new BTree.BTreeTuple();
- b.getNext(t);
- return t.key;
-
- } catch (IOException e) {
- throw new IOError(e);
- }
- }
-
- public Entry firstEntry() {
- K k = firstKey();
- return k==null? null : new SimpleEntry(k,get(k));
- }
-
- public Entry lastEntry() {
- K k = lastKey();
- return k==null? null : new SimpleEntry(k,get(k));
- }
-
- public Entry pollFirstEntry() {
- Entry first = firstEntry();
- if(first!=null)
- remove(first.getKey());
- return first;
- }
-
- public Entry pollLastEntry() {
- Entry last = lastEntry();
- if(last!=null)
- remove(last.getKey());
- return last;
- }
-
- public ConcurrentNavigableMap descendingMap() {
- throw new UnsupportedOperationException("not implemented yet");
- //TODO implement descending (reverse order) map
- }
-
-
- public NavigableSet keySet() {
- return navigableKeySet();
- }
-
- public NavigableSet navigableKeySet() {
- if(keySet2 == null)
- keySet2 = new BTreeSet((BTreeMap) this);
- return keySet2;
- }
-
- public NavigableSet descendingKeySet() {
- return descendingMap().navigableKeySet();
- }
-
-
-
- public ConcurrentNavigableMap tailMap(K fromKey) {
- return tailMap(fromKey,true);
- }
-
-
- public ConcurrentNavigableMap tailMap(K fromKey2, boolean inclusive) {
- K fromKey3 = Utils.max(this.fromKey,fromKey2,comparator());
- boolean inclusive2 = fromKey3 == toKey? toInclusive : inclusive;
-
- return new BTreeMap(tree, readonly, fromKey3, inclusive2, toKey, toInclusive);
- }
-
- public ConcurrentNavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
- Comparator comp = comparator();
- if (comp == null) comp = Utils.COMPARABLE_COMPARATOR;
- if (comp.compare(fromKey, toKey) > 0)
- throw new IllegalArgumentException("fromKey is bigger then toKey");
- return new BTreeMap(tree, readonly, fromKey, fromInclusive, toKey, toInclusive);
- }
-
- public ConcurrentNavigableMap subMap(K fromKey, K toKey) {
- return subMap(fromKey,true,toKey,false);
- }
-
-
- public BTree getTree() {
- return tree;
- }
-
-
- public void addRecordListener(RecordListener listener) {
- tree.addRecordListener(listener);
- }
-
- public DBAbstract getRecordManager() {
- return tree.getRecordManager();
- }
-
- public void removeRecordListener(RecordListener listener) {
- tree.removeRecordListener(listener);
- }
-
-
- public int size() {
- if (fromKey == null && toKey == null)
- return (int) tree._entries; //use fast counter on tree if Map has no bounds
- else {
- //had to count items in iterator
- Iterator iter = keySet().iterator();
- int counter = 0;
- while (iter.hasNext()) {
- iter.next();
- counter++;
- }
- return counter;
- }
-
- }
-
-
- public V putIfAbsent(K key, V value) {
- tree.lock.writeLock().lock();
- try{
- if (!containsKey(key))
- return put(key, value);
- else
- return get(key);
- }finally {
- tree.lock.writeLock().unlock();
- }
- }
-
- public boolean remove(Object key, Object value) {
- tree.lock.writeLock().lock();
- try{
- if (containsKey(key) && get(key).equals(value)) {
- remove(key);
- return true;
- } else return false;
- }finally {
- tree.lock.writeLock().unlock();
- }
-
-
- }
-
- public boolean replace(K key, V oldValue, V newValue) {
- tree.lock.writeLock().lock();
- try{
- if (containsKey(key) && get(key).equals(oldValue)) {
- put(key, newValue);
- return true;
- } else return false;
- }finally {
- tree.lock.writeLock().unlock();
- }
-
- }
-
- public V replace(K key, V value) {
- tree.lock.writeLock().lock();
- try{
- if (containsKey(key)) {
- return put(key, value);
- } else return null;
- }finally {
- tree.lock.writeLock().unlock();
- }
- }
-}
diff --git a/com.minres.scviewer.database.text/src/org/apache/jdbm/BTreeNode.java b/com.minres.scviewer.database.text/src/org/apache/jdbm/BTreeNode.java
deleted file mode 100644
index 3adb360..0000000
--- a/com.minres.scviewer.database.text/src/org/apache/jdbm/BTreeNode.java
+++ /dev/null
@@ -1,1550 +0,0 @@
-/*******************************************************************************
- * Copyright 2010 Cees De Groot, Alex Boisvert, Jan Kotek
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- ******************************************************************************/
-
-
-package org.apache.jdbm;
-
-import java.io.*;
-import java.util.ConcurrentModificationException;
-import java.util.List;
-
-/**
- * Node of a BTree.
- *
- * The node contains a number of key-value pairs. Keys are ordered to allow
- * dichotomic search. If value is too big, it is stored in separate record
- * and only recid reference is stored
- *
- * If the node is a leaf node, the keys and values are user-defined and
- * represent entries inserted by the user.
- *
- * If the node is non-leaf, each key represents the greatest key in the
- * underlying BTreeNode and the values are recids pointing to the children BTreeNodes.
- * The only exception is the rightmost BTreeNode, which is considered to have an
- * "infinite" key value, meaning that any insert will be to the left of this
- * pseudo-key
- *
- * @author Alex Boisvert
- * @author Jan Kotek
- */
-final class BTreeNode
- implements Serializer> {
-
- private static final boolean DEBUG = false;
-
-
- /**
- * Parent B+Tree.
- */
- transient BTree _btree;
-
-
- /**
- * This BTreeNode's record ID in the DB.
- */
- protected transient long _recid;
-
-
- /**
- * Flag indicating if this is a leaf BTreeNode.
- */
- protected boolean _isLeaf;
-
-
- /**
- * Keys of children nodes
- */
- protected K[] _keys;
-
-
- /**
- * Values associated with keys. (Only valid if leaf node)
- */
- protected Object[] _values;
-
-
- /**
- * Children nodes (recids) associated with keys. (Only valid if non-leaf node)
- */
- protected long[] _children;
-
-
- /**
- * Index of first used item at the node
- */
- protected byte _first;
-
-
- /**
- * Previous leaf node (only if this node is a leaf)
- */
- protected long _previous;
-
-
- /**
- * Next leaf node (only if this node is a leaf)
- */
- protected long _next;
-
- /**
- * Return the B+Tree that is the owner of this {@link BTreeNode}.
- */
- public BTree getBTree() {
- return _btree;
- }
-
- /**
- * No-argument constructor used by serialization.
- */
- public BTreeNode() {
- // empty
- }
-
-
- /**
- * Root node overflow constructor
- */
- @SuppressWarnings("unchecked")
- BTreeNode(BTree btree, BTreeNode root, BTreeNode overflow)
- throws IOException {
- _btree = btree;
-
- _isLeaf = false;
-
- _first = BTree.DEFAULT_SIZE - 2;
-
- _keys = (K[]) new Object[BTree.DEFAULT_SIZE];
- _keys[BTree.DEFAULT_SIZE - 2] = overflow.getLargestKey();
- _keys[BTree.DEFAULT_SIZE - 1] = root.getLargestKey();
-
- _children = new long[BTree.DEFAULT_SIZE];
- _children[BTree.DEFAULT_SIZE - 2] = overflow._recid;
- _children[BTree.DEFAULT_SIZE - 1] = root._recid;
-
- _recid = _btree._db.insert(this, this,false);
- }
-
-
- /**
- * Root node (first insert) constructor.
- */
- @SuppressWarnings("unchecked")
- BTreeNode(BTree btree, K key, V value)
- throws IOException {
- _btree = btree;
-
- _isLeaf = true;
-
- _first = BTree.DEFAULT_SIZE - 2;
-
- _keys = (K[]) new Object[BTree.DEFAULT_SIZE];
- _keys[BTree.DEFAULT_SIZE - 2] = key;
- _keys[BTree.DEFAULT_SIZE - 1] = null; // I am the root BTreeNode for now
-
- _values = new Object[BTree.DEFAULT_SIZE];
- _values[BTree.DEFAULT_SIZE - 2] = value;
- _values[BTree.DEFAULT_SIZE - 1] = null; // I am the root BTreeNode for now
-
- _recid = _btree._db.insert(this, this,false);
- }
-
-
- /**
- * Overflow node constructor. Creates an empty BTreeNode.
- */
- @SuppressWarnings("unchecked")
- BTreeNode(BTree btree, boolean isLeaf){
- _btree = btree;
-
- _isLeaf = isLeaf;
-
- // node will initially be half-full
- _first = BTree.DEFAULT_SIZE / 2;
-
- _keys = (K[]) new Object[BTree.DEFAULT_SIZE];
- if (isLeaf) {
- _values = new Object[BTree.DEFAULT_SIZE];
- } else {
- _children = new long[BTree.DEFAULT_SIZE];
- }
-
- try{
- _recid = _btree._db.insert(this, this,false);
- }catch(IOException e ){
- throw new IOError(e);
- }
- }
-
-
- /**
- * Get largest key under this BTreeNode. Null is considered to be the
- * greatest possible key.
- */
- K getLargestKey() {
- return _keys[BTree.DEFAULT_SIZE - 1];
- }
-
-
- /**
- * Return true if BTreeNode is empty.
- */
- boolean isEmpty() {
- if (_isLeaf) {
- return (_first == _values.length - 1);
- } else {
- return (_first == _children.length - 1);
- }
- }
-
-
- /**
- * Return true if BTreeNode is full.
- */
- boolean isFull() {
- return (_first == 0);
- }
-
-
- /**
- * Find the object associated with the given key.
- *
- * @param height Height of the current BTreeNode (zero is leaf node)
- * @param key The key
- * @return TupleBrowser positionned just before the given key, or before
- * next greater key if key isn't found.
- */
- BTree.BTreeTupleBrowser find(int height, final K key, final boolean inclusive)
- throws IOException {
- byte index = findChildren(key,inclusive);
-
- height -= 1;
-
- if (height == 0) {
- // leaf node
- return new Browser(this, index);
- } else {
- // non-leaf node
- BTreeNode child = loadNode(_children[index]);
- return child.find(height, key,inclusive);
- }
- }
-
-
- /**
- * Find value associated with the given key.
- *
- * @param height Height of the current BTreeNode (zero is leaf node)
- * @param key The key
- * @return TupleBrowser positionned just before the given key, or before
- * next greater key if key isn't found.
- */
- V findValue(int height, K key)
- throws IOException {
- byte index = findChildren(key,true);
-
- height -= 1;
-
- if (height == 0) {
-
- K key2 = _keys[index];
-// // get returns the matching key or the next ordered key, so we must
-// // check if we have an exact match
- if (key2 == null || compare(key, key2) != 0)
- return null;
-
- // leaf node
- if (_values[index] instanceof BTreeLazyRecord)
- return ((BTreeLazyRecord) _values[index]).get();
- else
- return (V) _values[index];
-
-
- } else {
- // non-leaf node
- BTreeNode child = loadNode(_children[index]);
- return child.findValue(height, key);
- }
- }
-
- /**
- * Find first entry and return a browser positioned before it.
- *
- * @return TupleBrowser positionned just before the first entry.
- */
- BTree.BTreeTupleBrowser findFirst()
- throws IOException {
- if (_isLeaf) {
- return new Browser(this, _first);
- } else {
- BTreeNode child = loadNode(_children[_first]);
- return child.findFirst();
- }
- }
-
- /**
- * Deletes this BTreeNode and all children nodes from the record manager
- */
- void delete()
- throws IOException {
- if (_isLeaf) {
- if (_next != 0) {
- BTreeNode nextNode = loadNode(_next);
- if (nextNode._previous == _recid) { // this consistency check can be removed in production code
- nextNode._previous = _previous;
- _btree._db.update(nextNode._recid, nextNode, nextNode);
- } else {
- throw new Error("Inconsistent data in BTree");
- }
- }
- if (_previous != 0) {
- BTreeNode previousNode = loadNode(_previous);
- if (previousNode._next != _recid) { // this consistency check can be removed in production code
- previousNode._next = _next;
- _btree._db.update(previousNode._recid, previousNode, previousNode);
- } else {
- throw new Error("Inconsistent data in BTree");
- }
- }
- } else {
- int left = _first;
- int right = BTree.DEFAULT_SIZE - 1;
-
- for (int i = left; i <= right; i++) {
- BTreeNode childNode = loadNode(_children[i]);
- childNode.delete();
- }
- }
-
- _btree._db.delete(_recid);
- }
-
- /**
- * Insert the given key and value.
- *
- * Since the Btree does not support duplicate entries, the caller must
- * specify whether to replace the existing value.
- *
- * @param height Height of the current BTreeNode (zero is leaf node)
- * @param key Insert key
- * @param value Insert value
- * @param replace Set to true to replace the existing value, if one exists.
- * @return Insertion result containing existing value OR a BTreeNode if the key
- * was inserted and provoked a BTreeNode overflow.
- */
- InsertResult insert(int height, K key, final V value, final boolean replace)
- throws IOException {
- InsertResult result;
- long overflow;
-
- final byte index = findChildren(key,true);
-
- height -= 1;
- if (height == 0) {
-
- //reuse InsertResult instance to avoid GC trashing on massive inserts
- result = _btree.insertResultReuse;
- _btree.insertResultReuse = null;
- if (result == null)
- result = new InsertResult();
-
- // inserting on a leaf BTreeNode
- overflow = -1;
- if (DEBUG) {
- System.out.println("BTreeNode.insert() Insert on leaf node key=" + key
- + " value=" + value + " index=" + index);
- }
- if (compare(_keys[index], key) == 0) {
- // key already exists
- if (DEBUG) {
- System.out.println("BTreeNode.insert() Key already exists.");
- }
- boolean isLazyRecord = _values[index] instanceof BTreeLazyRecord;
- if (isLazyRecord)
- result._existing = ((BTreeLazyRecord) _values[index]).get();
- else
- result._existing = (V) _values[index];
- if (replace) {
- //remove old lazy record if necesarry
- if (isLazyRecord)
- ((BTreeLazyRecord) _values[index]).delete();
- _values[index] = value;
- _btree._db.update(_recid, this, this);
- }
- // return the existing key
- return result;
- }
- } else {
- // non-leaf BTreeNode
- BTreeNode child = loadNode(_children[index]);
- result = child.insert(height, key, value, replace);
-
- if (result._existing != null) {
- // return existing key, if any.
- return result;
- }
-
- if (result._overflow == null) {
- // no overflow means we're done with insertion
- return result;
- }
-
- // there was an overflow, we need to insert the overflow node on this BTreeNode
- if (DEBUG) {
- System.out.println("BTreeNode.insert() Overflow node: " + result._overflow._recid);
- }
- key = result._overflow.getLargestKey();
- overflow = result._overflow._recid;
-
- // update child's largest key
- _keys[index] = child.getLargestKey();
-
- // clean result so we can reuse it
- result._overflow = null;
- }
-
- // if we get here, we need to insert a new entry on the BTreeNode before _children[ index ]
- if (!isFull()) {
- if (height == 0) {
- insertEntry(this, index - 1, key, value);
- } else {
- insertChild(this, index - 1, key, overflow);
- }
- _btree._db.update(_recid, this, this);
- return result;
- }
-
- // node is full, we must divide the node
- final byte half = BTree.DEFAULT_SIZE >> 1;
- BTreeNode newNode = new BTreeNode(_btree, _isLeaf);
- if (index < half) {
- // move lower-half of entries to overflow node, including new entry
- if (DEBUG) {
- System.out.println("BTreeNode.insert() move lower-half of entries to overflow BTreeNode, including new entry.");
- }
- if (height == 0) {
- copyEntries(this, 0, newNode, half, index);
- setEntry(newNode, half + index, key, value);
- copyEntries(this, index, newNode, half + index + 1, half - index - 1);
- } else {
- copyChildren(this, 0, newNode, half, index);
- setChild(newNode, half + index, key, overflow);
- copyChildren(this, index, newNode, half + index + 1, half - index - 1);
- }
- } else {
- // move lower-half of entries to overflow node, new entry stays on this node
- if (DEBUG) {
- System.out.println("BTreeNode.insert() move lower-half of entries to overflow BTreeNode. New entry stays");
- }
- if (height == 0) {
- copyEntries(this, 0, newNode, half, half);
- copyEntries(this, half, this, half - 1, index - half);
- setEntry(this, index - 1, key, value);
- } else {
- copyChildren(this, 0, newNode, half, half);
- copyChildren(this, half, this, half - 1, index - half);
- setChild(this, index - 1, key, overflow);
- }
- }
-
- _first = half - 1;
-
- // nullify lower half of entries
- for (int i = 0; i < _first; i++) {
- if (height == 0) {
- setEntry(this, i, null, null);
- } else {
- setChild(this, i, null, -1);
- }
- }
-
- if (_isLeaf) {
- // link newly created node
- newNode._previous = _previous;
- newNode._next = _recid;
- if (_previous != 0) {
- BTreeNode previous = loadNode(_previous);
- previous._next = newNode._recid;
- _btree._db.update(_previous, previous, this);
-
- }
- _previous = newNode._recid;
- }
-
- _btree._db.update(_recid, this, this);
- _btree._db.update(newNode._recid, newNode, this);
-
- result._overflow = newNode;
- return result;
- }
-
-
- /**
- * Remove the entry associated with the given key.
- *
- * @param height Height of the current BTreeNode (zero is leaf node)
- * @param key Removal key
- * @return Remove result object
- */
- RemoveResult remove(int height, K key)
- throws IOException {
- RemoveResult result;
-
- int half = BTree.DEFAULT_SIZE / 2;
- byte index = findChildren(key,true);
-
- height -= 1;
- if (height == 0) {
- // remove leaf entry
- if (compare(_keys[index], key) != 0) {
- throw new IllegalArgumentException("Key not found: " + key);
- }
- result = new RemoveResult();
-
- if (_values[index] instanceof BTreeLazyRecord) {
- BTreeLazyRecord r = (BTreeLazyRecord) _values[index];
- result._value = r.get();
- r.delete();
- } else {
- result._value = (V) _values[index];
- }
- removeEntry(this, index);
-
- // update this node
- _btree._db.update(_recid, this, this);
-
- } else {
- // recurse into Btree to remove entry on a children node
- BTreeNode child = loadNode(_children[index]);
- result = child.remove(height, key);
-
- // update children
- _keys[index] = child.getLargestKey();
- _btree._db.update(_recid, this, this);
-
- if (result._underflow) {
- // underflow occured
- if (child._first != half + 1) {
- throw new IllegalStateException("Error during underflow [1]");
- }
- if (index < _children.length - 1) {
- // exists greater brother node
- BTreeNode brother = loadNode(_children[index + 1]);
- int bfirst = brother._first;
- if (bfirst < half) {
- // steal entries from "brother" node
- int steal = (half - bfirst + 1) / 2;
- brother._first += steal;
- child._first -= steal;
- if (child._isLeaf) {
- copyEntries(child, half + 1, child, half + 1 - steal, half - 1);
- copyEntries(brother, bfirst, child, 2 * half - steal, steal);
- } else {
- copyChildren(child, half + 1, child, half + 1 - steal, half - 1);
- copyChildren(brother, bfirst, child, 2 * half - steal, steal);
- }
-
- for (int i = bfirst; i < bfirst + steal; i++) {
- if (brother._isLeaf) {
- setEntry(brother, i, null, null);
- } else {
- setChild(brother, i, null, -1);
- }
- }
-
- // update child's largest key
- _keys[index] = child.getLargestKey();
-
- // no change in previous/next node
-
- // update nodes
- _btree._db.update(_recid, this, this);
- _btree._db.update(brother._recid, brother, this);
- _btree._db.update(child._recid, child, this);
-
- } else {
- // move all entries from node "child" to "brother"
- if (brother._first != half) {
- throw new IllegalStateException("Error during underflow [2]");
- }
-
- brother._first = 1;
- if (child._isLeaf) {
- copyEntries(child, half + 1, brother, 1, half - 1);
- } else {
- copyChildren(child, half + 1, brother, 1, half - 1);
- }
- _btree._db.update(brother._recid, brother, this);
-
-
- // remove "child" from current node
- if (_isLeaf) {
- copyEntries(this, _first, this, _first + 1, index - _first);
- setEntry(this, _first, null, null);
- } else {
- copyChildren(this, _first, this, _first + 1, index - _first);
- setChild(this, _first, null, -1);
- }
- _first += 1;
- _btree._db.update(_recid, this, this);
-
- // re-link previous and next nodes
- if (child._previous != 0) {
- BTreeNode prev = loadNode(child._previous);
- prev._next = child._next;
- _btree._db.update(prev._recid, prev, this);
- }
- if (child._next != 0) {
- BTreeNode next = loadNode(child._next);
- next._previous = child._previous;
- _btree._db.update(next._recid, next, this);
-
- }
-
- // delete "child" node
- _btree._db.delete(child._recid);
- }
- } else {
- // node "brother" is before "child"
- BTreeNode brother = loadNode(_children[index - 1]);
- int bfirst = brother._first;
- if (bfirst < half) {
- // steal entries from "brother" node
- int steal = (half - bfirst + 1) / 2;
- brother._first += steal;
- child._first -= steal;
- if (child._isLeaf) {
- copyEntries(brother, 2 * half - steal, child,
- half + 1 - steal, steal);
- copyEntries(brother, bfirst, brother,
- bfirst + steal, 2 * half - bfirst - steal);
- } else {
- copyChildren(brother, 2 * half - steal, child,
- half + 1 - steal, steal);
- copyChildren(brother, bfirst, brother,
- bfirst + steal, 2 * half - bfirst - steal);
- }
-
- for (int i = bfirst; i < bfirst + steal; i++) {
- if (brother._isLeaf) {
- setEntry(brother, i, null, null);
- } else {
- setChild(brother, i, null, -1);
- }
- }
-
- // update brother's largest key
- _keys[index - 1] = brother.getLargestKey();
-
- // no change in previous/next node
-
- // update nodes
- _btree._db.update(_recid, this, this);
- _btree._db.update(brother._recid, brother, this);
- _btree._db.update(child._recid, child, this);
-
- } else {
- // move all entries from node "brother" to "child"
- if (brother._first != half) {
- throw new IllegalStateException("Error during underflow [3]");
- }
-
- child._first = 1;
- if (child._isLeaf) {
- copyEntries(brother, half, child, 1, half);
- } else {
- copyChildren(brother, half, child, 1, half);
- }
- _btree._db.update(child._recid, child, this);
-
- // remove "brother" from current node
- if (_isLeaf) {
- copyEntries(this, _first, this, _first + 1, index - 1 - _first);
- setEntry(this, _first, null, null);
- } else {
- copyChildren(this, _first, this, _first + 1, index - 1 - _first);
- setChild(this, _first, null, -1);
- }
- _first += 1;
- _btree._db.update(_recid, this, this);
-
- // re-link previous and next nodes
- if (brother._previous != 0) {
- BTreeNode prev = loadNode(brother._previous);
- prev._next = brother._next;
- _btree._db.update(prev._recid, prev, this);
- }
- if (brother._next != 0) {
- BTreeNode next = loadNode(brother._next);
- next._previous = brother._previous;
- _btree._db.update(next._recid, next, this);
- }
-
- // delete "brother" node
- _btree._db.delete(brother._recid);
- }
- }
- }
- }
-
- // underflow if node is more than half-empty
- result._underflow = _first > half;
-
- return result;
- }
-
-
- /**
- * Find the first children node with a key equal or greater than the given
- * key.
- *
- * @return index of first children with equal or greater key.
- */
- private byte findChildren(final K key, final boolean inclusive) {
- int left = _first;
- int right = BTree.DEFAULT_SIZE - 1;
- int middle;
- final int D = inclusive?0:1;
-
- // binary search
- while (true) {
- middle = (left + right) / 2;
- if (compare(_keys[middle], key) < D) {
- left = middle + 1;
- } else {
- right = middle;
- }
- if (left >= right) {
- return (byte) right;
- }
- }
- }
-
-
- /**
- * Insert entry at given position.
- */
- private static void insertEntry(BTreeNode node, int index,
- K key, V value) {
- K[] keys = node._keys;
- Object[] values = node._values;
- int start = node._first;
- int count = index - node._first + 1;
-
- // shift entries to the left
- System.arraycopy(keys, start, keys, start - 1, count);
- System.arraycopy(values, start, values, start - 1, count);
- node._first -= 1;
- keys[index] = key;
- values[index] = value;
- }
-
-
- /**
- * Insert child at given position.
- */
- private static