blob: a7b27e2d1d03e40f7956177afd7862ce6ec5f64c [file] [log] [blame]
/*
* 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 java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Methods common to all memory access resources, including attributes like byte order and capacity.
*
* <p>The classes in this package are not thread-safe.</p>
*
* @author Lee Rhodes
*/
public interface Resource extends AutoCloseable {
static MemoryRequestServer defaultMemReqSvr = null; //policy choice
/**
* Closes this resource if this can be closed via <em>AutoCloseable</em>.
* If this operation completes without exceptions, this resource will be marked as <em>not alive</em>,
* and subsequent operations on this resource will fail with {@link IllegalStateException}.
*
* @apiNote This operation is not idempotent; that is, closing an already closed resource <em>always</em>
* results in an exception being thrown. This reflects a deliberate design choice: resource state transitions
* should be manifest in the client code; a failure in any of these transitions reveals a bug in the underlying
* application logic.
*
* @throws IllegalStateException if this Resource is not <em>valid</em>.
* @throws IllegalStateException if this method is not accessed from the owning thread.
* @throws UnsupportedOperationException if this resource is not {@link AutoCloseable}.
*/
@Override
void close();
/**
* Returns true if the given object (<em>that</em>) is an instance of this class and has contents equal to
* this object.
* @param that the given Resource object
* @return true if the given object has equal contents to this object.
* @see #equalTo(long, Resource, long, long)
*/
default boolean equalTo(Resource that) {
if (that == null || this.getCapacity() != that.getCapacity()) { return false; }
else { return equalTo(0, that, 0, that.getCapacity()); }
}
/**
* Returns true if the given Resource has equal contents to
* this object in the given range of bytes. This will also check two distinct ranges within the
* same object for equals.
* @param thisOffsetBytes the starting offset in bytes for this object.
* @param that the given Resource
* @param thatOffsetBytes the starting offset in bytes for the given Resource object
* @param lengthBytes the size of the range in bytes
* @return true if the given Resource object has equal contents to this object in the given range of bytes.
* @throws IllegalStateException if either resource is not <em>valid</em>.
* @throws MemoryBoundsException if there is a bounds violation.
*/
boolean equalTo(long thisOffsetBytes, Resource that, long thatOffsetBytes, long lengthBytes);
/**
* Forces any changes made to the contents of this memory-mapped Resource to be written to the storage
* device described by the configured file descriptor.
*
* <p>If the file descriptor associated with this memory-mapped Resource resides on a local storage device then when
* this method returns, it is guaranteed that all changes made to this mapped Resource since it was created, or since
* this method was last invoked, will have been written to that device.</p>
*
* <p>If the file descriptor associated with this memory-mapped Resource does not reside on a local device then no
* such guarantee is made.</p>
*
* <p>If this memory-mapped Resource was not mapped in read/write mode
* ({@link java.nio.channels.FileChannel.MapMode#READ_WRITE}) then invoking this method may have no effect.
* In particular, this method has no effect for files mapped in read-only or private
* mapping modes. This method may or may not have an effect for implementation-specific mapping modes.</p>
*
* @throws IllegalStateException if this Resource is not <em>valid</em>.
* @throws IllegalStateException if this method is not accessed from the owning thread.
* @throws UnsupportedOperationException if this Resource is not memory-mapped, e.g. if {@code isMapped() == false}.
* @throws ReadOnlyException if this Resource is read-only.
* @throws RuntimeException if there is some other error writing the contents of this
* memory-mapped Resource to the associated storage device.
*/
void force();
/**
* Gets the current ByteOrder.
* This may be different from the ByteOrder of the backing resource and {@link ByteOrder#nativeOrder()}
* @return the current ByteOrder.
*/
ByteOrder getByteOrder();
/**
* Gets the capacity of this object in bytes
* @return the capacity of this object in bytes
*/
long getCapacity();
/**
* Gets the MemoryRequestServer object, if set, for the below resources to request additional memory.
*
* <p>WritableMemory enables this for ByteBuffer, Heap and Direct Memory backed resources.</p>
*
* <p>WritableBuffer enables this for ByteBuffer backed resources. However, the object returned is in the form of
* a WritableMemory. To convert to WritableBuffer use asWritableBuffer(). To enable for Heap and Direct Buffer
* resources, use the WritableMemory to configure and then call asWritableBuffer().</p>
*
* <p>Map backed resources will always return null.</p>
*
* <p>The user must customize the actions of the MemoryRequestServer by
* implementing the MemoryRequestServer interface.</p>
*
* <p>For WritableMemory, to enable at runtime set your custom MemoryRequestServer using one of these methods:</p>
* <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>
*
* <p>ForWritableBuffer, to enable at runtime set your custom MemoryRequestServer using the following method:</p>
* <ul>
* <li>{@link WritableBuffer#writableWrap(ByteBuffer, ByteOrder, MemoryRequestServer)}</li>
* </ul>
*
* <p>Simple implementation examples include the DefaultMemoryRequestServer in the main source tree, as well as
* the ExampleMemoryRequestServerTest and the use with ByteBuffer documented in the DruidIssue11544Test
* in the test source tree.</p>
*
* @return the MemoryRequestServer object or null.
*/
MemoryRequestServer getMemoryRequestServer();
/**
* Returns the offset of address zero of this object relative to the base address of the
* backing resource. This does not include the object header for heap arrays nor the initial
* offset of a memory-mapped file.
* @return the offset of address zero of this object relative to the base address of the
* backing resource.
*/
long getTotalOffset();
/**
* Returns true if this Memory is backed by a ByteBuffer.
* @return true if this Memory is backed by a ByteBuffer.
*/
boolean isByteBufferResource();
/**
* Returns true if the Native ByteOrder is the same as the ByteOrder of the
* current Buffer or Memory and the same ByteOrder as the given byteOrder.
* @param byteOrder the given ByteOrder
* @return true if the Native ByteOrder is the same as the ByteOrder of the
* current Buffer or Memory and the same ByteOrder as the given byteOrder.
*/
boolean isByteOrderCompatible(ByteOrder byteOrder);
/**
* If true, the backing resource is direct (off-heap) memory.
* This is the case for allocated direct memory, memory-mapped files,
* or from a wrapped ByteBuffer that was allocated direct.
* If false, the backing resource is the Java heap.
* @return true if the backing resource is direct (off-heap) memory.
*/
boolean isDirectResource();
/**
* Returns true if this instance is a duplicate of a Buffer instance.
* @return true if this instance is a duplicate of a Buffer instance.
*/
boolean isDuplicateBufferView();
/**
* Returns true if this object is backed by an on-heap primitive array or an on-heap ByteBuffer.
* @return true if this object is backed by an on-heap primitive array or an on-heap ByteBuffer.
*/
boolean isHeapResource();
/**
* Tells whether or not the contents of this memory-mapped Resource is resident in physical memory.
*
* <p>A return value of {@code true} implies that it is highly likely that all of the data in this memory-mapped
* Resource is resident in physical memory and may therefore be accessed without incurring any virtual-memory page
* faults or I/O operations.</p>
*
* <p>A return value of {@code false} does not necessarily imply that all of the data in this memory-mapped Resource
* is not resident in physical memory.</p>
*
* <p>The returned value is a hint, rather than a guarantee, because the underlying operating system may have paged
* out some of this Resource's data by the time that an invocation of this method returns.</p>
*
* @return true if it is likely that all of the data in this memory-mapped Resource is resident in physical memory
*
* @throws IllegalStateException if this Resource is not <em>valid</em>.
* @throws IllegalStateException if this method is not accessed from the owning thread.
* @throws UnsupportedOperationException if this Resource is not memory-mapped, e.g. if {@code isMapped() == false}.
*/
boolean isLoaded();
/**
* If true, this is a <i>Memory</i> or <i>WritableMemory</i> instance, which provides the Memory API.
* The Memory API is the principal API for this Memory Component.
* It provides a rich variety of direct manipulations of four types of resources:
* On-heap memory, direct (off-heap) memory, memory-mapped files, and ByteBuffers.
* If false, this is a <i>Buffer</i> or <i>WritableBuffer</i> instance, which provides the Buffer API.
*
* <p>The Buffer API is largely parallel to the Memory API except that it adds a positional API
* similar to that in <i>ByteBuffer</i>. The positional API is a convenience when iterating over structured
* arrays, or buffering input or output streams (thus the name).</p>
*
* @return true if this is a <i>Memory</i> or <i>WritableMemory</i> instance, which provides the Memory API,
* otherwise this is a <i>Buffer</i> or <i>WritableBuffer</i> instance, which provides the Buffer API.
*/
boolean isMemoryApi();
/**
* Returns true if the backing resource is a memory-mapped file.
* @return true if the backing resource is a memory-mapped file.
*/
boolean isMemoryMappedResource();
/**
* If true, all put and get operations will assume the non-native ByteOrder.
* Otherwise, all put and get operations will assume the native ByteOrder.
* @return true, if all put and get operations will assume the non-native ByteOrder.
*/
boolean isNonNativeOrder();
/**
* Returns true if this object or the backing resource is read-only.
* @return true if this object or the backing resource is read-only.
*/
boolean isReadOnly();
/**
* Returns true if this instance is a region view of another Memory or Buffer
* @return true if this instance is a region view of another Memory or Buffer
*/
boolean isRegionView();
/**
* Returns true if the backing resource of <i>this</i> is identical with the backing resource
* of <i>that</i>. The capacities must be the same. If <i>this</i> is a region,
* the region offset must also be the same.
* @param that A different non-null Resource
* @return true if the backing resource of <i>this</i> is the same as the backing resource
* of <i>that</i>.
*/
boolean isSameResource(Resource that);
/**
* Returns true if this object is valid and has not been closed.
* This is relevant only for direct (off-heap) memory and memory-mapped Files.
* @return true if this object is valid and has not been closed.
*/
boolean isValid();
/**
* Loads the contents of this memory-mapped Resource into physical memory.
*
* <p>This method makes a best effort to ensure that, when it returns, this contents of the memory-mapped Resource is
* resident in physical memory. Invoking this method may cause some number of page faults and
* I/O operations to occur.</p>
*
* @throws IllegalStateException if this Resource is not <em>valid</em>.
* @throws IllegalStateException if this method is not accessed from the owning thread.
* @throws UnsupportedOperationException if this Resource is not memory-mapped, e.g. if {@code isMapped() == false}.
*/
void load();
/**
* Sets the Default MemoryRequestServer
* @param memReqSvr the given MemoryRequestServer.
*/
void setMemoryRequestServer(MemoryRequestServer memReqSvr);
/**
* Returns a description of this object with an optional formatted hex string of the data
* for the specified a range. Used primarily for testing.
* @param header a descriptive header
* @param offsetBytes offset bytes relative to this object start
* @param lengthBytes number of bytes to convert to a hex string
// @param withData include output listing of byte data in the given range
* @return a formatted hex string in a human readable array
*/
String toHexString(String header, long offsetBytes, int lengthBytes);
/**
* Returns the 64-bit hash of the sequence of bytes in this object specified by
* <i>offsetBytes</i>, <i>lengthBytes</i> and a <i>seed</i>. Note that the sequence of bytes is
* always processed in the same order independent of endianness.
*
* @param offsetBytes the given offset in bytes to the first byte of the byte sequence.
* @param lengthBytes the given length in bytes of the byte sequence.
* @param seed the given long seed.
* @return the 64-bit hash of the sequence of bytes in this object specified by
* <i>offsetBytes</i> and <i>lengthBytes</i>.
*/
long xxHash64(long offsetBytes, long lengthBytes, long 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.
*/
long xxHash64(long in, long seed);
}