KOS Release 1.10

Improvement

onConfigSet()/onConfigChanged() called after Ready objects become ready

If a ConfigAware object also implements Ready, onConfigSet() will be deferred until the object becomes ready. By default, onConfigSet() simply calls onConfigChanged() so in most cases this means that the first call to onConfigChanged() will occur after the object is ready. This eliminates the need to put ready checks in onConfigChanged() to avoid race conditions during startup.

Note: If you override onConfigSet(), it will still be called before the object is ready.

New feature

New annotations to control callback policy for objects that implement Ready

The new ListenerPolicy and ListenerPolicies annotations can be used to configure when a listener that implements Ready receives callbacks. By default, a listener will receive a callback when the associated event occurs. For listeners that implement Ready, this can result in a race condition where callbacks are delivered before the object is in a ready state. These new annotations allow the listener to change how callbacks are processed during this window.

The new ListenerPolicy annotation allows a policy to be defined for either a single listener interface or all listener interfaces implemented by object. The available policies are:

  • CALLBACK: Perform the callback even if the object is not ready. This matches behavior without any policy applied.
  • NO_CALLBACK: Do not perform the callback to the listener. Useful for instances where callbacks don't contain state that needs to be tracked.
  • WHEN_READY: Deliver the callback after the listener becomes ready. This results in a time-shifted callback and listeners should be prepared for this. All deferred callbacks will be delivered in the order in which they were queued. However, once becoming ready, it is possible to receive a new callback on a separate thread before the queued callbacks complete.

This annotation provides the ability to bind the policy to a particular interface name, providing the ability to configure different listener interfaces on the same object with different policies. The ListenerPolicies annotation is simply a list of ListenerPolicy annotations, allowing multiple policies to be applied to a single object.

Deprecated

Deprecated ListenerList api

ListenerList contains multiple fireEvent() methods. The fireEvent(ListenerCaller caller ) version has been deprecated as it does not contain class information about the caller which is required to evaluate listener policies. Using this method prevents listeners of your services from leveraging callback policies.
New feature

Side loading manifest content from local filesystem

In support of running test/diagnostic applications on a production-ready device, there is now support for side-loading from the local disk. This allows users to copy kabs to the local filesystem and have them added to the manifest on next boot, effectively providing a way to replace content, add applications or even disable parts of the existing manifest. This is a restricted feature. It is only available for use while running in test mode and it requires a digitally signed grant from the KOS team to enable this feature. Please contact the KOS development team for more information.
New feature

Easy access to TroubleService

TroubleService is now accessible via the KosMain static accessor. This eliminates the need to inject TroubleService into hard to reach places where autowiring is not avaialble.
New feature

Device type can now be set at runtime

While previously the device type of a device was defined as the node type of the primary node, it is now possible to set the device type dynamically at runtime. This allows more flexibility in application design, such as a single application that represents multiple device types in the field. In addition to the default primary node type method, there are now two alternate ways to specify an alternate device type:
  • Native code can determine the device type on the primary node and write the device type to /run/kos/deviceType. If set before java starts on the primary node, this will be used as the device type of the entire device.
  • The system application on the primary node can use DeviceServer (the implementation of DeviceService on the primary node) to call setDeviceType(). The device type can only be set up until the system application reaches post-started state. This ensures that the device type is stable before any other nodes in the device boot, ensuring a consistent view of the device type across the entire device.
New feature

Compatibility checks between applications

As a collaborative application based platform, it is a common pattern for devices to be made up of many applications that rely on each other. The most common pattern of integrating applications is via an appliation SDK. However, issues can arise when one application uses an outdated SDK to access another application. As KOS 1.9 introduced SDK meta data embedding at compile time, KOS now uses this information to compare compatibility between applications at startup. When mismatches are found, KOS will log these gaps for easy visibility. This can also be used to check applications against KOS core and any installed extensions. However, to enable these checks, users must include the api-info maven dependncy from the KOS bom:
<dependency>
       <groupId>com.kosdev.kos.sdk.api&t;/groupId>
       <artifactId>api-info</artifactId>
    </dependency>
