Distributed Embedded Systems Computer Architecture and Operating Systems 2
Content 1. Motivation 2. An Overview of Distributed Software Architecture Approaches 2.1 Pro & Contra Middleware 2.2 Message-Based Architectures 2.3 Service-Based Architectures 2.4 Subscribe-Based Architectures 2.5 Component-Based Architectures 3. Example: MPI 4. Example: Web Services 5. Example: OPC UA 6. Example: DDS 7. Redundancy and Consistency 8. MultiCore Programming and Synchronous Languages
Subscribe-Based Architectures Idea Data-centric approach, i.e. all communication is with data objects. Data objects have a type, a value and further describing attributes (update timing, redundancy, etc). No direct communication between software modules. Components can write and read data values. Furthermore, components may be notified about value changes, e.g. by calling a callback function in the component. Subscribed-based architecture Component Component Component read current value set new value notify about new value set new value Temperature1:Double updatetime = "100ms" velocity:double updatetime = "10ms"
Subscribe-Based Architectures Idea Data is stored in a repository Application can access the data independent of the data s and the application s location Component Component Component set new value read current value set new value Communication System notify about new value velocity:double updatetime = "10ms" Temperature1:Double updatetime = "100ms" Data Repository
Subscribe-Based Architectures QoS Subscribers and publishers can model the required and provided Quality of Service (QoS). Subscribers and publishers can access the same data iff the provided QoS matches the required QoS. Component Component Component Read every 10ms only if alive publish every 100ms latency <50ms velocity:double Temperature1:Double
Subscribe-Based Architectures QoS Typical QoS are: 1. Deadline: data is provided or required at least every x time steps 2. Latency: maximum permitted delay between sending and receiving new data 3. Filter: subscriber wants a maximum of one new value every x time steps 4. Lifespan: required/provided data must be valid for at least x time steps 5. History: the history for required/provided data must be available for at least x time steps 6. Reliability: e.g. required/provided data must be produced or transmitted redundantly 7. Ownership: required/provided data is provided by a maximum of n publishers Component Component Component Read every 10ms only if alive publish every 100ms latency <50ms velocity:double Temperature1:Double
Subscribe-Based Architectures Subscriber Subscribers can use two different pattern to access data: 1. Callback method: Whenever new data is available, the repository calls the subscriber 2. Wait method: The subscriber waits (i.e. it is blocked) until new data is available. In this case, the subscriber has sleep until a set of predefined conditions are fulfilled. Typical conditions are: new data exists data crosses a threshold data ceases to exist time out...
Subscribe-Based Architectures Transactions Often several data elements have to change their value consistently. I.e. a group of several values changes have to be treated atomically. Subscribers receive all data at the same time or not at all
Introduction The Data Distribution Service (DDS) is defined by the The Object Management Group (OMG) Standardization of different Publish/Subscribe solution (CosEvent, CosNotification, JMS,...) Standard since 2002 DDS comprises two layer: Lower Layer: Efficient access to data Higher Layer: Easy integration into application, i.e. data
Idea General concept from: http://www.omg.org/spec/dds/1.2/
DCPS Structure DCPS conceptual model from: http://www.omg.org/spec/dds/1.2/
Example 1: Publisher Create the participant DomainParticipant participant = DomainParticipantFactory.get_instance().create_participant( 0, // Domain ID = 0 DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); if (participant == null) { System.err.println("Unable to create domain participant"); return; Source: RTI DDS Examples
Example 1: Publisher Create the topic, i.e. the published variable // Create the topic "Hello World" for the String type Topic topic = participant.create_topic( "Hello, World", This is the unique identifier for the topic StringTypeSupport.get_type_name(), DomainParticipant.TOPIC_QOS_DEFAULT, Quality of Service null, // listener StatusKind.STATUS_MASK_NONE); if (topic == null) { System.err.println("Unable to create topic."); return; Source: RTI DDS Examples
DCPS Structure Publisher-DataWriter relation from: http://www.omg.org/spec/dds/1.2/
Example 1: Publisher Create the writer, i.e. the method that can be used to write to the variable // Create the data writer using the default publisher StringDataWriter datawriter = (StringDataWriter) participant.create_datawriter( topic, Publisher.DATAWRITER_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); if (datawriter == null) { System.err.println("Unable to create data writer\n"); return; Source: RTI DDS Examples
Example 1: Publisher Write a new variable value try { datawriter.write( This is a new variable value, InstanceHandle_t.HANDLE_NIL); catch (RETCODE_ERROR e) { // This exception can be thrown from DDS write operation e.printstacktrace(); Source: RTI DDS Examples
DCPS Structure Topic-Key concept from: http://www.omg.org/spec/dds/1.2/
DCPS Structure Platform Independent Model (PIM) of DCPS from: http://www.omg.org/spec/dds/1.2/
DCPS Structure Infrastructure Module from: http://www.omg.org/spec/dds/1.2/
DCPS Structure Domain Module from: http://www.omg.org/spec/dds/1.2/
DCPS Structure Topic-Definition Module from: http://www.omg.org/spec/dds/1.2/
DCPS Structure Topic-Definition Module How are types transmitted if different platforms and different programming languages are involved? from: http://www.omg.org/spec/dds/1.2/
Example 1: Subscriber Create the the subscriber calls and the participant public class HelloSubscriber extends DataReaderAdapter {.. Must extend the DataReaderAdapter since HelloSubscriber is also used as a callback object DomainParticipant participant = DomainParticipantFactory.get_instance().create_participant( 0, // Domain ID = 0 DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); if (participant == null) { System.err.println("Unable to create domain participant"); return; Source: RTI DDS Examples
Example 1: Subscriber Create the topic, i.e. the wanted variable // Create the topic "Hello World" for the String type Topic topic = participant.create_topic( "Hello, World", This is the unique identifier for the topic StringTypeSupport.get_type_name(), DomainParticipant.TOPIC_QOS_DEFAULT, Quality of Service null, // listener StatusKind.STATUS_MASK_NONE); if (topic == null) { System.err.println("Unable to create topic."); return; Source: RTI DDS Examples
Example 1: Subscriber Create the reader which reads the variable // Create the data reader using the default publisher StringDataReader datareader = (StringDataReader) participant.create_datareader( topic, Subscriber.DATAREADER_QOS_DEFAULT, new HelloSubscriber(), // Listener StatusKind.DATA_AVAILABLE_STATUS); if (datareader == null) { System.err.println("Unable to create DDS Data Reader"); return; The on_data_availabe method of this object is called as a callback function Source: RTI DDS Examples
Example 1: Subscriber This callback function is called when new data arrives public void on_data_available(datareader reader) { StringDataReader stringreader = (StringDataReader) reader; SampleInfo info = new SampleInfo(); for (;;) { try { String sample = stringreader.take_next_sample(info); get new value if (info.valid_data) { System.out.println(sample); catch (RETCODE_NO_DATA nodata) { // No more data to read break; catch (RETCODE_ERROR e) { // An error occurred e.printstacktrace(); Source: RTI DDS Examples
Example 1 The publisher program: The subscriber program: Source: RTI DDS Examples
Types 3 solutions exists to access data: 1. support for basic types such as int32, double, string, 2. types are accessed via reflection 3. types are generated (from a language-independent description) at compile time via code generation
DCPS Structure DDS specifies that for non basic types special classes are generated at compile time. This allows for a type-safe access to data. Since the types are defined in a programming language independent specification language (IDL, Interface Definition Language), DSS supports different programming languages. No files have to be generated for basic types such as int, float, string,... Java IDL C Abstract Type Definition C# from: http://www.omg.org/spec/dds/1.2/
DCPS Structure The DDS specifies the following classes to be generated for a type foo : from: http://www.omg.org/spec/dds/1.2/
DCPS Structure Publication Module from: http://www.omg.org/spec/dds/1.2/
DCPS Structure Publication Module and transactions: A publisher may start a transaction by calling publisher.begin_coherent_changes() A publisher may end a transaction by calling publisher.end_coherent_changes() Within a transaction several changes might occur, these changes are treated atomically, i.e. they become visible to subscribers at the same time (or not at all). Several calls to publisher.begin_coherent_changes() and publisher.end_coherent_changes() might occur nestedly. The transaction end with the last call to publisher.end_coherent_changes(). from: http://www.omg.org/spec/dds/1.2/
DCPS Structure Subscription Module from: http://www.omg.org/spec/dds/1.2/
DCPS Structure Supported QoS from: http://www.omg.org/spec/dds/1.2/
QoS Example // Get the default QoS for the Topic participant.get_default_topic_qos(data_topic_qos); // We need exclusive ownership of this Topic so... data_topic_qos.ownership.kind = OwnershipQosPolicyKind.EXCLUSIVE_OWNERSHIP_QOS; // And create a Topic with Default QoS and default listener. // Note: Ownership is Shared by default. data_topic = participant.create_topic("throughput", ThroughputTypeSupport.get_type_name(), data_topic_qos, null, StatusKind.STATUS_MASK_NONE);
DCPS Structure Wait conditions: from: http://www.omg.org/spec/dds/1.2/
Publishing interaction (part 1): DCPS Structure from: http://www.omg.org/spec/dds/1.2/
Publishing interaction (part 2): DCPS Structure from: http://www.omg.org/spec/dds/1.2/
Subscription interaction (via listeners, possibility 1): DCPS Structure from: http://www.omg.org/spec/dds/1.2/
Subscription interaction (via listeners, possibility 2): DCPS Structure from: http://www.omg.org/spec/dds/1.2/
Subscription interaction (via wait-conditions, part 1): DCPS Structure from: http://www.omg.org/spec/dds/1.2/
Subscription interaction (via wait-conditions, part 2): DCPS Structure from: http://www.omg.org/spec/dds/1.2/
Transactions Publication Module reminder Start transaction End transaction from: http://www.omg.org/spec/dds/1.2/
Example 2 Publishing complex, user-defined data types Usage of code generation at compile-time Source: RTI DDS Examples
Example 2 Publisher Sends n packets to publisher Source: RTI DDS Examples
Example 2 Subscriber Computes statistic about received packets Source: RTI DDS Examples
Example 2 File Structure manually implemented manually implemented manually implemented generated files
Example 2 File HelloWorld.idl /* The following constants will be available in the generated code as macros. * If you use #define in an IDL file, the value will be substituite by a * preprocessor before generating the code (this constant won't be available * in your program). */ const long HELLODDS_MAX_PAYLOAD_SIZE = 8192; const long HELLODDS_MAX_STRING_SIZE = 64; /* This custom structure contains an opaque buffer (blob) of maximum size * 8Kb, an unsigned long and a simple string (max size=64 characters) */ struct HelloWorld { string<hellodds_max_string_size> prefix; long sample_id; sequence<octet, HELLODDS_MAX_PAYLOAD_SIZE> payload; ; Source: RTI DDS Examples
Example 2 File Hello.java: Main program, installs new type and starts publishers & subscribers public class Hello { public static void main(string[] argv) { CommandLineArguments args = new CommandLineArguments(); System.out.println("Hello Example Application"); // Finally start the application startapplication(args); System.out.println("Done."); Source: RTI DDS Examples
Example 2 File Hello.java: Main program, installs new type and starts publishers & subscribers private static void startapplication(final CommandLineArguments arg) { new participant DomainParticipant participant = DomainParticipantFactory.get_instance().create_participant( arg.domainid, DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); HelloWorldTypeSupport.register_type(participant, register type HelloWorldTypeSupport.get_type_name()); create topic Topic topic = participant.create_topic( arg.topicname, HelloWorldTypeSupport.get_type_name(), DomainParticipant.TOPIC_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); generated class definition generated class definition Source: RTI DDS Examples
Example 2 File Hello.java: Main program, installs new type and starts publishers & subscribers HelloPublisher publisher = new HelloPublisher( participant, topic, arg.verbose, arg.datasize, arg.samplecount); create publisher publisher.writesamples(); write samples HelloSubscriber subscriber = new HelloSubscriber( participant, topic, arg.verbose, arg.samplecount); create subsriber subscriber.waitfortermination(); wait until all samples have been received /* Shutdown, when samplecount is finite */ if(participant!= null) { participant.delete_contained_entities(); DomainParticipantFactory.TheParticipantFactory. delete_participant(participant); clean up DomainParticipantFactory.finalize_instance(); Source: RTI DDS Examples
File HelloPublisher.java Example 2 public class HelloPublisher { // Maximum consecutive write error after stopping the write process private static final int MAX_CONSECUTIVE_WRITE_ERROR = 5; private HelloWorldDataWriter _thedatawriter; private int _thedatasize; private int _theverbose; private int _thesamplecount = 0; Reference to generated class // ************************************************************************ /** * Builds a new HelloPublisher object and initialize the inner DDS * entities. * This method only creates the entities, but it does not actually write * the data. * To write the data, use the method run(). * * @param participant the DDS Domain participant * @param topic the DDS topic * @param verbose an integer to control the output verbosity * @param datasize the size of the payload data */ public HelloPublisher(DomainParticipant participant, Topic topic, int verbose, int datasize, int samplecount) { _thedatasize = datasize; _theverbose = verbose; _thesamplecount = samplecount; Source: RTI DDS Examples
File HelloPublisher.java Example 2 just like before... Publisher publisher = participant.create_publisher( DomainParticipant.PUBLISHER_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); if (publisher == null) { System.err.println("! Unable to create DDS Publisher"); throw new RuntimeException("HelloPublisher creation failed"); _thedatawriter = (HelloWorldDataWriter) publisher.create_datawriter(topic, Publisher.DATAWRITER_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); reference to generated class Source: RTI DDS Examples
File HelloPublisher.java Example 2 void writesamples() { HelloWorld instance = new HelloWorld(); // Initialize the data instance.prefix = "Hello world"; instance.payload.setsize(_thedatasize); byte arr[] = (byte [])instance.payload.getprimitivearray(); for (int i = 0; i < _thedatasize; ++i) { arr[i] = (byte)(i % 0xff); Source: RTI DDS Examples System.out.println("Sending data...\n"); int consecutiveerrors = 0; for (instance.sample_id = 0;; ++(instance.sample_id) ) { try { _thedatawriter.write(instance, InstanceHandle_t.HANDLE_NIL); catch(retcode_error e) { System.err.println("! Write error " + e.getclass().tostring() + ": " + e.getmessage()); if (++consecutiveerrors > MAX_CONSECUTIVE_WRITE_ERROR) { System.out.println("! Reached maximum number of failure, " + "stopping writer..."); return; // Always clear the error count in case of successful write consecutiveerrors = 0; if (_theverbose > 0 && (instance.sample_id % 10000) == 0) { System.out.println("Sent " + Integer.toString(instance.sample_id) + " samples..."); if (_thesamplecount!= 0 && (instance.sample_id >= _thesamplecount)) { System.out.println("\nSent " + Integer.toString(instance.sample_id) + " samples."); return;
File HelloSubscriber.java public class HelloSubscriber implements DataReaderListener { public HelloSubscriber(DomainParticipant participant, Topic topic, int verbose, int samplecount) { for the callbacks... Example 2 Subscriber subscriber = participant.create_subscriber( DomainParticipant.SUBSCRIBER_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); generated class definition _reader = (HelloWorldDataReader) subscriber.create_datareader( topic, Subscriber.DATAREADER_QOS_DEFAULT, this, StatusKind.STATUS_MASK_ALL); Source: RTI DDS Examples
File HelloSubscriber.java public void waitfortermination() { waits for end of transmission Example 2 for (;;) { try { Thread.sleep(POLL_PERIOD_MILLISEC); // If this is the first sample received, mark the sample ID and // get the time /* Then calculate the statistics */ catch (InterruptedException e) { /*ignore*/ Source: RTI DDS Examples
File HelloSubscriber.java Example 2 public void on_data_available(datareader reader) { HelloWorldDataReader HelloWorldReader = (HelloWorldDataReader)reader; if (_thesamplercvdmax!= 0 && (_thesamplercvdcount >= _thesamplercvdmax)) { return; try { HelloWorldReader.take( _dataseq, _infoseq, get data ResourceLimitsQosPolicy.LENGTH_UNLIMITED, SampleStateKind.ANY_SAMPLE_STATE, ViewStateKind.ANY_VIEW_STATE, InstanceStateKind.ANY_INSTANCE_STATE); for (int i = 0; i < _dataseq.size(); ++i) { SampleInfo info = (SampleInfo)_infoSeq.get(i); the callback function generated class if (info.valid_data) { _processdata((helloworld)_dataseq.get(i)); catch (RETCODE_NO_DATA nodata) { // No data to process finally { HelloWorldReader.return_loan(_dataSeq, _infoseq); Source: RTI DDS Examples
File HelloSubscriber.java public void on_sample_lost(datareader reader, SampleLostStatus status) { ++_thesamplelost; if (_theverbose > 0) { System.out.println("->Callback: sample lost."); public void on_requested_deadline_missed (DataReader reader, RequestedDeadlineMissedStatus status) { if (_theverbose > 0) { System.out.println("->Callback: requested deadline missed."); public void on_requested_incompatible_qos (DataReader reader, RequestedIncompatibleQosStatus status) { if (_theverbose > 0) { System.out.println("->Callback: requested incompatible QoS."); public void on_sample_rejected (DataReader reader, SampleRejectedStatus status) { if (_theverbose > 0) { System.out.println("->Callback: sample rejected."); public void on_liveliness_changed (DataReader reader, LivelinessChangedStatus status) { if (_theverbose > 0) { System.out.println("->Callback: liveliness changed."); Example 2 the callback function for lost samples the callback function for missed deadlines the callback function incompatible QoS the callback function used if the receiver does not want a sample the callback function called if the data turns dead public void on_subscription_matched (DataReader reader, SubscriptionMatchedStatus status) { if (_theverbose > 0) { System.out.println("->Callback: subscription matched."); Source: RTI DDS Examples
File HelloWorld.java (generated) Example 2 public class HelloWorld implements Copyable { public HelloWorld(HelloWorld other) { this(); copy_from(other); public static Object create() { return new HelloWorld(); public boolean equals(object o) { public Object copy_from(object src) { return this; public String tostring(string desc, int indent) {
File HelloWorldTypeSupport.java (generated) Example 2 public class HelloWorldTypeSupport extends TypeSupportImpl { private static final String TYPE_NAME = "HelloWorld"; private static final HelloWorldTypeSupport _singleton = new HelloWorldTypeSupport(); public static String get_type_name() { return _singleton.get_type_namei(); public static void register_type(domainparticipant participant, String type_name) { _singleton.register_typei(participant, type_name); public static void unregister_type(domainparticipant participant, String type_name) { _singleton.unregister_typei(participant, type_name); public static HelloWorldTypeSupport get_instance() { return _singleton; public static HelloWorldTypeSupport getinstance() { return get_instance(); public Object create_data() { return new HelloWorld(); public void destroy_data(object data) { return; public Object create_key() { return new HelloWorld(); public void destroy_key(object key) { return; public Object copy_data(object destination, Object source) { HelloWorld typeddst = (HelloWorld) destination; HelloWorld typedsrc = (HelloWorld) source; return typeddst.copy_from(typedsrc);
File HelloWorldDataWriter.java (generated) Example 2 public class HelloWorldDataWriter extends DataWriterImpl { public InstanceHandle_t register_instance(helloworld instance_data) { return register_instance_untyped(instance_data);. public void unregister_instance(helloworld instance_data, InstanceHandle_t handle) { unregister_instance_untyped(instance_data, handle); public void write(helloworld instance_data, InstanceHandle_t handle) { write_untyped(instance_data, handle); public void dispose(helloworld instance_data, InstanceHandle_t instance_handle){ dispose_untyped(instance_data, instance_handle); public void get_key_value(helloworld key_holder, InstanceHandle_t handle) { get_key_value_untyped(key_holder, handle); public InstanceHandle_t lookup_instance(helloworld key_holder) { return lookup_instance_untyped(key_holder); /*package*/ HelloWorldDataWriter(long native_writer, DataWriterListener listener, int mask, TypeSupportImpl type) { super(native_writer, listener, mask, type);
Example 2 File HelloWorldDataWriter.java (generated) public class HelloWorldDataReader extends DataReaderImpl { public void read(helloworldseq received_data, SampleInfoSeq info_seq, int max_samples, int sample_states, int view_states, int instance_states) { read_untyped(received_data, info_seq, max_samples, sample_states, view_states, instance_states); public void take(helloworldseq received_data, SampleInfoSeq info_seq, int max_samples, int sample_states, int view_states, int instance_states) { take_untyped(received_data, info_seq, max_samples, sample_states, view_states, instance_states); public void read_next_sample(helloworld received_data, SampleInfo sample_info) { read_next_sample_untyped(received_data, sample_info); public void get_key_value(helloworld key_holder, InstanceHandle_t handle){ get_key_value_untyped(key_holder, handle); public InstanceHandle_t lookup_instance(helloworld key_holder) { return lookup_instance_untyped(key_holder); /*package*/ HelloWorldDataReader(long native_reader, DataReaderListener listener, int mask, TypeSupportImpl data_type) { super(native_reader, listener, mask, data_type);
Example 3 Publishing complex, user-defined data types Usage reflection to access complex data Source: RTI DDS Examples
Example 3 Publisher Sends n packets to publisher Source: RTI DDS Examples
Example 3 Subscriber Computes statistic about received packets Source: RTI DDS Examples
File HelloWorldType.java: Dynamically generate type Example 3 public final class HelloWorldType { public static String gettypename() { return "HelloWorld";... public static TypeCode create() { TypeCodeFactory factory = TypeCodeFactory.get_instance(); TypeCode stringtc = null; try { stringtc = factory.create_string_tc(hellodds_max_string_size); TypeCode sequencetc = null; sequencetc = factory.create_sequence_tc(hellodds_max_payload_size, factory.get_primitive_tc(tckind.tk_octet)); TypeCode structtc = null; structtc = factory.create_struct_tc("helloworld", new StructMember[0]); structtc.add_member("prefix", // name (short)-1, // initial_id stringtc, // Typecode TypeCode.NONKEY_MEMBER, // member_flags (short)-1, // access false, // is_pointer (short)-1); // bits structtc.add_member("sampleid", (short)-1, factory.get_primitive_tc(tckind.tk_long), TypeCode.NONKEY_MEMBER, (short)-1, false, (short)-1); structtc.add_member("payload", (short)-1, sequencetc, TypeCode.NONKEY_MEMBER, (short)-1, false, (short)-1); return structtc; new struct member new struct member new type new struct member
Example 3 File Hello.java: Main program, installs new type and starts publishers & subscribers public class Hello { public static void main(string[] argv) { CommandLineArguments args = new CommandLineArguments(); System.out.println("Hello Example Application"); // Finally start the application startapplication(args); System.out.println("Done."); Source: RTI DDS Examples
Example 3 File Hello.java: Main program, installs new type and starts publishers & subscribers private static void startapplication(final CommandLineArguments arg) { new participant DomainParticipant participant = DomainParticipantFactory.get_instance().create_participant( arg.domainid, DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); // Create TypeCode, DynamicDataTypeSupport for dynamic data type TypeCode type = HelloWorldType.create(); if (type == null) { System.err.println("! Unable to create dynamic type code"); return; dynamically generate class definition // Create the Dynamic data type support object DynamicDataTypeSupport typesupport = new DynamicDataTypeSupport( type, DynamicDataTypeSupport.TYPE_PROPERTY_DEFAULT); // Register type before creating topic typesupport.register_type(participant, HelloWorldType.getTypeName()); register type Source: RTI DDS Examples
Example 3 File Hello.java: Main program, installs new type and starts publishers & subscribers create topic Topic topic = participant.create_topic( arg.topicname, HelloWorldTypeSupport.get_type_name(), DomainParticipant.TOPIC_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); Source: RTI DDS Examples
Example 3 File Hello.java: Main program, installs new type and starts publishers & subscribers HelloPublisher publisher = new HelloPublisher( participant, topic, arg.verbose, arg.datasize, arg.samplecount); create publisher publisher.writesamples(); write samples HelloSubscriber subscriber = new HelloSubscriber( participant, topic, arg.verbose, arg.samplecount); create subsriber subscriber.waitfortermination(); wait until all samples have been received /* Shutdown, when samplecount is finite */ if(participant!= null) { participant.delete_contained_entities(); DomainParticipantFactory.TheParticipantFactory. delete_participant(participant); clean up DomainParticipantFactory.finalize_instance(); Source: RTI DDS Examples
File HelloPublisher.java Example 3 public class HelloPublisher { // Maximum consecutive write error after stopping the write process private static final int MAX_CONSECUTIVE_WRITE_ERROR = 5; private DynamicDataWriter private int private int private DynamicData _thedatawriter; _theverbose; _thesamplecount; _theinstance; Reference to dynamic classes // ************************************************************************ /** * Builds a new HelloPublisher object and initialize the inner DDS * entities. * This method only creates the entities, but it does not actually write * the data. * To write the data, use the method run(). * * @param participant the DDS Domain participant * @param topic the DDS topic * @param verbose an integer to control the output verbosity * @param datasize the size of the payload data */ public HelloPublisher(DomainParticipant participant, Topic topic, TypeCode typecode, int verbose, int datasize, int samplecount) { _theverbose = verbose; _thesamplecount = samplecount; Source: RTI DDS Examples
File HelloPublisher.java Example 3 just like before... Publisher publisher = participant.create_publisher( DomainParticipant.PUBLISHER_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); if (publisher == null) { System.err.println("! Unable to create DDS Publisher"); throw new RuntimeException("HelloPublisher creation failed"); _thedatawriter = (DynamicDataWriter) publisher.create_datawriter(topic, Publisher.DATAWRITER_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); reference to dynamic writer Source: RTI DDS Examples
File HelloPublisher.java Example 3 _theinstance = new DynamicData(typeCode, DynamicData.PROPERTY_DEFAULT); /* The DynamicDataType has been defined (in HelloWorldType.cxx) to hold * a structure like the following one: * struct HelloWorld { * string<64> prefix; * long sampleid; * sequence<octet, 8192> payload; * ; */ _theinstance.set_string("prefix", DynamicData.MEMBER_ID_UNSPECIFIED, "Hello World!"); _theinstance.set_int("sampleid", DynamicData.MEMBER_ID_UNSPECIFIED, 0); byte [] payload = new byte[datasize]; for (int i = 0; i < datasize; ++i) { payload[i] = (byte)(i % 0xff); ByteSeq byteseq = new ByteSeq(payload); _theinstance.set_byte_seq("payload", DynamicData.MEMBER_ID_UNSPECIFIED, byteseq); write one field of the data write one field of the data write one field of the data write one field of the data Source: RTI DDS Examples
File HelloPublisher.java Example 3 void writesamples() { InstanceHandle_t instance_handle = InstanceHandle_t.HANDLE_NIL;...... try { _thedatawriter.write(_theinstance, instance_handle); send data catch(retcode_error e) { System.err.println("! Write error " + e.getclass().tostring() + ": " + e.getmessage()); if (++consecutiveerrors > MAX_CONSECUTIVE_WRITE_ERROR) { System.out.println("! Reached maximum number of failure, " + "stopping writer..."); return; Source: RTI DDS Examples
File HelloSubscriber.java public class HelloSubscriber implements DataReaderListener { public HelloSubscriber(DomainParticipant participant, Topic topic, int verbose, int samplecount) { for the callbacks... Example 3 Subscriber subscriber = participant.create_subscriber( DomainParticipant.SUBSCRIBER_QOS_DEFAULT, null, // listener StatusKind.STATUS_MASK_NONE); _reader = (DynamicDataReader) subscriber.create_datareader( topic, Subscriber.DATAREADER_QOS_DEFAULT, this, StatusKind.STATUS_MASK_ALL); dynamic class definition Source: RTI DDS Examples
File HelloSubscriber.java public void waitfortermination() { waits for end of transmission Example 3 for (;;) { try { Thread.sleep(POLL_PERIOD_MILLISEC); // If this is the first sample received, mark the sample ID and // get the time /* Then calculate the statistics */ catch (InterruptedException e) { /*ignore*/ Source: RTI DDS Examples
File HelloSubscriber.java Example 3 public void on_data_available(datareader reader) { DynamicDataReader HelloWorldReader = (DynamicDataReader)reader; if (_thesamplercvdmax!= 0 && (_thesamplercvdcount >= _thesamplercvdmax)) { return; try { HelloWorldReader.take( _dataseq, _infoseq, get data the callback function ResourceLimitsQosPolicy.LENGTH_UNLIMITED, SampleStateKind.ANY_SAMPLE_STATE, ViewStateKind.ANY_VIEW_STATE, InstanceStateKind.ANY_INSTANCE_STATE); dynamic reader for (int i = 0; i < _dataseq.size(); ++i) { SampleInfo info = (SampleInfo)_infoSeq.get(i); access one field of the structure if (info.valid_data) { _processdata((dynamicdata)_dataseq.get(i)); catch (RETCODE_NO_DATA nodata) { // No data to process finally { HelloWorldReader.return_loan(_dataSeq, _infoseq); Source: RTI DDS Examples
File HelloSubscriber.java public void on_sample_lost(datareader reader, SampleLostStatus status) { ++_thesamplelost; if (_theverbose > 0) { System.out.println("->Callback: sample lost."); public void on_requested_deadline_missed (DataReader reader, RequestedDeadlineMissedStatus status) { if (_theverbose > 0) { System.out.println("->Callback: requested deadline missed."); public void on_requested_incompatible_qos (DataReader reader, RequestedIncompatibleQosStatus status) { if (_theverbose > 0) { System.out.println("->Callback: requested incompatible QoS."); public void on_sample_rejected (DataReader reader, SampleRejectedStatus status) { if (_theverbose > 0) { System.out.println("->Callback: sample rejected."); public void on_liveliness_changed (DataReader reader, LivelinessChangedStatus status) { if (_theverbose > 0) { System.out.println("->Callback: liveliness changed."); Example 3 the callback function for lost samples the callback function for missed deadlines the callback function incompatible QoS the callback function used if the receiver does not want a sample the callback function called if the data turns dead public void on_subscription_matched (DataReader reader, SubscriptionMatchedStatus status) { if (_theverbose > 0) { System.out.println("->Callback: subscription matched."); Source: RTI DDS Examples