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

org.apache.camel.component.wal.IOUtil Maven / Gradle / Ivy

/*
 * 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.camel.component.wal;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import org.apache.camel.component.wal.exceptions.BufferOverflow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * I/O utilities for the write-ahead log
 */
final class IOUtil {
    private static final Logger LOG = LoggerFactory.getLogger(IOUtil.class);

    private IOUtil() {

    }

    /**
     * Writes to the channel at a given position, clearing the source after completion
     *
     * @param  fileChannel the channel to write to
     * @param  byteBuffer  the buffer containing the bytes to write to the channel
     * @param  position    the position to write to
     * @return             the number of bytes written
     * @throws IOException for any lower-level I/O failure
     */
    static long write(FileChannel fileChannel, ByteBuffer byteBuffer, long position) throws IOException {
        long bytesWritten = 0;
        byteBuffer.flip();

        while (byteBuffer.hasRemaining()) {
            bytesWritten += fileChannel.write(byteBuffer, position + bytesWritten);
        }

        byteBuffer.flip();
        byteBuffer.clear();

        return bytesWritten;
    }

    /**
     * Writes to the channel by appending the data at the end and clearing the source after completion
     *
     * @param  fileChannel the channel to write to
     * @param  byteBuffer  the buffer containing the bytes to write to the channel
     * @return             the number of bytes written
     * @throws IOException for any lower-level I/O failure
     */
    static long write(FileChannel fileChannel, ByteBuffer byteBuffer) throws IOException {
        long bytesWritten = 0;
        byteBuffer.flip();

        while (byteBuffer.hasRemaining()) {
            bytesWritten += fileChannel.write(byteBuffer);
        }

        byteBuffer.flip();
        byteBuffer.clear();

        return bytesWritten;
    }

    /**
     * Serializes a entry to the buffer
     *
     * @param  buffer         the buffer where the entry will be serialized too
     * @param  entry          the entry to serialize
     * @throws BufferOverflow if the buffer is too small for the entry
     */
    static void serialize(ByteBuffer buffer, LogEntry entry) throws BufferOverflow {
        serialize(buffer, entry.getEntryState().getCode(), entry.getKeyMetadata(), entry.getKey(), entry.getValueMetadata(),
                entry.getValue());
    }

    /**
     * Serializes a entry to the buffer
     *
     * @param  buffer         the buffer where the entry will be serialized too
     * @param  entryState     the entry state
     * @param  keyMetadata    the entry metadata
     * @param  key            the entry key
     * @param  valueMetadata  the entry value metadata
     * @param  value          the entry value
     * @throws BufferOverflow if the buffer is too small for the entry
     */
    static void serialize(
            ByteBuffer buffer, int entryState, int keyMetadata, byte[] key, int valueMetadata, byte[] value)
            throws BufferOverflow {
        checkBufferCapacity(buffer,
                Integer.BYTES + Integer.BYTES + key.length + Integer.BYTES + Integer.BYTES + value.length);

        buffer.putInt(entryState);
        buffer.putInt(keyMetadata);
        buffer.putInt(key.length);
        buffer.put(key);
        buffer.putInt(valueMetadata);
        buffer.putInt(value.length);
        buffer.put(value);
    }

    private static void checkBufferCapacity(ByteBuffer byteBuffer, int requestedSize) throws BufferOverflow {
        final int remaining = byteBuffer.remaining();

        if (remaining < requestedSize) {
            if (LOG.isTraceEnabled()) {
                LOG.trace("There is not enough space on the buffer for an offset entry: {} bytes remaining, {} bytes needed",
                        remaining, requestedSize);
            }

            throw new BufferOverflow(remaining, requestedSize);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy