io.aeron.logbuffer.HeaderWriter Maven / Gradle / Ivy
Show all versions of aeron-client Show documentation
/*
* Copyright 2014-2017 Real Logic Ltd.
*
* 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 io.aeron.logbuffer;
import org.agrona.UnsafeAccess;
import org.agrona.concurrent.UnsafeBuffer;
import java.nio.ByteOrder;
import static java.lang.Integer.reverseBytes;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static io.aeron.protocol.DataHeaderFlyweight.SESSION_ID_FIELD_OFFSET;
import static io.aeron.protocol.DataHeaderFlyweight.STREAM_ID_FIELD_OFFSET;
import static io.aeron.protocol.DataHeaderFlyweight.TERM_OFFSET_FIELD_OFFSET;
import static io.aeron.protocol.HeaderFlyweight.FRAME_LENGTH_FIELD_OFFSET;
import static io.aeron.protocol.HeaderFlyweight.VERSION_FIELD_OFFSET;
/**
* Utility for applying a header to a message in a term buffer.
*
* This class is designed to be thread safe to be used across multiple producers and makes the header
* visible in the correct order for consumers.
*/
public class HeaderWriter
{
private final long versionFlagsType;
private final long sessionId;
private final long streamId;
public HeaderWriter(final UnsafeBuffer defaultHeader)
{
if (ByteOrder.nativeOrder() == LITTLE_ENDIAN)
{
versionFlagsType = ((long)defaultHeader.getInt(VERSION_FIELD_OFFSET)) << 32;
sessionId = ((long)defaultHeader.getInt(SESSION_ID_FIELD_OFFSET)) << 32;
streamId = defaultHeader.getInt(STREAM_ID_FIELD_OFFSET) & 0xFFFF_FFFFL;
}
else
{
versionFlagsType = defaultHeader.getInt(VERSION_FIELD_OFFSET) & 0xFFFF_FFFFL;
sessionId = defaultHeader.getInt(SESSION_ID_FIELD_OFFSET) & 0xFFFF_FFFFL;
streamId = ((long)defaultHeader.getInt(STREAM_ID_FIELD_OFFSET)) << 32;
}
}
/**
* Write a header to the term buffer in {@link ByteOrder#LITTLE_ENDIAN} format using the minimum instructions.
*
* @param termBuffer to be written to.
* @param offset at which the header should be written.
* @param length of the fragment including the header.
* @param termId of the current term buffer.
*/
public void write(final UnsafeBuffer termBuffer, final int offset, final int length, final int termId)
{
final long lengthVersionFlagsType;
final long termOffsetSessionId;
final long streamAndTermIds;
if (ByteOrder.nativeOrder() == LITTLE_ENDIAN)
{
lengthVersionFlagsType = versionFlagsType | ((-length) & 0xFFFF_FFFFL);
termOffsetSessionId = sessionId | offset;
streamAndTermIds = streamId | (((long)termId) << 32);
}
else
{
lengthVersionFlagsType = versionFlagsType | ((((long)reverseBytes(-length))) << 32);
termOffsetSessionId = sessionId | ((((long)reverseBytes(offset))) << 32);
streamAndTermIds = streamId | (reverseBytes(termId) & 0xFFFF_FFFFL);
}
termBuffer.putLong(offset + FRAME_LENGTH_FIELD_OFFSET, lengthVersionFlagsType);
UnsafeAccess.UNSAFE.storeFence();
termBuffer.putLong(offset + TERM_OFFSET_FIELD_OFFSET, termOffsetSessionId);
termBuffer.putLong(offset + STREAM_ID_FIELD_OFFSET, streamAndTermIds);
}
}