Aeron.NET icon indicating copy to clipboard operation
Aeron.NET copied to clipboard

ExpandableArrayBuffer has exception

Open MarshalOfficial opened this issue 2 years ago • 7 comments

I attempted to upgrade Aeron.Cluster package in my project to the latest version to use ExpandableArrayBuffer, but it seems it's not expanding its size as we did in the Java version.

My old code with UnsafeBuffer and specific size:

            _requestBuffer = new UnsafeBuffer(new byte[2000]);

            request.Encode(_requestBuffer);

            var sendRequestResult = _client.SendRequests(_requestBuffer, 0, request.Length);

And my latest code with ExpandableArrayBuffer

            _requestBuffer = new ExpandableArrayBuffer();            

            request.Encode(_requestBuffer);

            var sendRequestResult = _client.SendRequests(_requestBuffer, 0, request.Length);

I got this error:

System.IndexOutOfRangeException: index=0, length=617, capacity=128
   at Adaptive.Agrona.Util.ThrowHelper.ThrowIndexOutOfRangeException(String message)
   at Adaptive.Agrona.ExpandableArrayBuffer.BoundsCheck(Int32 index, Int32 length)
   at Adaptive.Aeron.LogBuffer.ExclusiveTermAppender.AppendUnfragmentedMessage(Int32 termId, Int32 termOffset, HeaderWriter header, IDirectBuffer bufferOne, Int32 offsetOne, Int32 lengthOne, IDirectBuffer bufferTwo, Int32 offsetTwo, Int32 lengthTwo, ReservedValueSupplier reservedValueSupplier)
   at Adaptive.Aeron.ExclusivePublication.Offer(IDirectBuffer bufferOne, Int32 offsetOne, Int32 lengthOne, IDirectBuffer bufferTwo, Int32 offsetTwo, Int32 lengthTwo, ReservedValueSupplier reservedValueSupplier)
   at Adaptive.Cluster.Client.AeronCluster.Offer(IDirectBuffer buffer, Int32 offset, Int32 length)
   at MyCodeNamespace.ClusterClient.SendRequests(IDirectBuffer buffer, Int32 offset, Int32 length)

MarshalOfficial avatar Aug 10 '22 05:08 MarshalOfficial

Thanks for giving it a go @MarshalOfficial

Given that the buffer is still at its initial capacity of 128 and there have been no exceptions trying to write beyond that, I would check for a bug in the code that defines request.Length.

If not, please share a minimum example that I'm able to run.

JPWatson avatar Aug 12 '22 12:08 JPWatson

@JPWatson Thanks for following up on this. I put some code here, it might be helpful. I wrote below helper classes that "request" is an instance of this class:

 public abstract class RequestBase
    {
        public long CorrelationId { get; set; }
        public int Length { get; set; }

        public abstract void Encode(IMutableDirectBuffer directBuffer);
    }

public class UpdateOperationRequest : RequestBase
    {
        private GeneratedEncoderFromSBE _updateOperationEncoder = new GeneratedEncoderFromSBE();
        private readonly MessageHeaderEncoder _headerEncoder = new MessageHeaderEncoder();
        private readonly OpdateOperationDTO _data;

        public UpdateAccOperationRequest(OpdateOperationDTO data)
        {
            _data = data;
        }

        public override void Encode(IMutableDirectBuffer directBuffer)
        {
            _updateOperationEncoder.WrapAndApplyHeader(directBuffer, 0, _headerEncoder);
            _updateOperationEncoder.CorrelationId((ulong)CorrelationId);
            _updateOperationEncoder.OperationCode(_data.OperationCode);
            _updateOperationEncoder.Amount(_data.Amount);
            _updateOperationEncoder.EffectiveDate((ushort)_data.EffectiveDate);
            _updateOperationEncoder.IdType(_data.IdType);
            _updateOperationEncoder.Id(_data.Id);
            _updateOperationEncoder.RequestId(_data.RequestId);
            _updateOperationEncoder.TransactionId(_data.TransactionId);

            //Document is string type
            if (!string.IsNullOrWhiteSpace(_data.Document))
            {
                _updateOperationEncoder.PutDocument(Encoding.UTF8.GetBytes(_data.Document), 0);
            }

            Length = _updateOperationEncoder.EncodedLength() + _headerEncoder.EncodedLength();
        }
    }

And then I used this helper class when I want to send request:

            var request = new UpdateOperationRequest(data);
            
            var  _requestBuffer = new ExpandableArrayBuffer();            

            request.Encode(_requestBuffer);

            var sendRequestResult = _client.SendRequests(_requestBuffer, 0, request.Length);

MarshalOfficial avatar Aug 13 '22 05:08 MarshalOfficial

What is _updateOperationEncoder.PutDocument(Encoding.UTF8.GetBytes(_data.Document), 0) doing behind the scenes? How is this type generated GeneratedEncoderFromSBE?

JPWatson avatar Aug 13 '22 07:08 JPWatson

What is _updateOperationEncoder.PutDocument(Encoding.UTF8.GetBytes(_data.Document), 0) doing behind the scenes? How is this type generated GeneratedEncoderFromSBE?

It is a string type, you are right a better approach to fill that is below function:

_updateOperationEncoder.Document(_data.Document);

But still, I get this error:

System.ArgumentException: Source array was not long enough. Check the source index, length, and the array's lower bounds. (Parameter 'sourceArray')
         at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
         at System.Array.Copy(Array sourceArray, Array destinationArray, Int32 length)
         at Adaptive.Agrona.ExpandableArrayBuffer.EnsureCapacity(Int32 index, Int32 length)
         at Adaptive.Agrona.ExpandableArrayBuffer.PutStringWithoutLengthAscii(Int32 index, String value)
         at namespaces...GeneratedEncoderFromSBE.Document(String src)
         at namespaces...UpdateOperationRequest.Encode(IMutableDirectBuffer directBuffer)

MarshalOfficial avatar Aug 13 '22 08:08 MarshalOfficial

OK, squashed that bug from porting. I will add some tests.

JPWatson avatar Aug 13 '22 08:08 JPWatson

OK, squashed that bug from porting. I will add some tests.

@JPWatson Hi, Is there any update on this issue?

MarshalOfficial avatar Oct 03 '22 09:10 MarshalOfficial

Planning a release in the next week or two.

JPWatson avatar Oct 03 '22 16:10 JPWatson

Planning a release in the next week or two.

Not yet?

MarshalOfficial avatar Nov 15 '22 10:11 MarshalOfficial

Apologies. Now that the 1.40 release is out, I'm aiming for next week.

JPWatson avatar Nov 15 '22 16:11 JPWatson

If you're looking for faster turnaround times, there is an option for commercial support.

JPWatson avatar Nov 15 '22 16:11 JPWatson

Released 1.40.0

JPWatson avatar Jan 17 '23 13:01 JPWatson