接在Spread 简介(试译)之后,我跟啃骨头一样一点点儿地把SP_receive的man文档看完了。 这是我做的笔记,基本就是原文翻译,但是我英文太差,翻得太烂了点:( SP_receive NAME SP_receive, SP_scat_receive - Receive message from Spread SYNOPSIS #include 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 函数主要实现接收消息的功能。这个函数不仅接收数据消息,也接收成员关系数据。当前连接所在的所有组的消息都会到达同一个 “收件箱”,因此SP_receive函数一次会从任意一个组中间取回一条消息。当接收完成后,一些成员变量会被设置值,以标记这条消息的各种属性。 因为这个函数是程序从spread 系统中取回消息的唯一渠道,因此在Spread中的应用也是最复杂的。基于这条消息是数据消息,还是成员关系消息,许多 参数的含义都会改变。 没有消息到达的时候,SP_receive函数会阻塞。 mbox参数指定了要在哪个(spread)连接上获取消息。Service_type是指向一个变量的指针,这个变量会 指出当前接收到的消息是”数据消息“,还是成员关系消息。这个变量要么是REG_MESSAGE,要么是 MEMBER_SHIP_MESS,当然会是特定的类型.这个变量也是一个输入参数,在一般的情况下应该被置为0。如果您置为”DROP_RECV”,则表示您愿意接收“不可信消息”,这可能导般如果为消息或组列表分配的缓冲不够的话,消息会被清空。更多关于DROP_RECV的介绍会在后面提到。 后面的参数的含义是依赖于service_type这个变量的取值的.如果service_type的取值是REG_MESSAGE(比如数据消息),那么: sender参数是一个指向字符的指针,至少需要能容纳MAX_GROUP_NAME个字符。(很拗口吧?其实就是一个长度至为MAX_GROUP_NAME的字符串…) 这个参数将会被设置成为消息发送方的名称(它的组内名称) max_groups参数是你为groups参数分配的地址所能容纳的最大的组的个数。 Num_groups是一个整型指针,指向在groups参数中返回的组的个数。 groups 参数可以容纳max_groups个组名,每个组名是一个最多有MAX_GROUP_NAME个字符的字符串。所有接收这个消息的组都会被更在这儿,除非数组太小(此时groups尽可能多地接纳至到它满了为止,并且 num_groups会设为负的值).比如,如果你的groups数组能接收5个数组名,而这个消息被7个组接收,前5个组的名字会存在groups这个数组中,num_groups会被设为-7. 真正的消息内容存在命名为mess的缓冲区中,这个缓冲区最少要有max_mess个字节。如果接收的消息的长度要比这个缓冲区大,默认将会返回BUFFER_TOO_SHOFT错误,并在endian_mismatch字域中提供需要的长度。如果DROP_RECV标记被在service_type中传进来,那么mess会尽量多地存储消息内容,多余的内容会被丢弃掉,同时,SP_receive的返回值会指示一个错误。如果使用SP_scat_receive,那么mess和length参数会被一个scat_mess scatter结构体所取代,这个结构会存储它收到的消息和消息的长度。它们会被以接收的次序存储。 如果是MEMB_MESSAGE(比如,成员关系消息),并且特别指出是TRANS_MESS,那么: sender这个字符数据(字符串)就会设置为成员关系发生变化的组的名字。 max_groups和max_mess_len参数没有用,num_groups会是0,而groups参数因为当前正处于变动之中,暂时没有 了正常的组,由sender参数取代。mess_type参数设为-1,endian_mismatch参数为0(也因为组关系处于变动之中).mess参数只包含 关系变化作用的group的group_id。因此消息体就是: group_id; 因此本质上你所得到的信息就是通过sender参数和group_id值反映的哪个组产生了变动。 TRANS_MEMB_MESS 的重要性在于,它告诉应用程序,在它之后,在来自同一组的REG_MEMB_MESS之前,接收到的消息都是’clean up’消息,这些消息在真正改变成员关系之前需要保持常态。请阅读其他文档或研究文献以得到更多相关资料。 如果这是一条MEMB_MESSAGE(比如成员关系消息)并且指定了是REG_MEMB_MESS,那么: sender 字符数组指定了成员关系发生改变的组的名称。 max_groups和max_mess_len参数的含义跟前面一样,mess_type参数设定为当前进程在组成员数组中的索引。endian_mismatch会再次设为0. groups参数和mess内容用来提供当前组内发生的变化的两种信息。num_groups参数设置为新成员关系中的当前组的成员数(指变动发生后)。相对地,groups 这个数组会被设置为新成员关系中当前组的所有成员的组内名称。这个名称的顺序常常是按接收方的顺序排序的,这样当程序需要一个做代表时就能取一个出来。不同的Spread版本的顺序不同,当前版本的首先按连接到守护进程的顺序,其次是它的私有名称。守护进程的顺序是按照它们在spread.conf文件中列出来的顺序排列的。 第二类信息存储在消息体中,提供了当前进程中所有私有组名称,这些名称从原来的成员关系迁到了新的成员关系中。 所有的内容都一个挨一个地放在message缓冲中。因为这个结构在各个版本中经常变,最好的处理办法就是使用 我们提供的解析函数来将消息体翻译成定义好的描述成员关系的结构体。解析函数有两个变量,一个用来处理字 节流,一个用来处理scatters格式的消息体。 SP_get_memb_info SP_get_vs_sets_info SP_get_vs_set_members SP_scat_get_memb_info 这四个函数填入标准的应用程序用来设置以成员关系的gid和vs信息的结构体。 SP_scat_get_vs_sets_info SP_scat_get_vs_set_members 这样,如果一个程序需要得到它自己的vs_set(Spread版本4之前提供的信息),他们可以被两个函数调用来文档化。先用SP_get_memb_info然后用SP_get_vs_set_members; 每个vs_set定义成若干成员和一个成员关系字符数组(字符串)。这个数组的类型是char members[][MAX_GROUP_NAME]; 每个成员关系型的消息都可能含有一系列的vs_sets,当一个网络合并动作发生时,几个不同的部分可能同时发生合并,每个区块都有它自己的成员集合,这些既有旧成员关系的又有新成员关系的。 如果你想自行解析这个成员关系消息内容,下面的段落指出了当前的数据格式。这个格式肯定会改变(过去已经改变过好几次了),我们不对未来的改变做保证。如果您想自行解析数据,在更新Spread的版本时您需要更新您的代码。 成员关系消息体包含以下几段(它们是有顺序的)。每一段数据都是一个结构体,或者是一个整数(是整数时,一定是一个32位无符号的整数)。vs sets是这样定义的: group_id gid; unsigned int num_vs_sets; unsigned int local_vs_set_offset; 以及一系列vs_sets; 所有的vs_sets都序列地存在成员关系消息体中,读完了一个vs_set,另一个vs_set就在下一个字节开始了。 每一个vs_set都以一下整数num_vs_members开始,因而程序能够得到members数组的长度来进行读取。 unsigned int num_vs_members; char members[][MAX_GROUP_NAME] vs_set members数组有num_vs_members个组名,每一个都是一个固定长度的字符串。vs_set members 数组的内容取决于成员关系变更的类型: CAUSED_BY_JOIN: vs_set包含有加入进来的进程的私有组名。 CAUSED_BY_LEAVE: vs_set包含有退出的进程的私有组名。 CAUSED_BY_DISCONNECT: vs_set 包含有关闭连接的进程的私有组名。 CAUSED_BY_NETWORK: vs_set包含有形成新成员关系的各个成员组的组名称。每个加入的成员集合都有一个vs_set对应。包含有本地应用程序的私有组名的vs_set会有后来加入的成员。 如果这是一条MEMB_MESSAGE但是既不是REG_MEMB_MESS也不是TRANS_MEMB_MESS,那这就表明这种情形是接收消息的成员离开了组,这是一条通知消息。这种有时被称作”闪人通知”。 这个成员刚刚离开的组的成员们会收到一个正常的TRANS_MEMB_MESS,REG_MEMB_MESS消息对,就跟前面描述的一样。 SP_receive的参数如下: sender参数就是成员关系发生改变的组的名字。 mess_type and endian_mismatch fields will again be set to 0. max_groups和max_mess_len参数的含义与原来一样,mess_type和endian_dismatch参数再次置为0. groups数组和消息体提供发生变动的组的两种信息。num_groups会置为0,groups数组会置为0(既然这个成员不再是组的一个成员了。mess的消息体内容也是空。 返回值:返回返回消息的长度(当成功时)或在失败时返回以下任何一个: ILLEGAL_SESSION 指定的mbox不正确。 ILLEGAL_MESSAGE 消息包含一个正常的结构,比如一个scatter结构没有正确填充。 CONNECTION_CLOSED 在通信时发生了连接错误,接收无法完成。 GROUPS_TOO_SHORT 如果你的groups数组设定的太小了无法存下返回的数组,会返回一个GROUPS_TOO_SHORT的错误。 这时num_groups会返回负数。 BUFFER_TOO_SHORT 如果消息体缓冲(mess)设置的太短,存不下返回的消息时,会返回这个错误,就会返回这个错误,同时endian_mismatch参数会设置为需要的缓冲的长度。