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

net.openhft.chronicle.bytes.MappedBytes Maven / Gradle / Ivy

/*
 * Copyright 2016 higherfrequencytrading.com
 *
 * 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;

import net.openhft.chronicle.core.Memory;
import net.openhft.chronicle.core.OS;
import net.openhft.chronicle.core.io.IORuntimeException;
import net.openhft.chronicle.core.util.StringUtils;
import org.jetbrains.annotations.NotNull;

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

import static net.openhft.chronicle.core.util.StringUtils.extractChars;

/**
 * Bytes to wrap memory mapped data.
 */
public class MappedBytes extends AbstractBytes {
    public static boolean CHECKING = false;
    private final MappedFile mappedFile;

    // assume the mapped file is reserved already.
    protected MappedBytes(MappedFile mappedFile) throws IllegalStateException {
        super(NoBytesStore.noBytesStore(), NoBytesStore.noBytesStore().writePosition(), NoBytesStore.noBytesStore().writeLimit());
        this.mappedFile = mappedFile;
        clear();
    }

    @NotNull
    public static MappedBytes mappedBytes(@NotNull String filename, long chunkSize) throws FileNotFoundException, IllegalStateException {
        return mappedBytes(new File(filename), chunkSize);
    }

    @NotNull
    public static MappedBytes mappedBytes(@NotNull File file, long chunkSize) throws FileNotFoundException, IllegalStateException {
        return mappedBytes(file, chunkSize, OS.pageSize());
    }

    @NotNull
    public static MappedBytes mappedBytes(@NotNull File file, long chunkSize, long overlapSize) throws FileNotFoundException, IllegalStateException {
        MappedFile rw = MappedFile.of(file, chunkSize, overlapSize);
        return mappedBytes(rw);
    }

    @NotNull
    public static MappedBytes mappedBytes(MappedFile rw) {
        return CHECKING ? new CheckingMappedBytes(rw) : new MappedBytes(rw);
    }

    public void setNewChunkListener(NewChunkListener listener) {
        mappedFile.setNewChunkListener(listener);
    }

    public MappedFile mappedFile() {
        return mappedFile;
    }

    public MappedBytes withSizes(long chunkSize, long overlapSize) {
        MappedFile mappedFile2 = this.mappedFile.withSizes(chunkSize, overlapSize);
        if (mappedFile2 == this.mappedFile)
            return this;
        try {
            return mappedBytes(mappedFile2);
        } finally {
            release();
        }
    }

    @Override
    public BytesStore, Void> copy() {
        return NativeBytes.copyOf(this);
    }

    @Override
    public long capacity() {
        return mappedFile == null ? 0L : mappedFile.capacity();
    }

    @Override
    public long realCapacity() {
        return mappedFile.actualSize();
    }

    @Override
    protected void readCheckOffset(long offset, long adding, boolean given) throws BufferUnderflowException, IORuntimeException {
        if (!bytesStore.inside(offset)) {
            BytesStore oldBS = bytesStore;
            try {
                bytesStore = (BytesStore) mappedFile.acquireByteStore(offset);
                oldBS.release();
            } catch (IOException | IllegalStateException e) {
                throw new IORuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new BufferUnderflowException();
            }
        }
        super.readCheckOffset(offset, adding, given);
    }

    @Override
    protected void writeCheckOffset(long offset, long adding) throws BufferOverflowException, IORuntimeException {
        if (offset < 0 || offset > capacity() - adding)
            throw new IllegalArgumentException("Offset out of bound " + offset);
        if (!bytesStore.inside(offset)) {
            BytesStore oldBS = bytesStore;
            try {
                bytesStore = (BytesStore) mappedFile.acquireByteStore(offset);
                oldBS.release();
            } catch (IOException | IllegalStateException e) {
                throw new IORuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new BufferOverflowException();
            }
        }
    }

    @Override
    public long start() {
        return 0L;
    }

    @Override
    protected void performRelease() {
        super.performRelease();
        mappedFile.close();
    }

    @Override
    public boolean isElastic() {
        return true;
    }

    @NotNull
    @Override
    public Bytes write(@NotNull BytesStore bytes, long offset, long length)
            throws IORuntimeException, BufferUnderflowException, BufferOverflowException {
        if (length == 8) {
            writeLong(bytes.readLong(offset));

        } else if (bytes.bytesStore() instanceof NativeBytesStore && length >= 16) {
            rawCopy(bytes, offset, length);

        } else {
            BytesInternal.writeFully(bytes, offset, length, this);
        }
        return this;
    }

    public void rawCopy(@NotNull BytesStore bytes, long offset, long length)
            throws BufferOverflowException, BufferUnderflowException {
        long len = Math.min(writeRemaining(), Math.min(bytes.readRemaining(), length));
        if (len > 0) {
            OS.memory().copyMemory(bytes.address(offset), address(writePosition()), len);
            writePosition += len;
        }
    }

    @Override
    public Bytes append8bit(@NotNull CharSequence cs, int start, int end) throws IllegalArgumentException, BufferOverflowException, BufferUnderflowException, IndexOutOfBoundsException, IORuntimeException {
        return cs instanceof String
                ? append8bit0((String) cs, start, end - start)
                : super.append8bit(cs, start, end);
    }

    @Override
    public Bytes writeUtf8(String s) throws BufferOverflowException, IORuntimeException {
        char[] chars = extractChars(s);
        long utfLength = AppendableUtil.findUtf8Length(chars);
        writeStopBit(utfLength);
        appendUtf8(chars, 0, chars.length);
        return this;
    }

    public MappedBytes write8bit(CharSequence s, int start, int length) {
        // check the start.
        long pos = writePosition();
        writeCheckOffset(pos, 0);
        if (!(s instanceof String) || pos + length + 5 >= safeLimit()) {
            super.write8bit(s, start, length);
            return this;
        }

        writeStopBit(length);
        return append8bit0((String) s, start, length);
    }

    @NotNull
    private MappedBytes append8bit0(String s, int start, int length) {
        char[] chars = StringUtils.extractChars(s);
        long address = address(writePosition());
        Memory memory = OS.memory();
        int i = 0;
        for (; i < length - 3; i += 4) {
            int c0 = chars[i + start] & 0xff;
            int c1 = chars[i + start + 1] & 0xff;
            int c2 = chars[i + start + 2] & 0xff;
            int c3 = chars[i + start + 3] & 0xff;
            memory.writeInt(address, (c3 << 24) | (c2 << 16) | (c1 << 8) | c0);
            address += 4;
        }
        for (; i < length; i++) {
            char c = chars[i + start];
            memory.writeByte(address++, (byte) c);
        }
        writeSkip(length);
        return this;
    }

    @Override
    public Bytes appendUtf8(CharSequence cs, int start, int length) throws BufferOverflowException, IllegalArgumentException, IORuntimeException {
        // check the start.
        long pos = writePosition();
        writeCheckOffset(pos, 0);
        if (!(cs instanceof String) || pos + length + 5 >= safeLimit()) {
            super.appendUtf8(cs, start, length);
            return this;
        }

        char[] chars = StringUtils.extractChars((String) cs);
        long address = address(pos);
        Memory memory = OS.memory();
        int i = 0;
        non_ascii:
        {
            for (; i < length; i++) {
                char c = chars[i + start];
                if (c > 127) {
                    writeSkip(i);
                    break non_ascii;
                }
                memory.writeByte(address++, (byte) c);
            }
            writeSkip(length);
            return this;
        }
        for (; i < length; i++) {
            char c = chars[i + start];
            appendUtf8(c);
        }
        return this;
    }

    @Override
    public boolean sharedMemory() {
        return true;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy