All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.openhft.chronicle.bytes.internal.SingleMappedBytes Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2016-2022 chronicle.software
 *
 *     https://chronicle.software
 *
 * Licensed 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 net.openhft.chronicle.bytes.internal;

import net.openhft.chronicle.bytes.*;
import net.openhft.chronicle.bytes.util.DecoratedBufferOverflowException;
import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.core.Memory;
import net.openhft.chronicle.core.UnsafeMemory;
import net.openhft.chronicle.core.annotation.NonNegative;
import net.openhft.chronicle.core.io.ClosedIllegalStateException;
import net.openhft.chronicle.core.io.IORuntimeException;
import net.openhft.chronicle.core.io.ThreadingIllegalStateException;
import net.openhft.chronicle.core.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;

import static net.openhft.chronicle.core.Jvm.uncheckedCast;
import static net.openhft.chronicle.core.util.Longs.requireNonNegative;
import static net.openhft.chronicle.core.util.ObjectUtils.requireNonNull;

/**
 * A class that extends the {@link CommonMappedBytes} to provide a mechanism to wrap memory-mapped data.
 * This allows for high-performance file I/O operations by loading file segments into memory for
 * byte-level manipulations.
 *
 * 

Note: Instances of this class are not safe for use by multiple concurrent threads. * * @see CommonMappedBytes */ public class SingleMappedBytes extends CommonMappedBytes { /** * Constructs a SingleMappedBytes object wrapping the memory mapped to the specified file. * * @param mappedFile The MappedFile object to be wrapped. * @throws ClosedIllegalStateException If the resource has been released or closed. * @throws ThreadingIllegalStateException If this resource was accessed by multiple threads in an unsafe way */ public SingleMappedBytes(@NotNull final MappedFile mappedFile) throws IllegalStateException { this(mappedFile, ""); } /** * Constructs a SingleMappedBytes object wrapping the memory mapped to the specified file and associates it with the specified name. * * @param mappedFile The MappedFile object to be wrapped. * @param name The name to be associated with the SingleMappedBytes object. * @throws ClosedIllegalStateException If the resource has been released or closed. * @throws ThreadingIllegalStateException If this resource was accessed by multiple threads in an unsafe way */ @SuppressWarnings("this-escape") protected SingleMappedBytes(@NotNull final MappedFile mappedFile, final String name) throws IllegalStateException { super(mappedFile, name); try { bytesStore(uncheckedCast(mappedFile.acquireByteStore(this, 0))); } catch (@NotNull IOException e) { throw new IORuntimeException(e); } } @Override public @NotNull SingleMappedBytes write(@NonNegative final long offsetInRDO, final byte[] byteArray, @NonNegative int offset, @NonNegative final int length) throws IllegalStateException, BufferOverflowException { requireNonNegative(offsetInRDO); requireNonNull(byteArray); requireNonNegative(offset); requireNonNegative(length); throwExceptionIfClosed(); long wp = offsetInRDO; if ((length + offset) > byteArray.length) throw new ArrayIndexOutOfBoundsException("bytes.length=" + byteArray.length + ", " + "length=" + length + ", offset=" + offset); if (offsetInRDO + length > writeLimit) throw new DecoratedBufferOverflowException( String.format("write failed. offset: %d + length: %d > writeLimit: %d", offsetInRDO, length, writeLimit)); int remaining = length; while (remaining > 0) { long safeCopySize = copySize(wp); if (safeCopySize + mappedFile.overlapSize() >= remaining) { bytesStore.write(wp, byteArray, offset, remaining); return this; } bytesStore.write(wp, byteArray, offset, (int) safeCopySize); offset += (int) safeCopySize; wp += safeCopySize; remaining -= (int) safeCopySize; } return this; } @Override public @NotNull SingleMappedBytes write(@NonNegative final long writeOffset, @NotNull final RandomDataInput bytes, @NonNegative long readOffset, @NonNegative final long length) throws BufferOverflowException, BufferUnderflowException, IllegalStateException { requireNonNegative(writeOffset); ReferenceCountedUtil.throwExceptionIfReleased(bytes); requireNonNegative(readOffset); requireNonNegative(length); throwExceptionIfReleased(); long wp = writeOffset; if (writeOffset + length > writeLimit) throw new DecoratedBufferOverflowException( String.format("write failed. End of write: %d + %d > writeLimit: %d", writeOffset, length, writeLimit)); long remaining = length; while (remaining > 0) { long safeCopySize = copySize(wp); if (safeCopySize + mappedFile.overlapSize() >= remaining) { bytesStore.write(wp, bytes, readOffset, remaining); return this; } bytesStore.write(wp, bytes, readOffset, safeCopySize); readOffset += safeCopySize; wp += safeCopySize; remaining -= safeCopySize; } return this; } private long copySize(@NonNegative final long writePosition) { long size = mappedFile.chunkSize(); return size - writePosition % size; } @NotNull @Override public Bytes readPositionRemaining(@NonNegative final long position, @NonNegative final long remaining) throws BufferUnderflowException, IllegalStateException { // throwExceptionIfClosed final long limit = position + remaining; if (writeLimit < limit) writeLimit(limit); if (Jvm.isAssertEnabled()) readLimit(limit); else uncheckedWritePosition(limit); return readPosition(position); } @Override public @NotNull Bytes writeSkip(long bytesToSkip) throws BufferOverflowException, IllegalStateException { // only check up to 128 bytes are real. writeCheckOffset(writePosition(), Math.min(128, bytesToSkip)); // the rest can be lazily allocated. uncheckedWritePosition(writePosition() + bytesToSkip); return this; } @NotNull private BufferOverflowException newBufferOverflowException(@NonNegative final long offset) { BufferOverflowException exception = new BufferOverflowException(); exception.initCause(new IllegalArgumentException("Offset out of bound " + offset)); return exception; } @NotNull @Override public Bytes clear() throws IllegalStateException { long start = 0L; readPosition = start; uncheckedWritePosition(start); writeLimit = mappedFile.capacity(); return this; } @SuppressWarnings("restriction") @Override public int peekVolatileInt() throws IllegalStateException { @Nullable final MappedBytesStore bytesStore = (MappedBytesStore) (BytesStore) this.bytesStore; long address = bytesStore.address + bytesStore.translate(readPosition); @Nullable Memory memory = bytesStore.memory; // are we inside a cache line? if ((address & 63) <= 60) { ObjectUtils.requireNonNull(memory); UnsafeMemory.unsafeLoadFence(); return UnsafeMemory.unsafeGetInt(address); } else { return memory.readVolatileInt(address); } } // used by the Pretoucher, don't change this without considering the impact. @Override public boolean compareAndSwapLong(@NonNegative long offset, long expected, long value) throws BufferOverflowException, IllegalStateException { throwExceptionIfClosed(); if (offset < 0 || offset > capacity()) throw newBufferOverflowException(offset); return bytesStore.compareAndSwapLong(offset, expected, value); } @Override public Bytes write(@NotNull BytesStore bytes) throws BufferOverflowException, IllegalStateException { assert bytes != this : "you should not write to yourself !"; long length = bytes.readRemaining(); bytesStore.write(writePosition(), bytes); writeSkip(length); return this; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy