]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/util/binary/DeferredBinaryFile.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / util / binary / DeferredBinaryFile.java
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/util/binary/DeferredBinaryFile.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/util/binary/DeferredBinaryFile.java
new file mode 100644 (file)
index 0000000..161d945
--- /dev/null
@@ -0,0 +1,356 @@
+/*******************************************************************************\r
+ * Copyright (c) 2016 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.databoard.util.binary;
+
+import java.io.File;\r
+import java.io.IOException;\r
+import java.nio.ByteBuffer;\r
+\r
+/**\r
+ * This class is a custom write-only wrapper for {@link BinaryFile} and\r
+ * {@link BinaryMemory} that implements a {@link RandomAccessBinary} which is\r
+ * contained fully in memory until its size reaches a user-specified threshold.\r
+ * When that size threshold is exceeded, the {@link BinaryMemory} contents are\r
+ * flushed into a BinaryFile and from there on this implementation will continue\r
+ * to write to the BinaryFile.\r
+ * <p>\r
+ * Since it is based {@link BinaryFile} and {@link BinaryMemory}, this\r
+ * implementation is also buffered and <em>not</em> thread-safe.\r
+ * <p>\r
+ * The {@link SeekableBinaryReadable} part of the {@link RandomAccessBinary}\r
+ * interface is not implemented and will throw\r
+ * {@link UnsupportedOperationException}.\r
+ *\r
+ * @author Tuukka Lehtonen\r
+ * @since 1.22.1 & 1.24.0\r
+ * @see BinaryFile\r
+ * @see BinaryMemory\r
+ */
+public class DeferredBinaryFile implements RandomAccessBinary {
+\r
+    File file;\r
+    int threshold;\r
+    int fileBufferSize;\r
+\r
+    BinaryMemory memory;\r
+    RandomAccessBinary backend;
+
+    public DeferredBinaryFile(File file, int threshold, int fileBufferSize) throws IOException {\r
+        this.memory = new BinaryMemory(threshold+10000);\r
+        this.backend = memory;\r
+        this.threshold = threshold;\r
+        this.file = file;\r
+        this.fileBufferSize = fileBufferSize;\r
+    }\r
+\r
+    /**
+     * Closes the object. Note, this will close the input random access file.\r
+     * This method may be called several times.
+     *  
+     * @throws IOException
+     */
+    @Override\r
+    public synchronized void close() throws IOException {\r
+        if (backend == null)\r
+            return;\r
+        backend.close();
+        backend = null;
+    }
+\r
+    @Override\r
+    public synchronized boolean isOpen() {\r
+        return backend != null;\r
+    }\r
+
+    @Override
+    public byte readByte() throws IOException {
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    @Override\r
+    public char readChar() throws IOException {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    @Override\r
+    public int readUnsignedByte() throws IOException {\r
+        throw new UnsupportedOperationException();\r
+    }
+\r
+    @Override\r
+    public boolean readBoolean() throws IOException {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+
+    @Override
+    public void readFully(byte[] dst, int offset, int length) throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public void readFully(byte[] dst) throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public void readFully(ByteBuffer buf) throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public void readFully(ByteBuffer buf, int length) throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public double readDouble() throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public float readFloat() throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public int readInt() throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public long readLong() throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public short readShort() throws IOException {
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    @Override\r
+    public int readUnsignedShort() throws IOException {\r
+        throw new UnsupportedOperationException();\r
+    }
+\r
+    @Override\r
+    public String readUTF() throws IOException {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    public final String readLine() throws IOException {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    @Override
+    public long position() throws IOException {
+        return backend.position();\r
+    }
+
+    @Override\r
+    public void position(long newPosition) throws IOException {
+        backend.position(newPosition);\r
+    }
+
+    /**
+     * Flushes internal buffer
+     */
+    @Override\r
+    public void flush() throws IOException {
+        backend.flush();\r
+    }
+
+    /**
+     * Clears read&write buffer. The file can be modified elsewhere after this.
+     * 
+     * @throws IOException 
+     */
+    @Override\r
+    public void reset() throws IOException {
+        backend.reset();\r
+    }
+\r
+    @Override\r
+    public long skipBytes(long bytes) throws IOException {\r
+        return backend.skipBytes(bytes);\r
+    }\r
+
+    @Override\r
+    public int skipBytes(int bytes) throws IOException {\r
+        return backend.skipBytes(bytes);\r
+    }\r
+\r
+\r
+    // WRITE
+
+    @Override
+    public void write(int b) throws IOException {
+        backend.write(b);\r
+        if (memory != null)\r
+            threshold();\r
+    }\r
+\r
+    @Override\r
+    public void writeByte(int b) throws IOException {\r
+        backend.writeByte(b);\r
+        if (memory != null)\r
+            threshold();\r
+    }
+\r
+    @Override\r
+    public void writeBoolean(boolean v) throws IOException {\r
+        backend.writeBoolean(v);\r
+        if (memory != null)\r
+            threshold();\r
+    }\r
+
+    @Override
+    public void writeFully(ByteBuffer src) throws IOException {
+        backend.writeFully(src);\r
+        if (memory != null)\r
+            threshold();\r
+    }
+
+    @Override
+    public void writeFully(ByteBuffer src, int length) throws IOException {
+        backend.writeFully(src, length);\r
+        if (memory != null)\r
+            threshold();\r
+    }
+
+    @Override
+    public void write(byte[] src, int offset, int length) throws IOException {
+        backend.write(src, offset, length);\r
+    }
+
+    @Override
+    public void write(byte[] src) throws IOException {
+        backend.write(src);\r
+        if (memory != null)\r
+            threshold();\r
+    }
+
+    @Override
+    public void writeDouble(double value) throws IOException {
+        backend.writeDouble(value);\r
+        if (memory != null)\r
+            threshold();\r
+    }
+
+    @Override
+    public void writeFloat(float value) throws IOException {
+        backend.writeFloat(value);\r
+        if (memory != null)\r
+            threshold();\r
+    }
+
+    @Override
+    public void writeInt(int value) throws IOException {
+        backend.writeInt(value);\r
+        if (memory != null)\r
+            threshold();\r
+    }
+
+    @Override
+    public void writeLong(long value) throws IOException {
+        backend.writeLong(value);\r
+        if (memory != null)\r
+            threshold();\r
+    }
+
+    @Override
+    public void writeShort(int value) throws IOException {
+        backend.writeShort(value);\r
+        if (memory != null)\r
+            threshold();\r
+    }\r
+\r
+    @Override\r
+    public void writeChar(int value) throws IOException {\r
+        backend.writeChar(value);\r
+        if (memory != null)\r
+            threshold();\r
+    }\r
+\r
+    @Override\r
+    public void writeBytes(String s) throws IOException {\r
+        backend.writeBytes(s);\r
+        if (memory != null)\r
+            threshold();\r
+    }\r
+\r
+    @Override\r
+    public void writeChars(String s) throws IOException {\r
+        backend.writeChars(s);\r
+        if (memory != null)\r
+            threshold();\r
+    }
+\r
+    @Override\r
+    public void writeUTF(String s) throws IOException {\r
+        backend.writeUTF(s);\r
+        if (memory != null)\r
+            threshold();\r
+    }\r
+
+    @Override
+    public void insertBytes(long bytes, ByteSide side) throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public void removeBytes(long bytes, ByteSide side) throws IOException {
+        throw new UnsupportedOperationException();\r
+    }
+
+    @Override
+    public long length() throws IOException {
+        return backend.length();
+    }
+
+    @Override
+    public void setLength(long newLength) throws IOException {\r
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String toString() {
+        try {
+            return "DeferredBinaryFile(file="+file.getName()+", size="+length()+")";
+        } catch (IOException e) {
+            return "DeferredBinaryFile()";
+        }
+    }\r
+\r
+    private void threshold() throws IOException {\r
+        if (backend.position() >= threshold) {\r
+            backend = new BinaryFile(file, fileBufferSize);\r
+            long length = memory.position();\r
+            memory.position(0);\r
+            memory.toByteBuffer().position(0);\r
+            backend.writeFully(memory.toByteBuffer(), (int) length);\r
+            memory = null;\r
+        }\r
+    }\r
+\r
+    public boolean isInMemory() {\r
+        return memory != null;\r
+    }\r
+\r
+    public RandomAccessBinary getMemory() {\r
+        return memory;\r
+    }\r
+\r
+    public RandomAccessBinary getBackend() {\r
+        return backend;\r
+    }\r
+\r
+}
\ No newline at end of file