Der Kernel

Der Kernel ist die Hauptklasse von devel.one.

Er kann einfach ohne Factory mittels new angelegt werden und erwartet eine Collection von Argumenten, mit denen er u.a. seine ID sowie sein Konfigurationsverzeichnis erhält:

public static void main(final String[] aArgs) throws CException
{
    final CUtilArgs args = new CUtilArgs(aArgs);
    final Collection<IDatapoolRecord> recs = args.getDatapoolRecords();

    mKernel = new CKernel(recs);
}

Das ist schon alles. Der Kernel ist initialisiert und arbeitet.

Intern ist natürlich einiges passiert:

  • Das Konfigurationsverzeichnis wurde den Argumenten entnommen.
  • Die H2-Datenbank wurde dort erzeugt bzw. geöffnet.
  • Die Konfigurationsdatei datapool.xml wurde gelesen, und die Werte in den Datenpool geschrieben.
  • Die anderen mitgegebenen Argumente wurden auch in den Datenpool eingetragen.
  • Die Record-Datenbank - so vorhanden - wurde eingelesen. Sie enthält Beschreibungen von bekannten Nachrichten und Services.
  • Die Namensdatenbank wurde initialisiert. Sie sorgt für vernünftige LOG-Ausgaben, da hier kryptische IDs mit Bezeichnungs-Strings verknüpft werden.
  • Die Haupt-SlotFactory wird initialisiert. Die verschiedenen Slot-Factories für diverse Datentypen werden hier registriert. Slots werden in den Nachrichten verwendet und tragen die Nutzlast.
  • Die MessageLoggerFactory wird initialisiert.
  • die HSM Factory wird initialisiert. Hierarchische State Machines dienen zum Verwalten von zustandsbehafteten Nachrichten-Empfängern.
  • Die Message/Record-Datenbank wird geladen.
  • Die ServiceRegisterFactories werden initialisiert. Die ServiceRegistries der Namespaces halten hier ihre Services vor.
  • Die ListenerRegistry wird initialisiert. Sie verwaltet Observer/Observable-Listen, da beide in einem dynamischen System auch weg brechen können.
  • Die MessageHookRegistry wird initialisiert.
  • Die SignalRegistry wird initialisiert. Signals sind synchrone LowLevel-Benachrichtigungen. Sie werden auch gerne von uns in Single-Thread-Umgebungen verwendet, wie bei den Swing-GUIs.
  • Die Thread-Factory wird initialisiert.
  • Die Namespace-Registry wird erzeugt.
  • Der Timer-Service wird erzeugt.
  • Jetzt wird endlich der erste Namespace “System” erzeugt.
  • Optional wird der Namespace “Test” erzeugt.
  • Die System-Targets werden registriert.
  • Die PlugIns werden geladen.
  • Und fertig.

Mit dem Zugriff auf den Kernel sind Programme in der Lage, Namespaces zu erstellen bzw. zu nutzen. Dazu gehört auch das Anmelden von Targets, die dann am Nachrichtenverkehr teilnehmen können. Auch PlugIns werden mit der Überreichung des Kernels einfach und vollständig eingebunden.

SubSysteme

Der Kernel hat eine Reihe von Methoden, welche die einzelnen Subsysteme zurückgeben:

// Generelle Observer-Verwaltung
IListenerRegistry getListenerRegistry();

// Log-Verwaltung insbesondere zuständig für das Speichern von StartUp-Logs
CLogCatcher getLogCatcher();

// Hooks
IMessageHookRegistry getMessageHookRegistry();

// Messages werden natürlich geloggt
IMessageLoggerFactory getMessageLoggerFactory();

// Die Namens-Datenbank
INameDb getNameDb();

// Der Zugang zu den Namespaces
INamespaceRegistry getNamespaceRegistry();

// Wird auch intern benötigt
IServiceRegistryFactory getServiceRegistryFactory();

// Synchrone Low-Level-Benachrichtigung
ISignalRegistry getSignalRegistry();

// Factory für Slots, Registry für SlotFactories
ISlotFactory getSlotFactory();

// Timer
ITimerManager getTimerManager();

Natürlich sind das nur Subsysteme des Kernels. Alle weitergehenden Systeme sind nur über Services erreichbar.

Info

Es gibt einige formelle Methoden zu den äußeren Eigenschaften des Kernels:

// Die Host-ID der Instanz sowie die Lizenznummer
IHid getHID();

String getName();

String getDescription();

String getVendor();

int getKernelVersion();

Diese Eigenschaften werden über die Konfiguration eingestellt und bei einem Connect auch zu anderen Instanzen übertragen.

Start und Stop

void shutdown();

boolean isShutdown();

// Startzeit des Kernels (in Millisekunden) long getStartTime();

Senden von Messages

Der Kernel transportiert natürlich in erster Linie Nachrichten. Die Sende-Methoden sind redundant ausgeführt, da sie so oft genutzt werden:

void send(CEnvelope aEnvelope,
          CRecord aRecord) throws CException;

void send(CMessage aMsg) throws CException;

void sendNotification(CEnvelope aEnvelope,
                      CRecord aRecord) throws CException;

void sendNotification(CMessage aMsg) throws CException;

void sendRequest(CEnvelope aEnvelope,
                 CRecord aRecord) throws CException;

void sendRequest(CMessage aMsg) throws CException;

void sendBack(CEnvelope aEnvelope,
              CRecord aRecord) throws CException;

void sendBack(CMessage aMsg) throws CException;

Die send()-Methoden sind die Zentral-Methoden zum Versenden der Nachrichten im System. sendNotification() entfernt ein evtl. bestehendes wantAnswer-Bit, sendRequest() hingegen setzt das Bit, siehe bei den Messages.

Die sendBack()-Methoden wiederum werden nur benötigt, wenn man eine zurückgestellte Nachricht nun endlich zurücksenden möchte. Ansonsten schickt ja das System die Nachrichten automatisch zurück, abhängig von wantAnswer-Bit und dem Fehlerstatus; genaueres hier.

Target-Monitore

Um das An- und Abmelden von bestimmten Targets zu monitoren, bieten Kernel und Namespaces Target-Monitore an:

void registerTargetMonitor(ITargetAddress aTargetAddress,
                           ITargetAddress aObserverAddress) throws CException;

void deregisterTargetMonitor(ITargetAddress aTargetAddress,
                             ITargetAddress aObserverAddress) throws CException;

Klienten bekommen dann die Nachrichten

  • CRecordNotifyTargetRegistered.ID beim Anmelden des Targets
  • CRecordNotifyTargetDeregistered.ID beim Abmelden des Targets.

Weitere Methoden

Es gibt noch weitere Methoden:

// Gibt den häufig benötigten SYSTEM-Namespace zurück.
INamespace getSystemNamespace();

// Erweitert die Adresse um die eigene HID
ITargetAddress completeAddress(ITargetAddress aAddress);

// Prüfen, on die Message für einen lokalen Empfänger ist (HID-Vergleich)
boolean isLocal(INamespaceAddress aAddress);