#pragma module ADC_ICHC "ADC_ICHC-1-D" #define __MODULE__ "ADC_ICHC" /* **++ ** FACILITY: StarLet ADC server for OpenVMS ** ** MODULE DESCRIPTION: ** ** This module covers IntraCluster Hubs Communication functionality: a set of ** routines to Hub-to-Hub (in the OpenVMS cluster) data interchanges. ** ** AUTHORS: ** ** Ruslan R. Laishev ** ** CREATION DATE: 30-SEP-2009 ** ** DESIGN ISSUES: ** ** MODIFICATION HISTORY: ** ** {@tbs@}... **-- */ #include #include #include #include #include #include #include #include #include #include #include #include "macros.h" #define __NEW_STARLET 1 #include #include #include #include "adcdef.h" #include "adc_msg.h" extern int exit_flag,debug_flag,csid; typedef unsigned int (*ast_routine_t)(void *astprm); QUE ihub = {0,0}; $DESCRIPTOR(ass_fao, "ADC$!XW"); int icc_hand [ 32 ], icc_handsz = sizeof(icc_hand)/sizeof(icc_hand[0]); /* **++ ** FUNCTIONAL DESCRIPTION: ** ** It's an ICC related AST-routine suppose to perform processiong connect/disconnect ** events. ** ** FORMAL PARAMETERS: ** event_type: An event type (ICC_$C_EV_CONNECT/ICC_$C_EV_DISCONNECT) ** hand: A connection handler ** data_len: A data length ** data_bfr: A data buffer ** P5-P7: An event specific arguments ** ** RETURN VALUE: ** ** None. ** ** **-- */ static void evt_rtn_icc_conn_disc ( unsigned event_type, unsigned hand, unsigned data_len, char * data_bfr, unsigned P5, unsigned P6, void * P7 ) { int status; IOS_ICC icc_iosb; /* ** Performs a processiong of event */ if ( event_type == ICC$C_EV_DISCONNECT ) { /* ** Close connection with remote partner */ status = sys$icc_disconnectw(hand,&icc_iosb,0,0,0,0); _adc_log(ADC_ILINKDOWN,hand,status,icc_iosb.ios_icc$w_status); } else if ( event_type == ICC$C_EV_CONNECT ) { /* ** Just accept an incomming connection */ status = sys$icc_accept(hand,0,0,0,0); _adc_log(ADC_ILINKUP,hand,P6,status); } /* ** Stop sleeping, there is something to do!!! */ sys$wake(0,0); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** It's an ICC related AST-routine suppose to performs proccessiong data ** events: read ADC message from the ICC handle, enqueue it for processing ** into the common ADC Message queue ** ** FORMAL PARAMETERS: ** message_size: A message size in a buffer ** hand: An ICC-connection handle ** ctx: An user context ** ** RETURN VALUE: ** ** None. ** ** **-- */ void evt_rtn_icc_data ( unsigned message_size, unsigned hand, unsigned ctx ) { int status; ICHC_BUF *buf; IOS_ICC icc_iosb; /* ** Allocate a memory for buffer */ if ( !(1 & (status = _adc_getvm(&buf,sizeof(ICHC_BUF)))) ) lib$signal(status); if ( !(1 & (status = sys$icc_receivew(hand,&icc_iosb,0,0,buf->ichc_b_buf,message_size))) || !(1 & icc_iosb.ios_icc$w_status) ) _adc_log(ADC_ERRRECV,hand,status,icc_iosb.ios_icc$w_status,message_size); buf->ichc_w_len = message_size; if ( !(1 & (status = lib$insqti(buf,&ihub,&RETRY_COUNT))) ) lib$signal(status); /* ** Stop sleeping, there is something to do!!! */ sys$wake(0,0); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Opens an ICC association. A connection and disconnect events AS-routines ** the same. ** ** FORMAL PARAMETERS: ** ** assoc: An association name character string ** hand: A connection handler ** recvrtn: An receive processing AST-routine ** ** RETURN VALUE: ** ** VMS condition code ** ** **-- */ int ichc_astart ( struct dsc$descriptor *assoc, int *hand, void *recvrtn ) { /* ** Open an ICC association with given set of parameters: ** SYS$ICC_OPEN_ASSOC assoc_handle ,[assoc_name] ,[logical_name] , ** [logical_table] ,[conn_event_rtn] ,[disc_event_rtn] ** ,[recv_rtn] ,[maxflowbufcnt] ,[prot] */ return sys$icc_open_assoc(hand,assoc,0,0, evt_rtn_icc_conn_disc,evt_rtn_icc_conn_disc,recvrtn,12,2); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Close a has been opened ICC association. ** ** FORMAL PARAMETERS: ** ** hand: A connection handler ** ** RETURN VALUE: ** ** VMS condition code ** ** **-- */ int ichc_ashut ( int hand ) { return sys$icc_close_assoc(hand); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Performs a disconnection of ICC connection identified by a given connection handle. ** ** FORMAL PARAMETERS: ** ** hand: A connection handler ** ** RETURN VALUE: ** ** VMS condition code ** ** **-- */ int pcf$disc ( int hand ) { int status; IOS_ICC icc_iosb; if ( !hand ) return SS$_NORMAL; status = sys$icc_disconnectw(hand,&icc_iosb,0,0,0,0); _adc_log(ADC_OLINKDOWN,hand,status,icc_iosb.ios_icc$w_status); status = (status & 1)?icc_iosb.ios_icc$w_status:status; return (status == SS$_LINKDISCON)?SS$_NORMAL:status; } void * adc_ichc ( unsigned short *port ) { int status,bufl = 0,hand = 0, __csid = 0, idx = 0; unsigned char buf[64],ass[128]; struct dsc$descriptor ass_dsc,node_dsc; ILE3 items [] = {{sizeof(buf),SYI$_NODENAME,buf,&bufl}, {sizeof(__csid),SYI$_NODE_CSID,&__csid,0}, {0,0,0,0}}; IOSB iosb; IOS_ICC icc_iosb; /* ** Form a ICC association name/id */ INIT_SDESC(ass_dsc,sizeof(ass),ass); if ( !(1 & (status = sys$fao(&ass_fao,&ass_dsc.dsc$w_length,&ass_dsc,*port))) ) lib$signal(status); if ( !(1 & (status = ichc_astart(&ass_dsc,&hand,evt_rtn_icc_data))) ) lib$signal(status); /* ** Run over cluster members list and try to connect */ for ( hand = idx = 0; (1 & (status = sys$getsyiw(EFN$C_ENF,&(-1),0,&items,&iosb,0,0))) && (1 & iosb.iosb$w_status); hand = 0) { /* ** Don't connect to itself, and check free space in the connection handle ** table. */ if ( csid == __csid ) continue; else if ( idx > icc_handsz ) break; /* ** Forms a node name descriptor and try to connect */ INIT_SDESC(node_dsc,bufl,buf); if ( !(1 & (status = sys$icc_connectw(&icc_iosb,0,0, ICC$C_DFLT_ASSOC_HANDLE,&hand,&ass_dsc, &node_dsc,0,0,0,0,0,0,0))) && !(1 & icc_iosb.ios_icc$w_status) ) _adc_log(ADC_OLINKUP & (~STS$K_SUCCESS),hand,&node_dsc,&ass_dsc,status,icc_iosb.ios_icc$w_status); if ( (1 & status) && (1 & icc_iosb.ios_icc$w_status) ) _adc_log(ADC_OLINKUP,hand,&node_dsc,&ass_dsc,status,icc_iosb.ios_icc$w_status); if ( hand ) icc_hand[idx++] = hand; } pthread_exit(&status); return NULL; } #if 0 int main (void) { int status; status = adc_ichc_init(412); return status; } #endif