예제 #1
0
        public int AppendFragmentedMessage(HeaderWriter header, IDirectBuffer srcBuffer, int srcOffset, int length,
                                           int maxPayloadLength, ReservedValueSupplier reservedValueSupplier, int activeTermId)
        {
            int          numMaxPayloads   = length / maxPayloadLength;
            int          remainingPayload = length % maxPayloadLength;
            int          lastFrameLength  = remainingPayload > 0 ? BitUtil.Align(remainingPayload + DataHeaderFlyweight.HEADER_LENGTH, FrameDescriptor.FRAME_ALIGNMENT) : 0;
            int          requiredLength   = (numMaxPayloads * (maxPayloadLength + DataHeaderFlyweight.HEADER_LENGTH)) + lastFrameLength;
            long         rawTail          = GetAndAddRawTail(requiredLength);
            int          termId           = LogBufferDescriptor.TermId(rawTail);
            long         termOffset       = rawTail & 0xFFFFFFFFL;
            UnsafeBuffer termBuffer       = _termBuffer;
            int          termLength       = termBuffer.Capacity;

            CheckTerm(activeTermId, termId);

            long resultingOffset = termOffset + requiredLength;

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId);
            }
            else
            {
                int  frameOffset = (int)termOffset;
                byte flags       = FrameDescriptor.BEGIN_FRAG_FLAG;
                int  remaining   = length;

                do
                {
                    int bytesToWrite  = Math.Min(remaining, maxPayloadLength);
                    int frameLength   = bytesToWrite + DataHeaderFlyweight.HEADER_LENGTH;
                    int alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);

                    header.Write(termBuffer, frameOffset, frameLength, termId);
                    termBuffer.PutBytes(frameOffset + DataHeaderFlyweight.HEADER_LENGTH, srcBuffer,
                                        srcOffset + (length - remaining), bytesToWrite);

                    if (remaining <= maxPayloadLength)
                    {
                        flags |= FrameDescriptor.END_FRAG_FLAG;
                    }

                    FrameDescriptor.FrameFlags(termBuffer, frameOffset, flags);

                    if (null != reservedValueSupplier)
                    {
                        long reservedValue = reservedValueSupplier(termBuffer, frameOffset, frameLength);
                        termBuffer.PutLong(frameOffset + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, reservedValue, ByteOrder.LittleEndian);
                    }

                    FrameDescriptor.FrameLengthOrdered(termBuffer, frameOffset, frameLength);

                    flags        = 0;
                    frameOffset += alignedLength;
                    remaining   -= bytesToWrite;
                } while (remaining > 0);
            }

            return((int)resultingOffset);
        }
예제 #2
0
        public long AppendUnfragmentedMessage(HeaderWriter header, UnsafeBuffer srcBuffer, int srcOffset, int length, ReservedValueSupplier reservedValueSupplier)
#endif
        {
            int  frameLength   = length + DataHeaderFlyweight.HEADER_LENGTH;
            int  alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            long rawTail       = GetAndAddRawTail(alignedLength);
            long termOffset    = rawTail & 0xFFFFFFFFL;

            UnsafeBuffer termBuffer = _termBuffer;
            int          termLength = termBuffer.Capacity;

            long resultingOffset = termOffset + alignedLength;

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, LogBufferDescriptor.TermId(rawTail));
            }
            else
            {
                int offset = (int)termOffset;
                header.Write(termBuffer, offset, frameLength, LogBufferDescriptor.TermId(rawTail));
                termBuffer.PutBytes(offset + DataHeaderFlyweight.HEADER_LENGTH, srcBuffer, srcOffset, length);

                if (null != reservedValueSupplier)
                {
                    long reservedValue = reservedValueSupplier(termBuffer, offset, frameLength);
                    termBuffer.PutLong(offset + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, reservedValue);
                }

                FrameDescriptor.FrameLengthOrdered(termBuffer, offset, frameLength);
            }

            return(resultingOffset);
        }