If this dependency is not included for an application, a warning will be included in the log when the application is loaded.
Deprecated

Improved ConfigService logging

KOS relies heavily on the configuration system and all configuration changes are automatically logged for traceability. However, while configuration changes are visible, it is not easy to determine where the configuration change originated. In order to improve log data, ConfigService has introduced a source argument to all calls. The source is simply a string that represents the source of the change request. ConfigService remains backwards compatible as every method was duplicated to include a version with the source argument. The non-source versions are now marked deprecated to encourage adoption of the newer api's with better logging.
New feature

Spawn service rewrite

SpawnService was originally designed to dynamically spawn long running native applications such as device adapters. These adapters are typically spawned in response to hardware detection events and the adapters need to remain runningas long as the hardware is avaialble. SpawnService monitors processes and will automatically restart them if they exit unexpectedly, including support for respawn throttling and lifecycle monitoring. In multi-node environments, SpawnService can even spawn and monitor on different nodes across the network. However, SpawnService has been limited to daemon processes and cannot practically be used for running ad-hoc processes to completion. While developers can use java's ProcessBuilder to run ad-hoc processes, they cannot run as root and ProcessBuilder cannot be used to run processes on other nodes.

In order to address these limitations, SpawnService was significantly rewritten. It now formally introduces the concept of daemon and ad-hoc processes. While daemon procesess function materially the same, it is now possible to identify exit status of daemons, including access to signal numbers for abnormal exits. Ad-hoc processes share many features found in java's ProcessBuilder, including the ability to redirect output to a log file, or stream I/O to and from the process. These features also work when spawing processes on remote nodes.

Improvement

Improved toString() and logging for troubles

Troubles are a core feature of KOS and are used to identify abonormal conditions and state changes. However, troubles have relied on toString() implementation that was both space inefficient and difficult to read. This has been changed to leverage ToStringBuilder for use in building strings. The proper method of implementing toString() in a Trouble is to override toStringBuilder(), call super.toStringBuilder() to fetch the builder from the base class, append any additional values, and return the builder. Do not override toString().
New feature

Callback monitoring and logging

KOS is designed for devices which tends to generate asynchronous events which are propagated via callbacks to listeners. Listeners effectively represent unknown code to the caller and this introduces two major risks:
  • A listener throws an exception which requires every callback to perform defensive exception handling. When using ListenerList this is built in, but callbacks performed any other way require protection.
  • A listener may run for much longer than expected. This can introduce significant latency throughout the overall system, including stalling data pump threads.
In order to better protect and identify these cases, KOS now includes TimedCallback.call() which is series of static methods designed to perform callbacks. These methods automatically handle exceptions with logging and also time every callback, logging any listeners that take longer than the configured timeout.
New feature

Boards can now receive assembly lifecycle events

For Board classes that need to perform setup or tear down on Assembly install or uninstall events, they can simply implement the AssemblyInstallAware interface to receive callbacks.
New feature

Reverse linked chained manifests make dynamic manifest injection easier

KOS is designed around immutability and determinism rooted in a manifest that describes the state of the device. Dynamic content and other changes to a device are accomplished through the use of digitally signed chained manifests. While KOS has supported chained manifests from it's inception, it now introduces reverse linked chained manifests which allow for a hub and spoke automation process to query multiple parties for dynamic additions for a given device. If you're building a device managment system or dynamic content system for KOS, let us know so we can explain how this new feature can simplify content distribution.
New feature

Complete rewrite of UdevService for more powerful hardware integration

UdevService integrates with linux udev and allows KOS applications to discover devices and be notified of device events. The new iplementation now allows for the creation of UdevSubsystemMonitor objects which can perform custom device filtering and generate localized device events. Since every subsystem monitor is independent, applications can now have a private view of the deivce they care about. This is fully supported in a multi-node environment, allows applications on one node to monitor hardware events on another node in real time.