de.bsvrz.dav.daf.communication.lowLevel
Class LowLevelCommunication

java.lang.Object
  extended by de.bsvrz.dav.daf.communication.lowLevel.LowLevelCommunication
All Implemented Interfaces:
LowLevelCommunicationInterface

public class LowLevelCommunication
extends Object
implements LowLevelCommunicationInterface

Klasse zur Verwaltung der unteren Ebene von Datenverteilerverbindungen.

Die Aufgabe dieser Klasse ist es Telegramme zu versenden, zu empfangen und KeepAlive-Mechanismus zu verwalten.

Jede dieser Aufgaben wird durch mindestens einen Thread übernommen:

Empfang von Daten: ReceivingChannel (nimmt die Daten entgegen und legt diese in _receivingTable ab. Bei Konfigurationsanfragen kann es zur Zerstücklung von Telegrammen kommen, diese Teiltelgramme werden in _splittedTelegramsTable abgelegt und dort mit jedem empfang eines Teiltelegramms langsam zusammen gebaut und nach Vollendung an ClientHighLevelCommunication durchgereicht (nicht über den Worker-Thread). Beim empfang von Daten wird der KeepAlive-Thread benachrichtigt.), WorkerThread (bearbeitet die _receivingTable und reicht empfangene Telegramme an ClientHighLevelCommunication weiter).

Versand von Daten: SendingChannel (verschickt Telegramme aus der _sendingTable und benachrichtigt den KeepAlive Thread, sobald Daten verschickt wurden. Prüft die Laufzeit der einzelnen Telegramme und unterbricht die Verbindung sobald diese einen kritischen Wert unterschreitet).

KeepAlive-Mechanismus: KeepAliveThread (Verwaltet ob ein "KeepAlive" Telegramm verschickt werden muss. Dies ist abhängig davon, ob eine Telegramm versendet/empfangen wurde. Wurde eine bestimmte Anzahl Keepalive Telegramme versendet, so wird die Verbindung abgebaut. Wird nach dem versand eines KeepAlive Telegramms ein normales Telegramm empfangen/gesendet, so wird der KeepAlive-Telegrammzähler wieder auf 0 gesetzt. Anmerkung: Das KeepAlive Paket wird nicht über den SendingChannel-Thread verschickt, sondern direkt über den Outputstream.)

Alle vollständigen Telegramme werden in zwei TelegramQueue-Objekten gespeichert (eine für den Empfang, eine für den Versand). Die oben beschriebenen Threads (ausser der KeepAlive-Thread) arbeiten und synchronisieren sich auf den jeweiligen "PriorityTables".

Begriffsdefinitionen: Protokollsteuerung DaV-DAF (Klasse ClientHighLevelCommunication), Datenrepräsentation (Klassen DataInputStream und DataOutputStream), TCP-Kommunikationskanal (Klasse TCP_IP_Communication)

Author:
Kappich Systemberatung

Nested Class Summary
(package private)  class LowLevelCommunication.KeepAliveThread
          Dieser Thread verschickt Keepalive Telegramme und baut die Verbindung ab, wenn dreimal nacheinander eine bestimmte Zeit lang keine Daten mehr empfangen wurden.
(package private)  class LowLevelCommunication.ReceivingChannel
           
(package private)  class LowLevelCommunication.SendingChannel
          Dieser Thread verschickt Telegramme mittels einer Datenverteilerverbindung (Outputstream der Verbindung).
private  class LowLevelCommunication.ThroughputChecker
           
private static class LowLevelCommunication.ThroughputCheckerState
           
(package private)  class LowLevelCommunication.WorkerThread
           
 
Field Summary
private  ConnectionInterface _connection
          Die Kommunikationskomponente (TCP-IP...)
private static Debug _debug
           
private  boolean _disconnected
          Verbindungsstatusinformation
private  HighLevelCommunicationCallbackInterface _highLevelComponent
          Der Komponente die benachrichtigt werden soll, wenn eine neues Telegramm ankommt.
private  DataInputStream _inStream
          Der Inputstream dieser Verbindung
private  long _keepAliveReceiveTimeOut
          Die Zeit in der spätestens ein Telegramm empfangen werden muss.