예제 #3
0
        /// <summary>
        /// Scan a term buffer for a block of message fragments from and offset up to a limitOffset.
        ///
        /// A scan will terminate if a padding frame is encountered. If first frame in a scan is padding then a block
        /// for the padding is notified. If the padding comes after the first frame in a scan then the scan terminates
        /// at the offset the padding frame begins. Padding frames are delivered singularly in a block.
        ///
        /// Padding frames may be for a greater range than the limit offset but only the header needs to be valid so
        /// relevant length of the frame is <see cref="DataHeaderFlyweight.HEADER_LENGTH"/>
        /// </summary>
        /// <param name="termBuffer"> to scan for message fragments. </param>
        /// <param name="termOffset">     at which the scan should begin. </param>
        /// <param name="limitOffset">      at which the scan should stop. </param>
        /// <returns> the offset at which the scan terminated. </returns>
        public static int Scan(IAtomicBuffer termBuffer, int termOffset, int limitOffset)
        {
            var offset = termOffset;

            while (offset < limitOffset)
            {
                int frameLength = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                if (frameLength <= 0)
                {
                    break;
                }

                int alignedFrameLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);

                if (FrameDescriptor.IsPaddingFrame(termBuffer, offset))
                {
                    if (termOffset == offset)
                    {
                        offset += alignedFrameLength;
                    }

                    break;
                }

                if (offset + alignedFrameLength > limitOffset)
                {
                    break;
                }

                offset += alignedFrameLength;
            }


            return(offset);
        }
예제 #4
0
        public static long Read(UnsafeBuffer termBuffer, int offset, FragmentHandler handler, int fragmentsLimit, Header header, ErrorHandler errorHandler)
        {
            int fragmentsRead = 0;
            int capacity      = termBuffer.Capacity;

            try
            {
                do
                {
                    int frameLength = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                    if (frameLength <= 0)
                    {
                        break;
                    }

                    int termOffset = offset;
                    offset += BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);

                    if (!FrameDescriptor.IsPaddingFrame(termBuffer, termOffset))
                    {
                        header.SetBuffer(termBuffer, termOffset);

                        handler(termBuffer, termOffset + DataHeaderFlyweight.HEADER_LENGTH, frameLength - DataHeaderFlyweight.HEADER_LENGTH, header);

                        ++fragmentsRead;
                    }
                } while (fragmentsRead < fragmentsLimit && offset < capacity);
            }
            catch (Exception t)
            {
                errorHandler(t);
            }

            return(Pack(offset, fragmentsRead));
        }
예제 #5
0
        /// <summary>
        /// Pad a length of the term buffer with a padding record.
        /// </summary>
        /// <param name="termId"> for the current term.</param>
        /// <param name="termOffset"> in the term at which to append.</param>
        /// <param name="header"> for writing the default header.</param>
        /// <param name="length"> of the padding to be written.</param>
        /// <returns> the resulting offset of the term after success otherwise <see cref="FAILED"/>.</returns>
        public int AppendPadding(
            int termId,
            int termOffset,
            HeaderWriter header,
            int length)
        {
            int          frameLength   = length + DataHeaderFlyweight.HEADER_LENGTH;
            int          alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            UnsafeBuffer termBuffer    = _termBuffer;
            int          termLength    = termBuffer.Capacity;

            int resultingOffset = termOffset + alignedLength;

            PutRawTailOrdered(termId, resultingOffset);

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId);
            }
            else
            {
                header.Write(termBuffer, termOffset, frameLength, termId);
                FrameDescriptor.FrameType(termBuffer, termOffset, FrameDescriptor.PADDING_FRAME_TYPE);
                FrameDescriptor.FrameLengthOrdered(termBuffer, termOffset, frameLength);
            }

            return(resultingOffset);
        }
