org.apache.jena.tdb.base.file.BufferChannelMem 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.file ;
import java.nio.ByteBuffer ;
import org.apache.jena.atlas.lib.ByteBufferLib ;
import org.apache.jena.tdb.base.StorageException ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
public class BufferChannelMem implements BufferChannel {
private static Logger log = LoggerFactory.getLogger(BufferChannelMem.class) ;
// The "file pointer" is the position of this buffer.
private ByteBuffer bytes ;
private String name ;
private static int INIT_SIZE = 1024 ;
private static int INC_SIZE = 1024 ;
private final boolean TRACKING ;
static public BufferChannel create() {
return new BufferChannelMem("unnamed") ;
}
static public BufferChannel create(String name) {
return new BufferChannelMem(name) ;
}
private BufferChannelMem() {
// Unitialized blank.
TRACKING = false ;
}
private BufferChannelMem(String name) {
bytes = ByteBuffer.allocate(1024) ;
bytes.limit(0) ;
this.name = name ;
TRACKING = false ;
// Debugging : pick a filename.
// TRACKING = name.endsWith("prefixes.dat") ;
}
@Override
synchronized public BufferChannel duplicate() {
BufferChannelMem chan = new BufferChannelMem() ;
int x = bytes.position() ;
bytes.rewind() ;
chan.bytes = bytes.slice() ;
chan.bytes.position(0) ;
bytes.position(x) ;
return chan ;
}
@Override
synchronized public long position() {
checkIfClosed() ;
return bytes.position() ;
}
@Override
synchronized public void position(long pos) {
checkIfClosed() ;
if ( pos < 0 || pos > bytes.capacity() )
throw new StorageException("Out of range: " + pos) ;
bytes.position((int)pos) ;
}
@Override
synchronized public int read(ByteBuffer buffer) {
checkIfClosed() ;
if ( TRACKING )
log("read<<[" + buffer.capacity() + "]") ;
int x = bytes.position() ;
int len = buffer.limit() - buffer.position() ;
if ( len > bytes.remaining() )
len = bytes.remaining() ;
// Copy out, moving the position of the bytes of stroage.
for (int i = 0; i < len; i++) {
byte b = bytes.get() ;
buffer.put(b) ;
}
if ( TRACKING )
log("read>>") ;
return len ;
}
@Override
synchronized public int read(ByteBuffer buffer, long loc) {
checkIfClosed() ;
if ( TRACKING )
log("read<<@" + loc) ;
if ( loc < 0 || loc > bytes.limit() )
throw new StorageException("Out of range(" + name + "[read]): " + loc + " [0," + bytes.limit() + ")") ;
if ( loc == bytes.limit() )
log.warn("At the limit(" + name + "[read]): " + loc) ;
int x = bytes.position() ;
bytes.position((int)loc) ;
int len = read(buffer) ;
bytes.position(x) ;
if ( TRACKING )
log("read>>@" + loc) ;
return len ;
}
@Override
synchronized public int write(ByteBuffer buffer) {
checkIfClosed() ;
if ( TRACKING )
log("write<<[" + buffer.capacity() + "]") ;
int len = buffer.limit() - buffer.position() ;
int posn = bytes.position() ;
int freespace = bytes.capacity() - bytes.position() ;
if ( len > freespace ) {
int inc = len - freespace ;
inc += INC_SIZE ;
ByteBuffer bb2 = ByteBuffer.allocate(bytes.capacity() + inc) ;
bytes.position(0) ;
// Copy contents; make written bytes area the same as before.
bb2.put(bytes) ;
bb2.limit(bytes.limit()) ; // limit is used as the end of active
// bytes.
bb2.position(posn) ;
bytes = bb2 ;
}
if ( bytes.limit() < posn + len )
bytes.limit(posn + len) ;
bytes.put(buffer) ;
if ( TRACKING )
log("write>>") ;
return len ;
}
// Invert : write(ByteBuffer) = write(ByteBuffer,posn)
@Override
synchronized public int write(ByteBuffer buffer, long loc) {
checkIfClosed() ;
if ( TRACKING )
log("write<<@" + loc) ;
if ( loc < 0 || loc > bytes.limit() )
// Can write at loc = bytes()
throw new StorageException("Out of range(" + name + "[write]): " + loc + " [0," + bytes.limit() + ")") ;
int x = bytes.position() ;
bytes.position((int)loc) ;
int len = write(buffer) ;
bytes.position(x) ;
if ( TRACKING )
log("write>>@" + loc) ;
return len ;
}
@Override
synchronized public void truncate(long size) {
checkIfClosed() ;
int x = (int)size ;
if ( x < 0 )
throw new StorageException("Out of range: " + size) ;
if ( x > bytes.limit() )
return ;
if ( bytes.position() > x )
bytes.position(x) ;
bytes.limit(x) ;
}
@Override
synchronized public long size() {
checkIfClosed() ;
return bytes.limit() ;
}
@Override
synchronized public boolean isEmpty() {
checkIfClosed() ;
return size() == 0 ;
}
@Override
synchronized public void sync() {
checkIfClosed() ;
}
@Override
synchronized public void close() {
checkIfClosed() ;
bytes = null ;
}
private void checkIfClosed() {
if ( bytes == null )
throw new StorageException("Closed: " + name) ;
}
@Override
synchronized public String getLabel() {
return name ;
}
@Override
synchronized public String toString() {
return name ;
}
@Override
public String getFilename() {
return null ;
}
private void log(String op) {
if ( TRACKING ) {
String msg = op + " [" + name + "] " + ByteBufferLib.details(bytes) ;
log.debug(msg) ;
}
}
}