You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2017/10/03 19:34:33 UTC
[47/65] [abbrv] jena git commit: JENA-1397: Rename java packages
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrFileAccess.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrFileAccess.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrFileAccess.java
new file mode 100644
index 0000000..3f72585
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrFileAccess.java
@@ -0,0 +1,169 @@
+/*
+ * 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.dboe.base.block ;
+
+import static java.lang.String.format ;
+
+import org.apache.jena.atlas.lib.InternalErrorException ;
+import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.dboe.base.file.BlockAccess;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+/**
+ * Block manager that maps from the FileAccess layer to a BlockMgr. Add free
+ * block management (but we should layer with BlockMgrFreeChain)
+ */
+
+final public class BlockMgrFileAccess extends BlockMgrBase {
+ private static Logger log = LoggerFactory.getLogger(BlockMgrFileAccess.class) ;
+
+ private final BlockAccess file ;
+ private boolean closed = false ;
+ // Set on any write operations.
+ private boolean syncNeeded = false ;
+
+ // Create via the BlockMgrFactory.
+ /* package */BlockMgrFileAccess(BlockAccess blockAccess, int blockSize) {
+ super(blockAccess.getLabel(), blockSize) ;
+ file = blockAccess ;
+ }
+
+ @Override
+ protected Block allocate() {
+ syncNeeded = true ;
+ return file.allocate(blockSize) ;
+ }
+
+ @Override
+ public Block promote(Block block) {
+ return block ;
+ }
+
+ @Override
+ public Block getRead(long id) {
+ return getBlock(id, true) ;
+ }
+
+ @Override
+ public Block getWrite(long id) {
+ return getBlock(id, false) ;
+ }
+
+ private Block getBlock(long id, boolean readOnly) {
+ checkNotClosed() ;
+ Block block = file.read(id) ;
+ block.setReadOnly(readOnly) ;
+ return block ;
+ }
+
+ private void checkNotClosed() {
+ if ( closed )
+ throw new InternalErrorException(Lib.className(this)+" : already closed") ;
+ }
+
+ @Override
+ public void release(Block block) {
+ checkNotClosed() ;
+ }
+
+ @Override
+ public void write(Block block) {
+ checkNotClosed() ;
+ if ( block.isReadOnly() )
+ throw new BlockException("Attempt to write a read-only block ("+block.getId()+")" ) ;
+ syncNeeded = true ;
+ file.write(block) ;
+ }
+
+ @Override
+ public void overwrite(Block block) {
+ checkNotClosed() ;
+ syncNeeded = true ;
+ file.overwrite(block) ;
+ }
+
+ @Override
+ public void free(Block block) {
+ checkNotClosed() ;
+ // syncNeeded = true ;
+ // We do nothing about free blocks currently.
+ }
+
+ @Override
+ public boolean valid(int id) {
+ checkNotClosed() ;
+ return file.valid(id) ;
+ }
+
+ @Override
+ public void sync() {
+ checkNotClosed() ;
+ if ( syncNeeded )
+ file.sync() ;
+ else
+ syncNeeded = true ;
+ syncNeeded = false ;
+ }
+
+ @Override
+ public void syncForce() {
+ checkNotClosed() ;
+ file.sync() ;
+ }
+
+ @Override
+ public boolean isClosed() {
+ return closed ;
+ }
+
+ @Override
+ public void close() {
+ closed = true ;
+ file.close() ;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ checkNotClosed() ;
+ return file.isEmpty() ;
+ }
+
+ @Override
+ public long allocLimit() {
+ checkNotClosed() ;
+ return file.allocBoundary() ;
+ }
+
+ @Override
+ public void resetAlloc(long boundary) {
+ checkNotClosed() ;
+ file.resetAllocBoundary(boundary);
+ }
+
+ @Override
+ public String toString() {
+ return format("BlockMgrFileAccess[%d bytes]:%s", blockSize, file) ;
+ }
+
+ @Override
+ protected Logger log() {
+ return log ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrFreeChain.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrFreeChain.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrFreeChain.java
new file mode 100644
index 0000000..4612dd3
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrFreeChain.java
@@ -0,0 +1,84 @@
+/*
+ * 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.dboe.base.block ;
+
+import java.util.ArrayDeque ;
+import java.util.Deque ;
+
+/**
+ * Recycle blocks - but only in-session. At the end of JVM run, the blocks are
+ * made "permanent" as no one finds them again on restart.
+ */
+final public class BlockMgrFreeChain extends BlockMgrWrapper {
+ // Could keep Pair<Integer, ByteBuffer>
+ // List<Block> freeBlocks = new ArrayList<Block>() ;
+ private final Deque<Block> freeBlocks = new ArrayDeque<>() ; // Keep as heap?
+
+ public BlockMgrFreeChain(BlockMgr blockMgr) {
+ super(blockMgr) ;
+ }
+
+ @Override
+ public Block allocate(int blockSize) {
+ if ( !freeBlocks.isEmpty() ) {
+ Block block = freeBlocks.removeFirst() ;
+ block.getByteBuffer().position(0) ;
+ return block ;
+ }
+ return super.allocate(blockSize) ;
+ }
+
+ @Override
+ public void free(Block block) {
+ if ( block.getId() >= blockMgr.allocLimit() )
+ freeBlocks.add(block) ;
+ }
+
+ @Override
+ public void resetAlloc(long boundary) {
+ super.resetAlloc(boundary);
+ // Just clear - assumes this is effectively a transaction boundary.
+ freeBlocks.clear();
+// Iterator<Block> iter = freeBlocks.iterator() ;
+// while(iter.hasNext()) {
+// Block blk = iter.next() ;
+// if ( blk.getId() < boundary )
+// iter.remove();
+// }
+ }
+ @Override
+ public boolean valid(int id) {
+ for ( Block blk : freeBlocks ) {
+ if ( blk.getId() == id )
+ return true ;
+ }
+ return super.valid(id) ;
+ }
+
+ @Override
+ public void sync() {
+ // Flush free blocks?
+ super.sync() ;
+ }
+
+ @Override
+ public String toString() {
+ return "Free:" + super.toString() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrLogger.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrLogger.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrLogger.java
new file mode 100644
index 0000000..b72d143
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrLogger.java
@@ -0,0 +1,181 @@
+/*
+ * 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.dboe.base.block ;
+
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+public class BlockMgrLogger implements BlockMgr // extends BlockMgrWrapper
+{
+ private final BlockMgr blockMgr ;
+ protected final Logger log ;
+ protected final boolean logAllOperations ;
+ private final String label ;
+
+ public BlockMgrLogger(BlockMgr blockMgr, boolean logAllOperations) {
+ this(null, blockMgr.getLabel(), blockMgr, logAllOperations) ;
+ }
+
+ public BlockMgrLogger(String label, BlockMgr blockMgr, boolean logAllOperations) {
+ this(null, label, blockMgr, logAllOperations) ;
+ }
+
+ public BlockMgrLogger(Logger log, String label, BlockMgr blockMgr, boolean logAllOperations) {
+ this.blockMgr = blockMgr ;
+ if ( log == null )
+ log = LoggerFactory.getLogger(BlockMgr.class) ;
+ this.log = log ;
+ this.logAllOperations = logAllOperations ;
+ if ( label == null )
+ label = blockMgr.getLabel() ;
+ this.label = label ;
+ }
+
+ @Override
+ public String getLabel() {
+ return label ;
+ }
+
+ @Override
+ public Block allocate(int blockSize) {
+ Block x = blockMgr.allocate(blockSize) ;
+ info("Allocate(" + x.getId() + ")") ;
+ return x ;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ info("isEmpty()") ;
+ return blockMgr.isEmpty() ;
+ }
+
+ @Override
+ public long allocLimit() {
+ info("limit()") ;
+ return blockMgr.allocLimit() ;
+ }
+
+ @Override
+ public void resetAlloc(long boundary) {
+ info("resetAlloc("+boundary+")") ;
+ blockMgr.resetAlloc(boundary) ;
+ }
+
+ @Override
+ public Block getRead(long id) {
+ info("getRead(" + id + ")") ;
+ return blockMgr.getRead(id) ;
+ }
+
+ @Override
+ public Block getWrite(long id) {
+ info("getWrite(" + id + ")") ;
+ return blockMgr.getWrite(id) ;
+ }
+
+ @Override
+ public Block promote(Block block) {
+ info("promote(" + block.getId() + ")") ;
+ return blockMgr.promote(block) ;
+ }
+
+ @Override
+ public void release(Block block) {
+ info("release(" + block.getId() + ")") ;
+ blockMgr.release(block) ;
+ }
+
+ @Override
+ public void write(Block block) {
+ info("write(" + block.getId() + ")") ;
+ blockMgr.write(block) ;
+ }
+
+ @Override
+ public void overwrite(Block block) {
+ info("overwrite(" + block.getId() + ")") ;
+ blockMgr.overwrite(block) ;
+ }
+
+ @Override
+ public void free(Block block) {
+ info("freeBlock(" + block.getId() + ")") ;
+ blockMgr.free(block) ;
+ }
+
+ @Override
+ public boolean valid(int id) {
+ info("valid(" + id + ")") ;
+ return blockMgr.valid(id) ;
+ }
+
+ @Override
+ public void close() {
+ info("close") ;
+ blockMgr.close() ;
+ }
+
+ @Override
+ public boolean isClosed() {
+ info("isClosed") ;
+ return blockMgr.isClosed() ;
+ }
+
+ @Override
+ public void sync() {
+ info("sync") ;
+ blockMgr.sync() ;
+ }
+
+ @Override
+ public void syncForce() {
+ info("syncForce") ;
+ blockMgr.syncForce() ;
+ }
+
+ @Override
+ public void beginRead() {
+ info("> start read") ;
+ blockMgr.beginRead() ;
+ }
+
+ @Override
+ public void endRead() {
+ info("< finish read") ;
+ blockMgr.endRead() ;
+ }
+
+ @Override
+ public void beginUpdate() {
+ info("> start update") ;
+ blockMgr.beginUpdate() ;
+ }
+
+ @Override
+ public void endUpdate() {
+ info("< finish update") ;
+ blockMgr.endUpdate() ;
+ }
+
+ private void info(String string) {
+ if ( label != null )
+ string = label + ": " + string ;
+ log.info(string) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrReadonly.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrReadonly.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrReadonly.java
new file mode 100644
index 0000000..d3239c0
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrReadonly.java
@@ -0,0 +1,45 @@
+/*
+ * 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.dboe.base.block;
+
+import org.apache.jena.dboe.DBOpEnvException;
+
+public class BlockMgrReadonly extends BlockMgrWrapper
+{
+ public BlockMgrReadonly(BlockMgr blockMgr) {
+ super(blockMgr) ;
+ }
+
+ @Override public void beginUpdate() { throw new DBOpEnvException("Read-only block manager") ; }
+ @Override public void endUpdate() { throw new DBOpEnvException("Read-only block manager") ; }
+ @Override public Block allocate(int blockSize) { throw new DBOpEnvException("Read-only block manager") ; }
+ @Override public Block getWrite(long id) { throw new DBOpEnvException("Read-only block manager") ; }
+ @Override public Block promote(Block block) { throw new DBOpEnvException("Read-only block manager") ; }
+ @Override public void write(Block block) { throw new DBOpEnvException("Read-only block manager") ; }
+ @Override public void overwrite(Block block) { throw new DBOpEnvException("Read-only block manager") ; }
+ @Override public void free(Block block) { throw new DBOpEnvException("Read-only block manager") ; }
+
+// @Override
+// public void sync()
+// {
+// blockMgr.sync() ;
+// }
+
+ @Override public String toString() { return "RO:"+super.toString() ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrSwitcher.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrSwitcher.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrSwitcher.java
new file mode 100644
index 0000000..152ffb8
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrSwitcher.java
@@ -0,0 +1,40 @@
+/*
+ * 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.dboe.base.block;
+
+public class BlockMgrSwitcher extends BlockMgrWrapper
+{
+ protected final BlockMgr blockMgr1 ;
+ protected final BlockMgr blockMgr2 ;
+
+ public BlockMgrSwitcher(BlockMgr blockMgr1, BlockMgr blockMgr2)
+ {
+ super(blockMgr1) ;
+ this.blockMgr1 = blockMgr1 ;
+ this.blockMgr2 = blockMgr2 ;
+ }
+
+ public void switchover()
+ {
+ if ( super.blockMgr == blockMgr1 )
+ setBlockMgr(blockMgr2) ;
+ else
+ setBlockMgr(blockMgr1) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrSync.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrSync.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrSync.java
new file mode 100644
index 0000000..8d40eb8
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrSync.java
@@ -0,0 +1,149 @@
+/*
+ * 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.dboe.base.block ;
+
+
+/**
+ * Add synchronized to a BlockMgr. This is the same as BlockMgrWrapper but with
+ * 'synchronized' added
+ */
+
+public class BlockMgrSync implements BlockMgr {
+ protected final BlockMgr blockMgr ;
+
+ public BlockMgrSync(BlockMgr blockMgr) {
+ this.blockMgr = blockMgr ;
+ }
+
+ public BlockMgr getWrapped() {
+ return blockMgr ;
+ }
+
+ @Override
+ synchronized public Block allocate(int blockSize) {
+ return blockMgr.allocate(blockSize) ;
+ }
+
+ @Override
+ synchronized public Block getRead(long id) {
+ return blockMgr.getRead(id) ;
+ }
+
+ @Override
+ synchronized public Block getWrite(long id) {
+ return blockMgr.getWrite(id) ;
+ }
+
+ @Override
+ synchronized public Block promote(Block block) {
+ return blockMgr.promote(block) ;
+ }
+
+ @Override
+ synchronized public void release(Block block) {
+ blockMgr.release(block) ;
+ }
+
+ @Override
+ synchronized public void write(Block block) {
+ blockMgr.write(block) ;
+ }
+
+ @Override
+ synchronized public void overwrite(Block block) {
+ blockMgr.overwrite(block) ;
+ }
+
+ @Override
+ synchronized public void free(Block block) {
+ blockMgr.free(block) ;
+ }
+
+ @Override
+ synchronized public void sync() {
+ blockMgr.sync() ;
+ }
+
+ @Override
+ synchronized public void syncForce() {
+ blockMgr.syncForce() ;
+ }
+
+ @Override
+ synchronized public void close() {
+ blockMgr.close() ;
+ }
+
+ @Override
+ synchronized public boolean isEmpty() {
+ return blockMgr.isEmpty() ;
+ }
+
+ @Override
+ synchronized public long allocLimit() {
+ return blockMgr.allocLimit() ;
+ }
+
+
+ @Override
+ synchronized public void resetAlloc(long boundary) {
+ blockMgr.resetAlloc(boundary) ;
+ }
+
+ @Override
+ synchronized public void beginRead() {
+ blockMgr.beginRead() ;
+ }
+
+ @Override
+ synchronized public void endRead() {
+ blockMgr.endRead() ;
+ }
+
+ @Override
+ synchronized public void beginUpdate() {
+ blockMgr.beginUpdate() ;
+ }
+
+ @Override
+ synchronized public void endUpdate() {
+ blockMgr.endUpdate() ;
+ }
+
+ @Override
+ synchronized public boolean valid(int id) {
+ return blockMgr.valid(id) ;
+ }
+
+ @Override
+ synchronized public boolean isClosed() {
+ return blockMgr.isClosed() ;
+ }
+
+ @Override
+ synchronized public String getLabel() {
+ return blockMgr.getLabel() ;
+ }
+
+ @Override
+ public String toString() {
+ return "Sync:" + blockMgr.toString() ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrTracker.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrTracker.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrTracker.java
new file mode 100644
index 0000000..c3a167e
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrTracker.java
@@ -0,0 +1,414 @@
+/*
+ * 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.dboe.base.block ;
+
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.Alloc;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.BeginRead;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.BeginUpdate;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.EndRead;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.EndUpdate;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.Free;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.GetRead;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.GetWrite;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.Promote;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.Release;
+import static org.apache.jena.dboe.base.block.BlockMgrTracker.Action.Write;
+
+import java.util.ArrayList ;
+import java.util.List ;
+
+import org.apache.jena.atlas.lib.Pair ;
+import org.apache.jena.dboe.DBOpEnvException;
+import org.apache.jena.ext.com.google.common.collect.HashMultiset ;
+import org.apache.jena.ext.com.google.common.collect.Multiset ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+public class BlockMgrTracker /* extends BlockMgrWrapper */ implements BlockMgr {
+ private static Logger loggerDefault = LoggerFactory.getLogger(BlockMgrTracker.class) ;
+ public static boolean verbose = false ;
+
+ static enum Action {
+ Alloc, Promote, GetRead, GetWrite, Write, Release, Free,
+ BeginRead, EndRead,
+ BeginUpdate, EndUpdate
+ }
+ static final Long NoId = (long)-9 ;
+
+ // ---- State for tracking
+ // Track and count block references and releases
+ // No - the page is dirty.
+
+
+ protected final Multiset<Long> activeReadBlocks = HashMultiset.create() ;
+ protected final Multiset<Long> activeWriteBlocks = HashMultiset.create() ;
+ // Track the operations
+ protected final List<Pair<Action, Long>> actions = new ArrayList<>() ;
+ // ---- State for tracking
+
+ protected final BlockMgr blockMgr ;
+
+ private void clearInternalRW() {
+ activeReadBlocks.clear() ;
+ activeWriteBlocks.clear() ;
+ actions.clear() ;
+ }
+
+ private void clearInternalIter() {
+ clearInternalRW() ;
+ }
+
+ private int inRead = 0 ;
+ private boolean inUpdate = false ;
+ private boolean inBatch = false ;
+ private final Logger log ;
+ private final String label ;
+
+ public static BlockMgr track(BlockMgr blkMgr) {
+ return track(blkMgr.getLabel(), blkMgr) ;
+ }
+
+ private static BlockMgr track(String label, BlockMgr blkMgr) {
+ return new BlockMgrTracker(label, blkMgr) ;
+ }
+
+ private BlockMgrTracker(BlockMgr blockMgr) {
+ this(LoggerFactory.getLogger(BlockMgrTracker.class), blockMgr.getLabel(), blockMgr) ;
+ }
+
+ private BlockMgrTracker(String label, BlockMgr blockMgr) {
+ this(loggerDefault, label, blockMgr) ;
+ }
+
+ //
+ // public BlockMgrTracker(Class<?> cls, String label, BlockMgr blockMgr)
+ // {
+ // this(LoggerFactory.getLogger(cls), label, blockMgr) ;
+ // }
+
+ private BlockMgrTracker(Logger logger, String label, BlockMgr blockMgr) {
+ this.blockMgr = blockMgr ;
+ this.log = logger ;
+ this.label = blockMgr.getLabel() ;
+ }
+
+ private void add(Action action, Long id) {
+ actions.add(new Pair<>(action, id)) ;
+ }
+
+ @Override
+ public Block allocate(int blockSize) {
+ Block block ;
+ synchronized (this) {
+ checkUpdate(Alloc) ;
+ block = blockMgr.allocate(blockSize) ;
+ Long id = block.getId() ;
+ activeWriteBlocks.add(id) ;
+ add(Alloc, id) ;
+ }
+ return block ;
+ }
+
+ @Override
+ public Block getRead(long id) {
+ // What if this is a write block already?
+ synchronized (this) {
+ checkRead(GetRead) ;
+ Long x = id ;
+ add(GetRead, x) ;
+
+ if ( activeWriteBlocks.contains(x) )
+ activeWriteBlocks.add(x) ;
+ else
+ activeReadBlocks.add(x) ;
+ }
+ return blockMgr.getRead(id) ;
+ }
+
+ @Override
+ public Block getWrite(long id) {
+ synchronized (this) {
+ checkUpdate(GetWrite) ;
+ Long x = id ;
+ add(GetWrite, x) ;
+ activeWriteBlocks.add(x) ;
+ }
+ return blockMgr.getWrite(id) ;
+ }
+
+ @Override
+ public Block promote(Block block) {
+ synchronized (this) {
+ checkUpdate(Promote) ;
+ Long id = block.getId() ;
+ add(Promote, id) ;
+
+ if ( !activeWriteBlocks.contains(id) && !activeReadBlocks.contains(id) )
+ error(Promote, id + " is not an active block") ;
+
+ if ( activeReadBlocks.contains(id) )
+ // Remove one read count
+ // Really, do this if obtained via "getRead" and not "getWrite"
+ activeReadBlocks.remove(id) ;
+
+ // Double promotion results in only one entry.
+ if ( !activeWriteBlocks.contains(id) )
+ activeWriteBlocks.add(id) ;
+ }
+ return blockMgr.promote(block) ;
+ }
+
+ @Override
+ public void release(Block block) {
+ synchronized (this) {
+ checkRead(Release) ;
+ Long id = block.getId() ;
+ add(Release, id) ;
+
+ if ( !activeReadBlocks.contains(id) && !activeWriteBlocks.contains(id) )
+ error(Release, id + " is not an active block") ;
+
+ // May have been promoted.
+ if ( activeWriteBlocks.contains(id) )
+ activeWriteBlocks.remove(id) ;
+ else
+ activeReadBlocks.remove(block.getId()) ;
+ }
+ blockMgr.release(block) ;
+ }
+
+ @Override
+ public void write(Block block) {
+ writeTracker(block) ;
+ blockMgr.write(block) ;
+ }
+
+ @Override
+ synchronized public void overwrite(Block block) {
+ writeTracker(block) ;
+ blockMgr.overwrite(block) ;
+ }
+
+ private void writeTracker(Block block) {
+ synchronized (this) {
+ checkUpdate(Write) ;
+ Long id = block.getId() ;
+ add(Write, id) ;
+ if ( !activeWriteBlocks.contains(id) )
+ error(Write, id + " is not an active write block") ;
+ }
+ }
+
+ @Override
+ public void free(Block block) {
+ synchronized (this) {
+ checkUpdate(Free) ;
+ Long id = block.getId() ;
+ add(Free, id) ;
+ if ( activeReadBlocks.contains(id) )
+ error(Free, id + " is a read block") ;
+ else if ( !activeWriteBlocks.contains(id) )
+ error(Free, id + " is not a write block") ;
+ activeWriteBlocks.remove(id) ;
+ }
+ blockMgr.free(block) ;
+ }
+
+ @Override
+ public void sync() {
+ blockMgr.sync() ;
+ }
+
+ @Override
+ public void syncForce() {
+ blockMgr.syncForce() ;
+ }
+
+ @Override
+ public void close() {
+ blockMgr.close() ;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return blockMgr.isEmpty() ;
+ }
+
+ @Override
+ public long allocLimit() {
+ return blockMgr.allocLimit() ;
+ }
+
+ @Override
+ public void resetAlloc(long boundary) {
+ blockMgr.resetAlloc(boundary) ;
+ }
+
+ @Override
+ public boolean valid(int id) {
+ return blockMgr.valid(id) ;
+ }
+
+ @Override
+ public boolean isClosed() {
+ return blockMgr.isClosed() ;
+ }
+
+ @Override
+ synchronized public void beginRead() {
+ synchronized (this) {
+ if ( inUpdate )
+ error(BeginRead, "beginRead when already in update") ;
+ inRead++ ;
+ inUpdate = false ;
+ }
+ blockMgr.beginRead() ;
+ }
+
+ @Override
+ synchronized public void endRead() {
+ synchronized (this) {
+ if ( inRead == 0 )
+ error(EndRead, "endRead but not in read") ;
+ if ( inUpdate )
+ error(EndRead, "endRead when in update") ;
+
+ checkEmpty("Outstanding write blocks at end of read operations!", activeWriteBlocks) ;
+
+ if ( inRead == 0 ) {
+ // Check at end of multiple reads or a write
+ checkEmpty("Outstanding read blocks at end of read operations", activeReadBlocks) ;
+ clearInternalRW() ;
+ }
+
+ inUpdate = false ;
+ inRead-- ;
+ }
+ blockMgr.endRead() ;
+ }
+
+ @Override
+ public void beginUpdate() {
+ synchronized (this) {
+ if ( inRead > 0 )
+ error(BeginUpdate, "beginUpdate when already in read") ;
+ if ( inUpdate )
+ error(BeginUpdate, "beginUpdate when already in update") ;
+ inUpdate = true ;
+ }
+ blockMgr.beginUpdate() ;
+ }
+
+ @Override
+ public void endUpdate() {
+ synchronized (this) {
+ if ( !inUpdate )
+ error(EndUpdate, "endUpdate but not in update") ;
+ if ( inRead > 0 )
+ error(EndUpdate, "endUpdate when in read") ;
+
+ checkEmpty("Outstanding read blocks at end of update operations", activeReadBlocks) ;
+
+ checkEmpty("Outstanding write blocks at end of update operations", activeWriteBlocks) ;
+
+ inUpdate = false ;
+ inRead = 0 ;
+ clearInternalRW() ;
+ }
+ blockMgr.endUpdate() ;
+ }
+
+ private void checkUpdate(Action action) {
+// if ( ! inBatch )
+// warn(action, "update called outside a batch") ;
+ if ( ! inUpdate )
+ error(action, "called outside update") ;
+ }
+
+ private void checkRead(Action action) {
+ if ( !inUpdate && inRead == 0 )
+ error(action, "Called outside update and read") ;
+ }
+
+ private void checkEmpty(String string, Multiset<Long> blocks) {
+ if ( !blocks.isEmpty() ) {
+ error(string) ;
+ for ( Long id : blocks )
+ info(" Block: " + id) ;
+ history() ;
+ throw new DBOpEnvException() ;
+ // debugPoint() ;
+ }
+ }
+
+ private String msg(String string) {
+ if ( label == null )
+ return string ;
+ return label + ": " + string ;
+ }
+
+ private void info(String string) {
+ log.info(msg(string)) ;
+ }
+
+ private void warn(String string) {
+ log.warn(msg(string)) ;
+ }
+
+ private void warn(Action action, String string) {
+ warn(action + ": " + string) ;
+ }
+
+ private void error(String string) {
+ log.error(msg(string)) ;
+ }
+
+ private void error(Action action, String string) {
+ if ( verbose ) {
+ error(action + ": " + string) ;
+ history() ;
+ }
+ throw new BlockException(msg(action + ": " + string)) ;
+ // debugPoint() ;
+ }
+
+ // Do nothing - but use a a breakpoint point.
+ private void debugPoint() {}
+
+ private void history() {
+ info("History") ;
+ for ( Pair<Action, Long> p : actions ) {
+ if ( p.getRight() != NoId )
+ log.info(String.format("%s: %-12s %d", label, p.getLeft(), p.getRight())) ;
+ else
+ log.info(String.format("%s: %-12s", label, p.getLeft())) ;
+
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "BlockMgrTracker" + ((label == null) ? "" : (": " + label)) ;
+ }
+
+ @Override
+ public String getLabel() {
+ return label ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrWrapper.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrWrapper.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrWrapper.java
new file mode 100644
index 0000000..3fef19e
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockMgrWrapper.java
@@ -0,0 +1,149 @@
+/*
+ * 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.dboe.base.block ;
+
+
+public class BlockMgrWrapper implements BlockMgr {
+ protected BlockMgr blockMgr ;
+
+ public BlockMgrWrapper(BlockMgr blockMgr) {
+ setBlockMgr(blockMgr) ;
+ }
+
+ /** Set another BlockMgr as the target of the wrapper - return the old one */
+ protected final BlockMgr setBlockMgr(BlockMgr blockMgr) {
+ BlockMgr old = this.blockMgr ;
+ this.blockMgr = blockMgr ;
+ return old ;
+ }
+
+ public BlockMgr getWrapped() {
+ return blockMgr ;
+ }
+
+ @Override
+ public Block allocate(int blockSize) {
+ return blockMgr.allocate(blockSize) ;
+ }
+
+ @Override
+ public Block getRead(long id) {
+ return blockMgr.getRead(id) ;
+ }
+
+ @Override
+ public Block getWrite(long id) {
+ return blockMgr.getWrite(id) ;
+ }
+
+ @Override
+ public Block promote(Block block) {
+ return blockMgr.promote(block) ;
+ }
+
+ @Override
+ public void release(Block block) {
+ blockMgr.release(block) ;
+ }
+
+ @Override
+ public void write(Block block) {
+ blockMgr.write(block) ;
+ }
+
+ @Override
+ public void overwrite(Block block) {
+ blockMgr.overwrite(block) ;
+ }
+
+ @Override
+ public void free(Block block) {
+ blockMgr.free(block) ;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return blockMgr.isEmpty() ;
+ }
+
+ @Override
+ public long allocLimit() {
+ return blockMgr.allocLimit() ;
+ }
+
+ @Override
+ public void resetAlloc(long boundary) {
+ blockMgr.resetAlloc(boundary) ;
+ }
+
+ @Override
+ public void sync() {
+ blockMgr.sync() ;
+ }
+
+ @Override
+ public void syncForce() {
+ blockMgr.syncForce() ;
+ }
+
+ @Override
+ public boolean valid(int id) {
+ return blockMgr.valid(id) ;
+ }
+
+ @Override
+ public boolean isClosed() {
+ return blockMgr.isClosed() ;
+ }
+
+ @Override
+ public void close() {
+ blockMgr.close() ;
+ }
+
+ @Override
+ public void beginRead() {
+ blockMgr.beginRead() ;
+ }
+
+ @Override
+ public void endRead() {
+ blockMgr.endRead() ;
+ }
+
+ @Override
+ public void beginUpdate() {
+ blockMgr.beginUpdate() ;
+ }
+
+ @Override
+ public void endUpdate() {
+ blockMgr.endUpdate() ;
+ }
+
+ @Override
+ public String getLabel() {
+ return blockMgr.getLabel() ;
+ }
+
+ @Override
+ public String toString() {
+ return blockMgr.toString() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockParams.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockParams.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockParams.java
new file mode 100644
index 0000000..26242d0
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockParams.java
@@ -0,0 +1,27 @@
+/*
+ * 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.dboe.base.block;
+
+public interface BlockParams {
+ public FileMode getFileMode() ;
+ public Integer getBlockSize() ;
+ public Integer getBlockReadCacheSize() ;
+ public Integer getBlockWriteCacheSize() ;
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockType.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockType.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockType.java
new file mode 100644
index 0000000..ec9c1f5
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/BlockType.java
@@ -0,0 +1,68 @@
+/*
+ * 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.dboe.base.block;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.io.Printable ;
+import org.apache.jena.dboe.DBOpEnvException;
+import org.apache.jena.sparql.util.Named ;
+
+public enum BlockType implements Printable, Named
+{
+ // The id should fit into an unsigned byte.
+ FREE(-1, "Free"),
+ BTREE_NODE(5, "BTreeNode") ,
+ BPTREE_BRANCH(6, "BPlusTreeBranch") ,
+ BPTREE_LEAF(7, "BPlusTreeLeaf") ,
+ DICTIONARY(10, "Dictionary") ,
+ RECORD_BLOCK(99, "RecordBlock"),
+ UNDEF(255, "UndefinedBlockType")
+ ;
+
+ private final int id ;
+ private final String name ;
+
+ BlockType(int id, String name)
+ {
+ this.id = id ;
+ this.name = name ;
+
+ }
+
+ @Override
+ public void output(IndentedWriter out)
+ { out.print(getName()) ; }
+
+ final public int id() { return id ; }
+
+ @Override
+ final public String getName() { return name ; }
+
+ @Override public String toString() { return getName() ; }
+
+ public static BlockType extract(int x)
+ {
+ if ( x == BTREE_NODE.id() ) return BTREE_NODE ;
+ if ( x == BPTREE_BRANCH.id() ) return BPTREE_BRANCH ;
+ if ( x == BPTREE_LEAF.id() ) return BPTREE_LEAF ;
+ if ( x == RECORD_BLOCK.id() ) return RECORD_BLOCK ;
+ if ( x == DICTIONARY.id() ) return DICTIONARY ;
+ throw new DBOpEnvException("No known block type for "+x) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/FileMode.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/FileMode.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/FileMode.java
new file mode 100644
index 0000000..cccd1a1
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/block/FileMode.java
@@ -0,0 +1,27 @@
+/*
+ * 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.dboe.base.block;
+
+public enum FileMode
+{
+ /** Use memory mapped files */
+ mapped,
+ /** Use in-JVM caching */
+ direct ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/BufferBase.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/BufferBase.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/BufferBase.java
new file mode 100644
index 0000000..f42fffd
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/BufferBase.java
@@ -0,0 +1,263 @@
+/*
+ * 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.dboe.base.buffer;
+
+import static java.lang.String.format ;
+import static org.apache.jena.dboe.sys.Sys.NetworkOrder;
+import static org.apache.jena.dboe.sys.SystemIndex.FillByte;
+import static org.apache.jena.dboe.sys.SystemIndex.NullOut;
+
+import java.nio.ByteBuffer ;
+
+import org.apache.jena.atlas.lib.ByteBufferLib ;
+import org.apache.jena.dboe.base.record.RecordException;
+
+
+/** ByteBuffer specialization - Common operations for RecordBuffer and PtrBuffer */
+abstract class BufferBase
+{
+ public static final boolean CheckBuffer = false ;
+
+ protected ByteBuffer bb ;
+ protected int slotLen ;
+ protected int numSlot ; // Number of records in use
+ protected final 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("Misaligned 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 ( ! bb.isReadOnly() && NullOut )
+ clear(numSlot, maxSlot-numSlot) ;
+ }
+
+ // 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)) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/BufferException.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/BufferException.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/BufferException.java
new file mode 100644
index 0000000..9aafc2d
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/BufferException.java
@@ -0,0 +1,27 @@
+/*
+ * 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.dboe.base.buffer;
+
+public class BufferException extends RuntimeException
+{
+ public BufferException() { super() ; }
+ public BufferException(String msg) { super(msg) ; }
+ public BufferException(Throwable th) { super(th) ; }
+ public BufferException(String msg, Throwable th) { super(msg, th) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/PtrBuffer.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/PtrBuffer.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/PtrBuffer.java
new file mode 100644
index 0000000..5aefeba
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/PtrBuffer.java
@@ -0,0 +1,125 @@
+/*
+ * 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.dboe.base.buffer ;
+
+import static java.lang.String.format ;
+
+import java.nio.ByteBuffer ;
+import java.nio.IntBuffer ;
+
+import org.apache.jena.dboe.base.record.RecordException;
+import org.apache.jena.dboe.sys.Sys;
+import org.apache.jena.dboe.sys.SystemIndex;
+
+/** An IntBuffer with extra operations */
+
+final public class PtrBuffer extends BufferBase {
+ private IntBuffer iBuff ;
+
+ private PtrBuffer(int maxRec) {
+ this(ByteBuffer.allocate(SystemIndex.SizeOfPointer * maxRec), 0) ;
+ }
+
+ public PtrBuffer(ByteBuffer bb, int num) {
+ super(bb, SystemIndex.SizeOfPointer, num) ;
+ iBuff = bb.asIntBuffer() ;
+
+ if ( CheckBuffer ) {
+ // It is a IntBuffer with associated ByteBuffer
+ if ( iBuff.position() != 0 || bb.order() != Sys.NetworkOrder )
+ throw new RecordException("Duff pointer buffer") ;
+ }
+ }
+
+ public int get(int idx) {
+ checkBounds(idx, numSlot) ;
+ return _get(idx) ;
+ }
+
+ public int getHigh() {
+ if ( numSlot == 0 )
+ throw new IllegalArgumentException("Empty PtrBuffer") ;
+ return _get(numSlot - 1) ;
+ }
+
+ public int getLow() {
+ if ( numSlot == 0 )
+ throw new IllegalArgumentException("Empty PtrBuffer") ;
+ return _get(0) ;
+ }
+
+ public void add(int val) {
+ add(numSlot, val) ;
+ }
+
+ public void add(int idx, int val) {
+ if ( idx != numSlot ) {
+ checkBounds(idx, numSlot) ;
+ shiftUp(idx) ;
+ } else {
+ if ( numSlot >= maxSlot )
+ throw new BufferException(format("Out of bounds: idx=%d, ptrs=%d", idx, maxSlot)) ;
+ numSlot++ ;
+ }
+ // Add right at the top.
+ _set(idx, val) ;
+ }
+
+ public void set(int idx, int val) {
+ checkBounds(idx, numSlot) ;
+ _set(idx, val) ;
+ }
+
+ private final int _get(int idx) {
+ return iBuff.get(idx) ;
+ }
+
+ private final void _set(int idx, int val) {
+ iBuff.put(idx, val) ;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder() ;
+ str.append(format("Len=%d Max=%d ", numSlot, maxSlot)) ;
+
+ for ( int i = 0 ; i < numSlot ; i++ ) {
+ if ( i != 0 )
+ str.append(" ") ;
+ int x = _get(i) ;
+ str.append(format("%04d", x)) ;
+ }
+ return str.toString() ;
+ }
+
+ private static void checkBounds(int idx, int len) {
+ if ( idx < 0 || idx >= len )
+ throw new BufferException(format("Out of bounds: idx=%d, ptrs=%d", idx, len)) ;
+ }
+
+ /**
+ * A duplicate which does not share anything with the original - for testing
+ */
+ public PtrBuffer duplicate() {
+ PtrBuffer n = new PtrBuffer(maxSlot) ;
+ copy(0, n, 0, maxSlot) ; // numSlot
+ n.numSlot = numSlot ; // Reset
+ return n ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/RecordBuffer.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/RecordBuffer.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/RecordBuffer.java
new file mode 100644
index 0000000..5b2559c
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/RecordBuffer.java
@@ -0,0 +1,236 @@
+/*
+ * 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.dboe.base.buffer ;
+
+import static java.lang.String.format ;
+import static org.apache.jena.atlas.lib.Alg.encodeIndex ;
+
+import java.nio.ByteBuffer ;
+import java.util.Iterator ;
+
+import org.apache.jena.dboe.base.record.Record;
+import org.apache.jena.dboe.base.record.RecordFactory;
+import org.apache.jena.dboe.base.record.RecordMapper;
+
+final public class RecordBuffer extends BufferBase {
+ private RecordFactory factory ;
+
+ // Need own specialized binary search :-(
+
+ public RecordBuffer(RecordFactory recFactory, int maxRec) {
+ this(ByteBuffer.allocate(recFactory.recordLength() * maxRec), recFactory, 0) ;
+ }
+
+ public RecordBuffer(ByteBuffer bb, RecordFactory recFactory, int num) {
+ super(bb, recFactory.recordLength(), num) ;
+ this.factory = recFactory ;
+ }
+
+ public <X> X access(int idx, byte[] key, RecordMapper<X> mapper) {
+ checkBounds(idx, numSlot) ;
+ return _access(idx, key, mapper) ;
+ }
+
+ public Record get(int idx) {
+ checkBounds(idx, numSlot) ;
+ return _get(idx) ;
+ }
+
+ public Record getLow() {
+ if ( numSlot == 0 )
+ throw new IllegalArgumentException("getLow: Empty RecordBuffer") ;
+ return _get(0) ;
+ }
+
+ public Record getHigh() {
+ if ( numSlot == 0 )
+ throw new IllegalArgumentException("getHigh: Empty RecordBuffer") ;
+ return _get(numSlot - 1) ;
+ }
+
+ // Inserts at top.
+ public void add(Record record) {
+ add(numSlot, record) ;
+ }
+
+ // Inserts at slot idx
+ public void add(int idx, Record record) {
+ if ( idx != numSlot ) {
+ checkBounds(idx, numSlot) ;
+ shiftUp(idx) ; // Changes count.
+ } else {
+ if ( numSlot >= maxSlot )
+ throw new BufferException(format("Out of bounds: idx=%d, ptrs=%d", idx, maxSlot)) ;
+ numSlot++ ;
+ }
+ _set(idx, record) ;
+ }
+
+ // Overwrites the contents of slot idx
+ public void set(int idx, Record record) {
+ if ( idx == numSlot ) {
+ add(idx, record) ;
+ return ;
+ } else
+ checkBounds(idx, numSlot) ;
+ _set(idx, record) ;
+ }
+
+ // No checking bound : careful use only!
+
+ public <X> X _access(int idx, byte[] key, RecordMapper<X> mapper) {
+ return factory.access(bb, idx, key, mapper) ;
+ }
+
+ public Record _get(int idx) {
+ return factory.buildFrom(bb, idx) ;
+ }
+
+ // No bounds checking : careful use only!
+ void _set(int idx, Record rec) {
+ factory.insertInto(rec, bb, idx) ;
+ }
+
+ // Linear search for testing.
+ int find1(byte[] data) {
+ for ( int i = 0 ; i < numSlot ; i++ ) {
+ int x = compare(i, data) ;
+ if ( x == 0 )
+ return i ;
+ if ( x > 0 )
+ return encodeIndex(i) ;
+ }
+ return encodeIndex(numSlot) ;
+ }
+
+ // Binary search
+ public int find(Record k) {
+ return find(k, 0, numSlot) ;
+ }
+
+ public Iterator<Record> iterator() {
+ return new RecordBufferIterator(this) ;
+ }
+
+ /** Iterator over a range from min (inclusive) to max(exclusive) */
+ public Iterator<Record> iterator(Record min, Record max) {
+ return new RecordBufferIterator(this, min, max) ;
+ }
+
+ public Record findGet(Record k) {
+ int x = find(k) ;
+ if ( x >= 0 )
+ return get(x) ;
+ return null ;
+ }
+
+ /** return true is removed anything */
+ public boolean removeByKey(Record k) {
+ int x = find(k) ;
+ if ( x < 0 )
+ return false ;
+ super.remove(x) ;
+ return true ;
+ }
+
+ /** Search for key in range fromIndex (inclusive) to toIndex (exclusive) */
+ public int find(Record rec, int fromIndex, int toIndex) {
+ int low = fromIndex ;
+ int high = toIndex - 1 ;
+
+ byte[] key = rec.getKey() ;
+ // http://en.wikipedia.org/wiki/Binary_search
+
+ while (low <= high) {
+ int mid = (low + high) >>> 1 ; // int divide by 2
+
+ int x = compare(mid, key) ;
+ // System.out.printf("Compare: %d(%s) %s ==> %d\n", mid,
+ // Record.str(get(mid)), Record.str(data), x) ;
+
+ if ( x < 0 )
+ low = mid + 1 ;
+ else if ( x > 0 )
+ high = mid - 1 ;
+ else
+ return mid ;
+ }
+ // On exit, when not finding, low is the least value
+ // above, including off the end of the array.
+ return encodeIndex(low) ;
+ }
+
+ // Record compareByKey except we avoid touching bytes by exiting as soon as
+ // possible.
+ // No record created as would be by using
+ // compareByKey(RecordBuffer.get(idx), record)
+ // Compare the slot at idx with value.
+ private int compare(int idx, byte[] value) {
+ idx = idx * slotLen ;
+
+ for ( int i = 0 ; i < value.length ; i++ ) {
+ byte b1 = bb.get(idx + i) ;
+ byte b2 = value[i] ;
+ if ( b1 == b2 )
+ continue ;
+ return (b1 & 0xFF) - (b2 & 0xFF) ;
+ }
+ return 0 ;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder(40000) ;
+ str.append(format("Len=%d Max=%d: ", numSlot, bb.limit() / slotLen)) ;
+
+ // Print active slots as records.
+ for ( int i = 0 ; i < numSlot ; i++ ) {
+ if ( i != 0 )
+ str.append(" ") ;
+ Record r = _get(i) ;
+ str.append(r.toString()) ;
+ }
+
+ // // Print empty slots
+ // for ( int i = numSlot*slotLen ; i < maxSlot*slotLen ; i++ )
+ // {
+ // if ( i != 0 && i%slotLen == 0 )
+ // str.append(" ") ;
+ // byte b = bb.get(i) ;
+ // str.append(format("%02x", b)) ;
+ // }
+ String s = str.toString() ;
+ return s ;
+ }
+
+ private static void checkBounds(int idx, int len) {
+ if ( idx < 0 || idx >= len )
+ throw new IllegalArgumentException(format("Out of bounds: idx=%d, size=%d", idx, len)) ;
+ }
+
+ /**
+ * A duplicate which does not share anything with the original - for testing
+ */
+ public RecordBuffer duplicate() {
+ RecordBuffer n = new RecordBuffer(factory, maxSlot) ;
+ copy(0, n, 0, maxSlot) ; // numSlot
+ n.numSlot = numSlot ; // reset the allocated length
+ return n ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/RecordBufferIterator.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/RecordBufferIterator.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/RecordBufferIterator.java
new file mode 100644
index 0000000..ec488ef
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/buffer/RecordBufferIterator.java
@@ -0,0 +1,98 @@
+/*
+ * 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.dboe.base.buffer;
+
+import static org.apache.jena.atlas.lib.Alg.decodeIndex ;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.jena.dboe.base.record.Record;
+
+public class RecordBufferIterator implements Iterator<Record>
+{
+ private RecordBuffer rBuff ;
+ private int nextIdx ;
+ private Record slot = null ;
+ private final Record maxRec ;
+ private final Record minRec ;
+
+ RecordBufferIterator(RecordBuffer rBuff)
+ { this(rBuff, null, null); }
+
+ RecordBufferIterator(RecordBuffer rBuff, Record minRecord, Record maxRecord)
+ {
+ this.rBuff = rBuff ;
+ nextIdx = 0 ;
+ minRec = minRecord ;
+ if ( minRec != null )
+ {
+ nextIdx = rBuff.find(minRec) ;
+ if ( nextIdx < 0 )
+ nextIdx = decodeIndex(nextIdx) ;
+ }
+
+ maxRec = maxRecord ;
+ }
+
+ private void finish()
+ {
+ rBuff = null ;
+ nextIdx = -99 ;
+ slot = null ;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ if ( slot != null )
+ return true ;
+ if ( nextIdx < 0 )
+ return false ;
+ if ( nextIdx >= rBuff.size() )
+ {
+ finish() ;
+ return false ;
+ }
+
+ slot = rBuff.get(nextIdx) ;
+ if ( maxRec != null && Record.keyGE(slot, maxRec) )
+ {
+ // Finished - now to large
+ finish() ;
+ return false ;
+ }
+ nextIdx ++ ;
+ return true ;
+ }
+
+ @Override
+ public Record next()
+ {
+ if ( ! hasNext() )
+ throw new NoSuchElementException("RecordBufferIterator") ;
+ Record r = slot ;
+ slot = null ;
+ return r ;
+ }
+
+ @Override
+ public void remove()
+ { throw new UnsupportedOperationException("RecordBufferIterator.remove") ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/AlreadyLocked.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/AlreadyLocked.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/AlreadyLocked.java
new file mode 100644
index 0000000..4fcd92d
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/AlreadyLocked.java
@@ -0,0 +1,29 @@
+/*
+ * 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.dboe.base.file;
+
+import org.apache.jena.dboe.DBOpEnvException;
+
+/** Exception throws when an attempt to take a {@link ProcessFileLock}
+ * with a call of {@link ProcessFileLock#lockEx}
+ * is made and the lock is already held.
+ */
+public class AlreadyLocked extends DBOpEnvException {
+ public AlreadyLocked(String msg) { super(msg); }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFile.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFile.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFile.java
new file mode 100644
index 0000000..5be5035
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFile.java
@@ -0,0 +1,100 @@
+/*
+ * 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.dboe.base.file;
+
+import java.io.RandomAccessFile ;
+
+import org.apache.jena.atlas.lib.Closeable ;
+import org.apache.jena.atlas.lib.Sync ;
+
+/** An append-only, read-anywhere, binary file.
+ * A {@code BinaryDataFile} does not record the length and assumes the
+ * entries are self-defining.
+ *
+ * @see RandomAccessFile
+ */
+public interface BinaryDataFile extends Closeable, Sync {
+ // What about java.nio.channels.FileChannel?
+ // On OpenJDK, RandomAccessFile and FileChannelImpl both dive into native code.
+ //
+ // The choice seems to come down to ByteBuffers vs byte[]
+ // which in turn is a small/large data (scattered data)
+ // issue. We are currently expecting small(er) I/O so byte[]
+ // and being like Thrift is better.
+
+ // byte[] vs ByteBuffer
+
+ /** Open the file */
+ public void open() ;
+
+ /** Is it open? */
+ public boolean isOpen() ;
+
+ /** Read into a byte array, returning the number of bytes read.
+ * Reads are at an absolute position and a read is atomic/thread-safe.
+ *
+ * @param posn Location of the read operation.
+ * @param b byte array
+ *
+ * @return The number of bytes read
+ */
+ public default int read(long posn, byte b[]) {
+ return read(posn, b, 0, b.length);
+ }
+
+ /** Read into a byte array, returning the number of bytes read.
+ * Reads are at an absolute position and a read is atomic/thread-safe.
+ *
+ * @param posn Location of the read operation.
+ * @param b
+ * @param start of bytesarray to read into
+ * @param length Maximum number of bytes to read.
+ * @return The number of bytes read
+ */
+
+ public int read(long posn, byte b[], int start, int length) ;
+
+ /** Write bytes - bytes are always written to the end of the file.
+ * Return the location where the write started.
+ */
+ public default long write(byte b[]) {
+ return write(b, 0, b.length) ;
+ }
+
+ /** Write bytes - bytes are always written to the end of the file.
+ * Return the location where the write started.
+ */
+ public long write(byte b[], int start, int length) ;
+
+ /** Return the length of the file (including any buffered writes) */
+ public long length() ;
+
+ /** Truncate the file */
+ public void truncate(long length) ;
+
+ /** Return whether this is an empty file or not */
+ public default boolean isEmpty() { return length() == 0 ; }
+
+ @Override
+ public void sync() ;
+
+ @Override
+ public void close() ;
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFileMem.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFileMem.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFileMem.java
new file mode 100644
index 0000000..1c6941b
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFileMem.java
@@ -0,0 +1,115 @@
+/*
+ * 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.dboe.base.file;
+
+import org.apache.jena.atlas.RuntimeIOException ;
+import org.apache.jena.atlas.io.IO ;
+
+/** Implementation of {@link BinaryDataFile} in memory for testing
+ * and development use. Raw performance is not an objective.
+ *
+ * <li>This implementation is thread-safe.
+ */
+public class BinaryDataFileMem implements BinaryDataFile {
+
+ private boolean readMode ;
+ private SegmentedMemBuffer storage ;
+
+ public BinaryDataFileMem() {
+ }
+
+ @Override
+ synchronized
+ public void open() {
+ if ( storage != null )
+ throw new RuntimeIOException("Already open") ;
+ storage = new SegmentedMemBuffer() ;
+ readMode = true ;
+ }
+
+ @Override
+ synchronized
+ public boolean isOpen() {
+ return storage != null ;
+ }
+
+ @Override
+ synchronized
+ public int read(long posn, byte[] b, int start, int length) {
+ checkOpen() ;
+ switchToReadMode() ;
+ return storage.read(posn, b, start, length) ;
+ }
+
+ @Override
+ synchronized
+ public long write(byte[] b, int start, int length) {
+ checkOpen() ;
+ switchToWriteMode() ;
+ long x = storage.length() ;
+ storage.write(x, b, start, length) ;
+ return x ;
+ }
+
+ @Override
+ synchronized
+ public void truncate(long length) {
+ if ( length < 0 )
+ IO.exception(String.format("truncate: bad length : %d", length)) ;
+ checkOpen() ;
+ switchToWriteMode() ;
+ storage.truncate(length);
+ }
+
+ @Override
+ synchronized
+ public void sync() {
+ checkOpen() ;
+ storage.sync();
+ }
+
+ @Override
+ synchronized
+ public void close() {
+ if ( ! isOpen() )
+ return ;
+ storage.close();
+ storage = null ;
+ }
+
+ @Override
+ synchronized
+ public long length() {
+ return storage.length() ;
+ }
+
+ private void switchToReadMode() {
+ readMode = true ;
+ }
+
+ private void switchToWriteMode() {
+ readMode = false ;
+ }
+
+ private void checkOpen() {
+ if ( ! isOpen() )
+ throw new RuntimeIOException("Not open") ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/3d456654/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFileRandomAccess.java
----------------------------------------------------------------------
diff --git a/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFileRandomAccess.java b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFileRandomAccess.java
new file mode 100644
index 0000000..5ca3b68
--- /dev/null
+++ b/jena-db/jena-dboe-base/src/main/java/org/apache/jena/dboe/base/file/BinaryDataFileRandomAccess.java
@@ -0,0 +1,149 @@
+/*
+ * 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.dboe.base.file;
+
+import java.io.IOException ;
+import java.io.RandomAccessFile ;
+
+import org.apache.jena.atlas.RuntimeIOException ;
+import org.apache.jena.atlas.io.IO ;
+
+/** Implementation of {@link BinaryDataFile} using {@link RandomAccessFile}.
+ *
+ * <li>No buffering of reads or writes provided.
+ * <li>Not thread-safe.
+ *
+ * @see BinaryDataFileWriteBuffered
+ */
+public class BinaryDataFileRandomAccess implements BinaryDataFile {
+ // On OpenJDK, RandomAccessFile and FileChannelImpl both
+ // dive into native code.
+ protected RandomAccessFile file ;
+ protected boolean readMode ;
+ protected long readPosition ;
+ protected long writePosition ;
+ private final String filename ;
+
+ public BinaryDataFileRandomAccess(String filename) {
+ this.filename = filename ;
+ }
+
+ @Override
+ public void open() {
+ if ( file != null )
+ throw new RuntimeIOException("Already open") ;
+ try {
+ file = new RandomAccessFile(filename, "rw") ;
+ writePosition = file.length() ;
+ readPosition = 0 ;
+ readMode = true ;
+ }
+ catch (IOException e) { IO.exception(e); }
+ }
+
+ @Override
+ public boolean isOpen() {
+ return file != null ;
+ }
+
+ @Override
+ public int read(long posn, byte[] b, int start, int length) {
+ checkOpen() ;
+ switchToReadMode() ;
+ seek(posn) ;
+ try {
+ int x = file.read(b, start, length) ;
+ readPosition += x ;
+ return x ;
+ }
+ catch (IOException ex) { IO.exception(ex); return -1 ; }
+ }
+
+ @Override
+ public long write(byte[] b, int start, int length) {
+ checkOpen() ;
+ switchToWriteMode() ;
+ long x = writePosition ;
+ try {
+ file.write(b, start, length) ;
+ writePosition += length ;
+ }
+ catch (IOException ex) { IO.exception(ex) ; }
+ return x ;
+ }
+
+
+ // Move the RandomAccess file pointer.
+ private void seek(long posn) {
+ try { file.seek(posn) ; }
+ catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ @Override
+ public void truncate(long length) {
+ checkOpen() ;
+ switchToWriteMode() ;
+ try { file.setLength(length); }
+ catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ @Override
+ public void sync() {
+ checkOpen() ;
+ flush$() ;
+ }
+
+ protected void flush$() {
+ try { file.getFD().sync() ; }
+ catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ @Override
+ public void close() {
+ if ( ! isOpen() )
+ return ;
+ try { file.close(); }
+ catch (IOException ex) { IO.exception(ex) ; }
+ file = null ;
+ }
+
+ @Override
+ public long length() {
+ try { return file.length() ;}
+ catch (IOException ex) { IO.exception(ex) ; return -1 ;}
+ }
+
+ protected void switchToReadMode() {
+ if ( ! readMode )
+ readMode = true ;
+ }
+
+ protected void switchToWriteMode() {
+ if ( readMode ) {
+ readMode = false ;
+ seek(writePosition);
+ }
+ }
+
+ protected void checkOpen() {
+ if ( ! isOpen() )
+ throw new RuntimeIOException("Not open") ;
+ }
+}
+