예제 #6
0
        /// <summary>
        /// Append an unfragmented message to the the term buffer.
        /// </summary>
        /// <param name="header">    for writing the default header. </param>
        /// <param name="srcBuffer"> containing the message. </param>
        /// <param name="srcOffset"> at which the message begins. </param>
        /// <param name="length">    of the message in the source buffer. </param>
        /// <returns> the resulting offset of the term after the append on success otherwise <seealso cref="#TRIPPED"/> or <seealso cref="#FAILED"/>
        /// packed with the termId if a padding record was inserted at the end. </returns>
        public virtual long AppendUnfragmentedMessage(HeaderWriter header, IDirectBuffer srcBuffer, int srcOffset, int length)
        {
            int  frameLength   = length + DataHeaderFlyweight.HEADER_LENGTH;
            int  alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            long rawTail       = GetAndAddRawTail(alignedLength);
            long termOffset    = rawTail & 0xFFFFFFFFL;

            IAtomicBuffer termBuffer = _termBuffer;
            int           termLength = termBuffer.Capacity;

            long resultingOffset = termOffset + alignedLength;

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, TermId(rawTail));
            }
            else
            {
                int offset = (int)termOffset;
                header.Write(termBuffer, offset, frameLength, TermId(rawTail));
                termBuffer.PutBytes(offset + DataHeaderFlyweight.HEADER_LENGTH, srcBuffer, srcOffset, length);
                FrameDescriptor.FrameLengthOrdered(termBuffer, offset, frameLength);
            }

            return(resultingOffset);
        }
예제 #7
0
        /// <summary>
        /// Scan a term buffer for a block of message fragments from and offset up to a limit.
        /// </summary>
        /// <param name="termBuffer"> to scan for message fragments. </param>
        /// <param name="termOffset">     at which the scan should begin. </param>
        /// <param name="limit">      at which the scan should stop. </param>
        /// <returns> the offset at which the scan terminated. </returns>
        public static int Scan(IAtomicBuffer termBuffer, int termOffset, int limit)
        {
            var offset = termOffset;

            do
            {
                int frameLength = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                if (frameLength <= 0)
                {
                    break;
                }

                int alignedFrameLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
                offset += alignedFrameLength;
                if (offset >= limit)
                {
                    if (offset > limit)
                    {
                        offset -= alignedFrameLength;
                    }

                    break;
                }
            } while (true);

            return(offset);
        }
예제 #8
0
        /// <summary>
        /// Insert a packet of frames into the log at the appropriate offset as indicated by the term offset header.
        /// </summary>
        /// <param name="termBuffer"> into which the packet should be inserted. </param>
        /// <param name="offset">     offset in the term at which the packet should be inserted. </param>
        /// <param name="packet">     containing a sequence of frames. </param>
        /// <param name="length">     of the sequence of frames in bytes. </param>
        public static void Insert(IAtomicBuffer termBuffer, int offset, UnsafeBuffer packet, int length)
        {
            var firstFrameLength = packet.GetInt(0); // LITTLE_ENDIAN

            packet.PutIntOrdered(0, 0);

            termBuffer.PutBytes(offset, packet, 0, length);
            FrameDescriptor.FrameLengthOrdered(termBuffer, offset, firstFrameLength);
        }
예제 #9
0
        /// <summary>
        /// Insert a packet of frames into the log at the appropriate offset as indicated by the term termOffset header.
        /// </summary>
        /// <param name="termBuffer"> into which the packet should be inserted. </param>
        /// <param name="termOffset">     offset in the term at which the packet should be inserted. </param>
        /// <param name="packet">     containing a sequence of frames. </param>
        /// <param name="length">     of the sequence of frames in bytes. </param>
        public static void Insert(IAtomicBuffer termBuffer, int termOffset, UnsafeBuffer packet, int length)
        {
            var firstFrameLength = packet.GetInt(0); // LITTLE_ENDIAN

            packet.PutIntOrdered(0, 0);
            Thread.MemoryBarrier(); // UnsafeAccess.UNSAFE.storeFence();

            termBuffer.PutBytes(termOffset, packet, 0, length);
            FrameDescriptor.FrameLengthOrdered(termBuffer, termOffset, firstFrameLength);
        }
