---
name: "SP_receive"
section: "3"
platform: "linux"
package: "libspread1-dev"
version: "3.17.4-2+b1"
release: "Debian 6.0 (Squeeze)"
platforms: ["linux"]
url: "https://new.carta.tech/SP_receive"
---

# SP\_receive(3)

Receive message from Spread

## NAME

SP\_receive, SP\_scat\_receive - Receive message from Spread

## SYNOPSIS

**#include \<sp.h\>**

**int SP\_receive( mailbox** *mbox***, service \****service\_type***, char** *sender***\[MAX\_GROUP\_NAME\], int** *max\_groups***, int \****num\_groups***, char** *groups***\[\]\[MAX\_GROUP\_NAME\], int16 \****mess\_type***, int \****endian\_mismatch***, int** *max\_mess\_len***, char \****mess***);**

**int SP\_scat\_receive( mailbox** *mbox***, service \****service\_type***, char** *sender***\[MAX\_GROUP\_NAME\], int** *max\_groups***, int \****num\_groups***, char** *groups***\[\]\[MAX\_GROUP\_NAME\], int16 \****mess\_type***, int \****endian\_mismatch***, scatter \****scat\_mess***);**

## DESCRIPTION

**SP\_receive** is the general purpose receive function for the toolkit.  This receives not only data messages but also membership messages for the connection.  Messages for all groups joined on this connection will arrive to the same mailbox so a call to  **SP\_receive** will get a single 'message' from any one of the  groups. After the receive completes a number of fields are set to  values indicating meta information about the message (such as groups, mess\_type, endianness, type, etc).

This function is the most complex used in Spread because it is the  only way for the system to return information to the application. The meaning of many of the fields changes depending on whether the message is a data message or a membership message.

The  **SP\_receive** function will block if no messages are available.

The *mbox* gives which connection to receive a message on. *Service\_type* is a pointer to a variable of type 'service' which will be set  to the message type of the message just received.  This will be either a REG\_MESSAGE or MEMBERSHIP\_MESS, and the specific type. The variable that service\_type points to is also an input parameter and should be set to either 0, for normal semantics,  or DROP\_RECV (a defined constant) if you want to receive the 'non-reliable' semantics that will truncate messages if the provided buffers for message data and group lists are too small. More information about DROP\_RECV semantics are provided later in this man page.

The rest of the parameters differ in meaning depending on the  *service\_type.* If the *service\_type* is a REG\_MESSAGE (i.e. data message) then:

The *sender* is a pointer to an array of characters of at least MAX\_GROUP\_NAME size.   This will be set to the name of the sending connection(its private group name).

The  *max\_groups* is the maximum number of groups you have allocated space for in  the 'groups' array passed to the receive function.

*Num\_groups* is a pointer to an int which will be set to the number of groups  set in the 'groups' array.

The  *groups* array holds upto *max\_groups* group names, each of which is a string of at most MAX\_GROUP\_NAME characters. All of the groups which are receiving this message will be listed here, unless the array is too small and then as many as can fit will be listed and the  *num\_groups* value will be set to be negative. For example, if your groups array could store 5  group names, but a message for 7 groups arrived, the first five group names would appear in the *groups* array and   *num\_groups* would be set to -7.

The  *mess\_type* field will be set to the message type field the application sent with the  original message, this is only a short int (16bits). This value is already endian corrected before the application receives it.

*Endian\_mismatch* will be set to true (1) if the endianness of the sending machine  differs from that of this receiving machine. If the  **BUFFER\_TOO\_SHORT** error is returned then the endian\_mismatch field will be set to the size of  the incoming message as a negative value. So if the message requires 300 bytes of buffer space and only 200 bytes was provided in the  *mess* buffer,  *endian\_mismatch* will be set to -300.

The actual message body being received will be passed into the buffer given by *mess* which is at least  *max\_mess\_len* bytes in size. If the message being received is larger then this buffer the default behaivor will be to return a  **BUFFER\_TOO\_SHORT** error and provide the required length in the  *endian\_mismatch* field. If the DROP\_RECV flag was passed in the  *service\_type* field, then as much data as possible will be returned and the extra data will be discarded by the system and the return value of  **SP\_receive** will indictate an error. If the **SP\_scat\_receive** form is used then instead of the *mess* buffer and length fields, a single  *scat\_mess* scatter structure should be passed to receive filled in with whatever buffers you wish to receive into and their lengths. These buffers must be valid memory areas. They will be filled in by the receive call in the order they are listed.

If this is a MEMB\_MESSAGE (i.e. membership message) and it  specifically is a TRANS\_MESS, then:

The  *sender* char array will be set to the name of the group for which the membership change is occuring.

