Ludovic Pollet replied to the topic 'Fast BLOBs' in the forum. 1 year ago

Hi Denis

We certainly miss that documentation !

The fast-blob protocol is mostly the same than default one, with the following deviations:

  • The client must connect to unix domain socket (only supported under Linux, MacOS lacks some important feature there...).
  • the client has to reply to "pingRequest" messages by "pingReply" (this implements the back-pressure, see below why it's important). The uid attribute from the request must be repeated in the reply:
    <pingRequest uid='2'/>
    <pingReply uid='2'/>
  • on UNIX domain connection, the server can pass the blob content as an anciliary file descriptor (man7.org/linux/man-pages/man7/unix.7.html). The file descriptor can later be mmapped. In that case, the xml message will have the attached property set to true (and no enclen by the way):
    <setBLOBVector device='fakedev1' name='someblob' timestamp='2018-01-01T00:01:00'>
        <oneBLOB name='content' size='32' format='.fits' attached='true'/>
    </setBLOBVector>
Remark 1: It is guaranteed that the file descriptor(s) for attached blob(s) are received by the end of the xml message. The exact position probably depends on the OS.
Remark 2: The server may also decide to not used shared buffer so the client must still support the use existing base64 layout (for example for small blobs)
Remark 3: The transport of buffers as filedescriptor can be very very fast, so your client may receive GB of data without much processing. Without backpressure, memory in the client side may grow uncontrolled (ultimately leading to Out of memory error, possibly system wide invoking the OOM killer). For this reason, it is strongly advised that when a blob arrive, the client stops processing incoming messages (especially replying to pingRequests) until it has finished processing the blob.
Remark 4: To actually free the memory used by a filedescriptor, the client must close the fd, and munmap the memory area.

Some example of low level functions for these tasks can be found in the indi source file integs/test.cpp (integration tests), which is somewhat decoupled from indi so probably easier to read for a start:
  • integs/test.cpp: the unixSocketConnect function - to connect to a local socket by path name
  • integs/ConnectionMock.cpp, method ConnectionMock::read, shows how to read the input channel, collecting received fds at the same time
  • integs/SharedBuffer.cpp, shows how to access memory from a fd. It is in the write direction, while you client will want to read insted. So your client should use PROT_READ only and remove PROT_WRITE)

Tests codes in the integs directory may also be useful as they show the plain text version of the messages for various cases.

Hope this helps!

Read More...