PubSub+ Messaging API For C  7.31.0.7
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Solace Message Buffers

Solace Message Buffers

Solace Message Buffers provide clients with controlled buffer management. Applications that use Solace Message Buffers must first allocate a message buffer with solClient_msg_alloc(). This returns an opaque pointer to a Solace message buffer that must be released by the application when it is finished with the message. Message buffers are released by calling solClient_msg_free().

Applications are responsible for releasing all message buffers they allocate by solClient_msg_alloc() or solClient_msg_dup(). Message buffers received by callback are owned by the API and must not be released. However the application may also take ownership of these message buffers by returning SOLCLIENT_CALLBACK_TAKE_MSG on return from the receive message callback function. If the application returns SOLCLIENT_CALLBACK_TAKE_MSG, it must call solClient_msg_free() to release the message when it is finished with the message buffer.

Message buffers

The Message Buffer API provides functions to manipulate the common Solace message header fields that are optionally sent in the binary metadata portion of the Solace message. Applications can also use the structured data API to add containers (maps or streams) and their fields to the binary payload or to the User Property map contained within the binary metadata.

This does not prevent applications from ignoring these functions and treating these payloads as an opaque binary field for end-to-end communications.

The Solace common binary header fields that may be set/read by this message buffer API are:

  • ReplyTo - a ReplyTo destination.
  • SenderId - a Sender Identification. This field can be automatically generated when the session property SOLCLIENT_SESSION_PROP_GENERATE_SENDER_ID is enabled. When this property is enabled, and the SenderId is not explicitly set, the session ClientName is used as the SenderId.
    The SenderID is user-defined, carried end-to-end, and can also be matched in a selector, but otherwise is not relevant to the event broker.
  • Application MsgType - a string for an application specific MsgType. The ApplicationMessageType is user-defined, carried end-to-end, and can also be matched in a selector, but otherwise is not relevant to the event broker.
    In JMS applications, this field is carried as the JMSType Message Header Field.
  • Application MessageId - a string for an application-specific Message Identifier. The ApplicationMessageId is user-defined, carried end-to-end, and can also be matched in a selector, but otherwise is not relevant to the event broker.
    In JMS applications, this field is carried as the JMSMessageID Message Header Field.
  • Sequence Number - a 64-bit application Sequence Number, set by Publisher. This field may be automatically generated when the session property SOLCLIENT_SESSION_PROP_GENERATE_SEQUENCE_NUMBER is enabled. When this property is enabled, and the Sequence Number is not explicitly set, a unique and increasing sequence number is generated for each sent message.
    The SequenceNo is user-defined, carried end-to-end, and can also be matched in a selector, but otherwise is not relevant to the event broker.
  • CorrelationId - a string for an application-specific correlation tag. The CorrelationId is user-defined, carried end-to-end, and can also be matched in a selector, but otherwise is not relevant to the event broker. The CorrelationId may be used for peer-to-peer message synchronization.
    In JMS applications, this field is carried as the JMSCorrelationID Message Header Field.
  • Send Timestamp - a 64-bit field set by the Publisher. This field may be automatically generated when the session property SOLCLIENT_SESSION_PROP_GENERATE_SEND_TIMESTAMPS is enabled in the sending API.
  • Receive Timestamp - a read-only field inserted by the receiving API when the session property SOLCLIENT_SESSION_PROP_GENERATE_RCV_TIMESTAMPS is enabled in the receiving API.

Encoding Overhead of Data Types in Streams and Maps

The overhead of a stream or a map structure is 5 bytes, plus the contents of the stream or map. The list below shows the overhead of various data types when added to a stream or map. When adding to a map, the overhead is the overhead of the type to be stored, plus the overhead of the string field name. The overhead of the string field name is the same as the overhead shown below for a string value.

If a stream is added to the binary payload of a message, and the stream contains a solClient_int16_t and a solClient_int64_t, the stream size will be 19 bytes (5 bytes for the stream overhead, 4 bytes for the solClient_int16_t, and 10 bytes for the solClient_int64_t).

If a map is added to the binary payload of a message, and the map contains an entry of type solClient_int16_t with a field name of "FirstFieldName" and an entry of type solClient_int8_t with a field name of "SecondFieldName", the map will be 47 bytes (5 bytes for the map overhead, 17 bytes for the first field name string, 4 bytes for the solClient_int16_t value, 18 bytes for the second field name string, and 3 bytes for the solClient_int8_t value).

Solace Structured Data Maps

Solace structured data maps (solClient_msg_createBinaryAttachmentMap(), solClient_container_createMap(), solClient_msg_createUserPropertyMap()) provide the programmer with a structure whose members can be directly accessed by name. Programmers familiar with a hashMap will find the same concepts in a Solace structured data map. There is one notable exception - Solace structured data maps do not detect duplicate key names on 'add'. If a field is added to the map with a key name that already exist, both fields will be present in the map. Only one field can be retrieved by that key name and it is not defined which field will be retrieved.

Solace maps have been designed for efficient construction and transmission. The maps can be read fastest by iterating over the map using solClient_container_getNextField(). If each field in a map is retrieved by name instead, the read time for the whole map is order independent.

The key name field in Solace maps is case sensitive. For example, adding a field with the name key "field_1" and a field with name key "FIELD_1" will create two distinct fields that can both be retrieved.

Using Solace Message Buffers for Guaranteed messages

Solace messages buffers can be used to hold Guaranteed messages. You can call the accessor solClient_msg_setDeliveryMode() to set one of the following delivery modes:

The default mode of any message is SOLCLIENT_DELIVERY_MODE_DIRECT for the fast reliable delivery (not Guaranteed), known as Direct Delivery.

To provide the best possible latency and throughput, the C API does NOT copy the contents of the message. The message contents are maintained internally, exactly as presented to solClient_session_sendMsg(), until the message is acknowledged by the Solace Messaging Appliance. In the event that a message needs to be recovered by retransmission, the contents are seamlessly redelivered.

This means the application must ensure that the message buffer's contents remain untouched until notified by the session event callback that the message has been acknowledged. When sending a Guaranteed message, the application must not modify any data referenced by the message, until the SOLCLIENT_SESSION_EVENT_ACKNOWLEDGEMENT is received. This is essential for applications that set message buffer parts by pointer (solClient_msg_setBinaryAttachmentPtr, solClient_msg_setUserDataPtr, solClient_msg_setXmlPtr, solClient_msg_setTopicPtr, and solClient_msg_setQueueNamePtr). When the application memory is used to hold message parts it must not be modified before the message is acknowledged. If the C API manages all memory in the message, it may be modified but the application will pay a performance penalty to do so.

The message correlation tag is provided as a convenient location for an application to store stateful information. A pointer to the data with the correlation tag field is returned to the application with the SOLCLIENT_SESSION_EVENT_ACKNOWLEDGEMENT event. A typical application can set the correlation tag pointer to its own memory for later retrieval of the message pointer to free. For example:

struct myData {
solClient_msg_pt msg_p;
} *myData_p;
solClient_msg_alloc(&myData_p->msg_p);
// set up message attachments, etc. here
solClient_msg_setCorrelationTagPtr(msg_p, myData_p, sizeof(*myData_p));
solClient_msg_sendMsg(msg_p);
// ....
// session event callback handler for
// SOLCLIENT_SESSION_EVENT_ACKNOWLEDGEMENT
struct myData *myData_p = (struct myData *) eventInfo_p->info_p;
solClient_msg_free(&myData_p->msg_p);

Of course it is expected that your application will appropriately check the solClient_returnCode_t for each C API call and handle exceptions.