private  long _keepAliveSendTimeOut
          Die Zeit nach der spätestens ein KeepAlive-Telegramm gesendet werden muss, wenn in dieser Zeit kein sonstiges Telegramm gesendet wurde.
private  LowLevelCommunication.KeepAliveThread _keepAliveThread
          Der KeepAlivethread
private  int _mode
          Der Modus dieser Verbindung
private  DataOutputStream _outStream
          Der Outputstream dieser Verbindung
private  TelegramQueue<DataTelegram> _receiveQueue
          Queue, in der empfangene Telegramme zwischengespeichert werden.
private  LowLevelCommunication.ReceivingChannel _receivingChannel
          Der Empfangsthread dieser Kommunikation
private  LowLevelCommunication.SendingChannel _sendingChannel
          Der Sendethread dieser Kommunikation
private  TelegramQueue<DataTelegram> _sendQueue
          Queue, in der zu versendende Telegramme zwischengespeichert werden.
private  boolean _sendTerminationTelegramWhenClosing
          Kennung, die true ist, wenn ein Verbindungsterminierungstelegramm beim Schließen der Verbindung versendet werden soll.
private  SplittedApplicationTelegramsTable _splittedTelegramsTable
          Temporäre Liste der zerstückelten Telegramme
private  DataTelegram _terminationTelegram
           
private  LowLevelCommunication.ThroughputChecker _throughputChecker
           
private  LowLevelCommunication.WorkerThread _updater
          Der Aktuallisierungsthread
private  boolean _waitingForSendingChannel
           
static byte HANDLE_CONFIG_RESPONCES_MODE
          Wert für den mode-Parameter des Konstruktors, der bewirkt, dass Konfigurationsantworten ausgewertet und entsprechend an die höhere Kommunikationsebene weitergegeben werden.
static byte NORMAL_MODE
          Wert für den mode-Parameter des Konstruktors, der bewirkt, dass Konfigurationsantworten wie normale Datentelegramme verarbeitet werden.
 
Constructor Summary
LowLevelCommunication(ConnectionInterface connection, int sendBufferSize, int receiveBufferSize, long keepAliveSendTimeOut, long keepAliveReceiveTimeOut, byte mode, boolean connected)
           
 
Method Summary
 void connect(String mainAddress, int subAddress)
          Diese Methode baut eine Kommunikationsverbindung zu den angegebenen Adressen auf.

Nach dem Verbindungsaufbau werden die Referenzen auf den Sende- und den Empfangskanal festgehalten.

 void disconnect(boolean error, String message, DataTelegram terminationTelegram)
          Diese Methode wird von der Protokollschicht DaV-DAF aufgerufen, wenn die Kommunikationskanäle geschlossen werden sollen.
 ConnectionInterface getConnectionInterface()
          Gibt den Repräsentant der Verbindung zurück
(package private)  LowLevelCommunication.KeepAliveThread getKeepAliveThread()
          Diese Methode dient nur für automatisierte Tests und ist nicht für den realen Einsatz gedacht.
(package private)  LowLevelCommunication.ReceivingChannel getReceivingChannel()
          Diese Methode dient nur für automatisierte Tests und ist nicht für den realen Einsatz gedacht.
 String getSendBufferState()
          Liefert einen beschreibenden Text mit dem Zustand des Sendepuffers
(package private)  LowLevelCommunication.SendingChannel getSendingChannel()
          Diese Methode dient nur für automatisierte Tests und ist nicht für den realen Einsatz gedacht.
(package private)  LowLevelCommunication.WorkerThread getUpdaterThread()
          Diese Methode dient nur für automatisierte Tests und ist nicht für den realen Einsatz gedacht.
private  void handleAbnormalBehaviour(boolean sendTermination, String message)
           
 boolean isNotConnected()
          Gibt als Information zurück, ob die Kommunikationsverbindung unterbrochen ist.
 void send(DataTelegram telegram)
          Diese Methode wird von der Protokollschicht DaV-DAF aufgerufen, wenn ein Telegramm gesendet werden soll.
 void send(DataTelegram[] telegrams)
          Fügt mehrere Telegramme in die Sendetabelle ein.
 void setHighLevelComponent(HighLevelCommunicationCallbackInterface highLevelComponent)
          Setzt die Interpretationsschicht dieser Komponente für den internen Datenaustausch.
 void updateKeepAliveParameters(long keepAliveSendTimeOut, long keepAliveReceiveTimeOut)
          Diese Methode wird von der Protokollschicht DaV-DAF aufgerufen, wenn die Keepalive-Parameter-Verhandlung erfolgreich abgeschlossen ist und setzt somit die Timeouts des Keepaliveprozesses.
 void updateThroughputParameters(float throughputControlSendBufferFactor, long throughputControlInterval, int minimumThroughput)
          Diese Methode setzt die Parameter für die Durchsatzprüfung.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