예제 #10
0
        /// <summary>
        /// Append a fragmented message to the the term buffer.
        /// The message will be split up into fragments of MTU length minus header.
        /// </summary>
        /// <param name="header">           for writing the default header. </param>
        /// <param name="srcBuffer">        containing the message. </param>
        /// <param name="srcOffset">        at which the message begins. </param>
        /// <param name="length">           of the message in the source buffer. </param>
        /// <param name="maxPayloadLength"> that the message will be fragmented into. </param>
        /// <returns> the resulting offset of the term after the append on success otherwise <seealso cref="#TRIPPED"/> or <seealso cref="#FAILED"/>
        /// packed with the termId if a padding record was inserted at the end. </returns>
        public long AppendFragmentedMessage(HeaderWriter header, IDirectBuffer srcBuffer, int srcOffset, int length,
                                            int maxPayloadLength)
        {
            int numMaxPayloads   = length / maxPayloadLength;
            int remainingPayload = length % maxPayloadLength;
            int lastFrameLength  = remainingPayload > 0
                ? BitUtil.Align(remainingPayload + DataHeaderFlyweight.HEADER_LENGTH, FrameDescriptor.FRAME_ALIGNMENT)
                : 0;
            int requiredLength = (numMaxPayloads * (maxPayloadLength + DataHeaderFlyweight.HEADER_LENGTH)) +
                                 lastFrameLength;
            long rawTail    = GetAndAddRawTail(requiredLength);
            int  termId     = TermId(rawTail);
            long termOffset = rawTail & 0xFFFFFFFFL;

            IAtomicBuffer termBuffer = _termBuffer;
            int           termLength = termBuffer.Capacity;

            long resultingOffset = termOffset + requiredLength;

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId);
            }
            else
            {
                int  offset    = (int)termOffset;
                byte flags     = FrameDescriptor.BEGIN_FRAG_FLAG;
                int  remaining = length;
                do
                {
                    int bytesToWrite  = Math.Min(remaining, maxPayloadLength);
                    int frameLength   = bytesToWrite + DataHeaderFlyweight.HEADER_LENGTH;
                    int alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);

                    header.Write(termBuffer, offset, frameLength, termId);
                    termBuffer.PutBytes(offset + DataHeaderFlyweight.HEADER_LENGTH, srcBuffer,
                                        srcOffset + (length - remaining), bytesToWrite);

                    if (remaining <= maxPayloadLength)
                    {
                        flags |= FrameDescriptor.END_FRAG_FLAG;
                    }

                    FrameDescriptor.FrameFlags(termBuffer, offset, flags);
                    FrameDescriptor.FrameLengthOrdered(termBuffer, offset, frameLength);

                    flags      = 0;
                    offset    += alignedLength;
                    remaining -= bytesToWrite;
                } while (remaining > 0);
            }

            return(resultingOffset);
        }
예제 #11
0
        public static int Read(
            UnsafeBuffer termBuffer,
            int termOffset,
            IFragmentHandler handler,
            int fragmentsLimit,
            Header header,
            ErrorHandler errorHandler,
            long currentPosition,
            IPosition subscriberPosition)
        {
            int fragmentsRead = 0;
            int offset        = termOffset;
            int capacity      = termBuffer.Capacity;

            header.Buffer = termBuffer;

            try
            {
                while (fragmentsRead < fragmentsLimit && offset < capacity)
                {
                    int frameLength = FrameDescriptor.FrameLengthVolatile(termBuffer, offset);
                    if (frameLength <= 0)
                    {
                        break;
                    }

                    int frameOffset = offset;
                    offset += BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);

                    if (!FrameDescriptor.IsPaddingFrame(termBuffer, frameOffset))
                    {
                        header.Offset = frameOffset;
                        handler.OnFragment(termBuffer, frameOffset + DataHeaderFlyweight.HEADER_LENGTH, frameLength - DataHeaderFlyweight.HEADER_LENGTH, header);

                        ++fragmentsRead;
                    }
                }
            }

            catch (Exception t)
            {
                errorHandler(t);
            }
            finally
            {
                long newPosition = currentPosition + (offset - termOffset);
                if (newPosition > currentPosition)
                {
                    subscriberPosition.SetOrdered(newPosition);
                }
            }

            return(fragmentsRead);
        }
