c-Api solClient_flow_sendAck & solClient_msg_BinaryAttachmentPtr

vt100
vt100 Member Posts: 13

Hi , Apologies this is less of a discussion and more of a question.

via the c-api, is it valid to access the pointer obtained in the call to solClient_msg_BinaryAttachmentPtr, after calling solClient_flow_sendAck ( for the msgId for which the binaryAttachmentPtr was called)

i.e will the sendAck invalidate the pointer.

Many Thanks!!

Comments

  • Ragnar
    Ragnar Member, Employee Posts: 65 Solace Employee

    solClient_flow_sendAck() will not invalidate the pointer.

    The pointer obtained with solClient_msg_getBinaryAttachmentPtr() is valid as long as:

    • the opaqueMsg_pt is valid (solClient_msg_free() has not been called)
    • the binary attachment has not been modified by any method call such as solClient_msg_setBinaryAttachment()
  • Aaron
    Aaron Member, Administrator, Moderator, Employee Posts: 636 admin

    Isn't there some method for "taking" the message in CCSMP, where the app needs to tell the API not to nuke the message?

  • Ragnar
    Ragnar Member, Employee Posts: 65 Solace Employee

    Good point Aaron. The pointer returned by solClient_msg_getBinaryAttachmentPtr() is only valid as long as the application 'owns' the message.

    So if you intend to process a received message payload after returning from the receive message callback, which is always a good idea because callbacks should not do heavy work, then you will need to 'take the message' by returning SOLCLIENT_CALLBACK_TAKE_MSG. In this case, when you are done processing the message you need to call solClient_msg_free().

    Alternatively, you can copy the payload out into application buffers for processing, at which point you don't need the message or the pointer returned by solClient_msg_getBinaryAttachmentPtr() any more.

  • vt100
    vt100 Member Posts: 13

    Many Thanks Guys.

    The message callback function indeed copies out the data before returning with SOLCLIENT_CALLBACK_OK.
    i am looking at some random cases of the receiver getting slightly different data sent by the sender in the binaryattachment, and trying to rule out various scenarios

    The sender calls solClient_msg_getBinaryAttachmentPtr(), and then does a blocking solClient_session_sendMsg, and i am pretty sure that the data pointer is valid during the _sendMsg call ( it gets reclaimed afterwords).

    From what i understood from the docs, the data is copied into the api buffers during the solClient_session_sendMsg call ( and that includes what is pointed to by the dataptr used in the solClient_msg_getBinaryAttachmentPtr() .

    From what i can see, the sending process has not received the acks for these sent messages. The sending process has exited before the acks came i assume. The problem has manifested in some tests, so the process exiting before acks coming in is not unexpected

  • vt100
    vt100 Member Posts: 13
    edited June 2021 #6

    Hi Guys, looking at the this page https://docs.solace.com/API-Developer-Online-Ref-Documentation/c/msgbuffer.html, i suspect i know the problem.

    According to the page,

    _
    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
    _

    I think the corruption is happening because the datapointer is being reclaimed before the message is acked.

    Would be great if someone could confirm

    Thanks very much!!

  • Ragnar
    Ragnar Member, Employee Posts: 65 Solace Employee

    That is true if you use solClient_msg_setBinaryAttachPtr() or any of the 'setXXXPtr' methods.

    The docs could use a tune-up here. Trying to achieve zero-copy or one-copy (from user space to socket) for performance reasons on guaranteed messages is a false economy. The nature of the windowed protocol means the bottleneck is waiting for I/O not CPU. The time of a 'memcpy' is negligible on this data path.

    For this reason I strongly recommend you use solClient_msg_setBinaryAttachment() to set the payload. This is a copy-in operation into the Solace Message Buffer and removes the requirement you've quoted, and at the same time removes much unnecessary complexity from your code. I am sure you will find no noticeable performance difference, and if there is a small delta, it's worth it to keep the code simpler and more robust.

    solClient_msg_setBinaryAttachPtr() may make a difference for Direct messaging, which can be much faster. Also for Direct messaging there is no requirement to wait for acknowledgement and the 'ptr' you pass may be immediately released or reused on return from the method call. There is of course no guarantee of delivery so it's not a popular option.

  • vt100
    vt100 Member Posts: 13

    Many Thanks.
    The payload is non trivial ( i.e. ~30kb upwards, 2Mb max). Also there is already code to get rid of the message when the ack arrives.
    So the extra work needed to keep the buffer alive is just incrementing the refcount ( almost all objects are refcounted in the codebase).
    Would you still prefer solClient_msg_setBinaryAttachment ? ( just an opinion).

    solClient_msg_setBinaryAttachPtr() may make a difference for Direct messaging, which can be much faster. --> Could you not have the same problem with direct messaging ? i.e. solClient_session_sendMsg queues the message for transmission to the api, when the api comes around to sending into the socket, the dataptr inside the message is no longer containing valid data.

  • Ragnar
    Ragnar Member, Employee Posts: 65 Solace Employee

    You know your codebase best. If it's already part of your memory management and doesn't add complexity then there is no harm. I just wouldn't go out of my way to add complexity here given that the API will manage the memory for you if you use the copy-in interfaces.

    Guaranteed messages may be queued, up to a windows worth, when there is transport flow control (socket full). The reference to the message is also maintained internally in case it is necessary to retransmit before the ack arrives. Don't worry, this is refcounted with some copy-on-modification characteristics so your application can freely re-use the opaqueMsg_pt on return from send. It's just the 'copy-on-modification' doesn't apply to application pointers and the contents referenced.

    Direct messages are copied directly to transport and so on return from send there are no longer any API references to your application pointer that you set by solClient_msg_setBinaryAttachPtr()