NORMAL_MODE

public static final byte NORMAL_MODE
Wert für den mode-Parameter des Konstruktors, der bewirkt, dass Konfigurationsantworten wie normale Datentelegramme verarbeitet werden.

See Also:
Constant Field Values

HANDLE_CONFIG_RESPONCES_MODE

public static final byte HANDLE_CONFIG_RESPONCES_MODE
Wert für den mode-Parameter des Konstruktors, der bewirkt, dass Konfigurationsantworten ausgewertet und entsprechend an die höhere Kommunikationsebene weitergegeben werden.

See Also:
Constant Field Values

_debug

private static final Debug _debug

_connection

private ConnectionInterface _connection
Die Kommunikationskomponente (TCP-IP...)


_inStream

private DataInputStream _inStream
Der Inputstream dieser Verbindung


_outStream

private DataOutputStream _outStream
Der Outputstream dieser Verbindung


_receivingChannel

private LowLevelCommunication.ReceivingChannel _receivingChannel
Der Empfangsthread dieser Kommunikation


_sendingChannel

private LowLevelCommunication.SendingChannel _sendingChannel
Der Sendethread dieser Kommunikation


_updater

private LowLevelCommunication.WorkerThread _updater
Der Aktuallisierungsthread


_sendQueue

private TelegramQueue<DataTelegram> _sendQueue
Queue, in der zu versendende Telegramme zwischengespeichert werden.


_receiveQueue

private TelegramQueue<DataTelegram> _receiveQueue
Queue, in der empfangene Telegramme zwischengespeichert werden.


_highLevelComponent

private HighLevelCommunicationCallbackInterface _highLevelComponent
Der Komponente die benachrichtigt werden soll, wenn eine neues Telegramm ankommt.


_keepAliveThread

private LowLevelCommunication.KeepAliveThread _keepAliveThread
Der KeepAlivethread


_keepAliveSendTimeOut

private long _keepAliveSendTimeOut
Die Zeit nach der spätestens ein KeepAlive-Telegramm gesendet werden muss, wenn in dieser Zeit kein sonstiges Telegramm gesendet wurde.


_keepAliveReceiveTimeOut

private long _keepAliveReceiveTimeOut
Die Zeit in der spätestens ein Telegramm empfangen werden muss. Wenn diese Zeit dreimal hintereinander abgelaufen ist, wird die Verbindung terminiert.


_disconnected

private volatile boolean _disconnected
Verbindungsstatusinformation


_mode

private int _mode
Der Modus dieser Verbindung

See Also:
HANDLE_CONFIG_RESPONCES_MODE, NORMAL_MODE

_splittedTelegramsTable

private SplittedApplicationTelegramsTable _splittedTelegramsTable
Temporäre Liste der zerstückelten Telegramme


_sendTerminationTelegramWhenClosing

private boolean _sendTerminationTelegramWhenClosing
Kennung, die true ist, wenn ein Verbindungsterminierungstelegramm beim Schließen der Verbindung versendet werden soll.


_terminationTelegram

private DataTelegram _terminationTelegram

_throughputChecker

private LowLevelCommunication.ThroughputChecker _throughputChecker

_waitingForSendingChannel

private volatile boolean _waitingForSendingChannel
Constructor Detail

LowLevelCommunication

public LowLevelCommunication(ConnectionInterface connection,
                             int sendBufferSize,
                             int receiveBufferSize,
                             long keepAliveSendTimeOut,
                             long keepAliveReceiveTimeOut,
                             byte mode,
                             boolean connected)
                      throws ConnectionException
