/* This file is part of the db4o object database http://www.db4o.com
Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com
db4o is free software; you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published
by the Free Software Foundation.
db4o is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see http://www.gnu.org/licenses/. */
package com.db4o.internal.btree;
import com.db4o.foundation.*;
import com.db4o.internal.*;
/**
* @exclude
*/
public final class BTreePointer{
public static BTreePointer max(BTreePointer x, BTreePointer y) {
if (x == null) {
return x;
}
if (y == null) {
return y;
}
if (x.compareTo(y) > 0) {
return x;
}
return y;
}
public static BTreePointer min(BTreePointer x, BTreePointer y) {
if (x == null) {
return y;
}
if (y == null) {
return x;
}
if (x.compareTo(y) < 0) {
return x;
}
return y;
}
private BTreeNode _node;
private int _index;
private final Transaction _transaction;
private ByteArrayBuffer _nodeReader;
public BTreePointer shallowClone(){
return new BTreePointer(_transaction, _nodeReader, _node, _index);
}
public void copyTo(BTreePointer target) {
target._node = _node;
target._index = _index;
target._nodeReader = _nodeReader;
}
public BTreePointer(Transaction transaction, ByteArrayBuffer nodeReader, BTreeNode node, int index) {
if(transaction == null || node == null){
throw new ArgumentNullException();
}
_transaction = transaction;
_nodeReader = nodeReader;
_node = node;
_index = index;
}
public final int index(){
return _index;
}
public final BTreeNode node() {
return _node;
}
public final Object key() {
return _node.key(_transaction, _nodeReader, _index);
}
public BTreePointer next(){
int indexInMyNode = _index + 1;
while(indexInMyNode < _node.count()){
if(_node.indexIsValid(_transaction, indexInMyNode)){
return new BTreePointer(_transaction, _nodeReader, _node, indexInMyNode);
}
indexInMyNode ++;
}
int newIndex = -1;
BTreeNode nextNode = _node;
ByteArrayBuffer nextReader = null;
while(newIndex == -1){
nextNode = nextNode.nextNode();
if(nextNode == null){
return null;
}
nextReader = nextNode.prepareRead(_transaction);
newIndex = nextNode.firstKeyIndex(_transaction);
}
btree().convertCacheEvictedNodesToReadMode();
return new BTreePointer(_transaction, nextReader, nextNode, newIndex);
}
/**
* Duplicate code of next(), reusing this BTreePointer without creating a
* new BTreePointer, very dangerous to call because there may be side
* effects if this BTreePointer is used elsewhere and code relies on
* state the stay the same.
*/
public BTreePointer unsafeFastNext(){
int indexInMyNode = _index + 1;
while(indexInMyNode < _node.count()){
if(_node.indexIsValid(_transaction, indexInMyNode)){
_index = indexInMyNode;
return this;
}
indexInMyNode ++;
}
int newIndex = -1;
BTreeNode nextNode = _node;
ByteArrayBuffer nextReader = null;
while(newIndex == -1){
nextNode = nextNode.nextNode();
if(nextNode == null){
return null;
}
nextReader = nextNode.prepareRead(_transaction);
newIndex = nextNode.firstKeyIndex(_transaction);
}
btree().convertCacheEvictedNodesToReadMode();
_nodeReader = nextReader;
_node = nextNode;
_index = newIndex;
return this;
}
public BTreePointer previous() {
int indexInMyNode = _index - 1;
while(indexInMyNode >= 0){
if(_node.indexIsValid(_transaction, indexInMyNode)){
return new BTreePointer(_transaction, _nodeReader, _node, indexInMyNode);
}
indexInMyNode --;
}
int newIndex = -1;
BTreeNode previousNode = _node;
ByteArrayBuffer previousReader = null;
while(newIndex == -1){
previousNode = previousNode.previousNode();
if(previousNode == null){
return null;
}
previousReader = previousNode.prepareRead(_transaction);
newIndex = previousNode.lastKeyIndex(_transaction);
}
return new BTreePointer(_transaction, previousReader, previousNode, newIndex);
}
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(! (obj instanceof BTreePointer)){
return false;
}
BTreePointer other = (BTreePointer) obj;
if(_index != other._index){
return false;
}
return _node.equals(other._node);
}
public int hashCode() {
return _node.hashCode();
}
public String toString() {
return "BTreePointer(index=" + _index + ", node=" + _node + ")";
}
public int compareTo(BTreePointer y) {
if (null == y) {
throw new ArgumentNullException();
}
if (btree() != y.btree()) {
throw new IllegalArgumentException();
}
return btree().compareKeys(_transaction.context(), key(), y.key());
}
private BTree btree() {
return _node.btree();
}
public static boolean lessThan(BTreePointer x, BTreePointer y) {
return BTreePointer.min(x, y) == x
&& !equals(x, y);
}
public static boolean equals(BTreePointer x, BTreePointer y) {
if (x == null) {
return y == null;
}
return x.equals(y);
}
public boolean isValid() {
return _node.indexIsValid(_transaction, _index);
}
}