private void SendDg() { foreach (var node in Nodes) for (var iBuf = 0; iBuf < node.Buffer.Count; iBuf++) { var package = node.Buffer[iBuf]; if (package.IsDatagram && package.Sent == 0 && !package.AlreadySentOnThisTick) { // Sender part // ----------------------------------------------------------------- // Select local route for (var i = 0; i < Nodes[package.FromNow].Table.Count; i++) { var row = Nodes[package.FromNow].Table[i]; // ReSharper disable once InvertIf if (row.From == package.From && row.To == package.To && package.ReceivedFrom != row.SendTo && ConnectionIsFilled(package, row.SendThroughConnection)) { package.ToNow = row.SendTo; package.SelectedRoute = i; package.SendThroughConnection = row.SendThroughConnection; // If this is half duplex, make it taken Connections[package.SendThroughConnection].MakeItFreeOnNextTact = false; break; } } // Cannot find route (all routes are totally filled or half duplex to other current) if (package.SelectedRoute == -1) continue; var willSend = HowManySend(package); // For statistics //DatagramsSent++; if (!package.IsService) AvarageWaitTimeDatagram += TickNumber - package.CreatedOn; // If package is last in half duplex if (!Connections[package.SendThroughConnection].IsFullDuplex && package.Sent + willSend == package.SizeTotal()) Connections[package.SendThroughConnection].MakeItFreeOnNextTact = true; // Other side buffer is overflowed if (BufferSize <= Nodes[package.ToNow].Buffer.Count) { package.ReceiverHasOverflowedBuffer = true; // Package sended if (CheckIsPackageSent(package)) iBuf--; continue; } // Remember receiver index in buffer package.ReceiverBufIdx = Nodes[package.ToNow].Buffer.Count; // Receiver part // ----------------------------------------------------------------- var receiverPackage = new Package { To = package.To, From = package.From, IsDatagram = true, Id = package.Id, PartIdx = package.PartIdx, SizeInformation = package.SizeInformation, MyBufIdx = package.ReceiverBufIdx, // Itself FromNow = package.ToNow, Received = willSend, TickGeneratedOn = package.TickGeneratedOn, AlreadySentOnThisTick = true, ReceivedFrom = package.FromNow, IsService = package.IsService, ApprovesPackage = package.ApprovesPackage, //ApprovesMessage = package.ApprovesMessage, ApproveBufferIdxWhoWait = package.ApproveBufferIdxWhoWait, ApproveFrom = package.FromNow, //ApproveTo = package.ToNow, }; Nodes[package.ToNow].Buffer.Add(receiverPackage); // Package sended if (CheckIsPackageSent(package)) iBuf--; } } }
private void SendVc() { foreach (var node in Nodes) for (var iBuf = 0; iBuf < node.Buffer.Count; iBuf++) { var package = node.Buffer[iBuf]; if (!package.IsDatagram && package.Sent == 0 && !package.AlreadySentOnThisTick) { // Sender part // ----------------------------------------------------------------- // Select local route foreach (var row in Nodes[package.FromNow].Table.Where(row => row.From == package.From && row.To == package.To && package.ReceivedFrom != row.SendTo && row.PathPriority == package.Label)) { package.ToNow = row.SendTo; package.SendThroughConnection = row.SendThroughConnection; // If this is half duplex, make it taken Connections[package.SendThroughConnection].MakeItFreeOnNextTact = false; break; } if (package.ToNow == -1) // If sending to node without route to it (some connection is disabled) continue; var willSend = HowManySend(package); if (willSend == 0) continue; // For statistics //VirtualSent++; AvarageWaitTimeVirtual += TickNumber - package.CreatedOn; // If package is last in half duplex if (!Connections[package.SendThroughConnection].IsFullDuplex && package.Sent + willSend == package.SizeTotal()) Connections[package.SendThroughConnection].MakeItFreeOnNextTact = true; // Other side buffer is overflowed if (BufferSize <= Nodes[package.ToNow].Buffer.Count) { package.ReceiverHasOverflowedBuffer = true; // Package sended if (CheckIsPackageSent(package)) iBuf--; continue; } // Remember receiver index in buffer package.ReceiverBufIdx = Nodes[package.ToNow].Buffer.Count; // Receiver part // ----------------------------------------------------------------- var receiverPackage = new Package { To = package.To, From = package.From, IsDatagram = false, Id = package.Id, PartIdx = package.PartIdx, SizeInformation = package.SizeInformation, MyBufIdx = package.ReceiverBufIdx, // Itself FromNow = package.ToNow, Received = willSend, Label = package.Label, TickGeneratedOn = package.TickGeneratedOn, AlreadySentOnThisTick = true, ReceivedFrom = package.FromNow, IsService = package.IsService, ApprovesPackage = package.ApprovesPackage, //ApprovesMessage = package.ApprovesMessage, ApproveBufferIdxWhoWait = package.ApproveBufferIdxWhoWait, ApproveFrom = package.FromNow, //ApproveTo = package.ToNow, }; Nodes[package.ToNow].Buffer.Add(receiverPackage); // Package sent if (CheckIsPackageSent(package)) iBuf--; //if (CheckIsPackageSent(package)) //iBuf--; } } }
/// <summary> /// Checks how many bytes can be sent from package throughselected connection /// </summary> /// <param name="package">Specified package</param> /// <returns></returns> private int HowManySend(Package package) { var connSendThrough = Connections[package.SendThroughConnection]; int willSend; // Sending through full duplex if (connSendThrough.IsFullDuplex) { willSend = connSendThrough.TransferRate / 2; if (connSendThrough.SendingFromNode == package.FromNow) willSend -= connSendThrough.FilledFromNode; else willSend -= connSendThrough.FilledToNode; } else // Sending through half duplex { willSend = connSendThrough.TransferRate; if (connSendThrough.SendingFromNode == package.FromNow) willSend -= connSendThrough.FilledFromNode; else willSend -= connSendThrough.FilledToNode; } // "Send" if (package.SizeTotal() < package.Sent + willSend) willSend = package.SizeTotal() - package.Sent; package.Sent += willSend; // Set connection fill if (connSendThrough.IsFullDuplex) if (connSendThrough.SendingFromNode == package.FromNow) connSendThrough.FilledFromNode += willSend; else connSendThrough.FilledToNode += willSend; else // Sending through half duplex if (connSendThrough.SendingFromNode == package.FromNow) connSendThrough.FilledFromNode += willSend; else connSendThrough.FilledToNode += willSend; return willSend; }
private void DeletePackage(Package package) { var myNode = Nodes[package.FromNow]; for (var i = package.MyBufIdx + 1; i < myNode.Buffer.Count; i++) myNode.Buffer[i].MyBufIdx--; // Increase self buffer indexes for packages in my buffer foreach (var bufRow in Nodes.Where(t => t != myNode).SelectMany(node => node.Buffer.Where(t => t.ToNow == package.FromNow && package.MyBufIdx < t.ReceiverBufIdx))) bufRow.ReceiverBufIdx--; // Increase self buffer indexes for packages in my buffer //if (!package.IsService) foreach (var bufRow in Nodes.Where(t => t != myNode).SelectMany(node => node.Buffer.Where(t => t.ApprovesPackage && t.ApproveFrom == package.FromNow && package.MyBufIdx < t.ApproveBufferIdxWhoWait))) bufRow.ApproveBufferIdxWhoWait--; // For statistics if (package.FromNow == package.To && !package.IsService) if (package.IsDatagram) { MessagesReceivedDatagram++; AverageSendTimeDatagram += TickNumber - package.TickGeneratedOn; } else { MessagesReceivedVirtual++; AverageSendTimeVirtual += TickNumber - package.TickGeneratedOn; } // Remember to history package.TickCompletedOn = TickNumber; myNode.History.Add(package); myNode.Buffer.RemoveAt(package.MyBufIdx); }
/// <summary> /// Check connectinion for ability to transfer at least 1B /// </summary> /// <param name="package">Package try try to transfer</param> /// <param name="connection">Index of the connection</param> /// <returns></returns> private bool ConnectionIsFilled(Package package, int connection) { var connExplore = Connections[connection]; int willSend; // Sending through full duplex if (connExplore.IsFullDuplex) { willSend = connExplore.TransferRate / 2; if (package.IsDatagram && connExplore.SendingFromNode == package.FromNow || !package.IsDatagram && connExplore.SendingFromNode == package.From) willSend -= connExplore.FilledFromNode; else willSend -= connExplore.FilledToNode; } else // Sending through half duplex { willSend = connExplore.TransferRate; if (package.IsDatagram && connExplore.SendingFromNode == package.FromNow || !package.IsDatagram && connExplore.SendingFromNode == package.From) willSend -= connExplore.FilledFromNode; else willSend -= connExplore.FilledToNode; } return willSend != 0; }
/// <summary> /// Checks package for completed transfer /// </summary> /// <param name="package">Specified package</param> private bool CheckIsPackageSent(Package package) { if (package.Sent == package.SizeTotal() || // Sended from some node package.To == package.FromNow) // Reached next node { if (package.ImInfoAndICanBeDeleted || package.IsService) DeletePackage(package); // If need further send if (!package.ReceiverHasOverflowedBuffer && package.Sent == package.SizeTotal()) { var packageOtherSide = Nodes[package.ToNow].Buffer[package.ReceiverBufIdx]; if (!package.IsService) { Nodes[package.ToNow].Buffer.Add(new Package { IsService = true, ApprovesPackage = true, ApproveFrom = package.FromNow, //ApproveTo = package.ToNow, From = package.ToNow, To = package.FromNow, FromNow = package.ToNow, AlreadySentOnThisTick = true, Sent = 0, MyBufIdx = Nodes[package.ToNow].Buffer.Count, IsDatagram = true, ApproveBufferIdxWhoWait = package.MyBufIdx, }); if (package.IsDatagram) ServiceDg++; else ServiceVc++; // For statistics if (package.Sent == package.SizeTotal()) if (package.IsDatagram) DatagramsReceived++; else VirtualReceived++; // For global history if (packageOtherSide.FromNow == packageOtherSide.To) { var completedPacks = Nodes[packageOtherSide.FromNow].Buffer.Count(pack => pack.Id == packageOtherSide.Id); if (completedPacks == packageOtherSide.Parts && !CompletedMessages.Contains(packageOtherSide.Id)) { CompletedMessages.Add(packageOtherSide.Id); _messages[packageOtherSide.Id].MessageCompletedOn = TickNumber; } } packageOtherSide.Received = -1; packageOtherSide.Sent = 0; packageOtherSide.CreatedOn = TickNumber; // If other size package reached final destiny if (package.To == package.ToNow) DeletePackage(packageOtherSide); } else { if (package.ApprovesPackage) DeletePackage(packageOtherSide); } } if (package.ApprovesPackage && package.To == package.ToNow) { var packageInfo = Nodes[package.ApproveFrom].Buffer[package.ApproveBufferIdxWhoWait]; packageInfo.ImInfoAndICanBeDeleted = true; DeletePackage(packageInfo); } return true; } return false; }
/// <summary> /// Sends message (from template in parameter) /// </summary> /// <param name="package">Package with initial data</param> public void SendPackage(Package package) { // Divide to packages var packages = new List<Package>(); _messages.Add(new Package { Id = FreeId, MessageCreatedOn = TickNumber }); if (package.SizeTotal() <= SizeMaxPackage) // If message is in size like one package { package.FromNow = package.From; package.Id = FreeId; package.MyBufIdx = Nodes[package.From].Buffer.Count; package.Sent = 0; package.PartIdx = 0; package.TickGeneratedOn = TickNumber; // For statistics package.CreatedOn = TickNumber; // For statistics packages.Add(package); SendedMessagePart = 1; // For external world if (package.IsDatagram) DatagramsSent++; else VirtualSent++; } else // If bigger { // Divide message to packages var sizeMaxInf = SizeMaxPackage - Package.SizeHeader; var packagesNumber = Convert.ToInt32(Math.Ceiling(package.SizeInformation / (double)sizeMaxInf)); if (package.IsDatagram) DatagramsSent += packagesNumber; else VirtualSent += packagesNumber; SendedMessagePart = packagesNumber; // For external world var firstBufIdx = Nodes[package.From].Buffer.Count; for (var i = 0; i < packagesNumber - 1; i++) // Several the same packages packages.Add(new Package { To = package.To, FromNow = package.From, From = package.From, IsDatagram = package.IsDatagram, Id = FreeId, PartIdx = i, SizeInformation = sizeMaxInf, MyBufIdx = firstBufIdx + i, Sent = 0, Parts = packagesNumber, TickGeneratedOn = TickNumber, // For statistics CreatedOn = TickNumber // For statistics }); // Last package can be lesser in size var sizeLastInf = package.SizeInformation % sizeMaxInf; packages.Add(new Package { To = package.To, FromNow = package.From, From = package.From, IsDatagram = package.IsDatagram, Id = FreeId, PartIdx = packagesNumber - 1, SizeInformation = sizeLastInf, MyBufIdx = firstBufIdx + packagesNumber - 1, Sent = 0, Parts = packagesNumber, TickGeneratedOn = TickNumber, // For statistics CreatedOn = TickNumber // For statistics }); } // Add packages while it isn't filled foreach (var pack in packages.TakeWhile(pack => BufferSize > Nodes[package.From].Buffer.Count)) Nodes[package.From].Buffer.Add(pack); // Add new packages to buffer //Nodes[package.From].Buffer.AddRange(packages); FreeId++; }