RBNB DataTurbine V2.0B2

Simple API (SAPI)

User Manual

November 8, 2001

Copyright Creare Inc.


Table of Contents

Introduction
Purpose
Source and Sink Clients
Channel Structures and Naming
Common Fields and Methods
Constructors
Connections
Channel Lists
Data Types
Source API
Define Channel List
Time Stamps
Specify Channel Data
Send Data
Example Source Code
Sink API
Specify Channel List
Sink Modes
Get Data
Extract Data
Example Sink Code

Introduction

Purpose

This manual provides an overview of the RBNB Simple API (SAPI) for the V2.0 "RMap" based RBNB software. The SAPI is designed to provide maximum capability with minimum complexity. For a rigorous reference document, see the accompanying SAPI Reference Manual, generated directly from the source code with the javadoc utility.

The SAPI is implemented as a set of utility methods on top of the full RBNB Java API. Certain concessions are made to optimize portability, such as avoiding the use of overloaded methods.

Whereas this document most directly applies to the Java SAPI, the C/C++, Active X, Java Bean, and other APIs are directly layered on the Java SAPI.  Thus, except for minor syntax differences, this documentation is generally applicable for these other APIs as well.

Source and Sink Clients

An RBNB application is either a data Source or data Sink client (or both).  A Source sends data to the RBNB Server.  A Sink fetches data from an RBNB Server.  There are separate Source and Sink classes associated with each type of client, but there are many common concepts and methods as well.

Channel Structures and Naming

The underlying RMap data structures are hidden from the SAPI user, but their presence is felt in several ways.

For both Source and Sink clients, data channels are individually identified and "staged" using the AddChannel method prior to being transferred (Fetch or Flush). Behind the scenes, the SAPI incrementally builds up the corresponding RMap data structures.

Multi-tiered hierarchical channel structures can be created, requested, and referenced through a simple directory-like naming convention.  A fully specified channel name consists of three main parts:

Server/Source/Channel
Where:
Server:    serverName assigned at Server startup (command line argument)
Source:    clientName given by Source via OpenRBNBConnection method
Channel:   channelName given by Source via AddChannel method
Data Sources define channels (AddChannel) with the Server and Source parts implied. The channel name part may itself be multi-tiered, such as:
Chan0
Test43/C0
Test43/C1
A/B/C
Data Sinks request channels (AddChannel) using either relative or absolute (full-path) names. For example:
/Server/MySource/Test43/C2    # absolute path
MySource/Test43/C2            # relative path
Absolute paths start with a slash, and include the top level (parent) server all the way down to the channel name(s).  Relative paths do not start with a slash, and begin with the Source name(s) on the local server.

For Sinks, and when requesting a list of available Server channels, wildcards can also be used, as in:

MySource/Test*/...
Note:  As of the current release, the default Server name is "Server".

The following Table summarizes the wildcard syntax available to the AddChannel (Sink-only) and GetChannelList (Sink or Source) methods.
 

Match String Description
"*" All channels at this level (one deep)
"..." All channels this level and down (recursive depth).  Must be last part of multi-tiered name.
more to come
SAPI Channel Naming Wildcard Notation

Note:  As of the current release, wildcards are not very well supported.  The only supported use is the "..." notation used with the GetChannelList method.


Common Fields and Methods

The SAPI Source and Sink Classes are self-contained, i.e. you can develop a Sink application with no reference to the methods of the Source class, and vice versa.  These two classes do have some logically equivalent fields and methods, however, as described in common below.

Constructors

Source (int cacheSize, String archiveMode, int archiveSize)

Sink   (int cacheSize, String archiveMode, int archiveSize)

Both Source and Sink class constructors have a common set of arguments to set the ring buffer sizes and mode.  The cacheSize and archiveSize parameters specify the sizes of the RAM and disk ring buffers (in frames), respectively.  Each call to "Flush" by a Source constitutes one "frame".

The archiveMode parameter has one of the following values:

    "none"   - No archive is to be used (default)
    "load"   - Load the archive that matches this application clientName
    "create" - Create a new archive, delete an existing one if one is present
    "append" - Add to an existing archive, create a new one if necessary

For a Source client, these parameters have an obvious meaning and relate to the size and type of storage to be used for incoming source data.

