package org.wonderdb.block;
/*******************************************************************************
* Copyright 2013 Vilas Athavale
*
* 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.
*******************************************************************************/
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import org.apache.log4j.Logger;
import org.wonderdb.cache.impl.CacheEntryPinner;
import org.wonderdb.types.BlockPtr;
import org.wonderdb.types.DBType;
import org.wonderdb.types.ExtendedColumn;
import org.wonderdb.types.IndexKeyType;
import org.wonderdb.types.TypeMetadata;
import org.wonderdb.types.record.ObjectRecord;
import org.wonderdb.types.record.Record;
public abstract class BaseIndexBlock extends BaseBlock
implements IndexBlock {
BlockPtr parentPtr = null;
protected DBType maxKey = null;
public BaseIndexBlock(BlockPtr ptr) {
super(ptr);
}
public int findPosn(IndexQuery entry, boolean writeLock, Set<Object> pinnedBlocks, Stack<BlockPtr> callBlockStack) {
callBlockStack.push(this.getPtr());
int mid = Collections.binarySearch(getData(), entry, entry.getComparator());
if (mid < 0) {
mid = Math.abs(mid) -1;
}
return mid;
}
public DBType getMaxKey(TypeMetadata meta) {
readLock();
try {
if (maxKey == null) {
List<Record> list = getData();
if (list == null || list.size() == 0) {
maxKey = null;
return null;
} else {
Set<Object> pinnedBlocks = new HashSet<Object>();
try {
Record record = list.get(list.size()-1);
DBType value = null;
if (record instanceof ObjectRecord) {
DBType column = ((ObjectRecord) record).getColumn();
value = column;
if (value instanceof BlockPtr) {
IndexBlock block = (IndexBlock) BlockManager.getInstance().getBlock((BlockPtr) value, meta, pinnedBlocks);
maxKey = block.getMaxKey(meta);
} else if (value instanceof IndexKeyType) {
maxKey = value;
} else if (value instanceof ExtendedColumn) {
maxKey = ((ExtendedColumn) value).getValue(meta);
} else {
throw new RuntimeException("unexpected type received");
}
} else {
throw new RuntimeException("unexpected type received");
}
maxKey = maxKey.copyOf();
} finally {
CacheEntryPinner.getInstance().unpin(pinnedBlocks, pinnedBlocks);
}
}
}
} finally {
readUnlock();
}
if (maxKey == null) {
Logger.getLogger(getClass()).fatal("max key was null");
}
return maxKey;
}
public void addEntry(int posn, Record data) {
getData().add(posn, data);
if (posn+1 == getData().size()) {
this.setMaxKey(((ObjectRecord) data).getColumn());
}
}
public void setMaxKey(DBType key) {
if (key != null) {
maxKey = key.copyOf();
}
}
public BlockPtr getParent(Stack<BlockPtr> stack) {
return stack.isEmpty() ? null : stack.pop();
}
public void setParent(BlockPtr ptr) {
this.parentPtr = ptr != null ? (BlockPtr) ptr.copyOf() : null;
}
}