/*
* 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.kafka.common.record;
import java.io.IOException;
import java.nio.channels.GatheringByteChannel;
/**
* Interface for accessing the records contained in a log. The log itself is represented as a sequence of record
* batches (see {@link RecordBatch}).
*
* For magic versions 1 and below, each batch consists of an 8 byte offset, a 4 byte record size, and a "shallow"
* {@link Record record}. If the batch is not compressed, then each batch will have only the shallow record contained
* inside it. If it is compressed, the batch contains "deep" records, which are packed into the value field of the
* shallow record. To iterate over the shallow batches, use {@link #batches()}; for the deep records, use
* {@link #records()}. Note that the deep iterator handles both compressed and non-compressed batches: if the batch is
* not compressed, the shallow record is returned; otherwise, the shallow batch is decompressed and the deep records
* are returned.
*
* For magic version 2, every batch contains 1 or more log record, regardless of compression. You can iterate
* over the batches directly using {@link #batches()}. Records can be iterated either directly from an individual
* batch or through {@link #records()}. Just as in previous versions, iterating over the records typically involves
* decompression and should therefore be used with caution.
*
* See {@link MemoryRecords} for the in-memory representation and {@link FileRecords} for the on-disk representation.
*/
public interface Records {
int OFFSET_OFFSET = 0;
int OFFSET_LENGTH = 8;
int SIZE_OFFSET = OFFSET_OFFSET + OFFSET_LENGTH;
int SIZE_LENGTH = 4;
int LOG_OVERHEAD = SIZE_OFFSET + SIZE_LENGTH;
// the magic offset is at the same offset for all current message formats, but the 4 bytes
// between the size and the magic is dependent on the version.
int MAGIC_OFFSET = 16;
/**
* The size of these records in bytes.
* @return The size in bytes of the records
*/
int sizeInBytes();
/**
* Attempts to write the contents of this buffer to a channel.
* @param channel The channel to write to
* @param position The position in the buffer to write from
* @param length The number of bytes to write
* @return The number of bytes actually written
* @throws IOException For any IO errors
*/
long writeTo(GatheringByteChannel channel, long position, int length) throws IOException;
/**
* Get the record batches. Note that the signature allows subclasses
* to return a more specific batch type. This enables optimizations such as in-place offset
* assignment (see for example {@link DefaultRecordBatch}), and partial reading of
* record data (see {@link FileLogInputStream.FileChannelRecordBatch#magic()}.
* @return An iterator over the record batches of the log
*/
Iterable<? extends RecordBatch> batches();
/**
* Check whether all batches in this buffer have a certain magic value.
* @param magic The magic value to check
* @return true if all record batches have a matching magic value, false otherwise
*/
boolean hasMatchingMagic(byte magic);
/**
* Check whether this log buffer has a magic value compatible with a particular value
* (i.e. whether all message sets contained in the buffer have a matching or lower magic).
* @param magic The magic version to ensure compatibility with
* @return true if all batches have compatible magic, false otherwise
*/
boolean hasCompatibleMagic(byte magic);
/**
* Convert all batches in this buffer to the format passed as a parameter. Note that this requires
* deep iteration since all of the deep records must also be converted to the desired format.
* @param toMagic The magic value to convert to
* @return A Records instance (which may or may not be the same instance)
*/
Records downConvert(byte toMagic);
/**
* Get an iterator over the records in this log. Note that this generally requires decompression,
* and should therefore be used with care.
* @return The record iterator
*/
Iterable<Record> records();
}