The Kernel

The kernel is the main class of devel.one.

It can simply be created without a new factory and expects a collection of arguments. The main argument is its configuration directory and its NODE ID:

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);
}

That’s all. The kernel is initialized and working.

Internally, of course, something happened:

  • The configuration directory was taken from the arguments.
  • The H2 database was created or opened.
  • The configuration file datapool.xml has been read, and the values written to the data pool.
  • The other given arguments were also entered into the data pool.
  • The record database, if available, has been read. It contains descriptions of known messages and services.
  • The name database was initialized. It ensures reasonable LOG output, since here cryptic IDs are linked with identifier strings.
  • The main SlotFactory is initialized. The different slot factories for various data types are registered here. Slots are used in the messages and bear the payload.
  • The MessageLoggerFactory is initialized.
  • The HSM Factory is initialized. Hierarchical state machines are used to manage conditional message recipients.
  • The message / record database is loaded.
  • The ServiceRegisterFactories are initialized. The ServiceRegistries of the Namespaces hold their services here.
  • The ListenerRegistry is initialized. It manages observer / observable lists, since both can also break away in a dynamic system.
  • The MessageHookRegistry is initialized.
  • The SignalRegistry is initialized. Signal are synchronous low level notifications. They are also used by us in single-threaded environments like the Swing GUIs.
  • The thread factory is initialized.
  • The namespace registry is created.
  • The timer service is generated.
  • Now finally the first namespace “System” is created.
  • Optionally, the namespace “Test” is generated.
  • The system targets are registered.
  • The plug-ins are loaded.
  • And done.

With access to the kernel, programs are able to create or use namespaces. This includes the registration of targets, which can then participate in the message traffic. Plugins are also easily and completely integrated with the presentation of the kernel.

Subsystems

The kernel has a set of methods that return the individual subsystems:

// General observer administration
IListenerRegistry getListenerRegistry();

// Log management is in particular responsible for storing startup logs
CLogCatcher getLogCatcher();

// Hooks
IMessageHookRegistry getMessageHookRegistry();

// Messages are naturally logged
IMessageLoggerFactory getMessageLoggerFactory();

// The name database
INameDb getNameDb();

// Access to the namespaces
INamespaceRegistry getNamespaceRegistry();

// Is also required internally
IServiceRegistryFactory getServiceRegistryFactory();

// Synchronous low-level notification
ISignalRegistry getSignalRegistry();

// Factory for slots, registry for SlotFactories
ISlotFactory getSlotFactory();

// Timer
ITimerManager getTimerManager();

Of course these are only subsystems of the kernel. All other systems can only be accessed via services.

Information

There are some formal methods to the outer properties of the kernel:

// The NODE ID of the instance and the license number
INodeID getNodeID();

String getName();

String getDescription();

String getVendor();

int getKernelVersion();

These properties are set via the configuration and transferred to other instances in the case of a connect.

Start and Stop

void shutdown();

boolean isShutdown();

// Kernel start time (in milliseconds) long getStartTime();

Sending messages

The kernel, of course, primarily transports messages. The sending methods are redundant because they are used so often:

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;

The send() methods are the central methods for sending the messages in the system. sendNotification() removes a wantAnswer bit, sendRequest(), however, sets the bit, see the :ref: Messages<ANSWER>.

The sendBack() methods, on the other hand, are only needed if you want to return a stored message. Otherwise, the system automatically sends the messages back, depending on the wantAnswer bit and the error status; more precisely here.

Target monitors

To monitor logging in and out of certain targets, Kernel and Namespaces provide target monitors:

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

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

Clients then receive the messages

  • CRecordNotifyTargetRegistered.ID when the target is registered
  • CRecordNotifyTargetDeregistered.ID When the target is deleted

Other methods

There are other methods:

// Returns the frequently-used SYSTEM namespace.
INamespace getSystemNamespace();

// Expands the address with your own NODEID
ITargetAddress completeAddress(ITargetAddress aAddress);

// Check if the message Is determined for a local receiver (NODEID comparison)
boolean isLocal(INamespaceAddress aAddress);