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

jetbrains.exodus.log.RandomAccessByteIterable Maven / Gradle / Ivy

There is a newer version: 9.8.0.76914
Show newest version
/**
 * Copyright 2010 - 2022 JetBrains s.r.o.
 *
 * 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
 *
 * https://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 jetbrains.exodus.log;

import jetbrains.exodus.ArrayByteIterable;
import jetbrains.exodus.ByteIterable;
import org.jetbrains.annotations.NotNull;

class RandomAccessByteIterable extends ByteIterableWithAddress {

    @NotNull
    private final Log log;

    public RandomAccessByteIterable(final long address, @NotNull final Log log) {
        super(address);
        this.log = log;
    }

    @Override
    public ByteIteratorWithAddress iterator() {
        return new CompoundByteIterator(getDataAddress(), log);
    }

    public ByteIteratorWithAddress iterator(final int offset) {
        return new CompoundByteIterator(getDataAddress() + offset, log);
    }

    public int compareTo(final int offset, final int len, @NotNull final ByteIterable right) {
        return compare(offset, len, right, log, getDataAddress());
    }

    @NotNull
    public RandomAccessByteIterable clone(final int offset) {
        return new RandomAccessByteIterable(getDataAddress() + offset, log);
    }

    private static int compare(final int offset, final int len, final ByteIterable right, Log log, final long address) {
        final LogCache cache = log.cache;
        final int pageSize = log.getCachePageSize();
        final int mask = pageSize - 1;
        long alignedAddress = address + offset;
        long endAddress = alignedAddress + len;
        endAddress -= ((int) endAddress) & mask;
        int leftStep = ((int) alignedAddress) & mask;
        alignedAddress -= leftStep;
        ArrayByteIterable left = cache.getPageIterable(log, alignedAddress);

        final int leftLen = left.getLength();
        if (leftLen <= leftStep) { // alignment is >= 0 for sure
            BlockNotFoundException.raise(log, alignedAddress);
        }
        byte[] leftArray = left.getBytesUnsafe();
        final byte[] rightArray = right.getBytesUnsafe();
        final int rightLen = right.getLength();
        int rightStep = 0;
        int limit = Math.min(len, Math.min(leftLen - leftStep, rightLen));

        while (true) {
            while (rightStep < limit) {
                byte b1 = leftArray[leftStep++];
                byte b2 = rightArray[rightStep++];
                if (b1 != b2) {
                    return (b1 & 0xff) - (b2 & 0xff);
                }
            }
            if (rightStep == rightLen || alignedAddress >= endAddress) {
                return len - rightLen;
            }
            // move left array to next cache page
            left = cache.getPageIterable(log, alignedAddress += pageSize);
            leftArray = left.getBytesUnsafe();
            leftStep = 0;
            limit = Math.min(len, Math.min(left.getLength() + rightStep, rightLen));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy