Skip to content

Conversation

Horusiath
Copy link
Contributor

This should fix the issue reported in #2995 (PR contains tests which reproduced the issue). It also upgrades the codebase to C# 7.

@Aaronontheweb
Copy link
Member

@Horusiath some UDP specs on Mono failing following this change

@Danthar
Copy link
Member

Danthar commented Aug 18, 2017

Because you also refactored to use new patterns and stuff. Its hard to review. Could you point out what you changed to fix the problem ?

@Horusiath
Copy link
Contributor Author

Horusiath commented Aug 18, 2017

Essentially the problem was that I didn't updated the UDP handler code in line to the changes I was making in TcpConnection during Akka.IO rework. In previous versions we were sending ByteString via socket chunk by chunk (waiting for the previous chunk to be sent before sending next one). New implementation (that already is present in TcpConnection) makes smart distinction between compact and multi-chunk ByteStrings:

  • Compact byte string consist only of single chunk, so it's simply set as SocketAsyncEventArgs.SetBuffer(buffer.Array, buffer.Offset, buffer.Count) before sending.
  • However multi-chunk byte string can also be send in a single call, thanks to SocketAsyncEventArgs.BufferList property.

I've extracted logic responsible for recognizing which method to use (SetBuffer/BufferList) from TcpConnection into single extension method SocketAsyncEventArgs.SetBuffer(ByteString), which now allows us to handle socket send request via TCP/UDP in quite similar way.

I'll take a look at issue on Mono later today.

@alexvaluyskiy
Copy link
Contributor

@Horusiath you made a lot of API changes, it will be impossible to ship it in 1.3.x. Is it possible to bring back some constructors and properties and make them obsoleted?

@Horusiath
Copy link
Contributor Author

Horusiath commented Aug 18, 2017

@alexvaluyskiy 90% of API changes is about sealing message classes (which should be sealed). There's a one change in the Send constructor, but the problem is more that you shouldn't even build it via constructor - which should be hidden - but rather via Send.Create(ByteString). I can make an obsoleted constructor, but Send.Payload should be ByteString anyway.

I guess it's not a big deal, as it's more to be used by us than users, and we can ask for forgiveness the 1-2 people, whos project will broke by that.

@Horusiath Horusiath force-pushed the udp-post-v1.3-fixes branch from 364a835 to d4012aa Compare August 19, 2017 06:46
@Horusiath
Copy link
Contributor Author

Horusiath commented Aug 19, 2017

The reason of failure on Mono found: Mono doesn't support using BufferList at this point. This probably means, that the same problem concerns TCP, we just didn't have tests to detect that.

As I definitely don't want to fallback the whole ability to send multiple buffers at once or build a separate (and very complex) buffer send awaiting logic just to cover Mono, my proposal is: If we detect, that we're on Mono, we use ByteString.Compact() method, to squash multi-buffer ByteString into single-buffer one. This is copying operation. it sucks for performance and memory usage, but it will cripple only some of the cases (multi-buffer ByteStrings) and only on Mono.

Are we fine with that? /cc @akkadotnet/core

// Mono doesn't support BufferList - falback to compacting ByteString
var compacted = data.Compact();
var buffer = compacted.Buffers[0];
args.SetBuffer(buffer.Array, buffer.Offset, buffer.Count);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we detect a Mono runtime, we'll try to fallback and compact multiple byte buffers into one (this operations copies buffers onto newly allocated array).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me

@Aaronontheweb
Copy link
Member

If we detect, that we're on Mono, we use ByteString.Compact() method, to squash multi-buffer ByteString into single-buffer one.

Fine with me. Not our job to implement the missing parts of the Mono runtime.

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@@ -61,6 +62,20 @@ public void The_UDP_Fire_and_Forget_implementation_must_be_able_to_send_without_
}

[Fact]
public void The_UDP_Fire_and_Forget_implementation_must_be_able_to_send_multipart_ByteString_without_binding()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

// Mono doesn't support BufferList - falback to compacting ByteString
var compacted = data.Compact();
var buffer = compacted.Buffers[0];
args.SetBuffer(buffer.Array, buffer.Offset, buffer.Count);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me

@@ -152,44 +152,48 @@ public NoAck(object token)
/// </summary>
public sealed class Send : Command
{
[Obsolete("Akka.IO.Udp.Send public constructors are obsolete. Use `Send.Create` or `Send(ByteString, EndPoint, Event)` instead.")]
public Send(IEnumerator<ByteBuffer> payload, Event ack)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@@ -35,6 +35,16 @@ public sealed class ByteString : IEquatable<ByteString>, IEnumerable<byte>
#region creation methods

/// <summary>
/// INTERNAL API: remove this method once <see cref="Udp.Send"/> public constructor will be removed.
/// </summary>
internal static ByteString FromBuffers(IEnumerator<ByteBuffer> buffers)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@Aaronontheweb Aaronontheweb merged commit c12d085 into akkadotnet:dev Aug 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants