You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by dc...@apache.org on 2021/08/19 22:18:24 UTC
svn commit: r49567 [8/14] - in /dev/datasketches/memory/2.0.0-RC1: ./
apache-datasketches-memory-2.0.0-src/
apache-datasketches-memory-2.0.0-src/datasketches-memory-java11/
apache-datasketches-memory-2.0.0-src/datasketches-memory-java11/src/
apache-dat...
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMemory.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMemory.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/WritableMemory.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,641 @@
+/*
+ * 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.datasketches.memory;
+
+import static org.apache.datasketches.memory.internal.Util.negativeCheck;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Objects;
+
+import org.apache.datasketches.memory.internal.BaseWritableMemoryImpl;
+import org.apache.datasketches.memory.internal.Prim;
+import org.apache.datasketches.memory.internal.UnsafeUtil;
+
+/**
+ * Defines the writable API for offset access to a resource.
+ *
+ * @author Lee Rhodes
+ */
+public interface WritableMemory extends Memory {
+
+ //BYTE BUFFER
+ /**
+ * Accesses the given <i>ByteBuffer</i> for write operations. The returned <i>WritableMemory</i> object has
+ * the same byte order, as the given <i>ByteBuffer</i>.
+ * @param byteBuffer the given <i>ByteBuffer</i>. It must be non-null, with capacity ≥ 0, and writable.
+ * @return a new <i>WritableMemory</i> for write operations on the given <i>ByteBuffer</i>.
+ */
+ static WritableMemory writableWrap(ByteBuffer byteBuffer) {
+ return writableWrap(byteBuffer, byteBuffer.order(), defaultMemReqSvr);
+ }
+
+ /**
+ * Accesses the given <i>ByteBuffer</i> for write operations. The returned <i>WritableMemory</i> object has
+ * the given byte order, ignoring the byte order of the given <i>ByteBuffer</i> for future writes and following reads.
+ * However, this does not change the byte order of data already in the <i>ByteBuffer</i>.
+ * @param byteBuffer the given <i>ByteBuffer</i>. It must be non-null, with capacity ≥ 0, and writable.
+ * @param byteOrder the byte order to be used. It must be non-null.
+ * @return a new <i>WritableMemory</i> for write operations on the given <i>ByteBuffer</i>.
+ */
+ static WritableMemory writableWrap(ByteBuffer byteBuffer, ByteOrder byteOrder) {
+ return writableWrap(byteBuffer, byteOrder, defaultMemReqSvr);
+ }
+
+ /**
+ * Accesses the given <i>ByteBuffer</i> for write operations. The returned <i>WritableMemory</i> object has
+ * the given byte order, ignoring the byte order of the given <i>ByteBuffer</i> for future reads and writes.
+ * However, this does not change the byte order of data already in the <i>ByteBuffer</i>.
+ * @param byteBuffer the given <i>ByteBuffer</i>. It must be non-null, with capacity ≥ 0, and writable.
+ * @param byteOrder the byte order to be used. It must be non-null.
+ * @param memReqSvr A user-specified <i>MemoryRequestServer</i>, which may be null.
+ * This is a callback mechanism for a user client to request a larger <i>WritableMemory</i>.
+ * @return a new <i>WritableMemory</i> for write operations on the given <i>ByteBuffer</i>.
+ */
+ static WritableMemory writableWrap(ByteBuffer byteBuffer, ByteOrder byteOrder, MemoryRequestServer memReqSvr) {
+ Objects.requireNonNull(byteBuffer, "byteBuffer must be non-null");
+ Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
+ negativeCheck(byteBuffer.capacity(), "byteBuffer");
+ if (byteBuffer.isReadOnly()) { throw new ReadOnlyException("byteBuffer must be writable."); }
+ return BaseWritableMemoryImpl.wrapByteBuffer(byteBuffer, false, byteOrder, memReqSvr);
+ }
+
+ //MAP
+ /**
+ * Maps the entire given file into native-ordered WritableMemory for write operations
+ * Calling this method is equivalent to calling
+ * {@link #writableMap(File, long, long, ByteOrder) writableMap(file, 0, file.length(), ByteOrder.nativeOrder())}.
+ * @param file the given file to map. It must be non-null, with length ≥ 0, and writable.
+ * @return WritableMapHandle for managing the mapped Memory.
+ * Please read Javadocs for {@link Handle}.
+ */
+ static WritableMapHandle writableMap(File file) {
+ return writableMap(file, 0, file.length(), ByteOrder.nativeOrder());
+ }
+
+ /**
+ * Maps the specified portion of the given file into Memory for write operations.
+ *
+ * <p><b>Note:</b> Always qualify this method with the class name, e.g.,
+ * <i>WritableMemory.map(...)</i>.
+ * @param file the given file to map. It must be non-null, writable and length ≥ 0.
+ * @param fileOffsetBytes the position in the given file in bytes. It must not be negative.
+ * @param capacityBytes the size of the mapped Memory. It must not be negative.
+ * @param byteOrder the byte order to be used for the given file. It must be non-null.
+ * @return WritableMapHandle for managing the mapped Memory.
+ * Please read Javadocs for {@link Handle}.
+ */
+ static WritableMapHandle writableMap(File file, long fileOffsetBytes, long capacityBytes, ByteOrder byteOrder) {
+ Objects.requireNonNull(file, "file must be non-null.");
+ Objects.requireNonNull(byteOrder, "byteOrder must be non-null.");
+ if (!file.canWrite()) { throw new ReadOnlyException("file must be writable."); }
+ negativeCheck(file.length(), "file.length()");
+ negativeCheck(fileOffsetBytes, "fileOffsetBytes");
+ negativeCheck(capacityBytes, "capacityBytes");
+ return BaseWritableMemoryImpl.wrapMap(file, fileOffsetBytes, capacityBytes, false, byteOrder);
+ }
+
+ //ALLOCATE DIRECT
+ /**
+ * Allocates and provides access to capacityBytes directly in native (off-heap) memory.
+ * Native byte order is assumed.
+ * The allocated memory will be 8-byte aligned, but may not be page aligned.
+ *
+ * <p><b>NOTE:</b> Native/Direct memory acquired may have garbage in it.
+ * It is the responsibility of the using application to clear this memory, if required,
+ * and to call <i>close()</i> when done.</p>
+ *
+ * @param capacityBytes the size of the desired memory in bytes. It must be ≥ 0.
+ * @return WritableHandle for this off-heap resource.
+ * Please read Javadocs for {@link Handle}.
+ */
+ static WritableHandle allocateDirect(long capacityBytes) {
+ return allocateDirect(capacityBytes, ByteOrder.nativeOrder(), defaultMemReqSvr);
+ }
+
+ /**
+ * Allocates and provides access to capacityBytes directly in native (off-heap) memory.
+ * The allocated memory will be 8-byte aligned, but may not be page aligned.
+ *
+ * <p><b>NOTE:</b> Native/Direct memory acquired may have garbage in it.
+ * It is the responsibility of the using application to clear this memory, if required,
+ * and to call <i>close()</i> when done.</p>
+ *
+ * @param capacityBytes the size of the desired memory in bytes. It must be ≥ 0.
+ * @param byteOrder the given byte order. It must be non-null.
+ * @param memReqSvr A user-specified MemoryRequestServer, which may be null.
+ * This is a callback mechanism for a user client of direct memory to request more memory.
+ * @return WritableHandle for this off-heap resource.
+ * Please read Javadocs for {@link Handle}.
+ */
+ static WritableHandle allocateDirect(long capacityBytes, ByteOrder byteOrder, MemoryRequestServer memReqSvr) {
+ Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
+ negativeCheck(capacityBytes, "capacityBytes");
+ return BaseWritableMemoryImpl.wrapDirect(capacityBytes, byteOrder, memReqSvr);
+ }
+
+ //REGIONS
+ /**
+ * A writable region is a writable view of this object.
+ * This returns a new <i>WritableMemory</i> representing the defined writable region with the
+ * given offsetBytes and capacityBytes.
+ * <ul>
+ * <li>Returned object's origin = this objects' origin + <i>offsetBytes</i></li>
+ * <li>Returned object's capacity = <i>capacityBytes</i></li>
+ * </ul>
+ *
+ * @param offsetBytes the starting offset with respect to this object. It must be ≥ 0.
+ * @param capacityBytes the capacity of the returned object in bytes. It must be ≥ 0.
+ * @return a new <i>WritableMemory</i> representing the defined writable region.
+ */
+ default WritableMemory writableRegion(long offsetBytes, long capacityBytes) {
+ return writableRegion(offsetBytes, capacityBytes, getTypeByteOrder());
+ }
+
+ /**
+ * A writable region is a writable view of this object.
+ * This returns a new <i>WritableMemory</i> representing the defined writable region with the
+ * given offsetBytes, capacityBytes and byte order.
+ * <ul>
+ * <li>Returned object's origin = this objects' origin + <i>offsetBytes</i></li>
+ * <li>Returned object's capacity = <i>capacityBytes</i></li>
+ * <li>Returned object's byte order = <i>byteOrder</i></li>
+ * </ul>
+ *
+ * @param offsetBytes the starting offset with respect to this object. It must be ≥ 0.
+ * @param capacityBytes the capacity of the returned object in bytes. It must be ≥ 0.
+ * @param byteOrder the given byte order. It must be non-null.
+ * @return a new <i>WritableMemory</i> representing the defined writable region.
+ */
+ WritableMemory writableRegion(long offsetBytes, long capacityBytes, ByteOrder byteOrder);
+
+ //AS WRITABLE BUFFER
+ /**
+ * Returns a new <i>WritableBuffer</i> with a writable view of this object.
+ * <ul>
+ * <li>Returned object's origin = this object's origin</li>
+ * <li>Returned object's <i>start</i> = 0</li>
+ * <li>Returned object's <i>position</i> = 0</li>
+ * <li>Returned object's <i>end</i> = this object's capacity</li>
+ * <li>Returned object's <i>capacity</i> = this object's capacity</li>
+ * <li>Returned object's <i>start</i>, <i>position</i> and <i>end</i> are mutable</li>
+ * </ul>
+ * @return a new <i>WritableBuffer</i> with a view of this WritableMemory
+ */
+ default WritableBuffer asWritableBuffer() {
+ return asWritableBuffer(getTypeByteOrder());
+ }
+
+ /**
+ * Returns a new <i>WritableBuffer</i> with a writable view of this object
+ * with the given byte order.
+ * <ul>
+ * <li>Returned object's origin = this object's origin</li>
+ * <li>Returned object's <i>start</i> = 0</li>
+ * <li>Returned object's <i>position</i> = 0</li>
+ * <li>Returned object's <i>end</i> = this object's capacity</li>
+ * <li>Returned object's <i>capacity</i> = this object's capacity</li>
+ * <li>Returned object's <i>start</i>, <i>position</i> and <i>end</i> are mutable</li>
+ * </ul>
+ * @param byteOrder the given byte order
+ * @return a new <i>WritableBuffer</i> with a view of this WritableMemory
+ */
+ WritableBuffer asWritableBuffer(ByteOrder byteOrder);
+
+
+ //ALLOCATE HEAP VIA AUTOMATIC BYTE ARRAY
+ /**
+ * Creates on-heap WritableMemory with the given capacity and the native byte order.
+ * @param capacityBytes the given capacity in bytes. It must be ≥ 0.
+ * @return a new WritableMemory for write operations on a new byte array.
+ */
+ static WritableMemory allocate(int capacityBytes) {
+ return allocate(capacityBytes, ByteOrder.nativeOrder(), defaultMemReqSvr);
+ }
+
+ /**
+ * Creates on-heap WritableMemory with the given capacity and the given byte order.
+ * @param capacityBytes the given capacity in bytes. It must be ≥ 0.
+ * @param byteOrder the given byte order to allocate new Memory object with. It must be non-null.
+ * @return a new WritableMemory for write operations on a new byte array.
+ */
+ static WritableMemory allocate(int capacityBytes, ByteOrder byteOrder) {
+ return allocate(capacityBytes, byteOrder, defaultMemReqSvr);
+ }
+
+ /**
+ * Creates on-heap WritableMemory with the given capacity and the given byte order.
+ * @param capacityBytes the given capacity in bytes. It must be ≥ 0.
+ * @param byteOrder the given byte order to allocate new Memory object with. It must be non-null.
+ * @param memReqSvr A user-specified <i>MemoryRequestServer</i>, which may be null.
+ * This is a callback mechanism for a user client to request a larger <i>WritableMemory</i>.
+ * @return a new WritableMemory for write operations on a new byte array.
+ */
+ static WritableMemory allocate(int capacityBytes, ByteOrder byteOrder, MemoryRequestServer memReqSvr) {
+ final byte[] arr = new byte[capacityBytes];
+ negativeCheck(capacityBytes, "capacityBytes");
+ return writableWrap(arr, 0, capacityBytes, byteOrder, memReqSvr);
+ }
+
+
+ //ACCESS PRIMITIVE HEAP ARRAYS for WRITE
+
+ /**
+ * Wraps the given primitive array for write operations assuming native byte order.
+ *
+ * <p><b>Note:</b> Always qualify this method with the class name, e.g.,
+ * <i>WritableMemory.wrap(...)</i>.
+ * @param array the given primitive array. It must be non-null.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(byte[] array) {
+ return writableWrap(array, 0, array.length, ByteOrder.nativeOrder(), defaultMemReqSvr);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations with the given byte order.
+ *
+ * <p><b>Note:</b> Always qualify this method with the class name, e.g.,
+ * <i>WritableMemory.wrap(...)</i>.
+ * @param array the given primitive array. It must be non-null.
+ * @param byteOrder the byte order to be used. It must be non-null.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(byte[] array, ByteOrder byteOrder) {
+ return writableWrap(array, 0, array.length, byteOrder, defaultMemReqSvr);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations with the given byte order.
+ *
+ * <p><b>Note:</b> Always qualify this method with the class name, e.g.,
+ * <i>WritableMemory.wrap(...)</i>.
+ * @param array the given primitive array. It must be non-null.
+ * @param offsetBytes the byte offset into the given array. It must be ≥ 0.
+ * @param lengthBytes the number of bytes to include from the given array. It must be ≥ 0.
+ * @param byteOrder the byte order to be used. It must be non-null.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(byte[] array, int offsetBytes, int lengthBytes, ByteOrder byteOrder) {
+ return writableWrap(array, offsetBytes, lengthBytes, byteOrder, defaultMemReqSvr);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations with the given byte order. If the given
+ * lengthBytes is zero, backing storage, byte order and read-only status of the returned
+ * WritableMemory object are unspecified.
+ *
+ * <p><b>Note:</b> Always qualify this method with the class name, e.g.,
+ * <i>WritableMemory.wrap(...)</i>.
+ * @param array the given primitive array. It must be non-null.
+ * @param offsetBytes the byte offset into the given array. It must be ≥ 0.
+ * @param lengthBytes the number of bytes to include from the given array. It must be ≥ 0.
+ * @param byteOrder the byte order to be used. It must be non-null.
+ * @param memReqSvr A user-specified <i>MemoryRequestServer</i>, which may be null.
+ * This is a callback mechanism for a user client to request a larger <i>WritableMemory</i>.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(byte[] array, int offsetBytes, int lengthBytes, ByteOrder byteOrder,
+ MemoryRequestServer memReqSvr) {
+ Objects.requireNonNull(array, "array must be non-null");
+ Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
+ negativeCheck(offsetBytes, "offsetBytes");
+ negativeCheck(lengthBytes, "lengthBytes");
+ UnsafeUtil.checkBounds(offsetBytes, lengthBytes, array.length);
+ return BaseWritableMemoryImpl.wrapHeapArray(array, offsetBytes, lengthBytes, false, byteOrder, memReqSvr);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations assuming native byte order.
+ * @param array the given primitive array. It must be non-null.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(boolean[] array) {
+ Objects.requireNonNull(array, "array must be non-null");
+ final long lengthBytes = array.length << Prim.BOOLEAN.shift();
+ return BaseWritableMemoryImpl.wrapHeapArray(array, 0, lengthBytes, false, ByteOrder.nativeOrder(), null);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations assuming native byte order.
+ * @param array the given primitive array.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(char[] array) {
+ Objects.requireNonNull(array, "array must be non-null");
+ final long lengthBytes = array.length << Prim.CHAR.shift();
+ return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations assuming native byte order.
+ * @param array the given primitive array.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(short[] array) {
+ Objects.requireNonNull(array, "arr must be non-null");
+ final long lengthBytes = array.length << Prim.SHORT.shift();
+ return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations assuming native byte order.
+ * @param array the given primitive array.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(int[] array) {
+ Objects.requireNonNull(array, "arr must be non-null");
+ final long lengthBytes = array.length << Prim.INT.shift();
+ return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations assuming native byte order.
+ * @param array the given primitive array.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(long[] array) {
+ Objects.requireNonNull(array, "arr must be non-null");
+ final long lengthBytes = array.length << Prim.LONG.shift();
+ return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations assuming native byte order.
+ * @param array the given primitive array.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(float[] array) {
+ Objects.requireNonNull(array, "arr must be non-null");
+ final long lengthBytes = array.length << Prim.FLOAT.shift();
+ return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+ }
+
+ /**
+ * Wraps the given primitive array for write operations assuming native byte order.
+ * @param array the given primitive array.
+ * @return a new WritableMemory for write operations on the given primitive array.
+ */
+ static WritableMemory writableWrap(double[] array) {
+ Objects.requireNonNull(array, "arr must be non-null");
+ final long lengthBytes = array.length << Prim.DOUBLE.shift();
+ return BaseWritableMemoryImpl.wrapHeapArray(array, 0L, lengthBytes, false, ByteOrder.nativeOrder(), null);
+ }
+ //END OF CONSTRUCTOR-TYPE METHODS
+
+ //PRIMITIVE putX() and putXArray()
+ /**
+ * Puts the boolean value at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param value the value to put
+ */
+ void putBoolean(long offsetBytes, boolean value);
+
+ /**
+ * Puts the boolean array at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param srcArray The source array.
+ * @param srcOffsetBooleans offset in array units
+ * @param lengthBooleans number of array units to transfer
+ */
+ void putBooleanArray(long offsetBytes, boolean[] srcArray, int srcOffsetBooleans, int lengthBooleans);
+
+ /**
+ * Puts the byte value at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param value the value to put
+ */
+ void putByte(long offsetBytes, byte value);
+
+ /**
+ * Puts the byte array at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param srcArray The source array.
+ * @param srcOffsetBytes offset in array units
+ * @param lengthBytes number of array units to transfer
+ */
+ void putByteArray(long offsetBytes, byte[] srcArray, int srcOffsetBytes, int lengthBytes);
+
+ /**
+ * Puts the char value at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param value the value to put
+ */
+ void putChar(long offsetBytes, char value);
+
+ /**
+ * Puts the char array at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param srcArray The source array.
+ * @param srcOffsetChars offset in array units
+ * @param lengthChars number of array units to transfer
+ */
+ void putCharArray(long offsetBytes, char[] srcArray, int srcOffsetChars, int lengthChars);
+
+ /**
+ * Encodes characters from the given CharSequence into UTF-8 bytes and puts them into this
+ * <i>WritableMemory</i> begining at the given offsetBytes.
+ * This is specifically designed to reduce the production of intermediate objects (garbage),
+ * thus significantly reducing pressure on the JVM Garbage Collector.
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param src The source CharSequence to be encoded and put into this WritableMemory. It is
+ * the responsibility of the caller to provide sufficient capacity in this
+ * <i>WritableMemory</i> for the encoded Utf8 bytes. Characters outside the ASCII range can
+ * require 2, 3 or 4 bytes per character to encode.
+ * @return the number of bytes encoded
+ */
+ long putCharsToUtf8(long offsetBytes, CharSequence src);
+
+ /**
+ * Puts the double value at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param value the value to put
+ */
+ void putDouble(long offsetBytes, double value);
+
+ /**
+ * Puts the double array at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param srcArray The source array.
+ * @param srcOffsetDoubles offset in array units
+ * @param lengthDoubles number of array units to transfer
+ */
+ void putDoubleArray(long offsetBytes, double[] srcArray, int srcOffsetDoubles, int lengthDoubles);
+
+ /**
+ * Puts the float value at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param value the value to put
+ */
+ void putFloat(long offsetBytes, float value);
+
+ /**
+ * Puts the float array at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param srcArray The source array.
+ * @param srcOffsetFloats offset in array units
+ * @param lengthFloats number of array units to transfer
+ */
+ void putFloatArray(long offsetBytes, float[] srcArray, int srcOffsetFloats, int lengthFloats);
+
+ /**
+ * Puts the int value at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param value the value to put
+ */
+ void putInt(long offsetBytes, int value);
+
+ /**
+ * Puts the int array at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param srcArray The source array.
+ * @param srcOffsetInts offset in array units
+ * @param lengthInts number of array units to transfer
+ */
+ void putIntArray(long offsetBytes, int[] srcArray, int srcOffsetInts, int lengthInts);
+
+ /**
+ * Puts the long value at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param value the value to put
+ */
+ void putLong(long offsetBytes, long value);
+
+ /**
+ * Puts the long array at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param srcArray The source array.
+ * @param srcOffsetLongs offset in array units
+ * @param lengthLongs number of array units to transfer
+ */
+ void putLongArray(long offsetBytes, long[] srcArray, int srcOffsetLongs, int lengthLongs);
+
+ /**
+ * Puts the short value at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param value the value to put
+ */
+ void putShort(long offsetBytes, short value);
+
+ /**
+ * Puts the short array at the given offset
+ * @param offsetBytes offset bytes relative to this <i>WritableMemory</i> start
+ * @param srcArray The source array.
+ * @param srcOffsetShorts offset in array units
+ * @param lengthShorts number of array units to transfer
+ */
+ void putShortArray(long offsetBytes, short[] srcArray, int srcOffsetShorts, int lengthShorts);
+
+ //Atomic Methods
+ /**
+ * Atomically adds the given value to the long located at offsetBytes.
+ * @param offsetBytes offset bytes relative to this Memory start
+ * @param delta the amount to add
+ * @return the the previous value
+ */
+ long getAndAddLong(long offsetBytes, long delta);
+
+ /**
+ * Atomically sets the current value at the memory location to the given updated value
+ * if and only if the current value {@code ==} the expected value.
+ * @param offsetBytes offset bytes relative to this Memory start
+ * @param expect the expected value
+ * @param update the new value
+ * @return {@code true} if successful. False return indicates that
+ * the current value at the memory location was not equal to the expected value.
+ */
+ boolean compareAndSwapLong(long offsetBytes, long expect, long update);
+
+ /**
+ * Atomically exchanges the given value with the current value located at offsetBytes.
+ * @param offsetBytes offset bytes relative to this Memory start
+ * @param newValue new value
+ * @return the previous value
+ */
+ long getAndSetLong(long offsetBytes, long newValue);
+
+ //OTHER WRITE METHODS
+ /**
+ * Returns the primitive backing array, otherwise null.
+ * @return the primitive backing array, otherwise null.
+ */
+ Object getArray();
+
+ /**
+ * Clears all bytes of this Memory to zero
+ */
+ void clear();
+
+ /**
+ * Clears a portion of this Memory to zero.
+ * @param offsetBytes offset bytes relative to this Memory start
+ * @param lengthBytes the length in bytes
+ */
+ void clear(long offsetBytes, long lengthBytes);
+
+ /**
+ * Clears the bits defined by the bitMask
+ * @param offsetBytes offset bytes relative to this Memory start.
+ * @param bitMask the bits set to one will be cleared
+ */
+ void clearBits(long offsetBytes, byte bitMask);
+
+ /**
+ * Fills all bytes of this Memory region to the given byte value.
+ * @param value the given byte value
+ */
+ void fill(byte value);
+
+ /**
+ * Fills a portion of this Memory region to the given byte value.
+ * @param offsetBytes offset bytes relative to this Memory start
+ * @param lengthBytes the length in bytes
+ * @param value the given byte value
+ */
+ void fill(long offsetBytes, long lengthBytes, byte value);
+
+ /**
+ * Sets the bits defined by the bitMask
+ * @param offsetBytes offset bytes relative to this Memory start
+ * @param bitMask the bits set to one will be set
+ */
+ void setBits(long offsetBytes, byte bitMask);
+
+
+ //OTHER WRITABLE API METHODS
+ /**
+ * WritableMemory enables this for ByteBuffer, Heap and Direct Memory backed resources.
+ * Map backed resources will always return null.
+ * Gets the MemoryRequestServer object, if set, for the above resources to request additional memory.
+ * The user must customize the actions of the MemoryRequestServer by
+ * implementing the MemoryRequestServer interface and set using one of these methods:
+ * <ul><li>{@link WritableMemory#allocateDirect(long, ByteOrder, MemoryRequestServer)}</li>
+ * <li>{@link WritableMemory#allocate(int, ByteOrder, MemoryRequestServer)}</li>
+ * <li>{@link WritableMemory#writableWrap(ByteBuffer, ByteOrder, MemoryRequestServer)}</li>
+ * </ul>
+ * Simple implementation examples include the DefaultMemoryRequestServer in the main tree, as well as
+ * the ExampleMemoryRequestServerTest and the use with ByteBuffer documented in the DruidIssue11544Test
+ * in the test tree.
+ * @return the MemoryRequestServer object or null.
+ */
+ MemoryRequestServer getMemoryRequestServer();
+
+}
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/XxHash.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/XxHash.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/XxHash.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,192 @@
+/*
+ * 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.datasketches.memory;
+
+import static org.apache.datasketches.memory.internal.XxHash64.hash;
+import static org.apache.datasketches.memory.internal.XxHash64.hashBooleans;
+import static org.apache.datasketches.memory.internal.XxHash64.hashBytes;
+import static org.apache.datasketches.memory.internal.XxHash64.hashChars;
+import static org.apache.datasketches.memory.internal.XxHash64.hashDoubles;
+import static org.apache.datasketches.memory.internal.XxHash64.hashFloats;
+import static org.apache.datasketches.memory.internal.XxHash64.hashInts;
+import static org.apache.datasketches.memory.internal.XxHash64.hashLongs;
+import static org.apache.datasketches.memory.internal.XxHash64.hashShorts;
+
+/**
+ * The XxHash is a fast, non-cryptographic, 64-bit hash function that has
+ * excellent avalanche and 2-way bit independence properties.
+ * This java version adapted the C++ version and the OpenHFT/Zero-Allocation-Hashing implementation
+ * referenced below as inspiration.
+ *
+ * <p>The C++ source repository:
+ * <a href="https://github.com/Cyan4973/xxHash">
+ * https://github.com/Cyan4973/xxHash</a>. It has a BSD 2-Clause License:
+ * <a href="http://www.opensource.org/licenses/bsd-license.php">
+ * http://www.opensource.org/licenses/bsd-license.php</a>. See LICENSE.
+ *
+ * <p>Portions of this code were adapted from
+ * <a href="https://github.com/OpenHFT/Zero-Allocation-Hashing/blob/master/src/main/java/net/openhft/hashing/XxHash.java">
+ * OpenHFT/Zero-Allocation-Hashing</a>, which has an Apache 2 license as does this site. See LICENSE.
+ *
+ * @author Lee Rhodes
+ */
+public final class XxHash {
+
+ private XxHash() { /* singleton */ }
+
+ /**
+ * Hash the given arr starting at the given offset and continuing for the given length using the
+ * given seed.
+ * @param arr the given array
+ * @param offsetBooleans starting at this offset
+ * @param lengthBooleans continuing for this length
+ * @param seed the given seed
+ * @return the hash
+ */
+ public static long hashBooleanArr(final boolean[] arr, final long offsetBooleans,
+ final long lengthBooleans, final long seed) {
+ return hashBooleans(arr, offsetBooleans, lengthBooleans, seed);
+ }
+
+ /**
+ * Hash the given arr starting at the given offset and continuing for the given length using the
+ * given seed.
+ * @param arr the given array
+ * @param offsetBytes starting at this offset
+ * @param lengthBytes continuing for this length
+ * @param seed the given seed
+ * @return the hash
+ */
+ public static long hashByteArr(final byte[] arr, final long offsetBytes,
+ final long lengthBytes, final long seed) {
+ return hashBytes(arr, offsetBytes, lengthBytes, seed);
+ }
+
+ /**
+ * Hash the given arr starting at the given offset and continuing for the given length using the
+ * given seed.
+ * @param arr the given array
+ * @param offsetShorts starting at this offset
+ * @param lengthShorts continuing for this length
+ * @param seed the given seed
+ * @return the hash
+ */
+ public static long hashShortArr(final short[] arr, final long offsetShorts,
+ final long lengthShorts, final long seed) {
+ return hashShorts(arr, offsetShorts, lengthShorts, seed);
+ }
+
+ /**
+ * Hash the given arr starting at the given offset and continuing for the given length using the
+ * given seed.
+ * @param arr the given array
+ * @param offsetChars starting at this offset
+ * @param lengthChars continuing for this length
+ * @param seed the given seed
+ * @return the hash
+ */
+ public static long hashCharArr(final char[] arr, final long offsetChars,
+ final long lengthChars, final long seed) {
+ return hashChars(arr, offsetChars, lengthChars, seed);
+ }
+
+ /**
+ * Hash the given arr starting at the given offset and continuing for the given length using the
+ * given seed.
+ * @param arr the given array
+ * @param offsetInts starting at this offset
+ * @param lengthInts continuing for this length
+ * @param seed the given seed
+ * @return the hash
+ */
+ public static long hashIntArr(final int[] arr, final long offsetInts,
+ final long lengthInts, final long seed) {
+ return hashInts(arr, offsetInts, lengthInts, seed);
+ }
+
+ /**
+ * Hash the given arr starting at the given offset and continuing for the given length using the
+ * given seed.
+ * @param arr the given array
+ * @param offsetLongs starting at this offset
+ * @param lengthLongs continuing for this length
+ * @param seed the given seed
+ * @return the hash
+ */
+ public static long hashLongArr(final long[] arr, final long offsetLongs,
+ final long lengthLongs, final long seed) {
+ return hashLongs(arr, offsetLongs, lengthLongs, seed);
+ }
+
+ /**
+ * Returns a 64-bit hash from a single long. This method has been optimized for speed when only
+ * a single hash of a long is required.
+ * @param in A long.
+ * @param seed A long valued seed.
+ * @return the hash.
+ */
+ public static long hashLong(final long in, final long seed) {
+ return hash(in, seed);
+ }
+
+ /**
+ * Hash the given arr starting at the given offset and continuing for the given length using the
+ * given seed.
+ * @param arr the given array
+ * @param offsetFloats starting at this offset
+ * @param lengthFloats continuing for this length
+ * @param seed the given seed
+ * @return the hash
+ */
+ public static long hashFloatArr(final float[] arr, final long offsetFloats,
+ final long lengthFloats, final long seed) {
+ return hashFloats(arr, offsetFloats, lengthFloats, seed);
+ }
+
+ /**
+ * Hash the given arr starting at the given offset and continuing for the given length using the
+ * given seed.
+ * @param arr the given array
+ * @param offsetDoubles starting at this offset
+ * @param lengthDoubles continuing for this length
+ * @param seed the given seed
+ * @return the hash
+ */
+ public static long hashDoubleArr(final double[] arr, final long offsetDoubles,
+ final long lengthDoubles, final long seed) {
+ return hashDoubles(arr, offsetDoubles, lengthDoubles, seed);
+ }
+
+ /**
+ * Hash the given arr starting at the given offset and continuing for the given length using the
+ * given seed.
+ * @param str the given string
+ * @param offsetChars starting at this offset
+ * @param lengthChars continuing for this length
+ * @param seed the given seed
+ * @return the hash
+ */
+ public static long hashString(final String str, final long offsetChars,
+ final long lengthChars, final long seed) {
+ return org.apache.datasketches.memory.internal.XxHash64.hashString(str, offsetChars, lengthChars, seed);
+ }
+
+}
+
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AccessByteBuffer.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AccessByteBuffer.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AccessByteBuffer.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,92 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Acquires access to a ByteBuffer.
+ *
+ * @author Lee Rhodes
+ * @author Praveenkumar Venkatesan
+ * @author Roman Leventov
+ */
+@SuppressWarnings("restriction")
+final class AccessByteBuffer {
+
+ static final ByteBuffer ZERO_READ_ONLY_DIRECT_BYTE_BUFFER =
+ ByteBuffer.allocateDirect(0).asReadOnlyBuffer();
+
+ private static final long NIO_BUFFER_ADDRESS_FIELD_OFFSET =
+ UnsafeUtil.getFieldOffset(java.nio.Buffer.class, "address");
+ private static final long NIO_BUFFER_CAPACITY_FIELD_OFFSET =
+ UnsafeUtil.getFieldOffset(java.nio.Buffer.class, "capacity");
+ private static final long BYTE_BUFFER_HB_FIELD_OFFSET =
+ UnsafeUtil.getFieldOffset(java.nio.ByteBuffer.class, "hb");
+ private static final long BYTE_BUFFER_OFFSET_FIELD_OFFSET =
+ UnsafeUtil.getFieldOffset(java.nio.ByteBuffer.class, "offset");
+
+ final long nativeBaseOffset;
+ final long capacityBytes;
+ final long regionOffset;
+ final Object unsafeObj;
+ final boolean resourceReadOnly;
+ final ByteOrder byteOrder; //not used externally, here for reference.
+
+ /**
+ * The given ByteBuffer may be either readOnly or writable
+ * @param byteBuf the given ByteBuffer
+ */
+ AccessByteBuffer(final ByteBuffer byteBuf) {
+ capacityBytes = byteBuf.capacity();
+ resourceReadOnly = byteBuf.isReadOnly();
+ byteOrder = byteBuf.order();
+ final boolean direct = byteBuf.isDirect();
+ if (direct) {
+ nativeBaseOffset = ((sun.nio.ch.DirectBuffer) byteBuf).address();
+ unsafeObj = null;
+ regionOffset = 0L; //address() is already adjusted for direct slices, so regionOffset = 0
+ } else {
+ nativeBaseOffset = 0L;
+ // ByteBuffer.arrayOffset() and ByteBuffer.array() throw ReadOnlyBufferException if
+ // ByteBuffer is read-only. This uses reflection for both writable and read-only cases.
+ // Includes the slice() offset for heap.
+ regionOffset = unsafe.getInt(byteBuf, BYTE_BUFFER_OFFSET_FIELD_OFFSET);
+ unsafeObj = unsafe.getObject(byteBuf, BYTE_BUFFER_HB_FIELD_OFFSET);
+ }
+ }
+
+ /**
+ * This method is adapted from
+ * https://github.com/odnoklassniki/one-nio/blob/master/src/one/nio/mem/DirectMemory.java
+ * : wrap(...). See LICENSE.
+ */
+ static ByteBuffer getDummyReadOnlyDirectByteBuffer(final long address, final int capacity) {
+ final ByteBuffer buf = ZERO_READ_ONLY_DIRECT_BYTE_BUFFER.duplicate();
+ unsafe.putLong(buf, NIO_BUFFER_ADDRESS_FIELD_OFFSET, address);
+ unsafe.putInt(buf, NIO_BUFFER_CAPACITY_FIELD_OFFSET, capacity);
+ buf.limit(capacity);
+ return buf;
+ }
+
+}
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,135 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
+
+import java.util.logging.Logger;
+
+/**
+ * Provides access to direct (native) memory.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+@SuppressWarnings("restriction")
+final class AllocateDirect {
+ static final Logger LOG = Logger.getLogger(AllocateDirect.class.getCanonicalName());
+
+ private final Deallocator deallocator;
+ private final long nativeBaseOffset;
+ private final MemoryCleaner cleaner;
+
+ /**
+ * Base Constructor for allocate native memory.
+ *
+ * <p>Allocates and provides access to capacityBytes directly in native (off-heap) memory
+ * leveraging the MemoryImpl interface.
+ * The allocated memory will be 8-byte aligned, but may not be page aligned.
+ * @param capacityBytes the the requested capacity of off-heap memory. Cannot be zero.
+ */
+ AllocateDirect(final long capacityBytes) {
+ final boolean pageAligned = NioBits.isPageAligned();
+ final long pageSize = NioBits.pageSize();
+ final long allocationSize = capacityBytes + (pageAligned ? pageSize : 0);
+ NioBits.reserveMemory(allocationSize, capacityBytes);
+
+ final long nativeAddress;
+ try {
+ nativeAddress = unsafe.allocateMemory(allocationSize);
+ } catch (final OutOfMemoryError err) {
+ NioBits.unreserveMemory(allocationSize, capacityBytes);
+ throw new RuntimeException(err);
+ }
+ if (pageAligned && ((nativeAddress % pageSize) != 0)) {
+ //Round up to page boundary
+ nativeBaseOffset = (nativeAddress & ~(pageSize - 1L)) + pageSize;
+ } else {
+ nativeBaseOffset = nativeAddress;
+ }
+ deallocator = new Deallocator(nativeAddress, allocationSize, capacityBytes);
+ cleaner = new MemoryCleaner(this, deallocator);
+ }
+
+ boolean doClose() {
+ try {
+ if (deallocator.deallocate(false)) {
+ // This Cleaner.clean() call effectively just removes the Cleaner from the internal linked
+ // list of all cleaners. It will delegate to Deallocator.deallocate() which will be a no-op
+ // because the valid state is already changed.
+ cleaner.clean();
+ return true;
+ }
+ return false;
+ } finally {
+ BaseStateImpl.reachabilityFence(this);
+ }
+ }
+
+ long getNativeBaseOffset() {
+ return nativeBaseOffset;
+ }
+
+ StepBoolean getValid() {
+ return deallocator.getValid();
+ }
+
+ static final class Deallocator implements Runnable {
+ //This is the only place the actual native address is kept for use by unsafe.freeMemory();
+ private final long nativeAddress;
+ private final long allocationSize;
+ private final long capacity;
+ private final StepBoolean valid = new StepBoolean(true); //only place for this
+
+ Deallocator(final long nativeAddress, final long allocationSize, final long capacity) {
+ BaseStateImpl.currentDirectMemoryAllocations_.incrementAndGet();
+ BaseStateImpl.currentDirectMemoryAllocated_.addAndGet(capacity);
+ this.nativeAddress = nativeAddress;
+ this.allocationSize = allocationSize;
+ this.capacity = capacity;
+ assert (nativeAddress != 0);
+ }
+
+ StepBoolean getValid() {
+ return valid;
+ }
+
+ @Override
+ public void run() {
+ deallocate(true);
+ }
+
+ boolean deallocate(final boolean calledFromCleaner) {
+ if (valid.change()) {
+ if (calledFromCleaner) {
+ // Warn about non-deterministic resource cleanup.
+ LOG.warning("A WritableHandle was not closed manually");
+ }
+ unsafe.freeMemory(nativeAddress);
+ NioBits.unreserveMemory(allocationSize, capacity);
+ BaseStateImpl.currentDirectMemoryAllocations_.decrementAndGet();
+ BaseStateImpl.currentDirectMemoryAllocated_.addAndGet(-capacity);
+ return true;
+ }
+ return false;
+ }
+ }
+
+}
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,317 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.logging.Logger;
+
+import org.apache.datasketches.memory.Map;
+import org.apache.datasketches.memory.MemoryCloseException;
+
+import sun.nio.ch.FileChannelImpl;
+
+/**
+ * Allocates direct memory used to memory map files for read operations.
+ * (including those > 2GB).
+ *
+ * <p>To understand how it works, reference native code for map0, unmap0:
+ * <a href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/f940e7a48b72/src/solaris/native/sun/nio/ch/FileChannelImpl.c">
+ * FileChannelImpl.c</a></p>
+ *
+ * <p>To understand how it works, reference native code for load0(), isLoaded0(), and force0():
+ * <a href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/f940e7a48b72/src/solaris/native/java/nio/MappedByteBuffer.c">
+ * MappedByteBuffer.c</a></p>
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ * @author Praveenkumar Venkatesan
+ */
+@SuppressWarnings("restriction")
+class AllocateDirectMap implements Map {
+ static final Logger LOG = Logger.getLogger(AllocateDirectMap.class.getCanonicalName());
+
+ private static final int MAP_RO = 0;
+ private static final int MAP_RW = 1;
+
+ private static final Method FILE_CHANNEL_IMPL_MAP0_METHOD;
+ static final Method FILE_CHANNEL_IMPL_UNMAP0_METHOD;
+
+ private static final Method MAPPED_BYTE_BUFFER_LOAD0_METHOD;
+ private static final Method MAPPED_BYTE_BUFFER_ISLOADED0_METHOD;
+ static final Method MAPPED_BYTE_BUFFER_FORCE0_METHOD;
+
+ static {
+ try { //The FileChannelImpl methods map0 and unmap0 still exist in 16
+ FILE_CHANNEL_IMPL_MAP0_METHOD = FileChannelImpl.class
+ .getDeclaredMethod("map0", int.class, long.class, long.class); //JDK14 add boolean.class
+ FILE_CHANNEL_IMPL_MAP0_METHOD.setAccessible(true);
+
+ FILE_CHANNEL_IMPL_UNMAP0_METHOD = FileChannelImpl.class
+ .getDeclaredMethod("unmap0", long.class, long.class); //OK through jDK16
+ FILE_CHANNEL_IMPL_UNMAP0_METHOD.setAccessible(true);
+
+
+ //The MappedByteBuffer methods load0, isLoaded0 and force0 are removed in 15
+ MAPPED_BYTE_BUFFER_LOAD0_METHOD = MappedByteBuffer.class
+ .getDeclaredMethod("load0", long.class, long.class); //JDK15 removed
+ MAPPED_BYTE_BUFFER_LOAD0_METHOD.setAccessible(true);
+
+ MAPPED_BYTE_BUFFER_ISLOADED0_METHOD = MappedByteBuffer.class
+ .getDeclaredMethod("isLoaded0", long.class, long.class, int.class); //JDK15 removed
+ MAPPED_BYTE_BUFFER_ISLOADED0_METHOD.setAccessible(true);
+
+ MAPPED_BYTE_BUFFER_FORCE0_METHOD = MappedByteBuffer.class
+ .getDeclaredMethod("force0", FileDescriptor.class, long.class, long.class); //JDK15 removed
+ MAPPED_BYTE_BUFFER_FORCE0_METHOD.setAccessible(true);
+ } catch (final SecurityException | NoSuchMethodException e) {
+ throw new RuntimeException("Could not reflect static methods: " + e);
+ }
+ }
+
+ private final Deallocator deallocator;
+ private final MemoryCleaner cleaner;
+
+ final long capacityBytes;
+ final RandomAccessFile raf;
+ final long nativeBaseOffset;
+ final boolean resourceReadOnly;
+
+ //called from AllocateDirectWritableMap constructor
+ @SuppressWarnings("resource")
+ AllocateDirectMap(final File file, final long fileOffsetBytes, final long capacityBytes,
+ final boolean localReadOnly) {
+ this.capacityBytes = capacityBytes;
+ resourceReadOnly = isFileReadOnly(file);
+ final long fileLength = file.length();
+ if ((localReadOnly || resourceReadOnly) && fileOffsetBytes + capacityBytes > fileLength) {
+ throw new IllegalArgumentException(
+ "Read-only mode and requested map length is greater than current file length: "
+ + "Requested Length = " + (fileOffsetBytes + capacityBytes)
+ + ", Current File Length = " + fileLength);
+ }
+ raf = mapper(file, fileOffsetBytes, capacityBytes, resourceReadOnly);
+ nativeBaseOffset = map(raf.getChannel(), resourceReadOnly, fileOffsetBytes, capacityBytes);
+ deallocator = new Deallocator(nativeBaseOffset, capacityBytes, raf);
+ cleaner = new MemoryCleaner(this, deallocator);
+ }
+
+ //Map Interface
+
+ @Override
+ public void load() {
+ madvise();
+ // Performance optimization. Read a byte from each page to bring it into memory.
+ final int ps = NioBits.pageSize();
+ final int count = NioBits.pageCount(capacityBytes);
+ long offset = nativeBaseOffset;
+ for (int i = 0; i < count; i++) {
+ unsafe.getByte(offset);
+ offset += ps;
+ }
+ }
+
+ @Override
+ public boolean isLoaded() {
+ try {
+ final int pageCount = NioBits.pageCount(capacityBytes);
+ return (boolean) MAPPED_BYTE_BUFFER_ISLOADED0_METHOD
+ //isLoaded0 is effectively static, so ZERO_READ_ONLY_DIRECT_BYTE_BUFFER is not modified
+ .invoke(AccessByteBuffer.ZERO_READ_ONLY_DIRECT_BYTE_BUFFER,
+ nativeBaseOffset,
+ capacityBytes,
+ pageCount);
+ } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ throw new RuntimeException(
+ String.format("Encountered %s exception while loading", e.getClass()));
+ }
+ }
+ // End Map Interface
+
+ @Override
+ public void close() {
+ doClose("AllocateDirectMap");
+ }
+
+ boolean doClose(final String resource) {
+ try {
+ if (deallocator.deallocate(false)) {
+ // This Cleaner.clean() call effectively just removes the Cleaner from the internal linked
+ // list of all cleaners. It will delegate to Deallocator.deallocate() which will be a no-op
+ // because the valid state is already changed.
+ cleaner.clean();
+ return true;
+ }
+ return false;
+ } catch (final Exception e) {
+ throw new MemoryCloseException(resource);
+ } finally {
+ BaseStateImpl.reachabilityFence(this);
+ }
+ }
+
+ StepBoolean getValid() {
+ return deallocator.getValid();
+ }
+
+ // Private methods
+ /**
+ * called by load(). Calls the native method load0 in MappedByteBuffer.java, implemented
+ * in MappedByteBuffer.c. See reference at top of class. load0 allows setting a mapping length
+ * of greater than 2GB.
+ */
+ private void madvise() {
+ try {
+ MAPPED_BYTE_BUFFER_LOAD0_METHOD
+ //load0 is effectively static, so ZERO_READ_ONLY_DIRECT_BYTE_BUFFER is not modified
+ .invoke(AccessByteBuffer.ZERO_READ_ONLY_DIRECT_BYTE_BUFFER,
+ nativeBaseOffset,
+ capacityBytes);
+ } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ throw new RuntimeException(
+ String.format("Encountered %s exception while loading", e.getClass()));
+ }
+ }
+
+ //Does the actual mapping work, resourceReadOnly must already be set
+ private static RandomAccessFile mapper(final File file, final long fileOffset,
+ final long capacityBytes, final boolean resourceReadOnly) {
+
+ final String mode = resourceReadOnly ? "r" : "rw";
+ final RandomAccessFile raf;
+ try {
+ raf = new RandomAccessFile(file, mode);
+ if (fileOffset + capacityBytes > raf.length()) {
+ raf.setLength(fileOffset + capacityBytes);
+ }
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ return raf;
+ }
+
+ /**
+ * Creates a mapping of the FileChannel starting at position and of size length to pages
+ * in the OS. This may throw OutOfMemory error if you have exhausted memory.
+ * You can try to force garbage collection and re-attempt.
+ *
+ * <p>map0 is a native method of FileChannelImpl.java implemented in FileChannelImpl.c.
+ * See reference at top of class.</p>
+ *
+ * @param fileChannel the FileChannel
+ * @param position the offset in bytes into the FileChannel
+ * @param lengthBytes the length in bytes
+ * @return the native base offset address
+ * @throws RuntimeException Encountered an exception while mapping
+ */
+ private static long map(final FileChannel fileChannel, final boolean resourceReadOnly,
+ final long position, final long lengthBytes) {
+ final int pagePosition = (int) (position % unsafe.pageSize());
+ final long mapPosition = position - pagePosition;
+ final long mapSize = lengthBytes + pagePosition;
+ final int mapMode = resourceReadOnly ? MAP_RO : MAP_RW;
+ //final boolean isSync = true; //required as of JDK14, but it is more complex
+ try {
+ final long nativeBaseOffset = //JDK14 add isSync
+ (long) FILE_CHANNEL_IMPL_MAP0_METHOD.invoke(fileChannel, mapMode, mapPosition, mapSize);
+ return nativeBaseOffset;
+ } catch (final InvocationTargetException e) {
+ throw new RuntimeException("Exception while mapping", e.getTargetException());
+ } catch (final IllegalAccessException e) {
+ throw new RuntimeException("Exception while mapping", e);
+ }
+ }
+
+ public static boolean isFileReadOnly(final File file) {
+ return (!file.canWrite());
+ }
+
+ private static final class Deallocator implements Runnable {
+ private final RandomAccessFile myRaf;
+ private final FileChannel myFc;
+ //This is the only place the actual native offset is kept for use by unsafe.freeMemory();
+ private final long actualNativeBaseOffset;
+ private final long myCapacity;
+ private final StepBoolean valid = new StepBoolean(true); //only place for this
+
+ Deallocator(final long nativeBaseOffset, final long capacityBytes,
+ final RandomAccessFile raf) {
+ BaseStateImpl.currentDirectMemoryMapAllocations_.incrementAndGet();
+ BaseStateImpl.currentDirectMemoryMapAllocated_.addAndGet(capacityBytes);
+ myRaf = raf;
+ assert myRaf != null;
+ myFc = myRaf.getChannel();
+ actualNativeBaseOffset = nativeBaseOffset;
+ assert actualNativeBaseOffset != 0;
+ myCapacity = capacityBytes;
+ assert myCapacity != 0;
+ }
+
+ StepBoolean getValid() {
+ return valid;
+ }
+
+ @Override
+ public void run() {
+ deallocate(true);
+ }
+
+ boolean deallocate(final boolean calledFromCleaner) {
+ if (valid.change()) {
+ if (calledFromCleaner) {
+ // Warn about non-deterministic resource cleanup.
+ LOG.warning("A WritableMapHandleImpl was not closed manually");
+ }
+ try {
+ unmap();
+ }
+ finally {
+ BaseStateImpl.currentDirectMemoryMapAllocations_.decrementAndGet();
+ BaseStateImpl.currentDirectMemoryMapAllocated_.addAndGet(-myCapacity);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Removes existing mapping. <i>unmap0</i> is a native method in FileChannelImpl.c. See
+ * reference at top of class.
+ */
+ private void unmap() throws RuntimeException {
+ try {
+ FILE_CHANNEL_IMPL_UNMAP0_METHOD.invoke(myFc, actualNativeBaseOffset, myCapacity);
+ myRaf.close();
+ } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException | IOException e) {
+ throw new RuntimeException(
+ String.format("Encountered %s exception while freeing memory", e.getClass()));
+ }
+ }
+ } //End of class Deallocator
+
+}
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,63 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.datasketches.memory.ReadOnlyException;
+import org.apache.datasketches.memory.WritableMap;
+
+/**
+ * Allocates direct memory used to memory map files for write operations
+ * (including those > 2GB).
+ *
+ * @author Lee Rhodes
+ * @author Roman Leventov
+ * @author Praveenkumar Venkatesan
+ */
+//Called from WritableMemoryImpl, implements combo of WritableMemoryImpl with WritableMap resource
+final class AllocateDirectWritableMap extends AllocateDirectMap implements WritableMap {
+
+ AllocateDirectWritableMap(final File file, final long fileOffsetBytes,
+ final long capacityBytes, final boolean localReadOnly) {
+ super(file, fileOffsetBytes, capacityBytes, localReadOnly);
+ }
+
+ //Added by WritableMap Interface
+
+ @Override
+ public void force() {
+ if (resourceReadOnly) {
+ throw new ReadOnlyException("MemoryImpl Mapped File is Read Only.");
+ }
+ try {
+ MAPPED_BYTE_BUFFER_FORCE0_METHOD
+ //force0 is effectively static, so ZERO_READ_ONLY_DIRECT_BYTE_BUFFER is not modified
+ .invoke(AccessByteBuffer.ZERO_READ_ONLY_DIRECT_BYTE_BUFFER,
+ raf.getFD(),
+ nativeBaseOffset,
+ capacityBytes);
+ } catch (final IOException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ throw new RuntimeException(String.format("Encountered %s exception in force. " + e.getClass()));
+ }
+ }
+}
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,117 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for ByteBuffer, non-native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class BBNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
+ private static final int id = BUFFER | NONNATIVE | BYTEBUF;
+ private final Object unsafeObj;
+ private final long nativeBaseOffset; //used to compute cumBaseOffset
+ private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until we are done with it.
+ private final MemoryRequestServer memReqSvr;
+ private final byte typeId;
+
+ BBNonNativeWritableBufferImpl(
+ final Object unsafeObj,
+ final long nativeBaseOffset,
+ final long regionOffset,
+ final long capacityBytes,
+ final int typeId,
+ final ByteBuffer byteBuf,
+ final MemoryRequestServer memReqSvr) {
+ super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+ this.unsafeObj = unsafeObj;
+ this.nativeBaseOffset = nativeBaseOffset;
+ this.byteBuf = byteBuf;
+ this.memReqSvr = memReqSvr;
+ this.typeId = (byte) (id | (typeId & 0x7));
+ }
+
+ @Override
+ BaseWritableBufferImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+ final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly) | REGION;
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, byteBuf, memReqSvr)
+ : new BBNonNativeWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, byteBuf, memReqSvr);
+ }
+
+ @Override
+ BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr)
+ : new BBNonNativeWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr);
+ }
+
+ @Override
+ BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly);
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableMemoryImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr)
+ : new BBNonNativeWritableMemoryImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr);
+ }
+
+ @Override
+ public ByteBuffer getByteBuffer() {
+ assertValid();
+ return byteBuf;
+ }
+
+ @Override
+ public MemoryRequestServer getMemoryRequestServer() {
+ assertValid();
+ return memReqSvr;
+ }
+
+ @Override
+ long getNativeBaseOffset() {
+ return nativeBaseOffset;
+ }
+
+ @Override
+ int getTypeId() {
+ return typeId & 0xff;
+ }
+
+ @Override
+ Object getUnsafeObject() {
+ assertValid();
+ return unsafeObj;
+ }
+
+}
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,107 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for ByteBuffer, non-native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class BBNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
+ private static final int id = MEMORY | NONNATIVE | BYTEBUF;
+ private final Object unsafeObj;
+ private final long nativeBaseOffset; //used to compute cumBaseOffset
+ private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until we are done with it.
+ private final MemoryRequestServer memReqSvr;
+ private final byte typeId;
+
+ BBNonNativeWritableMemoryImpl(
+ final Object unsafeObj,
+ final long nativeBaseOffset,
+ final long regionOffset,
+ final long capacityBytes,
+ final int typeId,
+ final ByteBuffer byteBuf,
+ final MemoryRequestServer memReqSvr) {
+ super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+ this.unsafeObj = unsafeObj;
+ this.nativeBaseOffset = nativeBaseOffset;
+ this.byteBuf = byteBuf;
+ this.memReqSvr = memReqSvr;
+ this.typeId = (byte) (id | (typeId & 0x7));
+ }
+
+ @Override
+ BaseWritableMemoryImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+ final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly) | REGION;
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableMemoryImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, getByteBuffer(), memReqSvr)
+ : new BBNonNativeWritableMemoryImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, getByteBuffer(), memReqSvr);
+ }
+
+ @Override
+ BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly);
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr)
+ : new BBNonNativeWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr);
+ }
+
+ @Override
+ public ByteBuffer getByteBuffer() {
+ assertValid();
+ return byteBuf;
+ }
+
+ @Override
+ public MemoryRequestServer getMemoryRequestServer() {
+ assertValid();
+ return memReqSvr;
+ }
+
+ @Override
+ long getNativeBaseOffset() {
+ return nativeBaseOffset;
+ }
+
+ @Override
+ int getTypeId() {
+ return typeId & 0xff;
+ }
+
+ @Override
+ Object getUnsafeObject() {
+ assertValid();
+ return unsafeObj;
+ }
+
+}
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,117 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for ByteBuffer, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class BBWritableBufferImpl extends NativeWritableBufferImpl {
+ private static final int id = BUFFER | NATIVE | BYTEBUF;
+ private final Object unsafeObj;
+ private final long nativeBaseOffset; //used to compute cumBaseOffset
+ private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until we are done with it.
+ private final MemoryRequestServer memReqSvr;
+ private final byte typeId;
+
+ BBWritableBufferImpl(
+ final Object unsafeObj,
+ final long nativeBaseOffset,
+ final long regionOffset,
+ final long capacityBytes,
+ final int typeId,
+ final ByteBuffer byteBuf,
+ final MemoryRequestServer memReqSvr) {
+ super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+ this.unsafeObj = unsafeObj;
+ this.nativeBaseOffset = nativeBaseOffset;
+ this.byteBuf = byteBuf;
+ this.memReqSvr = memReqSvr;
+ this.typeId = (byte) (id | (typeId & 0x7));
+ }
+
+ @Override
+ BaseWritableBufferImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+ final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly) | REGION;
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, byteBuf, memReqSvr)
+ : new BBNonNativeWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, byteBuf, memReqSvr);
+ }
+
+ @Override
+ BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr)
+ : new BBNonNativeWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr);
+ }
+
+ @Override
+ BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly);
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableMemoryImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr)
+ : new BBNonNativeWritableMemoryImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr);
+ }
+
+ @Override
+ public ByteBuffer getByteBuffer() {
+ assertValid();
+ return byteBuf;
+ }
+
+ @Override
+ public MemoryRequestServer getMemoryRequestServer() {
+ assertValid();
+ return memReqSvr;
+ }
+
+ @Override
+ long getNativeBaseOffset() {
+ return nativeBaseOffset;
+ }
+
+ @Override
+ int getTypeId() {
+ return typeId & 0xff;
+ }
+
+ @Override
+ Object getUnsafeObject() {
+ assertValid();
+ return unsafeObj;
+ }
+
+}
Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,107 @@
+/*
+ * 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.datasketches.memory.internal;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for ByteBuffer, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class BBWritableMemoryImpl extends NativeWritableMemoryImpl {
+ private static final int id = MEMORY | NATIVE | BYTEBUF;
+ private final Object unsafeObj;
+ private final long nativeBaseOffset; //used to compute cumBaseOffset
+ private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until we are done with it.
+ private final MemoryRequestServer memReqSvr;
+ private final byte typeId;
+
+ BBWritableMemoryImpl(
+ final Object unsafeObj,
+ final long nativeBaseOffset,
+ final long regionOffset,
+ final long capacityBytes,
+ final int typeId,
+ final ByteBuffer byteBuf,
+ final MemoryRequestServer memReqSvr) {
+ super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+ this.unsafeObj = unsafeObj;
+ this.nativeBaseOffset = nativeBaseOffset;
+ this.byteBuf = byteBuf;
+ this.memReqSvr = memReqSvr;
+ this.typeId = (byte) (id | (typeId & 0x7));
+ }
+
+ @Override
+ BaseWritableMemoryImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+ final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly) | REGION;
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableMemoryImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, getByteBuffer(), memReqSvr)
+ : new BBNonNativeWritableMemoryImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, getByteBuffer(), memReqSvr);
+ }
+
+ @Override
+ BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final ByteOrder byteOrder) {
+ final int type = setReadOnlyType(typeId, readOnly);
+ return Util.isNativeByteOrder(byteOrder)
+ ? new BBWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr)
+ : new BBNonNativeWritableBufferImpl(
+ unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), type, byteBuf, memReqSvr);
+ }
+
+ @Override
+ public ByteBuffer getByteBuffer() {
+ assertValid();
+ return byteBuf;
+ }
+
+ @Override
+ public MemoryRequestServer getMemoryRequestServer() {
+ assertValid();
+ return memReqSvr;
+ }
+
+ @Override
+ long getNativeBaseOffset() {
+ return nativeBaseOffset;
+ }
+
+ @Override
+ int getTypeId() {
+ return typeId & 0xff;
+ }
+
+ @Override
+ Object getUnsafeObject() {
+ assertValid();
+ return unsafeObj;
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org