예제 #12
0
        /// <summary>
        /// Append pre-formatted block of message fragments into the term buffer.
        /// <para>
        /// <em>WARNING: This is internal API used by {@code ExclusivePublication#offerBlock} method.</em>
        /// </para>
        /// </summary>
        /// <param name="termId">     for the current term. </param>
        /// <param name="termOffset"> in the term at which to append. </param>
        /// <param name="buffer">     which contains block of messages. </param>
        /// <param name="offset">     within the buffer at which the block begins. </param>
        /// <param name="length">     of the block in bytes (always aligned). </param>
        /// <returns> the resulting offset of the term after success otherwise <seealso cref="FAILED"/>. </returns>
        public int AppendBlock(int termId, int termOffset, IMutableDirectBuffer buffer, int offset, int length)
        {
            int resultingOffset    = termOffset + length;
            int lengthOfFirstFrame = buffer.GetInt(offset, ByteOrder.LittleEndian);

            buffer.PutInt(offset, 0, ByteOrder.LittleEndian);
            _termBuffer.PutBytes(termOffset, buffer, offset, length);
            FrameDescriptor.FrameLengthOrdered(_termBuffer, termOffset, lengthOfFirstFrame);
            PutRawTailOrdered(termId, resultingOffset);

            return(resultingOffset);
        }
예제 #13
0
        private long HandleEndOfLogCondition(UnsafeBuffer termBuffer, long termOffset, HeaderWriter header,
                                             int termLength, int termId)
        {
            if (termOffset < termLength)
            {
                int offset        = (int)termOffset;
                int paddingLength = termLength - offset;
                header.Write(termBuffer, offset, paddingLength, termId);
                FrameDescriptor.FrameType(termBuffer, offset, FrameDescriptor.PADDING_FRAME_TYPE);
                FrameDescriptor.FrameLengthOrdered(termBuffer, offset, paddingLength);
            }

            return(FAILED);
        }
예제 #14
0
        public int AppendUnfragmentedMessage(
            HeaderWriter header,
            DirectBufferVector[] vectors,
            int length,
            ReservedValueSupplier reservedValueSupplier,
            int activeTermId)
        {
            int          frameLength   = length + DataHeaderFlyweight.HEADER_LENGTH;
            int          alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            UnsafeBuffer termBuffer    = _termBuffer;
            int          termLength    = termBuffer.Capacity;

            long rawTail    = GetAndAddRawTail(alignedLength);
            int  termId     = LogBufferDescriptor.TermId(rawTail);
            long termOffset = rawTail & 0xFFFFFFFFL;


            CheckTerm(activeTermId, termId);

            long resultingOffset = termOffset + alignedLength;

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId);
            }
            else
            {
                int frameOffset = (int)termOffset;
                header.Write(termBuffer, frameOffset, frameLength, LogBufferDescriptor.TermId(rawTail));

                int offset = frameOffset + DataHeaderFlyweight.HEADER_LENGTH;

                foreach (var vector in vectors)
                {
                    termBuffer.PutBytes(offset, vector.buffer, vector.offset, vector.length);
                    offset += vector.length;
                }

                if (null != reservedValueSupplier)
                {
                    long reservedValue = reservedValueSupplier(termBuffer, frameOffset, frameLength);
                    termBuffer.PutLong(frameOffset + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, reservedValue, ByteOrder.LittleEndian);
                }

                FrameDescriptor.FrameLengthOrdered(termBuffer, frameOffset, frameLength);
            }

            return((int)resultingOffset);
        }
예제 #15
0
        public int AppendUnfragmentedMessage(
            int termId,
            int termOffset,
            HeaderWriter header,
            DirectBufferVector[] vectors,
            int length,
            ReservedValueSupplier reservedValueSupplier)
#endif
        {
            int          frameLength   = length + DataHeaderFlyweight.HEADER_LENGTH;
            int          alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            UnsafeBuffer termBuffer    = _termBuffer;
            int          termLength    = termBuffer.Capacity;

            int resultingOffset = termOffset + alignedLength;

            PutRawTailOrdered(termId, resultingOffset);

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId);
            }
            else
            {
                header.Write(termBuffer, termOffset, frameLength, termId);

                var offset = termOffset + DataHeaderFlyweight.HEADER_LENGTH;

                foreach (var vector in vectors)
                {
                    termBuffer.PutBytes(offset, vector.buffer, vector.offset, vector.length);
                    offset += vector.length;
                }

                if (null != reservedValueSupplier)
                {
                    long reservedValue = reservedValueSupplier(termBuffer, termOffset, frameLength);
                    termBuffer.PutLong(termOffset + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, reservedValue, ByteOrder.LittleEndian);
                }

                FrameDescriptor.FrameLengthOrdered(termBuffer, termOffset, frameLength);
            }

            return(resultingOffset);
        }
