private int ReceiveFromPkgBuffer(byte[] buffer, int offset, int size) { //size > 0 if (myPkg.Available > 0) { var sizeToCopy = Math.Min(size, myPkg.Available); myPkg.MoveTo(buffer, offset, sizeToCopy); return(sizeToCopy); } else { while (true) { myPkgHeaderBuffer.Clear(); if (!myPkgHeaderBuffer.Read(ref mySocketBuffer, ReceiveFromSocket)) { return(0); } Int32 len = UnsafeReader.ReadInt32FromBytes(myPkgHeaderBuffer.Data); Int64 seqN = UnsafeReader.ReadInt64FromBytes(myPkgHeaderBuffer.Data, sizeof(Int32)); if (len == ACK_MSG_LEN) { SendBuffer.Acknowledge(seqN); } else { myPkg.Clear(); if (!myPkg.Read(ref mySocketBuffer, ReceiveFromSocket, len)) { return(0); } if (seqN > myMaxReceivedSeqn || seqN == 1 /*TODO new client, possible duplicate problem if ack for seqN=1 from previous client's connection hasn't passed*/) { myMaxReceivedSeqn = seqN; //will be acknowledged when we read whole message Assertion.Assert(myPkg.Available > 0, "myPkgBuffer.Available > 0"); var sizeToCopy = Math.Min(size, myPkg.Available); myPkg.MoveTo(buffer, offset, sizeToCopy); return(sizeToCopy); } else { myAcktor.SendAsync(seqN); } } } } }
public unsafe void StressTestWithAck() { // LogLog.SeverityFilter = LoggingLevel.VERBOSE; // LogLog.RecordsChanged += record => { Console.WriteLine(record.Format(true)); }; long prev = 0; ByteBufferAsyncProcessor buffer = null; buffer = new ByteBufferAsyncProcessor("TestAsyncProcessor", 8, delegate(byte[] data, int offset, int len, ref long seqN) { long l = 0; Log.Root.Catch(() => { fixed(byte *b = data) { l = UnsafeReader.CreateReader(b, 8).ReadLong(); Assert.True(l > prev); prev = l; if (l % 1 == 0) { Ack(l); } } }); seqN = l; }); buffer.ShrinkIntervalMs = 10; buffer.Start(); void Ack(long seqn) { buffer?.Acknowledge(seqn); } var start = Environment.TickCount; bool Until() => Environment.TickCount - start < 1000; long next = 0; var tasks = new List <Task>(); for (int i = 0; i < 4; i++) { tasks.Add(Task.Run(() => { var rnd = new Random(); while (Until()) { lock (tasks) { using (var cookie = UnsafeWriter.NewThreadLocalWriter()) { cookie.Writer.Write(++next); buffer.Put(cookie); } } if (rnd.Next(1000) < 1) { Thread.Sleep(1); } if (rnd.Next(1000) < 5) { buffer.Clear(); } } })); } Task.WaitAll(tasks.ToArray()); // Console.WriteLine(next); // Console.WriteLine(buffer.ChunkCount); }
public unsafe void TestReprocess() { long prev = 0; ByteBufferAsyncProcessor buffer = null; List <long> log = new List <long>(); buffer = new ByteBufferAsyncProcessor("TestAsyncProcessor", 8, delegate(byte[] data, int offset, int len, ref long seqN) { try { fixed(byte *b = data) { long l = UnsafeReader.CreateReader(b, 8).ReadLong(); if (seqN != 0) { Assert.AreEqual(l, seqN); } seqN = l; log.Add(l); Assert.True(l > prev); prev = l; } } catch (Exception e) { Log.Root.Error(e); } }); buffer.ShrinkIntervalMs = 10; buffer.Start(); PutLong(buffer, 1); PutLong(buffer, 2); PutLong(buffer, 3); PutLong(buffer, 4); SpinWait.SpinUntil(() => buffer.AllDataProcessed); Assert.AreEqual(new List <int> { 1, 2, 3, 4 }, log); buffer.Acknowledge(2); prev = 2; buffer.ReprocessUnacknowledged(); PutLong(buffer, 5); SpinWait.SpinUntil(() => buffer.AllDataProcessed); Assert.AreEqual(new List <int> { 1, 2, 3, 4, 3, 4, 5 }, log); buffer.Acknowledge(5); buffer.ReprocessUnacknowledged(); SpinWait.SpinUntil(() => buffer.AllDataProcessed); Assert.AreEqual(new List <int> { 1, 2, 3, 4, 3, 4, 5 }, log); }
private int ReceiveFromPkgBuffer(byte[] buffer, int offset, int size) { //size > 0 if (myPkg.Available > 0) { var sizeToCopy = Math.Min(size, myPkg.Available); myPkg.MoveTo(buffer, offset, sizeToCopy); return(sizeToCopy); } else { while (true) { myPkgHeaderBuffer.Clear(); if (!myPkgHeaderBuffer.Read(ref mySocketBuffer, ReceiveFromSocket)) { return(0); } Int32 len = UnsafeReader.ReadInt32FromBytes(myPkgHeaderBuffer.Data); if (len == PING_LEN) { Int32 receivedTimestamp = UnsafeReader.ReadInt32FromBytes(myPkgHeaderBuffer.Data, sizeof(Int32)); Int32 receivedCounterpartTimestamp = UnsafeReader.ReadInt32FromBytes(myPkgHeaderBuffer.Data, sizeof(Int32) + sizeof(Int32)); Log.Trace()?.Log($"{Id}: Received PING package " + $"receivedTimestamp={receivedTimestamp}, " + $"receivedCounterpartTimestamp={receivedCounterpartTimestamp}, " + $"currentTimeStamp={myCurrentTimeStamp}, " + $"counterpartTimestamp={myCounterpartTimestamp}, " + $"counterpartNotionTimestamp={myCounterpartNotionTimestamp}"); myCounterpartTimestamp = receivedTimestamp; myCounterpartNotionTimestamp = receivedCounterpartTimestamp; if (ConnectionEstablished(myCurrentTimeStamp, myCounterpartNotionTimestamp)) { HeartbeatAlive.Value = true; } continue; } Int64 seqN = UnsafeReader.ReadInt64FromBytes(myPkgHeaderBuffer.Data, sizeof(Int32)); if (len == ACK_MSG_LEN) { SendBuffer.Acknowledge(seqN); } else { myPkg.Clear(); if (!myPkg.Read(ref mySocketBuffer, ReceiveFromSocket, len)) { return(0); } if (seqN > myMaxReceivedSeqn || seqN == 1 /*TODO new client, possible duplicate problem if ack for seqN=1 from previous client's connection hasn't passed*/) { myMaxReceivedSeqn = seqN; //will be acknowledged when we read whole message Assertion.Assert(myPkg.Available > 0, "myPkgBuffer.Available > 0"); var sizeToCopy = Math.Min(size, myPkg.Available); myPkg.MoveTo(buffer, offset, sizeToCopy); return(sizeToCopy); } else { myAcktor.SendAsync(seqN); } } } } }