Class CriticalDataService

All Implemented Interfaces:
CtxEventListener, ContextHandleAware, HandleAware, Ready, ReadyAndReadyListener, ReadyListener, BoardLinkListener, HardwareListener

public class CriticalDataService extends AbstractService implements BoardLinkListener
Critical data service stores small amounts of critical data in various boards within the system and uses a voting algorithm to decide which set of data is correct. This can be used to store important information such as serial number which would otherwise be lost if the board running KOS was to be replaced.

Critical data is encoded as json and compressed with a CRC32 header for actual storage. This allows arbitrary json data to be stored in critical data while still attempting to minimize the space required. The CRC32 also allows junk data to be detected and flagged as invalid. Individual CriticalDataSource implementations are expected to know the length of critical data and return the correct number of bytes. A typical solution for this is to write the length of the array before writing the array itself.

Critical data is namespaced and is effectively a map with the key being the name of the critical data to operate on. This allows multiple services to share critical data without requiring a global format for all data.

Care should be taken to minimize the size of json data where possible. Critical data is often a very limited resource, sometimes providing as little as 100 bytes of storage depending on the hardware backing the source. All critical data is stored on every source so the upper limit for data is the smallest source capacity.

As critical data is inherently distributed across different hardware, it can take some time for critical data to become available, if it becomes available at all. The criticalDataReady indicator can be used to determine when critical data becomes ready and even get a callback when ready. The CriticalDataListener interface provides additional events such as when critical data is changed or if critical data is unavailable.

Version:
2024-06-24
  • Field Details

  • Constructor Details

    • CriticalDataService

      public CriticalDataService()
  • Method Details

    • onBeanReady

      public boolean onBeanReady()
      Description copied from interface: ReadyAndReadyListener
      Override in subclasses to be notified when all dependencies are ready. Return true to indicate that this bean is also ready. If the bean needs to call setReady() later due to some async processing, return false to prevent setReady() from being called automatically.

      It is recommended to override this method rather than onDependenciesReady() as a majority of the time it requires calling super.onDependneciesReady() or explicitly calling setReady() which defaults to a failure mode.

      Specified by:
      onBeanReady in interface ReadyAndReadyListener
      Returns:
      true if this object is now ready
    • getCriticalDataReady

      public ReadyIndicator getCriticalDataReady()
      Return the ReadyIndicator that can be used to detect if critical data is already ready, or can generate a callback when critical data is ready for use.
    • isCriticalDataReady

      public boolean isCriticalDataReady()
      Return true if the critical data is ready for use. This is simply a wrapper for getCriticalDataReady().isReady() .
      Returns:
      true if critical data is ready for use
    • getCriticalData

      public <T> T getCriticalData(String name, Class<T> clazz) throws CriticalDataException
      Return the named critical data as an instance of the specified class. This will deserialize the named section from json format back to the specified class.
      Parameters:
      name - the name of the data to return
      Returns:
      the named critical data
      Throws:
      CriticalDataException - if critical data not available or can't be parsed
    • setCriticalData

      public void setCriticalData(String name, Object data, Class<?> view) throws CriticalDataException
      Set the new critical data and write back to all the sources.
      Parameters:
      name - the name of the data to set
      data - the new critical data (null will remove the name entirely)
      view - optional view to json conversion
      Throws:
      CriticalDataException - if critical data not available or can't be set
    • removeCriticalData

      public void removeCriticalData(String name)
      Remove the named critical data and write back to the source.
      Parameters:
      name - the name of the data to remove
    • setAllCriticalData

      public void setAllCriticalData(JsonNode json) throws CriticalDataException
      Set all of critical data with the specified json data. This is typically used during testing or manufacturing to set critical data when none already exists. This will replace the current critical data if any exists.
      Parameters:
      json - json representation of all critical data
      Throws:
      CriticalDataException - if critical data can't be set
    • updateAllSourcesIfNeeded

      public void updateAllSourcesIfNeeded()
      Update all the sources with critical data if needed.
    • ready

      public void ready(CriticalDataSource source)
      Called when a CriticalDataSource becomes ready for use. Normally a source will be checked when it is added, but if not ready at that point, this should be called to indicate that it is ready and should be checked again. Even if critical data has been selected, this will force the data to be replicated to the source.
    • addSource

      public void addSource(CriticalDataSource source)
      Add a new source to the service with the default weight for the source. A source can only be added once. Subsequent calls for the same source will be ignored.
      Parameters:
      source - the new source
    • addSource

      public void addSource(CriticalDataSource source, Double weight)
      Add a new source to the service with the specified weight. This will only add the source and set the weight if the source has not already been added.
      Parameters:
      source - the new source
      weight - the weight for the source or null to leave source unchanged
    • removeSource

      public void removeSource(CriticalDataSource source)
      Remove a source from the service. This only needs to be called if the source is not in a BeanContext as it will be automatically removed when the context is destroyed.
      Parameters:
      source - the source to remove
    • addInternalSource

      public CriticalDataSource addInternalSource(double weight)
      Add the local host as a critical data source. This will use the local disk to store critical data for this source. This source can only be added once. Subsequent calls will simply return the same source. If this this call creates the source, the max size will be set to 1kb.
      Parameters:
      weight - the weight of the source (only used on first call)
      Returns:
      the internal source
    • addInternalSource

      public CriticalDataSource addInternalSource(int maxLength, double weight)
      Add the local host as a critical data source. This will use the local disk to store critical data for this source. This source can only be added once. Subsequent calls will simply return the same source.
      Parameters:
      maxLength - the max bytes of critical data this source can store
      weight - the weight of the source (only used on first call)
      Returns:
      the internal source
    • onBoardLink

      public void onBoardLink(Board board)
      Description copied from interface: BoardLinkListener
      Called when a board is linked.
      Specified by:
      onBoardLink in interface BoardLinkListener
      Parameters:
      board - the board that was linked
    • onBoardUnlink

      public void onBoardUnlink(Board board)
      Description copied from interface: BoardLinkListener
      Called when a board is unlinked.
      Specified by:
      onBoardUnlink in interface BoardLinkListener
      Parameters:
      board - the board that was unlinked