The  *max\_groups* and  *max\_mess\_len* fields are not used and the *num\_groups* is 0 and  *groups* since there are no normal groups for a transitional membership, the sender field is used instead.  The  *mess\_type* field is set to -1. The *endian\_mismatch* field will be zero since the transitional does not have any endian issues. The *mess* field will be left empty. So in essence the only information you get is the  *sender* field is  set to the group name which received a transitional membership change. The importance of the TRANS\_MEMB\_MESS is that it tells the application that all messages received after it and before the REG\_MEMB\_MESS for the same group are 'clean up' messages to put the messages in a consistant state before actually changing memberships.  For more explanations of this please see other documentation and research papers.

If This is a MEMB\_MESSAGE (i.e. membership message) and it  specifically is a REG\_MEMB\_MESS, then:

The  *sender* char array will be set to the name of the group for which the membership change is occuring.

The  *max\_groups* and *max\_mess\_len* fields have the same meaning as before, and the  *mess\_type* field will be set to the index of this process in the array of group members. The *endian\_mismatch* field will again be set to 0 since there are no endian issues with regular memberships.

The *groups* array and *mess* body are used to provide two kinds of membership information about the change that just occured in this group.  The  *num\_groups* field will be set to the number of members in the group in the  **new** membership (i.e. after the change occured). Correspondingly the  *groups* array will be set to the private group names of all members of this group in the  **new** membership.  This list of names is always in the same order at all receipients and thus can be used to deterministically pick a group representative if one is needed by the application.

The second set of information is stored in the message body and provides a list of all the private group names of those processes which came with your process from the old group membership into this new membership. The data buffer will include the following fields:

- **group\_id;**

  - **int num\_vs\_members;**

  - **char vs\_set\[\]\[MAX\_GROUP\_NAME\];**

  The location of the beginning of each field is provided by the accessor functions **SP\_get\_gid\_offset\_memb\_mess,** **SP\_get\_num\_vs\_offset\_memb\_mess, and** **SP\_get\_vs\_set\_offset\_memb\_mess.** Each accessor function gives the byte offset in the message body of the corresponding field.

The vs\_set array will have num\_vs\_members group names, each of which is a fixed length string.  The content of the vs\_set array is dependent  upon the type of the membership change:

- **CAUSED\_BY\_JOIN:**

  Vs\_set contains the private group of the joining process.

- **CAUSED\_BY\_LEAVE:**

  Vs\_set contains the private group of the leaving process.

- **CAUSED\_BY\_DISCONNECT:**

  Vs\_set contains the private group of the disconnecting process.

- **CAUSED\_BY\_NETWORK:**

  Vs\_set contains the group names of the members of the new membership who came  with  **me** (the current process) to the new membership. Of course, all  **new** members can be determined by comparing it with the groups parameter of the SP\_receive call.

If this is a MEMB\_MESSAGE (i.e. membership message) and it is **neither** a REG\_MEMB\_MESS or a TRANS\_MEMB\_MESS, then it represents exactly the  situtation where the member receiving this message has left a group and this is notification that the leave has occured, thus it is sometimes called  a  **self-leave** message.  The simplest test for this is if a message is CAUSED\_BY\_LEAVE and  REG\_MEMB\_MESS is FALSE then it is a  **self-leave** message.  TRANS\_MEMB\_MESS never have a CAUSED\_BY\_ type because they only serve to signal upto where SAFE delivery and AGREED delivery (with no holes) is guaranteed in the complete  **old** group membership.

The other members of the group this member just left will receive a normal TRANS\_MEMB\_MESS,  REG\_MEMB\_MESS pair as described above showing the membership change.

The fields of SP\_receive in this case will be as follows:

The  *sender* char array will be set to the name of the group for which the membership change is occuring.

The  *max\_groups* and *max\_mess\_len* fields have the same meaning as before, and the  *mess\_type* and  *endian\_mismatch* fields will again be set to 0.

The *groups* array and *mess* body are used to provide two kinds of membership information about the change that just occured in this group.  The  *num\_groups* field will be set to 0 and the  *groups* array will be empty, since this member is no longer part of the group and thus has no knowledge of it. The *mess* body will also be empty.

## RETURN VALUES

Returns the size of the message received  on success or one of the following errors ( \< 0 ):

- **ILLEGAL\_SESSION**

  The  *mbox* given to receive on was illegal.

- **ILLEGAL\_MESSAGE**

  The message had an illegal structure, like a scatter not filled out correctly.

- **CONNECTION\_CLOSED**

  During communication to receive the message communication errors occured and the receive could not be completed.

- **GROUPS\_TOO\_SHORT**

  If the  *groups* array is too short to hold the entire list of groups this message was sent to  then this error is returned and the  *num\_groups* field will be set to the negative of the number of groups needed.

- **BUFFER\_TOO\_SHORT**

  If the message body buffer *mess* is too short to hold the message being received then this error is returned and the  *endian\_mismatch* field is set to the negative value of the required buffer length.

## BUGS

None.

## AUTHOR

Yair Amir \<yairamir@cnds.jhu.edu\>\
 Jonathan Stanton \<jonathan@cnds.jhu.edu\>\
 Commedia Project \<commedia@cnds.jhu.edu\>

## SEE ALSO

[**libsp**(3)](/libsp/3.md)
