code: /*
   * 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);
  
  }
  