예제 #16
0
        /// <summary>
        /// Append an unfragmented message to the the term buffer.
        /// </summary>
        /// <param name="termId">                for the current term. </param>
        /// <param name="termOffset">            in the term at which to append. </param>
        /// <param name="header">                for writing the default header. </param>
        /// <param name="bufferOne">             containing the first part of the message. </param>
        /// <param name="offsetOne">             at which the first part of the message begins. </param>
        /// <param name="lengthOne">             of the first part of the message. </param>
        /// <param name="bufferTwo">             containing the second part of the message. </param>
        /// <param name="offsetTwo">             at which the second part of the message begins. </param>
        /// <param name="lengthTwo">             of the second part of the message. </param>
        /// <param name="reservedValueSupplier"> <seealso cref="ReservedValueSupplier"/> for the frame. </param>
        /// <returns> the resulting offset of the term after the append on success otherwise <seealso cref="FAILED"/>. </returns>
        public int AppendUnfragmentedMessage(
            int termId,
            int termOffset,
            HeaderWriter header,
            IDirectBuffer bufferOne,
            int offsetOne,
            int lengthOne,
            IDirectBuffer bufferTwo,
            int offsetTwo,
            int lengthTwo,
            ReservedValueSupplier reservedValueSupplier)
        {
            int          frameLength   = lengthOne + lengthTwo + DataHeaderFlyweight.HEADER_LENGTH;
            int          alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);
            UnsafeBuffer termBuffer    = _termBuffer;
            int          termLength    = termBuffer.Capacity;

            int resultingOffset = termOffset + alignedLength;

            PutRawTailOrdered(termId, resultingOffset);

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId);
            }
            else
            {
                header.Write(termBuffer, termOffset, frameLength, termId);
                termBuffer.PutBytes(termOffset + DataHeaderFlyweight.HEADER_LENGTH, bufferOne, offsetOne, lengthOne);
                termBuffer.PutBytes(termOffset + DataHeaderFlyweight.HEADER_LENGTH + lengthOne, bufferTwo, offsetTwo, lengthTwo);

                if (null != reservedValueSupplier)
                {
                    long reservedValue = reservedValueSupplier(termBuffer, termOffset, frameLength);
                    termBuffer.PutLong(termOffset + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, reservedValue, ByteOrder.LittleEndian);
                }

                FrameDescriptor.FrameLengthOrdered(termBuffer, termOffset, frameLength);
            }

            return(resultingOffset);
        }
예제 #17
0
        private long HandleEndOfLogCondition(UnsafeBuffer termBuffer, long termOffset, HeaderWriter header,
                                             int termLength, int termId)
        {
            int resultingOffset = FAILED;

            if (termOffset <= termLength)
            {
                resultingOffset = TRIPPED;

                if (termOffset < termLength)
                {
                    int offset        = (int)termOffset;
                    int paddingLength = termLength - offset;
                    header.Write(termBuffer, offset, paddingLength, termId);
                    FrameDescriptor.FrameType(termBuffer, offset, FrameDescriptor.PADDING_FRAME_TYPE);
                    FrameDescriptor.FrameLengthOrdered(termBuffer, offset, paddingLength);
                }
            }

            return(LogBufferDescriptor.PackTail(termId, resultingOffset));
        }
예제 #18
0
        /// <summary>
        /// Try to gap fill the current term at a given offset if the gap contains no data.
        ///
        /// Note: the gap offset plus gap length must end on a <seealso cref="FrameDescriptor.FRAME_ALIGNMENT"/> boundary.
        /// </summary>
        /// <param name="logMetaDataBuffer"> containing the default headers </param>
        /// <param name="termBuffer">        to gap fill </param>
        /// <param name="termId">            for the current term. </param>
        /// <param name="gapOffset">         to fill from </param>
        /// <param name="gapLength">         to length of the gap. </param>
        /// <returns> true if the gap has been filled with a padding record or false if data found. </returns>
        public static bool TryFillGap(UnsafeBuffer logMetaDataBuffer, UnsafeBuffer termBuffer, int termId, int gapOffset, int gapLength)
        {
            int offset = gapOffset + gapLength - FrameDescriptor.FRAME_ALIGNMENT;

            while (offset >= gapOffset)
            {
                if (0 != termBuffer.GetInt(offset))
                {
                    return(false);
                }

                offset -= FrameDescriptor.FRAME_ALIGNMENT;
            }

            LogBufferDescriptor.ApplyDefaultHeader(logMetaDataBuffer, termBuffer, gapOffset);
            FrameDescriptor.FrameType(termBuffer, gapOffset, HeaderFlyweight.HDR_TYPE_PAD);
            FrameDescriptor.FrameTermOffset(termBuffer, gapOffset);
            FrameDescriptor.FrameTermId(termBuffer, gapOffset, termId);
            FrameDescriptor.FrameLengthOrdered(termBuffer, gapOffset, gapLength);

            return(true);
        }
