org.apache.jena.tdb.base.buffer.BufferBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jena-tdb Show documentation
Show all versions of jena-tdb Show documentation
TDB is a storage subsystem for Jena and ARQ, it is a native triple store providing persistent storage of triples/quads.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.jena.tdb.base.buffer;
import static java.lang.String.format ;
import static org.apache.jena.tdb.sys.SystemTDB.FillByte ;
import static org.apache.jena.tdb.sys.SystemTDB.NetworkOrder ;
import static org.apache.jena.tdb.sys.SystemTDB.NullOut ;
import java.nio.ByteBuffer ;
import org.apache.jena.atlas.lib.ByteBufferLib ;
import org.apache.jena.tdb.base.record.RecordException ;
/** ByteBuffer specialization - Common operations for RecordBuffer and PtrBuffer */
abstract class BufferBase
{
public static boolean CheckBuffer = false ;
protected ByteBuffer bb ;
protected int slotLen ;
protected int numSlot ; // Number of records in use
protected int maxSlot ; // Maximum number of records
protected BufferBase(ByteBuffer bb, int slotLen, int num)
{
if ( CheckBuffer )
{
if ( ! bb.order().equals(NetworkOrder) || !bb.hasArray() )
throw new RecordException("Duff buffer (byte order is not network order)") ;
if ( bb.limit() == 0 )
throw new RecordException("Duff buffer (zero length byte buffer)") ;
int size = bb.limit() ;
int slots = size/slotLen ;
if ( size%slotLen != 0 )
throw new RecordException(format("Misalinged buffer: size=%d, keyLen=%d",size, slotLen)) ;
if ( slots < num )
throw new RecordException(format("Wrong size: slots=%d, len=%d", slots, num)) ;
}
this.bb = bb ;
this.slotLen = slotLen ;
this.numSlot = num ;
this.maxSlot = bb.limit()/slotLen ;
if ( NullOut )
clear(numSlot, maxSlot-numSlot) ;
}
//private BufferBase() {}
// Why so many final methods? This code is performace critical and "final" methods
// can be inlined by the JIT - or just not have object dispatch done each time
// because the destination is fixed.
// (and here - there are quite a few assumed relationships of the ints).
final
public void copy(int srcIdx, BufferBase dst, int dstIdx, int len)
{
if ( len == 0 )
return ;
// Check end index is inside the buffer.
checkBounds(srcIdx+len-1, maxSlot) ;
BufferBase src = this ; // Clarity
if ( dst.numSlot < dstIdx-1 )
// Allow copy to be just off the end of dst.
throw new IllegalArgumentException(format("copy: Out of bounds: dstIdx=%d, dst size=%d", dstIdx, dst.numSlot)) ;
if ( src.slotLen != dst.slotLen )
throw new RecordException(format("copy: records of differnt sizes: %d, %d",src.slotLen, dst.slotLen)) ;
// How do we set the numRec in dst? max(dstIdx+len, old count)
ByteBufferLib.bbcopy(src.bb, srcIdx, dst.bb, dstIdx, len, slotLen) ;
dst.numSlot = Math.max(dstIdx+len, dst.numSlot) ;
}
final
public void copyToTop(BufferBase dst)
{
copy(0, dst, dst.numSlot, numSlot) ; }
/** Remove top element */
final public void removeTop()
{
if ( numSlot == 0 )
throw new IndexOutOfBoundsException("removeTop: empty buffer") ;
clear(numSlot-1) ;
numSlot-- ;
}
final public void remove(int idx) { shiftDown(idx) ; }
/** Does not reset the size */
final
public void clear(int idx, int len)
{
if ( NullOut )
ByteBufferLib.bbfill(bb, idx, (idx+len), FillByte, slotLen) ;
}
/** Does not reset the size */
final public void clear() { clear(0, maxSlot) ; numSlot = 0 ; }
/** Does not reset the size */
final public void clear(int idx) { clear(idx, 1) ; }
/** Is the record at idx set clear or not?
This is done without regard to buffer size.
Requires NullOut to be accurate.
Testing.
*/
final public boolean isClear(int idx)
{
checkBounds(idx, maxSlot) ;
int x = idx*slotLen ;
int y = (idx+1)*slotLen ;
for ( int i = x ; i < y ; i++ )
if ( bb.get(i) != FillByte )
{
// byte b = bb.get(i) ;
// lib.ByteBufferLib.print(bb) ;
return false ;
}
return true ;
}
final public boolean isFull()
{
return numSlot >= maxSlot ;
}
final public boolean isEmpty()
{
return numSlot == 0 ;
}
final public void incSize() { incSize(1) ; }
final public void incSize(int n)
{
if ( numSlot+n > maxSlot )
throw new IllegalArgumentException(format("inc(%d): out of range: max=%d", n, maxSlot)) ;
numSlot += n ;
}
final public void decSize() { decSize(1) ; }
final public void decSize(int n)
{
if ( numSlot-n < 0 )
throw new IllegalArgumentException(format("dec(%d): out of range: max=%d", n, maxSlot)) ;
numSlot -= n ;
}
final public int slotLen() { return slotLen ; }
final public int getSize() { return numSlot ; }
final public void setSize(int n)
{
if ( n < 0 || n > maxSlot )
throw new IllegalArgumentException(format("size(%d): out of range: max=%d", n, maxSlot)) ;
numSlot = n ;
}
final public int size() { return numSlot ; }
final public int maxSize() { return maxSlot ; }
final public void shiftUp(int idx) { shiftUpN(idx, 1) ; }
final public void shiftUpN(int idx, int num)
{
checkBounds(idx, numSlot) ;
if ( numSlot + num > maxSlot )
throw new IllegalArgumentException(format("Shift up(%d): out of range: len=%d max=%d", num, num, maxSlot)) ;
ByteBufferLib.bbcopy(bb, idx, idx+num, (numSlot-idx), slotLen) ; // src, dst
if ( NullOut )
clear(idx, num) ;
numSlot += num ;
}
final public void shiftDown(int idx) { shiftDownN(idx, 1) ; }
final public void shiftDownN(int idx, int num)
{
checkBounds(idx, numSlot) ;
if ( idx+num > numSlot )
throw new IllegalArgumentException(format("Shift down(%d,%d): out of range: len=%d", idx, num, num)) ;
ByteBufferLib.bbcopy(bb, idx+num, idx, (numSlot-num-idx), slotLen) ; // src, dst
if ( NullOut )
clear(numSlot-num, num) ;
numSlot -= num ;
}
// @Override
// final public String toString()
// {
// StringBuilder str = new StringBuilder() ;
// str.append(format("Len=%d Count=%d ", bb.limit()/recLen, num)) ;
//
// for ( int i = 0 ; i < max*recLen ; i++ )
// {
// if ( i != 0 && i%recLen == 0 )
// str.append(" ") ;
// byte b = bb.get(i) ;
// str.append(format("%02x", b)) ;
// }
// return str.toString() ;
// }
/** Move the element from the high end of this to the low end of other */
public void shiftRight(BufferBase other)
{
if ( other.numSlot >= other.maxSlot )
throw new BufferException("No space in destination buffer") ;
if ( numSlot <= 0 )
throw new BufferException("Empty buffer") ;
if ( other.numSlot > 0 )
other.shiftUp(0) ;
else
other.numSlot++ ;
// Copy high to low slot.
ByteBufferLib.bbcopy(bb, (numSlot-1), other.bb, 0, 1, slotLen) ;
removeTop() ;
}
/** Move the element from the low end of other to the high end of this */
public void shiftLeft(BufferBase other)
{
if ( numSlot >= maxSlot )
throw new BufferException("No space in destination buffer") ;
if ( other.numSlot <= 0 )
throw new BufferException("Empty buffer") ;
// Copy low to above high slot.
ByteBufferLib.bbcopy(other.bb, 0, bb, numSlot, 1, slotLen) ;
// Correct length.
numSlot ++ ;
other.shiftDown(0) ;
}
final private static void checkBounds(int idx, int len)
{
if ( idx < 0 || idx >= len )
throw new BufferException(format("Out of bounds: idx=%d, size=%d", idx, len)) ;
}
}