private void TryBuffer(EndpointManager.Send s) { try { _resendBuffer = _resendBuffer.Buffer(s); } catch (Exception ex) { throw new HopelessAssociation(_localAddress, _remoteAddress, Uid, ex); } }
private void UpdateSavedState(EndpointManager.Link key, EndpointManager.ResendState expectedState) { if (expectedState == null) { if (_receiveBuffers.ContainsKey(key)) { var updatedValue = new EndpointManager.ResendState(_uid, _ackedReceiveBuffer); _receiveBuffers.AddOrUpdate(key, updatedValue, (link, state) => updatedValue); UpdateSavedState(key, updatedValue); } } else { var canReplace = _receiveBuffers.ContainsKey(key) && _receiveBuffers[key].Equals(expectedState); if (canReplace) { _receiveBuffers[key] = Merge(new EndpointManager.ResendState(_uid, _ackedReceiveBuffer), expectedState); } else { EndpointManager.ResendState previousValue; _receiveBuffers.TryGetValue(key, out previousValue); UpdateSavedState(key, previousValue); } } }
private void HandleSend(EndpointManager.Send send) { if (send.Message is ISystemMessage) { var sequencedSend = send.Copy(NextSeq()); TryBuffer(sequencedSend); //If we have not confirmed the remote UID we cannot transfer the system message at this point, so just buffer it. // GotUid will kick ResendAll causing the messages to be properly written. if (UidConfirmed) _writer.Tell(sequencedSend); } else { _writer.Tell(send); } }
private EndpointManager.ResendState Merge(EndpointManager.ResendState current, EndpointManager.ResendState oldState) { if (current.Uid == oldState.Uid) return new EndpointManager.ResendState(_uid, oldState.Buffer.MergeFrom(current.Buffer)); return current; }
private bool WriteSend(EndpointManager.Send send) { try { if (_handle == null) throw new EndpointException( "Internal error: Endpoint is in state Writing, but no association handle is present."); if (_provider.RemoteSettings.LogSend) { var msgLog = string.Format("RemoteMessage: {0} to [{1}]<+[{2}] from [{3}]", send.Message, send.Recipient, send.Recipient.Path, send.SenderOption ?? _system.DeadLetters); _log.Debug(msgLog); } var pdu = _codec.ConstructMessage(send.Recipient.LocalAddressToUse, send.Recipient, SerializeMessage(send.Message), send.SenderOption, send.Seq, _lastAck); //todo: RemoteMetrics https://github.com/akka/akka/blob/dc0547dd73b54b5de9c3e0b45a21aa865c5db8e2/akka-remote/src/main/scala/akka/remote/Endpoint.scala#L742 //todo: max payload size validation var ok = _handle.Write(pdu); if (ok) { _ackDeadline = NewAckDeadline(); _lastAck = null; return true; } return false; } catch (SerializationException ex) { _log.Error(ex, "Transient association error (association remains live)"); return true; } catch (EndpointException ex) { PublishAndThrow(ex, LogLevel.ErrorLevel); } catch (Exception ex) { PublishAndThrow(new EndpointException("Failed to write message to the transport", ex), LogLevel.ErrorLevel); } return false; }
/// <summary> /// Internal function used for filtering endpoints that need to be pruned due to non-recovery past their deadlines /// </summary> private static bool PruneFilterFunction(EndpointManager.EndpointPolicy policy) { var rValue = true; policy.Match() .With<EndpointManager.Gated>(g => rValue = g.TimeOfRelease.HasTimeLeft) .With<EndpointManager.Quarantined>(q => rValue = q.Deadline.HasTimeLeft) .Default(msg => rValue = true); return rValue; }
private void HandleSend(EndpointManager.Send send) { if (send.Message is ISystemMessage) { var sequencedSend = send.Copy(NextSeq()); TryBuffer(sequencedSend); // If we have not confirmed the remote UID we cannot transfer the system message at this point just buffer it. // GotUid will kick ResendAll() causing the messages to be properly written. // Flow control by not sending more when we already have many outstanding. if (UidConfirmed && _resendBuffer.NonAcked.Count <= _settings.SysResendLimit) _writer.Tell(sequencedSend); } else { _writer.Tell(send); } }
private bool WriteSend(EndpointManager.Send send) { try { if (_handle == null) throw new EndpointException( "Internal error: Endpoint is in state Writing, but no association handle is present."); if (_provider.RemoteSettings.LogSend) { _log.Debug("RemoteMessage: {0} to [{1}]<+[{2}] from [{3}]", send.Message, send.Recipient, send.Recipient.Path, send.SenderOption ?? _system.DeadLetters); } var pdu = _codec.ConstructMessage(send.Recipient.LocalAddressToUse, send.Recipient, SerializeMessage(send.Message), send.SenderOption, send.Seq, _lastAck); _remoteMetrics.LogPayloadBytes(send.Message, pdu.Length); if (pdu.Length > Transport.MaximumPayloadBytes) { var reason = new OversizedPayloadException( string.Format("Discarding oversized payload sent to {0}: max allowed size {1} bytes, actual size of encoded {2} was {3} bytes.", send.Recipient, Transport.MaximumPayloadBytes, send.Message.GetType(), pdu.Length)); _log.Error(reason, "Transient association error (association remains live)"); return true; } else { var ok = _handle.Write(pdu); if (ok) { _ackDeadline = NewAckDeadline(); _lastAck = null; return true; } } return false; } catch (SerializationException ex) { _log.Error(ex, "Transient association error (association remains live)"); return true; } catch (EndpointException ex) { PublishAndThrow(ex, LogLevel.ErrorLevel); } catch (Exception ex) { PublishAndThrow(new EndpointException("Failed to write message to the transport", ex), LogLevel.ErrorLevel); } return false; }