예제 #19
0
        public int AppendFragmentedMessage(
            int termId,
            int termOffset,
            HeaderWriter header,
            DirectBufferVector[] vectors,
            int length,
            int maxPayloadLength,
            ReservedValueSupplier reservedValueSupplier)
        {
            int numMaxPayloads   = length / maxPayloadLength;
            int remainingPayload = length % maxPayloadLength;
            int lastFrameLength  = remainingPayload > 0
                ? BitUtil.Align(remainingPayload + DataHeaderFlyweight.HEADER_LENGTH, FrameDescriptor.FRAME_ALIGNMENT)
                : 0;
            int requiredLength = (numMaxPayloads * (maxPayloadLength + DataHeaderFlyweight.HEADER_LENGTH)) +
                                 lastFrameLength;
            UnsafeBuffer termBuffer = _termBuffer;
            int          termLength = termBuffer.Capacity;

            int resultingOffset = termOffset + requiredLength;

            PutRawTailOrdered(termId, resultingOffset);

            if (resultingOffset > termLength)
            {
                resultingOffset = HandleEndOfLogCondition(termBuffer, termOffset, header, termLength, termId);
            }
            else
            {
                int  frameOffset  = termOffset;
                byte flags        = FrameDescriptor.BEGIN_FRAG_FLAG;
                int  remaining    = length;
                int  vectorIndex  = 0;
                int  vectorOffset = 0;

                do
                {
                    int bytesToWrite  = Math.Min(remaining, maxPayloadLength);
                    int frameLength   = bytesToWrite + DataHeaderFlyweight.HEADER_LENGTH;
                    int alignedLength = BitUtil.Align(frameLength, FrameDescriptor.FRAME_ALIGNMENT);

                    header.Write(termBuffer, frameOffset, frameLength, termId);

                    int bytesWritten  = 0;
                    int payloadOffset = frameOffset + DataHeaderFlyweight.HEADER_LENGTH;

                    do
                    {
                        var vector          = vectors[vectorIndex];
                        int vectorRemaining = vector.length - vectorOffset;
                        int numBytes        = Math.Min(bytesToWrite - bytesWritten, vectorRemaining);

                        termBuffer.PutBytes(payloadOffset, vector.buffer, vector.offset + vectorOffset, numBytes);

                        bytesWritten  += numBytes;
                        payloadOffset += numBytes;
                        vectorOffset  += numBytes;

                        if (vectorRemaining <= numBytes)
                        {
                            vectorIndex++;
                            vectorOffset = 0;
                        }
                    } while (bytesWritten < bytesToWrite);

                    if (remaining <= maxPayloadLength)
                    {
                        flags |= FrameDescriptor.END_FRAG_FLAG;
                    }

                    FrameDescriptor.FrameFlags(termBuffer, frameOffset, flags);

                    if (null != reservedValueSupplier)
                    {
                        long reservedValue = reservedValueSupplier(termBuffer, frameOffset, frameLength);
                        termBuffer.PutLong(frameOffset + DataHeaderFlyweight.RESERVED_VALUE_OFFSET, reservedValue, ByteOrder.LittleEndian);
                    }

                    FrameDescriptor.FrameLengthOrdered(termBuffer, frameOffset, frameLength);

                    flags        = 0;
                    frameOffset += alignedLength;
                    remaining   -= bytesToWrite;
                } while (remaining > 0);
            }

            return(resultingOffset);
        }