By default, Sink clients have a single cache frame for storing its current data request.  Note that even for Sinks, data requests are RMaps, and that multiple requests can be stored in sequence.  This advanced sink request-buffer forms the foundation for future optimizations and the development of "Virtual RMaps".

Connections

Both Source and Sink classes have methods to open and close connections between the client application and an RBNB server.

void OpenRBNBConnection(String serverAddress, String clientName, String userName, String password)

To open a connection identify the server (serverAddress), and identify the client (clientName).  The clientName is used for display in applications such as rbnbAdmin, and provides a handle for other applications to administer and access data from this client.

Clients optionally provide a userName and password as part of the connection process.  If these are defaulted to NULL, there will be no user name by which you can be granted access to restricted data.

Note:  As of the current release, userName and password authorization is not implemented.

void CloseRBNBConnection(boolean keepCache, boolean keepArchive)

Upon shutting down a connection, the client application can specify whether or not to maintain data in the cache and/or archive portions of the ring buffer.  Specify keepArchive=false to delete the disk archive associated with this connection.

Channel Lists

To efficiently specify the channels to Fetch or Flush, use the AddChannel method to build up a local channel reference list.

int AddChannel(String channelName)

Each call to AddChannel builds up the list of channels to be either sent or fetched by the Source or Sink, respectively.  AddChannel returns an index that increments with the number of channels added.  For Sources, this index can be used as the reference index for use in the PutChannel method.  For Sinks, it is possible to get less or more channels than you specify (e.g. using wildcards), so you must inquire (with channelName or channelIndex) about which channels have been Fetched.

int ChannelIndex(String channelName)

This utility method provides a means to get the channel index given the channelName.  For Sources, the return value of addChannel is a reliable channel index.  For Sinks, you may need to use this method to determine the reference index of Fetched channels.

String ChannelName(int index)

This utility method provides a means to get the channelName given the channel index. For Sinks, you can use this method to discover which channels were successfully Fetched.

void ClearChannels()

This method clears out the channel list built by the AddChannel method, and frees associated memory.  Use it when you want to build a new channel list from a "clean slate".

String[] GetChannelList(String matchStr)

Both Source and Sink clients can request a list of all data channels known to the connected RBNB server.  This list is returned in the full API as an RMap hierarchy, but in the SAPI it is parsed into a convenient array of Strings.  The matchStr parameter restricts the returned channel list per a wildcard matching scheme.

Note:  The channel list may include channels from Sources other than the local application.  I.e. this list can include more channels than those locally specified via the AddChannel method.

Memory allocation note for C/C++ programmers:
The data buffers returned by ChannelName and GetChannelList are automatically allocated by the API, but are then "owned" and should be released by the client application. A special C/C++ utility function, rbnbFreeChannelList(clist, nchan) is provided for this purpose.

Data Types

Data sent and received from an RBNB Server (PutChannel, ChannelType) can be denoted as a particular primitive data type, per the following table.
 
Data Type Code Description
TYPE_FLOAT32 Single precision (32 bit) floating point number
TYPE_FLOAT64 Double precision (64 bit) floating point number
TYPE_INT8 8-bit integer (byte) 
TYPE_INT16 16-bit integer (short int)
TYPE_INT32 32-bit integer (int)
TYPE_INT64 64-bit integer (long)
TYPE_STRING Variable length String (character array) object
TYPE_UNKNOWN Unknown or unspecified (byte array)
SAPI Data Type Codes

When specifying a primitive Data Type with a word length greater than 8 bits (1 byte), the word order (MSB,LSB) is automatically set to match that of the local native CPU upon which the Source application runs.


Source API

