2. Introduction¶
2.1. Google Protocol Buffers for DDS¶
Vortex OpenSplice is capable of using the Google Protocol Buffer (GPB) system for publishing and subscribing GPB messages in a DDS system. This makes it possible to use GPB as an alternative to OMG-IDL for those who prefer to use GPB rather than IDL. With the seamless integration of GPB and DDS technologies there is no need for OMG-IDL knowledge or visibility when working with GPB data models, and no OMG-DDS data-types are needed in the application (no explicit type-mapping between GPB and DDS types is required).
This results in an easy migration of GPB users to DDS(-based data-sharing) with data-centric GPB with support for keys, filters and (future) QoS-annotations (ony a few DDS calls are needed). Also easy migration of DDS applications to GPB(-based data-modeling), only the field accessors change.
This Tutorial will describe how this is done for the language bindings Java5 and ISO-C++ by defining a GPB message layout which is compiled into proper interfaces for the Vortex DDS system.
2.1.1. GPB Installation and usage with DDS¶
Google Protocol Buffers (GPB) can be downloaded from the following locations:
Linux: https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz
Windows: https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.zip
After unpacking follow the install instructions located in install.txt in the unpacked directory. For windows there is a visual studio solution file that will build everything that is needed.
2.1.2. IDL usage in a DDS system¶
In a Data Distributed System (DDS) as a Global DataSpace (GDS) for ubiquitous information-sharing in distributed systems as specified by the Object Management Group (OMG), the data is traditionally captured in the platform- and language-independent OMG-IDL language. The relational model of DDS is supported by the notion of identifying key fields in these data structures where structure/content-awareness by the middleware allows for dynamic querying and filtering of data.
2.1.3. Google Protocol Buffers¶
Google Protocol Buffers (GPB) are a flexible, efficient, automated
mechanism for serializing structured data; think XML, but smaller,
faster, and simpler. One can define how data needs
to be structured once, after which language-specific source code can
be generated to easily write and read this structured data to and
from a variety of data streams using a variety of
languages. The information structure is defined in so-called protocol
buffer message types in .proto
files. Each protocol buffer message is
a small logical record of information, containing a series of name-value
pairs. This approach is quite similar to using IDL for data modeling in
combination with an IDL compiler (as available in OpenSplice and DDS
implementations in general).
Additionally, the GPB data structure can be updated without breaking deployed programs that are compiled against the ‘old’ format, similar to the xTypes concept as defined for DDS.
2.1.3.1. Using a GPB data-model instead of an IDL data-model¶
For an IDL-OMG based application, the IDL file is compiled with the IDL-PP compiler to generate the needed classes.
For Java as an example, Address.idl
will (among others)
be compiled into:
Address.java
AddressTypesSupport.java
AddressDataWriter.java
AddressDataReader.java
…
Using a GPB data-model, it is not necessary to create IDL files. The
protoc_gen_ddsJava
plug-in in OpenSplice will create them from the
given .proto
data-model.
For the GPB .proto
based application, the .proto
file is first
compiled by the Google protoc
compiler. This compiler will call the
protoc_gen_ddsJava
plug-in in OpenSplice with the
.proto
data parsed into a CodeGeneratorRequest
protocol
buffer.
The OpenSplice plug-in will generate an IDL file from this data. Any field member that is marked as key or filterable is explicitly mapped to a member in the IDL type.
The complete serialized .proto
message is stored in the generic
ospl_protobuf_data
attribute as a sequence of bytes (making it
opaque data for DDS). The mapping between data types is
given in the table Mapping of GPB types to DDS types.
As the next step the IDL-PP compiler will generate the previously-named
files from the idl file needed for the DDS domain.
The Google protoc
compiler will generate the classes needed for the
GPB domain.
The dds options for the proto file are given in the
omg/dds/descriptor.proto file listed below.
This proto file shows how the different dds options on the proto
file are interpreted, and gives the unique id 1016
to the dds types.
- Note that the id 1016 has officially been granted to the Vortex product by Google.This ensures these options are always unique and won’t clash with any options used by users.
How mapping is done between the different languages is shown below in the table Mapping of GPB types to DDS types.
2.1.3.2. omg/dds/descriptor.proto¶
syntax = "proto2";
import "google/protobuf/descriptor.proto";
package omg.dds;
option java_package = "org.omg.dds.protobuf";
option java_outer_classname = "DescriptorProtos";
/* These options are required for any .proto message that needs to be available
* in DDS.
*
* - name: An optional scoped name to allow overriding the name of the type in
* DDS. The dot('.') can be used as a scoping separator. In case the name
* starts with a dot, the name will be interpreted as an absolute scope name.
* If not, the name will be considered relative to the scope of the message
* including its 'package'.
*/
message MessageOptions {
optional string name = 1 [default = ""];
}
extend google.protobuf.MessageOptions {
optional omg.dds.MessageOptions type = 1016;
}
/* These options are provided to assign specific behaviour to a member of a
* DDS-enabled .proto message in DDS. These options will only be applied in case
* the omg.dds.MessageOptions.type has been applied to the message in which the
* member is modeled.
*
* - key: Make the member part of the key of the type in DDS. Each unique
* key-value will become a separate instance with its own history in DDS. Only
* 'required' members can be made part of the key and key-definitions cannot
* be modified in future versions of the message. Members that are part of the
* key are automatically filterable as well.
*
* - filterable: Ensure the member is filterable in DDS using a so-called
* ContentFilteredTopic or QueryCondition. Only 'required' members can be made
* filterable and filterable definitions cannot be modified in future versions
* of the message.
*
* - name: Override the name of the member in DDS. This only applies to members
* that are marked as key and/or filterable.
*/
message FieldOptions {
optional bool key = 1 [default = false];
optional bool filterable = 2 [default = false];
optional string name = 3 [default = ""];
}
extend google.protobuf.FieldOptions {
optional omg.dds.FieldOptions member = 1016;
}
2.1.3.3. Mapping of GPB types to DDS types¶
.proto Type |
Notes |
C++ Type |
Java Type |
DDS IDL Type |
---|---|---|---|---|
double |
double |
double |
double |
|
float |
float |
float |
float |
|
int32 |
Uses variable-length encoding. Inefficient for encoding negative numbers; if your field is likely to have negative values, use sint32 instead |
int32 |
int |
long |
int64 |
Uses variable-length encoding. Inefficient for encoding negative numbers; if your field is likely to have negative values, use sint64 instead |
int64 |
long |
long long |
uint32 |
Uses variable-length encoding |
uint32 |
int |
unsigned long |
uint64 |
Uses variable-length encoding |
uint64 |
long |
unsigned long long |
sint32 |
Uses variable-length encoding. Signed int value. These encode negative numbers more efficiently than regular int32s. |
int32 |
int |
long |
sint64 |
Uses variable-length encoding. Signed int value. These encode negative numbers more efficiently than regular int64s. |
int64 |
long |
long long |
fixed32 |
Always four bytes. More efficient than uint32 if values are often greater than 2^28. |
uint32 |
int |
unsigned long |
fixed64 |
Always eight bytes. More efficient than uint64 if values are often greater than 2^56. |
uint64 |
long |
unsigned long long |
sfixed32 |
Always four bytes. |
int32 |
int |
long |
sfixed64 |
Always eight bytes. |
int64 |
long |
long long |
bool |
bool |
boolean |
bool |
|
string |
A string must always contain UTF-8 encoded or 7-bit ASCII text |
string |
String |
string |