Parameters:
connection - Verbindungsobjekt über dass die Kommunikation mit dem Kommunikationspartner realisiert wird.
sendBufferSize - Sendetabellenkapazität (in Byte)
receiveBufferSize - Empfangstabellenkapazität (in Byte)
keepAliveSendTimeOut - Zeitspanne in ms. Wird solange kein Telegramm verschickt, wird ein KeepAlive-Telegramm verschickt.
keepAliveReceiveTimeOut - Zeitspanne in ms. Wird solange keine Telegramm empfangen, wird ein Zähler herabgesetzt. Erreicht der Zähler 0 wird die Verbindung terminiert. Wird zwischendurch ein Telegramm empfangen, wird der Zähler auf das maximum gesetzt.
mode - Modus für das Konfigurationsdatenverhalten. Falls hier der Wert HANDLE_CONFIG_RESPONCES_MODE übergeben wird, dann werden Konfigurationsantworten ausgewertet und entsprechend an die höhere Kommunikationsebene weitergegeben. Falls hier der Wert NORMAL_MODE übergeben wird, dann werden Konfigurationsantworten wie normale Datentelegramme verarbeitet.
connected - Information, ob die Verbindung bereits erfolgt ist oder nicht (connected)
Throws:
ConnectionException - Wenn das Verbindungsobjekt sich nicht im erwarteten Zustand befindet.
Method Detail

getKeepAliveThread

LowLevelCommunication.KeepAliveThread getKeepAliveThread()
Diese Methode dient nur für automatisierte Tests und ist nicht für den realen Einsatz gedacht.

Returns:
KeepAlive-Thread oder null wenn dieser noch nicht aktiviert wurde.

getReceivingChannel

LowLevelCommunication.ReceivingChannel getReceivingChannel()
Diese Methode dient nur für automatisierte Tests und ist nicht für den realen Einsatz gedacht.

Returns:
ReceivingChannel-Thread oder null wenn dieser noch nicht aktiviert wurde.

getSendingChannel

LowLevelCommunication.SendingChannel getSendingChannel()
Diese Methode dient nur für automatisierte Tests und ist nicht für den realen Einsatz gedacht.

Returns:
SendingChannel-Thread oder null wenn dieser noch nicht aktiviert wurde.

getUpdaterThread

LowLevelCommunication.WorkerThread getUpdaterThread()
Diese Methode dient nur für automatisierte Tests und ist nicht für den realen Einsatz gedacht.

Returns:
Updater-Thread oder null wenn dieser noch nicht aktiviert wurde.

getConnectionInterface

public final ConnectionInterface getConnectionInterface()
Description copied from interface: LowLevelCommunicationInterface
Gibt den Repräsentant der Verbindung zurück

Specified by:
getConnectionInterface in interface LowLevelCommunicationInterface
Returns:
Repräsentant der Verbindung

setHighLevelComponent

public final void setHighLevelComponent(HighLevelCommunicationCallbackInterface highLevelComponent)
Description copied from interface: LowLevelCommunicationInterface
Setzt die Interpretationsschicht dieser Komponente für den internen Datenaustausch. Erst nach Aufruf dieser Methode von der Protokollschicht DaV-DAF werden die Kommunikations-Threads gestartet, weil sonst keine Telegramme interpretiert oder weitergeleitet werden können.

Specified by:
setHighLevelComponent in interface LowLevelCommunicationInterface
Parameters:
highLevelComponent - Komponente, die benachrichtigt werden muss, wenn neue Nachrichten empfangen werden.

updateKeepAliveParameters

public final void updateKeepAliveParameters(long keepAliveSendTimeOut,
                                            long keepAliveReceiveTimeOut)
Description copied from interface: LowLevelCommunicationInterface
Diese Methode wird von der Protokollschicht DaV-DAF aufgerufen, wenn die Keepalive-Parameter-Verhandlung erfolgreich abgeschlossen ist und setzt somit die Timeouts des Keepaliveprozesses.

Specified by:
updateKeepAliveParameters in interface LowLevelCommunicationInterface
Parameters:
keepAliveSendTimeOut - Sendekeepalivetimeout
keepAliveReceiveTimeOut - Empfangekeepalivetimeout

updateThroughputParameters

public final void updateThroughputParameters(float throughputControlSendBufferFactor,
                                             long throughputControlInterval,
                                             int minimumThroughput)