A data Source client has the following tasks, which may be repeated as desired:
  • Define a channel list
  • Set TimeStamp(s)
  • Specify data for channel(s)
  • Flush data to RBNB server
  • Define Channel List

    Per the discussion above, a Source channel list is defined by calls to the AddChannel method.  The AddChannel method associates channel names with channel indices, which in turn are used for efficient, potentially repeated references in the PutChannel method.

    Time Stamps

    A Source sets the timestamp for subsequent data transmittal using either a manual or automatic method.

    void SetTime(double start, double duration)

    This method manually sets the timestamp to the specified start time, with an interval of duration.  Note that a duration of zero is legal, and indicates an "instantaneous" point in time for the associated data.

    Each manual timestamp applies to the data specified by one or more subsequent calls to PutChannel, until a time-setting method is called again.  Thus, you can choose to timestamp data point by point, channel by channel, or frame by frame depending on how you interleave your calls to SetTime and PutChannel.

    RBNB timestamps must monotonically increase.  Thus, if you are manually providing timestamps, be sure to always increase the value of the start time with each subsequent call to SetTime.

    void AutoTimeStamp(String timeMode)

    This method sets the timestamp for subsequent data transmittals using one of the following automatic modes:

        "next"      - increment timestamp by one (1) each time
        "timeofday" - set timestamp to system time-of-day at the point of each transmittal

    Automatic time stamps are updated once upon each data Flush.  Thus, automatic timestamps are always frame by frame.  Use the SetTime method to timestamp data channel by channel or point by point.

    Specify Channel Data

    The PutChannel methods specify the channel data to send at the next call to the Flush method.  These methods reference the channels by the index returned by AddChannel. They provide data either as a generic byte-array or as a particular data type.

    PutChannel may be called multiple times per channel per Flush, building up a many-point-per-channel data frame in a piecemeal manner as may be convenient to the application.  The SAPI has sophisticated "Deep CVT" logic which automatically consolidates and organizes data into efficient RMap structures.  It will always be somewhat more efficient to handle fewer, larger data buffers, however.

    Memory allocation note for C/C++ programmers:
    The data buffers provided by a source to the API are "owned" by the client application.  I.e. the client application is responsible to allocate and free its own data buffers.

    void PutChannel(int chanIndex, byte[] rawData, int typeID)

    The generic PutChannel method sets the data to be sent as a byte-array plus an associated typeID.  The typeID is one of the Data Type Codes.  Use the channel index from the associated AddChannel method, or use the ChannelIndex method.

    Note:  Mixing different Data Types in a single channel is not supported, and may cause difficulties for Sink applications that try to extract mixed-type data.

    void PutChannelAsXXX(int chanIndex, XXX[] data)

    The family of PutChannelAsXXX methods specifies the primitive type of the supplied data array, where XXX corresponds to one of the Data Type Codes.  For example, PutChannelAsFloat32 lets you directly send a floating point data array with no need to first convert it to a byte array. (Overloaded methods are not used to enhance portability of the SAPI).

    NotePutChannelAsString puts a single String object, which is considered to be an indivisible data word.

    Send Data

    Once things are set up, send the data to the server.

    int Flush(boolean blockingIO)

    After staging information with the time setting (e.g. SetTime) and PutChannel methods, specified data channels are sent as a consolidated RMap with the Flush method.

    Each call to Flush involves round-trip network communication, therefore staging larger data frames (with larger buffers and/or multiple calls to PutChannel) prior to flushing them may provide a significant performance advantage. Of course, you need to also consider the associated impact on memory use and latency when deciding how often to Flush your data.

    If the blockingIO parameter is true, it will block until the data is sent.  If there is no data to send, calling Flush(true) will synchronize your application with the server.   It returns the number of channels sent.

    Note: Only channels with new data (via PutChannel) since the previous call to Flush are actually sent, not necessarily the entire Channel List.

    Example Source Code

    The following code opens a connection to a local RBNB server and sends a message string to it.
     

       Source mySource = new Source();
       mySource.OpenRBNBConnection("localhost", "mySource");
       int index = mySource.AddChannel("myChan");
       mySource.AutoTimeStamp("timeofday");
       mySource.PutChannelAsString(index, "Hello World!");
       mySource.Flush(true);
    Example Source Code Snippet


    Sink API

    A data Sink client has the following tasks, repeated as desired:
  • Specify a channel list to request
  • Select a sink mode
  • Fetch data from RBNB server
  • Extract data and time from API buffer(s)
  • Specify Channel List

    Per the discussion above, the Sink channel list is defined by calls to the AddChannel method.

    Sink Modes

    There are three types of sink data fetch modes: Each sink fetch mode applies to the group of channels specified by the current Channel List.  The channel list must be specified prior to setting the Sink Mode, as these methods initiate the transfer of data from the server.

    void Subscribe()

    This is the simplest data fetch mode.  It takes no arguments and returns no value.  It initiates a streaming "push" of data (from server to client) for all specified channels starting at the time of this call, and proceeding into the future.  A single call to Subscribe can be followed by repeated calls to Fetch, where the next frame of data is received.  Note that the frame size is determined by the source application(s).

    Subscribe is the most efficient mode in that data frames are streamed from the server without waiting for acknowledgment from the sink client.  If the client does not keep up, the data delivered will fall further and further behind until it falls off the beginning (oldest) data in the source ring buffer, at which point the stream aborts.

    void Monitor(int gapControl)

    This provides a variation on the subscribe mode.  It initiates a stream of "current" data that will skip-forward as necessary to stay up to date.  Full source frames are returned each Fetch. The gapControl argument specifies how many frames behind it can get before it will jump ahead (and miss data) in order to stay current.

    When Monitor mode keeps up, it is much like Subscribe, except that there is more round-trip traffic between the client and server for Monitor mode (to establish the gapControl criterion).  Unlike Subscribe mode, the stream will not abort if the client doesn't keep up; but data can be dropped with resulting gaps.

    void Request(double start, double duration, String timeRef)

    The basic Request mode asks for a time-slice of data beginning at start and running for a duration amount thereafter.  The timeRef argument specifies the time-reference for start to be absolute, oldest, or newest.

    When dealing with a timeRef of newest, there are some special notes:

    void Request(double start, double duration, String timeRef, int fetchRepeat, double fetchInterval, boolean fetchByFrame)

    The optional form of Request includes additional fetch parameters.  You can specify the Request to be automatically repeated fetchRepeat times, with the timestamp start advanced by fetchInterval amount each request.

    Normally (with the default fetchByFrame=false ), a single Request results in a single consolidated Fetch response.  Set fetchByFrame=true to cause the data returned by Fetch to be on a source frame-by-frame basis.  This means the size of the data per Fetch matches the frame-size set by the respective Source.  Thus, a single Request can require multiple calls to Fetch.  Requesting data by frame may be more efficient or convenient, for example with indivisible video frames.

    Get Data

    After building the Channel List and setting the Sink Mode (in that order), get the RBNB data using the Fetch method.

    int Fetch(boolean blockingIO)

    This method reads the data from the RBNB server for all channels in the current local Channel List (built by AddChannel).  It returns the number of channels retrieved.

    If the blockingIO parameter is true, it will block until the data is retrieved.  Otherwise, it will either return a positive integer indicating data was ready and has been read, or a zero (0) indicating no data was yet available.

    Extract Data

    Fetched data is stored in buffers that are accessed via the Extract methods.

    The ChannelData and ChannelTime methods return the data associated with the given channel.  Channels are denoted by chanIndex, which always runs from 0 to (N-1), where N is the return value of Fetch.  The channel name can be determined from the channel index via the channelName method.  Or, knowing the name, the chanIndex can be derived from the channel name via the ChannelIndex method.
     

    Memory allocation note for C/C++ programmers:
    The data buffers for the fetched data are automatically allocated by the API, but are then "owned" by the client application.  I.e. the client application is responsible to free the extracted data and time buffers, using the standard system free() function.

    byte[] ChannelData(int chanIndex)

    This generic extract data method gets data as a byte-array.

    XXX[] ChannelDataAsXXX(int chanIndex)

    The family of ChannelAsXXX methods specifies the primitive data type of the returned data array, where XXX corresponds to one of the Data Type Codes.  For example, ChannelDataAsFloat32 lets you retrieve a floating point data array with no need to convert it from a byte array.  If the fetched data does not match the type, an exception will be thrown.  You can check the type using the ChannelType method.

    NoteChannelDataAsString gets an array of String objects, where each String is considered to be an indivisible, individually time-stamped, variable-length data word.

    double[] ChannelTimes(chanIndex)

    This method returns an array of double precision RBNB time values for the specified channel index. There will be one time point per data point.

    If necessary, the point times will be linearly interpolated from the underlying start time and duration of the corresponding data array.  See SetTime.

    int ChannelType(int chanIndex)

    This method returns a Data Type Code for the primitive data type of the fetched data for a given channel.  It can be used to determine which of the ChannelDataAsXXX methods to call.

    Example Sink Code

    The following code snippet will fetch the message sent to the local RBNB Server by the Example Source Code.
     

       Sink mySink = new Sink();
       mySink.OpenRBNBConnection("localhost", "mySink");
       mySink.AddChannel("mySource/myChan");
       mySink.Request(0., 1., "oldest");
       mySink.Fetch(true);
       System.out.println( mySink.ChannelName(0) ": " + mySink.ChannelDataAsString(0)[0] );
    Example Sink Code Snippet