Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


Bulk Data NT


Software Design and How-to Manual
Approved by:Date:Signature:


Bogdan Jeram

ESO

...

|Owner |Bogdan Jeram (bjeram@eso.org)|

Keywords:
Change Record

REVISION

DATE

AUTHOR

SECTION/PAGE AFFECTED

REMARKS

1.0

24-07-2013

B. Jeram

All

Created.
















...


A method to create a new sender flow (BulkDataNTSenderFlow) on the sender stream. As first parameter it takes (receiver) flow name. Optional is possible to provide also sender flow configuration (SenderFlowConfiguration), a sender flow status callback (BulkDataNTSenderFlowStatusCallback), and a flag if the callback should be deleted with the flow.

 BulkDataNTSenderFlow* createFlow(const char *flowName, 

...

A receiver flow is represented with class BulkDataNTReceiverFlow. A new receiver flow object can be created by invoking createFlow method on a receiver stream object (BulkDataNTReceiverStream). At the construction time it is possible to provide a receiver callback object, otherwise the receiver stream class creates one using class given as template parameter. The callback object can be retrieved at any time by invoking:

 BulkDataNTCallback * getCallbackObject()

or template version:

 template<class T> T * getCallback()

Receiver callback – class BulkDataNTCallback

Class BulkDataNTCallback, more precise, its implementation provides the way that the data are received, and the notification of different receiver's event like errors. For the data transmitting the three methods that reflects the bulk data protocol, have to be implemented.

 virtual int cbStart(unsigned char *userParam_p, unsigned int size=0)

which 0which is called when the parameter data arrives to the sender. This method corresponds to sender flow method startSend.
When the data arrives to the receiver side (to the receiver flow) the method:

virtual int cbReceive(unsigned char *frame_p, unsigned int size=0)

is =0is invoked. The method corresponds to the sendData method of the sender flow. For larger data (bigger than 64k) this method is invoked several times.

At the end of transmission it is called:

virtual int cbStop ()

In addition the receiver callback mechanism gives to the user a possibility to get notified about possible errors:

virtual void onError(ACSErr::CompletionImpl &error)

The method is called when an error happens in the flow's callback (cbStart/cbReceive/cbStop). The error is contained in the error completion.


A separate callback method that is invoked in case of the data is lost:

virtual void onDataLost(unsigned long frameCount, unsigned long totalFrames, ACSErr::CompletionImpl &error)

which gives to the user information about at which frame the data lost occurred(frameCount), and what is the total number of the occurrence(totalFrames).


Notification about a new sender connection, or disconnection is done by calling:

virtual void onSenderConnect() virtual void onSenderDisconnect()

In the implementation of the receiver callback class can be useful to get information about the stream/flow and receiver for what can be used methods:

const char * getStreamName() 
const char * getFlowName() 
const char * getReceiverName()

Configuration classes

We could see that when we create a stream or flow we can give also a configuration. For this purpose there have been introduced 4 classes:

...


To actually send the data, the respective methods of the BulkDataNTSenderFlow class for each flow have to be called inside the three methods described above. In particular, the user has to call:

  • getSenderStream("Stream1")>getFlow("FlowA")>startSend(…) in startSend
  • getSenderStream("Stream1")>getFlow("FlowA")>sendData(…) in paceData
  • getSenderStream("Stream1")>getFlow("FlowA")>stopSend(…) in stopSend

BulkDataNTSenderStream {}getSenderStream{*}(const char *name) returns the sender stream for the name (in our example "Stream1") which has to be created in the connect method using information from CDB. If we have more streams in the sender component we have to "loop" over all of them.

...


Primary the configuration in CDB for the bulk data NT was ment to be used for configuring stream/flows that receiver/sender bulk data component is going to create, but configuration can be used/read also directly from C++.
Sender and receiver components reads information about which streams and flows should be created from the configuration data base – CDB. There is also possible to give additional configuration like timeout, for a particular stream/flow. The configuration is given in XML format, where there is an XML element for each stream (SenderStream or ReceiverStream), which can contain one or more flow XML elements (SenderFlow or ReceiverFlow). Stream and flow configuration can be specified using XML attributes in either stream or flow element.
An example of a configuration for two streams: Array1Stream and Array2Stream with 2 flows each: SpectralData, WVR for a sender component: <SenderStream


<SenderStream Name="Array1Stream">

...

 <SenderFlow Name="SpectralData"/>

...

 <SenderFlow Name="WVR"/>
</SenderStream >

...

 <SenderStream Name="Array2Stream">

...

 <SenderFlow Name="SpectralData"/>

...

 <SenderFlow Name="WVR"/>
</SenderStream >


and corresponding configuration for receiver component(s): <ReceiverStream


<ReceiverStream Name="Array1Stream">

...

 <ReceiverFlow Name="SpectralData"/>

...

 <ReceiverFlow Name="WVR"/>
</ReceiverStream >

...

 <ReceiverStream Name="Array2Stream">

...

 <ReceiverFlow Name="SpectralData"/>

...

 <ReceiverFlow Name="WVR"/>
</ReceiverStream >


As we can see we have to give to sender and receiver the same names for stream and flows to be able to establish the communication between them.

...

If the CDB configuration is used in for defineing and configuring streams and flows inside a component the names of the stream and flows are equal to the corresponding names in the CDB. We can say that the stream/flow name and the configuration name are bound together.With the new bulk data it is possible to distinguish between stream/flow name and the configuration name. For this purpose it was added functionality to easy use the CDB configuration also directly from C++ API. In such a way we can for example define a default configuration(s) for streams/flows that can be used in someone's application/component. As described in section 2.2.7 there are defined 4 classes which instance represents configuring for a stream/flow. The configuration can be feed by invoking proper setter method(s), or it can be read from CDB.
The best is to look into an example how to retrieve a (default) configuration = how to use the C++ API: Let's assume that we have in CDB (alma branch) under folder DefaultCorrBDNTCfg in file DefaultCorrBDNTCfg.xml following configuration:


...
<ReceiverStream Name="DefaultCORRStreamCfg">
<ReceiverFlow Name="DefaultCORRSpectralDataFlowCfg"
cbReceiveProcessTimeoutSec="0.02"
>
</ReceiverFlow>
<ReceiverFlow Name="DefaultCORRXYZFlowCfg"/>
</ReceiverStream>
..


and we would like to use this configuration for our stream(s) and flow(s).First we have to obtain/read the (XML) data, in the standard way from the CDB:


CDB::DAL_ptr dal_p = getContainerServices()->getCDB();
ACE_CString CDBpath="alma/";
CDBpath += "DefaultCorrBDNTCfg"; //node name in CDB like
char *xmlNode = dal_

...

p→get_DAO(CDBpath.c_str());


So now we have the configuration XML string from CDB which should be fed to the parser:


BulkDataConfigurationParser parser_m = new BulkDataConfigurationParser( "DefaultCorrBDNTCfg{*}" );
//if you want to have more than one BulkDataConfigurationParser (=more than one cfg node in CDB), should each have unique name / could be component name.
parser_m->parseReceiverConfig(xmlNode); //xmlNode can be also a XML string

Now, we have to obtain proper the configuration from the parser, in this case for ReceiverStream (ReceiverStreamConfiguration) and ReceiverFlow (ReceiverFlowConfiguration), but it is equivalent for the sender side (SenderStreamConfiguration / SenderFlowConfiguration)


 ReceiverStreamConfiguration* rcvStrCfg = parser_m->getReceiverStreamConfiguration("DefaultCORRStreamCfg"); // get Receiver Stream cfg
// now we create receiver stream with the configuration
BulkDataNTReceiverStream<MyCallback> stream = new BulkDataNTReceiverStream<MyCallback>("MyStream", *{}rcvStrCfg{*});

And similar we get the configuration for the ReceiverFlow:

 ReceiverFlowConfiguration {}rcvSpecDataFlowCfg* = parser_m->getReceiverFlowConfiguration("DefaultCORRStreamCfg", "DefaultCORRSpectralDataFlowCfg");
 BulkDataNTReceiverFlow * specDataFlow = stream->createFlow("SpectralDataFlow", {}rcvSpecDataFlowCfg{*});