Description copied from interface: LowLevelCommunicationInterface
Diese Methode setzt die Parameter für die Durchsatzprüfung. Sie wird von der Protokollschicht DaV-DAF aufgerufen, wenn die Parameter für die Durchsatzprüfung erfolgreich verhandelt wurden.

Specified by:
updateThroughputParameters in interface LowLevelCommunicationInterface
Parameters:
throughputControlSendBufferFactor - Füllungsgrad des Sendepuffers als Faktor zwischen 0 und 1, ab dem die Durchsatzprüfung anfängt zu arbeiten.
throughputControlInterval - Zeit zwischen zwei Durchsatzprüfungen in Millisekunden
minimumThroughput - Minimal zulässiger Verbindungsdurchsatz in Bytes pro Sekunde

connect

public final void connect(String mainAddress,
                          int subAddress)
                   throws ConnectionException
Diese Methode baut eine Kommunikationsverbindung zu den angegebenen Adressen auf. Sie wird von der Protokollschicht DaV-DAF während der Verbindungsinitialisierung aufgerufen.

Nach dem Verbindungsaufbau werden die Referenzen auf den Sende- und den Empfangskanal festgehalten. Diese werden von den Threads benutzt um Daten zu senden oder empfangen.

Specified by:
connect in interface LowLevelCommunicationInterface
Parameters:
mainAddress - Adresse des Kommunikationspartners dieser Verbindung.
subAddress - Subadresse der Adresse.
Throws:
ConnectionException - Falls die Verbindung nicht hergestellt werden kann.

isNotConnected

public final boolean isNotConnected()
Description copied from interface: LowLevelCommunicationInterface
Gibt als Information zurück, ob die Kommunikationsverbindung unterbrochen ist.

Specified by:
isNotConnected in interface LowLevelCommunicationInterface
Returns:
true = Es besteht keine Verbindung; false = sonst

send

public final void send(DataTelegram telegram)
Diese Methode wird von der Protokollschicht DaV-DAF aufgerufen, wenn ein Telegramm gesendet werden soll.

Fügt ein Telegramm in die Sendetabelle ein.

Specified by:
send in interface LowLevelCommunicationInterface
Parameters:
telegram - Das zu versendende Telegramm.

send

public final void send(DataTelegram[] telegrams)
Description copied from interface: LowLevelCommunicationInterface
Fügt mehrere Telegramme in die Sendetabelle ein.

Specified by:
send in interface LowLevelCommunicationInterface
Parameters:
telegrams - Die zu versendenden Telegramme.
See Also:
LowLevelCommunicationInterface.send(de.bsvrz.dav.daf.communication.lowLevel.telegrams.DataTelegram)

disconnect

public final void disconnect(boolean error,
                             String message,
                             DataTelegram terminationTelegram)
Diese Methode wird von der Protokollschicht DaV-DAF aufgerufen, wenn die Kommunikationskanäle geschlossen werden sollen.

Zunächst wird der Empfangsthread geschlossen; dadurch werden keine Daten mehr empfangen. Danach wird der Keep-alive-Thread geschlossen. Daraufhin wird gewartet, bis der Sendethread alle Telegramme aus der Sendetabelle gesendet hat, damit keine Daten verloren gehen. Anschließend wird der Sendethread beendet. Zuletzt werden die Kommunikationskanäle geschlossen.

Specified by:
disconnect in interface LowLevelCommunicationInterface
Parameters:
error - Besagt, ob es sich um eine Terminierung mit Fehler handelt. Falls true werden sämtliche noch zum Versand gepufferten Telegramme verworfen; falls false wird versucht, sämtliche zum Versand gepufferten Telegramme zu versenden.
message - Ursache der Terminierung im Fehlerfall.
terminationTelegram - Das Telegramm, dass als letztes Telegramm vor dem Schließen der Verbindung versendet werden soll oder null, falls kein abschließendes Telegramm versendet werden soll.

handleAbnormalBehaviour

private void handleAbnormalBehaviour(boolean sendTermination,
                                     String message)

getSendBufferState

public String getSendBufferState()
Description copied from interface: LowLevelCommunicationInterface
Liefert einen beschreibenden Text mit dem Zustand des Sendepuffers

Specified by:
getSendBufferState in interface LowLevelCommunicationInterface
Returns:
Zustand des Sendepuffers