Changeset 16

Show
Ignore:
Timestamp:
09/06/07 13:03:56 (1 year ago)
Author:
tmiller
Message:

New simpler API where the shm segment is created in the helper process.
This came out of (and at the request of) discussions with the SIPC consumers.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/binary-mq/libsipc/include/sipc/sipc.h

    r4 r16  
    3030typedef struct sipc_msg sipc_msg_t; 
    3131 
     32/* SIPC roles */ 
     33#define SIPC_CREATOR 0 
     34#define SIPC_SENDER 1 
     35#define SIPC_RECEIVER 2 
     36 
    3237/* IPC types */ 
    3338#define SIPC_SYSV_SHM 0 
     
    3540#define SIPC_NUM_TYPES 2 
    3641 
    37 /* sipc_init(char *key, enum sipc_types ipc_type, int sender
     42/* sipc_open(char *key, int role, int ipc_type, size_t size
    3843 *      key             Unique key to identify IPC communication channel, 
    3944 *                      must be the same for the sender and reciever. 
    40  *      ipc_types       Which IPC type used, must be the same for sender  
     45 *      role            SIPC_CREATOR if this application is the IPC creator, 
     46 *                      SIPC_SENDER for the sender and SIPC_RECEIVER 
     47 *                      for the reciever 
     48 *      ipc_type        Which IPC type used, must be the same for sender  
    4149 *                      and reciever. 
    42  *      sender          1 if this application is the IPC sender, 0 
    43  *                      for the reciever 
     50 *      size            Maximum message size to be transmitted. 
    4451 * 
    45  *      sipc_init must be called before any other function to initialize 
    46  *      the sipc_t struct. The returned pointer can be reused after  
    47  *      disconnecting. Caller must call sipc_destroy to free the memory. 
     52 *      sipc_open must be called before any other function to initialize 
     53 *      the sipc_t struct.  Caller must call sipc_close to free the memory. 
    4854 */ 
    49 sipc_t *sipc_init(char *key, const int ipc_type, size_t size, int sender);  
     55sipc_t *sipc_open(char *key, int role, int ipc_type, size_t size);  
    5056 
    5157/* Free the sipc struct and its contents */ 
    52 void sipc_destroy_handle(sipc_t *sipc); 
     58void sipc_close(sipc_t *sipc); 
    5359 
    5460/* Called by a helper application to destroy an IPC resource. 
    5561 * This function should *NOT* be called by normal users of the library. */ 
    56 void sipc_destroy_resource(char *key, int ipc_type); 
    57  
    58 /* Called by a helper application to create an IPC resource.  
    59  * This function should *NOT* be called by normal users of the library. */ 
    60 int sipc_create(char *key, int ipc_type); 
    61  
    62 /* Connect to IPC resource. sipc must already be initialized via sipc_init  
    63  * returns 0 on success, non-0 on failure */ 
    64 int sipc_connect(sipc_t *sipc); 
    65  
    66 /* Disconnect from an IPC resource. sipc can be reused after a disconnection.  
    67  * returns 0 on success, <0 on failure */ 
    68 void sipc_disconnect(sipc_t *sipc); 
     62void sipc_unlink(char *key, int ipc_type); 
    6963 
    7064/* Blocking call to send msglen bytes of data.  
     
    9185 
    9286#endif 
    93  
  • branches/binary-mq/libsipc/src/libsipc.map

    r4 r16  
    11{ 
    22  global: 
    3         sipc_init; sipc_destroy_handle; 
    4         sipc_create; sipc_destroy_resource;      
    5         sipc_connect; sipc_disconnect; 
    6         sipc_send_data; sipc_recv_data; 
     3        sipc_open; 
     4        sipc_close; 
     5        sipc_unlink; 
     6        sipc_send_data; 
     7        sipc_recv_data; 
    78        sipc_get_data_ptr; 
    89        sipc_shm_recv_done; 
  • branches/binary-mq/libsipc/src/mqueue_internal.c

    r12 r16  
    4141         
    4242        msqid = msgget(key, MQ_PERMS|IPC_CREAT|IPC_EXCL); 
    43         if (msqid < 0)  { 
     43        if (msqid < 0) 
    4444                fprintf(stderr, "msgget: %s\n", strerror(errno));                
    45                 return -1; 
    46         } 
    4745 
    48         return 0
     46        return msqid
    4947} 
    5048 
     
    6664} 
    6765 
    68 int hidden mqueue_connect(key_t key, int sender
     66int hidden mqueue_connect(key_t key, int role
    6967{ 
    70         int flags = 0, msqid = 0; 
    71         flags = sender ? 0200 : 0400;    
     68        int flags, msqid; 
     69 
     70        switch (role) { 
     71        case SIPC_SENDER: 
     72                flags = 0200; 
     73                break; 
     74        case SIPC_RECEIVER: 
     75                flags = 0400; 
     76                break; 
     77        default: 
     78                return -1; 
     79        } 
    7280         
    7381        msqid = msgget(key, flags); 
  • branches/binary-mq/libsipc/src/sipc.c

    r4 r16  
    11/* Author: Joshua Brindle <jbrindle@tresys.com> 
    22*          David Windsor <dwindsor@tresys.com> 
    3 *  
     3* 
    44* Copyright (C) 2006, 2007 Tresys Technology, LLC 
    55* Developed Under US JFCOM Sponsorship 
     
    3434}; 
    3535 
    36 sipc_t *sipc_init(char *key, const int ipc_type, size_t len, int sender
     36sipc_t *sipc_open(char *key, int role, int ipc_type, size_t len
    3737{ 
    3838        sipc_t *new_sipc = NULL; 
    3939        key_t sipc_key; 
    40  
    41         new_sipc = calloc(1, sizeof(sipc_t)); 
    42         if (!new_sipc) 
    43                 goto err; 
    4440 
    4541        if (ipc_type >= SIPC_NUM_TYPES || ipc_type < 0) 
     
    5349        } 
    5450 
     51        new_sipc = calloc(1, sizeof(sipc_t)); 
     52        if (!new_sipc) 
     53                goto err; 
    5554        new_sipc->key = sipc_key; 
    5655        new_sipc->ipc_type = ipc_type; 
    57         new_sipc->sender = sender;              
     56        new_sipc->role = role; 
    5857        new_sipc->len = len; 
    5958        new_sipc->msg_len = SIPC_MSGLEN_NOT_SET; 
    6059 
    61         /* call backend specific init to fill in function table */      
     60        /* call backend specific init to fill in function table */ 
    6261        if (sipc_init_f[ipc_type](new_sipc)) 
    6362                goto err; 
    64          
     63 
     64        /* 
     65         * Create the underlying ipc object or attach to an existing 
     66         * one depending on what role we are playing. 
     67         */ 
     68        switch (role) { 
     69        case SIPC_CREATOR: 
     70                if (new_sipc->funcs->sipc_create(new_sipc) < 0) 
     71                        goto err; 
     72                break; 
     73        case SIPC_SENDER: 
     74        case SIPC_RECEIVER: 
     75                if (new_sipc->funcs->sipc_attach(new_sipc) < 0) 
     76                        goto err; 
     77                break; 
     78        default: 
     79                goto err; 
     80        } 
     81 
    6582        return new_sipc; 
    6683err: 
     
    6986} 
    7087 
    71 void sipc_destroy_handle(sipc_t *sipc) 
     88void sipc_close(sipc_t *sipc) 
    7289{ 
    7390        if (!sipc) 
    7491                return; 
    7592 
    76         sipc->funcs->sipc_destroy_handle(sipc); 
     93        sipc->funcs->sipc_detach(sipc); 
    7794        free(sipc); 
    7895} 
    7996 
    80 void sipc_destroy_resource(char *key, int ipc_type) 
     97void sipc_unlink(char *key, int ipc_type) 
    8198{ 
    8299        key_t sipc_key; 
     
    86103                fprintf(stderr, "ftok: %s\n", strerror(errno)); 
    87104                return; 
    88         }       
     105        } 
    89106 
    90         /* Choose which type of IPC resource we create */ 
    91         switch (ipc_type) {              
     107        /* XXX - if we can require an sipc * we can avoid hard-coding */ 
     108        /* Choose which type of IPC resource to destroy */ 
     109        switch (ipc_type) { 
    92110        case SIPC_SYSV_MQUEUES: 
    93111                mqueue_destroy_resource(sipc_key); 
     
    97115                shm_destroy_resource(sipc_key); 
    98116                break; 
    99         default: 
    100                 return; 
    101         }              
    102  
    103 } 
    104  
    105 int sipc_create(char *key, int ipc_type) 
    106 { 
    107         key_t sipc_key; 
    108  
    109         sipc_key = ftok(key, 'a'); 
    110         if ((int)sipc_key < 0) { 
    111                 fprintf(stderr, "ftok: %s\n", strerror(errno)); 
    112                 return -1; 
    113117        } 
    114          
    115         if (ipc_type >= SIPC_NUM_TYPES || ipc_type < 0) 
    116                 return -1; 
    117  
    118         /* Choose which type of IPC resource we create */ 
    119         switch (ipc_type) {              
    120         case SIPC_SYSV_MQUEUES: 
    121         case SIPC_SYSV_SHM: 
    122                 return mqueue_create(sipc_key); 
    123         default: 
    124                 return -1; 
    125         }              
    126 } 
    127  
    128 int sipc_connect(sipc_t *sipc) 
    129 { 
    130         if (!sipc) 
    131                 return -1; 
    132          
    133         return sipc->funcs->sipc_connect(sipc); 
    134 } 
    135  
    136 void sipc_disconnect(sipc_t *sipc) 
    137 { 
    138         if (!sipc) 
    139                 return; 
    140  
    141         sipc->funcs->sipc_disconnect(sipc); 
    142118} 
    143119 
     
    154130        if (!sipc) 
    155131                return -1; 
    156          
     132 
    157133        return sipc->funcs->sipc_send_data(sipc, msg_len); 
    158134} 
     
    167143 
    168144void sipc_error(sipc_t *sipc, const char *fmt, ...) 
    169 {       
     145{ 
    170146        if (!sipc) 
    171147                return; 
  • branches/binary-mq/libsipc/src/sipc_internal.h

    r4 r16  
    3838 
    3939/* Creation functions */ 
     40int sipc_mqueue_create(sipc_t *sipc); 
     41int sipc_shm_create(sipc_t *sipc); 
    4042int mqueue_create(key_t key); 
     43 
     44/* Attach functions */ 
     45int sipc_mqueue_attach(sipc_t *sipc); 
     46int sipc_shm_attach(sipc_t *sipc); 
     47 
     48/* Detach functions */ 
     49void sipc_mqueue_detach(sipc_t *sipc); 
     50void sipc_shm_detach(sipc_t *sipc); 
    4151 
    4252/* Destruction functions */ 
     
    5060/* all ipc backends must implement all of these functions */ 
    5161struct sipc_func_table { 
    52         int (*sipc_connect) (sipc_t *sipc); 
    53         void (*sipc_disconnect) (sipc_t *sipc); 
     62        int (*sipc_create) (sipc_t *sipc); 
     63        int (*sipc_attach) (sipc_t *sipc); 
    5464        char *(*sipc_get_data_ptr) (sipc_t *sipc); 
    5565        int (*sipc_send_data) (sipc_t *sipc, int msg_len); 
    5666        int (*sipc_recv_data) (sipc_t *sipc, char **data, int *len); 
    57         void (*sipc_destroy_handle) (sipc_t *sipc); 
     67        void (*sipc_detach) (sipc_t *sipc); 
    5868        void (*_sipc_error) (const char *fmt, va_list ap); 
    5969}; 
     
    6272        key_t key; 
    6373        int ipc_type; 
    64         int sender
     74        int role
    6575        union { 
    6676                int fd; /* file desciptor for socket connections */ 
  • branches/binary-mq/libsipc/src/sipc_mqueue.c

    r8 r16  
    4040 
    4141static struct sipc_func_table mqueue_funcs = { 
    42         .sipc_connect = sipc_mqueue_connect
    43         .sipc_disconnect = sipc_mqueue_disconnect
     42        .sipc_create = sipc_mqueue_create
     43        .sipc_attach = sipc_mqueue_attach
    4444        .sipc_get_data_ptr = sipc_mqueue_get_data_ptr, 
    4545        .sipc_send_data = sipc_mqueue_send_data, 
    4646        .sipc_recv_data = sipc_mqueue_recv_data, 
    47         .sipc_destroy_handle = sipc_mqueue_destroy_handle
     47        .sipc_detach = sipc_mqueue_detach
    4848        ._sipc_error = sipc_mqueue_error, 
    4949}; 
     
    6666 
    6767        sipc->funcs = &mqueue_funcs; 
     68        sipc->data = NULL; 
    6869 
    6970        /* Determine maximum size of a message from proc */ 
    7071        SIPC_MQUEUE_MSG_SZ = get_max_msg(sipc); 
    71         if (SIPC_MQUEUE_MSG_SZ < 0) { 
    72                 free(sipc->data); 
    73                 return -1; 
    74         } 
    75                  
     72        if (SIPC_MQUEUE_MSG_SZ < 0) 
     73                return -1; 
     74         
     75        return 0; 
     76
     77 
     78/* Create a message queue having the specified key.  
     79 * This function should only be called by a helper application 
     80 * and not by the sender or reciever. */ 
     81int sipc_mqueue_create(sipc_t *sipc) 
     82
     83        int msqid; 
     84 
     85        msqid = mqueue_create(sipc->key); 
     86        if (msqid < 0)  { 
     87                fprintf(stderr, "msgget: %s\n", strerror(errno)); 
     88                return -1; 
     89        } 
     90 
     91        sipc->msqid = msqid; 
     92        return 0; 
     93
     94 
     95void sipc_mqueue_detach(sipc_t *sipc) 
     96
     97        free(sipc->data);      
     98        sipc->data = NULL; 
     99
     100 
     101/* Attach to an existing message queue. */ 
     102int sipc_mqueue_attach(sipc_t *sipc) 
     103
    76104        /* Allocate data member */ 
    77         sipc->data = NULL; 
    78105        sipc->data = calloc(1, sipc->len); 
    79106        if (!sipc->data) { 
     
    81108             return -1; 
    82109        } 
    83          
    84         return 0; 
    85 
    86  
    87 void sipc_mqueue_destroy_handle(sipc_t *sipc) 
    88 
    89         free(sipc->data);      
    90 
    91  
    92 /* Create a message queue, or connect to an existing 
    93  * message queue. */ 
    94 int sipc_mqueue_connect(sipc_t *sipc) 
    95 
    96         sipc->msqid = mqueue_connect(sipc->key, sipc->sender); 
     110 
     111        sipc->msqid = mqueue_connect(sipc->key, sipc->role); 
    97112        if (sipc->msqid < 0) { 
    98113                sipc_error(sipc, "msgget: %s\n", strerror(errno)); 
    99                 return -1; 
    100         } 
    101          
    102         return 0; 
    103 
    104  
    105 /* Do nothing here; disconnecting from the 
    106  * message queue is done by a disconnector process */ 
    107 void sipc_mqueue_disconnect(sipc_t *sipc) 
    108 
     114                free(sipc->data); 
     115                sipc->data = NULL; 
     116                return -1; 
     117        } 
     118         
     119        return 0; 
    109120} 
    110121 
     
    123134        struct msgbuf *mbuf = NULL; 
    124135 
    125         if (!sipc->sender
     136        if (sipc->role != SIPC_SENDER
    126137                goto err;        
    127138 
     
    177188        if (!data) 
    178189                goto err; 
    179         if (sipc->sender) { 
    180                 sipc_error(sipc, "sipc_send_data called with sender flag enabled in IPC structure\n"); 
     190        if (sipc->role != SIPC_RECEIVER) { 
     191                sipc_error(sipc, "sipc_send_data called without receiver flag enabled in IPC structure\n"); 
    181192                goto err; 
    182193        } 
  • branches/binary-mq/libsipc/src/sipc_shm.c

    r11 r16  
    3737 
    3838#define SHM_RPERMS S_IRUSR|S_IRGRP|S_IROTH 
    39 #define SHM_SPERMS SHM_RPERMS|S_IWUSR|S_IWGRP|S_IWOTH|IPC_CREAT|IPC_EXCL 
     39#define SHM_SPERMS SHM_RPERMS|S_IWUSR|S_IWGRP|S_IWOTH 
     40#define SHM_CPERMS SHM_RPERMS|SHM_SPERMS|IPC_CREAT|IPC_EXCL 
    4041 
    4142static struct sipc_func_table shm_funcs = { 
    42         .sipc_connect = sipc_shm_connect
    43         .sipc_disconnect = sipc_shm_disconnect
     43        .sipc_create = sipc_shm_create
     44        .sipc_attach = sipc_shm_attach
    4445        .sipc_get_data_ptr = sipc_shm_get_data_ptr,  
    4546        .sipc_send_data = sipc_shm_send_data, 
    4647        .sipc_recv_data = sipc_shm_recv_data,        
    47         .sipc_destroy_handle = sipc_shm_destroy_handle
     48        .sipc_detach = sipc_shm_detach
    4849        ._sipc_error = sipc_shm_error 
    4950}; 
     
    6061} 
    6162 
    62 /* Do nothing here; destroying the shm segment is done  
    63  * by a destructor process. */ 
    64 /* Processes should detach from shared memory in sipc_shm_disconnect */ 
    65 void sipc_shm_destroy_handle(sipc_t *sipc) 
    66 {        
    67 
    68  
    69 /* We already have attached to shm segment, so here we connect side channel */ 
    70 int sipc_shm_connect(sipc_t *sipc) 
     63int sipc_shm_create(sipc_t *sipc) 
     64
     65        if (!sipc) 
     66                goto err; 
     67 
     68        /* Create the shm segment */ 
     69        sipc->s.shmid = shmget(sipc->key, sipc->len, SHM_CPERMS); 
     70        if (sipc->s.shmid < 0) { 
     71                sipc_error(sipc, "shmget: %s\n", strerror(errno)); 
     72                goto err; 
     73        } 
     74 
     75        /* Create the side channel */ 
     76        sipc->s.msqid = mqueue_create(sipc->key); 
     77        if (sipc->s.shmid < 0) 
     78                goto err; 
     79 
     80        /* Set capacity of side channel to 1 message */ 
     81        if (sipc->role == SIPC_SENDER && 
     82            mqueue_set_capacity(sipc->s.msqid, sizeof(struct msgbuf)) < 0)  
     83                goto err; 
     84 
     85        return 0; 
     86         
     87err: 
     88        if (sipc->s.shmid != (key_t)-1) 
     89                shmctl(sipc->s.shmid, IPC_RMID, NULL); 
     90        return -1; 
     91
     92 
     93int sipc_shm_attach(sipc_t *sipc) 
    7194{ 
    7295        int flags = 0; 
     
    7598                goto err; 
    7699 
    77         /* Create the shm segment */ 
    78         flags = sipc->sender ? SHM_SPERMS : SHM_RPERMS; 
     100        /* Get the (existing) shm segment */ 
     101        flags = sipc->role == SIPC_SENDER ? SHM_SPERMS : SHM_RPERMS; 
    79102        sipc->s.shmid = shmget(sipc->key, sipc->len, flags); 
    80103        if (sipc->s.shmid < 0) { 
     
    84107         
    85108        /* Attach to the shm segment */ 
    86         flags = sipc->sender ? 0 : SHM_RDONLY; 
     109        flags = sipc->role == SIPC_SENDER ? 0 : SHM_RDONLY; 
    87110        if ((sipc->data = shmat(sipc->s.shmid, NULL, flags)) == (char *)-1) { 
    88111                sipc_error(sipc, "shmat: %s\n", strerror(errno)); 
     
    91114 
    92115        /* Connect side channel */ 
    93         sipc->s.msqid = mqueue_connect(sipc->key, sipc->sender); 
     116        sipc->s.msqid = mqueue_connect(sipc->key, sipc->role); 
    94117        if (sipc->s.msqid < 0) { 
    95118                sipc_error(sipc, "%s\n", "Unable to connect message queue"); 
     
    97120        } 
    98121 
    99         /* Set capacity of side channel to 1 message */ 
    100         if (sipc->sender && mqueue_set_capacity(sipc->s.msqid, sizeof(struct msgbuf)) < 0)  
    101                 goto err; 
    102  
    103122        return 0; 
    104123err: 
    105         sipc_disconnect(sipc); 
     124        sipc_shm_detach(sipc); 
    106125        return -1; 
    107126} 
    108127 
    109 void sipc_shm_disconnect(sipc_t *sipc) 
     128void sipc_shm_detach(sipc_t *sipc) 
    110129{ 
    111130        if (!sipc) 
     
    113132         
    114133        /* If we're the receiver, disconnect side channel */ 
    115         if (!sipc->sender)     
     134        if (sipc->role == SIPC_RECEIVER)       
    116135                mqueue_disconnect(sipc->s.msqid); 
    117136             
     
    121140                        sipc_error(sipc, "shmdt: %s\n", strerror(errno)); 
    122141        } 
    123  
    124142} 
    125143