📄 scs_protocol.c
字号:
Lock_cbvte( cbvte ) cb = Get_cb( cbvte ); if( scsbp->rconnid.seq_num != cbvte->connid.seq_num ) { if( scsbp->mtype == SCS_ACCEPT_REQ || scsbp->mtype == SCS_REJECT_REQ || scsbp->mtype == SCS_CONN_RSP ) { aborted_conn = 1; } else { event_code = SE_BADCONNID; Unlock_cbvte( cbvte ) } } } if( event_code ) { pb = ( *pccb->Get_pb )( pccb, scsbp, BUF ); ( void )( *pccb->Crash_path )( pccb, pb, event_code, RECEIVE_BUF, scsbp ); Unlock_scadb() return; } else { pb = cb->pb; } } switch( scsbp->mtype ) { case SCS_CONN_REQ: { register cbq *lcb; if((( pb = ( *pccb->Get_pb )( pccb, scsbp, BUF )) == NULL || pb->pinfo.state != PS_OPEN ) && ( *pccb->Open_path )( pccb, pb, scsbp ) != RET_SUCCESS ) { ( void )( *pccb->Add_msg )( pccb, scsbp ); Unlock_scadb() return; } cbvte = NULL; Conn_rsp( scsbp )->Req_status = ADR_NOLISTENER; for( lcb = scs_listeners.flink; lcb != &scs_listeners; lcb = lcb->flink ) { if( Comp_name( Conn_req( scsbp )->rproc_name, Lcb->cinfo.lproc_name )) { if( Lcb->cinfo.cstate != CS_LISTEN ) { ( void )panic( SCSPANIC_LQUEUE ); } else if(( cb = scs_alloc_cb( CS_CONN_REC, NULL, pb ))) { lcbvte = Get_cbvte( Lcb->cinfo.lconnid ); cb->control = Lcb->control; cb->cinfo.snd_credit = Conn_req( scsbp )->credit; Move_connid( Conn_req( scsbp )->sconnid, cb->cinfo.rconnid ) cb->cinfo.min_rec_credit = Conn_req( scsbp )->min_credit; Move_name( Conn_req( scsbp )->rproc_name, cb->cinfo.lproc_name ) Move_name( Conn_req( scsbp )->sproc_name, cb->cinfo.rproc_name ) Move_data( Conn_req( scsbp )->sproc_data, cb->cinfo.rconn_data ) cbvte = Get_cbvte( cb->cinfo.lconnid ); Lock_cbvte( cbvte ) Insert_cb( cb, pb ) Conn_rsp( scsbp )->Req_status = ADR_SUCCESS; Move_connid( cb->cinfo.lconnid, Conn_req( scsbp )->rconnid ) notify_event = CRE_CONN_REC; } else { Conn_rsp( scsbp )->Req_status = ADR_NORESOURCE; } break; } } break; } case SCS_CONN_RSP: if( aborted_conn || cb->cinfo.status.abort_fork ) { ; } else if( cb->cinfo.cstate == CS_CONN_SNT ) { if( Conn_rsp( scsbp )->Req_status == ADR_SUCCESS ) { cb->cinfo.cstate = CS_CONN_ACK; } else { status = Conn_rsp( scsbp )->Req_status; cb->errlogopt.rreason = status; ( void )scs_log_event( cb, W_TERM_FCONN, CONN_EVENT ); cb->cinfo.cstate = CS_CLOSED; notify_event = CRE_CONN_DONE; } } else { event_code = SE_BADCSTATE; } break; case SCS_ACCEPT_REQ: if( aborted_conn || cb->cinfo.status.abort_fork ) { Accept_rsp( scsbp )->Req_status = ADR_DISCONN; } else if( cb->cinfo.cstate == CS_CONN_ACK ) { Accept_rsp( scsbp )->Req_status = ADR_SUCCESS; Move_connid( Accept_req( scsbp )->sconnid, cb->cinfo.rconnid ) cb->cinfo.snd_credit = Accept_req( scsbp )->credit; cb->cinfo.min_rec_credit = Accept_req( scsbp )->min_credit; Move_data( Accept_req( scsbp )->sproc_data, cb->cinfo.rconn_data ) ( void )scs_log_event( cb, I_NEW_CONN, CONN_EVENT ); cb->cinfo.cstate = CS_OPEN; notify_event = CRE_CONN_DONE; semaphore = 1; } else { event_code = SE_BADCSTATE; } break; case SCS_ACCEPT_RSP: if( cb->cinfo.cstate == CS_ACCEPT_SNT ) { notify_event = CRE_ACCEPT_DONE; if( Accept_rsp( scsbp )->Req_status == ADR_SUCCESS ) { ( void )scs_log_event( cb, I_NEW_CONN, CONN_EVENT ); cb->cinfo.cstate = CS_OPEN; semaphore = 1; } else { status = Accept_rsp( scsbp )->Req_status; cb->errlogopt.rreason = status; ( void )scs_log_event( cb, W_TERM_FCONN, CONN_EVENT ); cb->cinfo.cstate = CS_CLOSED; } } else { event_code = SE_BADCSTATE; } break; case SCS_REJECT_REQ: if( aborted_conn || cb->cinfo.status.abort_fork ) { ; } else if( cb->cinfo.cstate == CS_CONN_ACK ) { status = Reject_req( scsbp )->reason; cb->errlogopt.rreason = status; ( void )scs_log_event( cb, W_REJECT_FCONN, CONN_EVENT ); cb->cinfo.cstate = CS_CLOSED; notify_event = CRE_CONN_DONE; } else { event_code = SE_BADCSTATE; } break; case SCS_REJECT_RSP: if( cb->cinfo.cstate == CS_REJECT_SNT ) { cb->cinfo.cstate = CS_CLOSED; if( !cb->cinfo.status.disconnect ) { notify_event = CRE_REJECT_DONE; } else { notify_event = CRE_DISCONN_DONE; } cb->errlogopt.rreason = cb->cinfo.reason; ( void )scs_log_event( cb, W_REJECT_FCONN, CONN_EVENT ); } else { event_code = SE_BADCSTATE; } break; case SCS_DISCONN_REQ: while( Test_cbvte_sem( cbvte )) { Unlock_cbvte( cbvte ) Unlock_scadb() Lock_scadb() Lock_cbvte( cbvte ) if( scsbp->sconnid.seq_num != cbvte->connid.seq_num || cb->cinfo.cstate == CS_PATH_FAILURE ) { ( void )( *pccb->Add_msg )( pccb, scsbp ); Unlock_cbvte( cbvte ) Unlock_scadb() return; } } if ( cb->cinfo.cstate == CS_OPEN ) { cb->cinfo.cstate = CS_DISCONN_REC; Remove_pb_waitq( cb ) notify_event = CRE_DISCONN_REC; status = Disconn_req( scsbp )->reason; semaphore = 1; } else if( cb->cinfo.cstate == CS_DISCONN_SNT ) { cb->cinfo.cstate = CS_DISCONN_MTCH; } else if( cb->cinfo.cstate == CS_DISCONN_ACK ) { ( void )scs_log_event( cb, W_TERM_CONN, CONN_EVENT ); cb->cinfo.cstate = CS_CLOSED; notify_event = CRE_DISCONN_DONE; } else { event_code = SE_BADCSTATE; } break; case SCS_DISCONN_RSP: if( cb->cinfo.cstate == CS_DISCONN_SNT ) { cb->cinfo.cstate = CS_DISCONN_ACK; } else if( cb->cinfo.cstate == CS_DISCONN_MTCH ) { ( void )scs_log_event( cb, W_TERM_CONN, CONN_EVENT ); cb->cinfo.cstate = CS_CLOSED; notify_event = CRE_DISCONN_DONE; } else { event_code = SE_BADCSTATE; } break; case SCS_CREDIT_REQ: { register long credits; /* Only credit requests for open connections are processed. Credit * requests for connections in the DISCONN_SNT connection state( * the local SYSAP has requested connection termination but the * request has not yet been acknowledged by the remote SCS ) are * not processed and the path is crashed if the connection is * found to be in any other state. */ if( cb->cinfo.cstate == CS_OPEN ) { if(( credits = scsbp->credit ) > 0 ) { cb->cinfo.snd_credit += credits; if( cb->cinfo.status.cwait ) { cb->cinfo.status.cwait = 0; notify_event = CRE_CREDIT_AVAIL; semaphore = 1; } } else if( credits < 0 ) { if(( credits = cb->cinfo.snd_credit - cb->cinfo.min_snd_credit ) <= 0 ) { scsbp->credit = 0; } else { if( credits < -scsbp->credit ) { scsbp->credit = -credits; cb->cinfo.snd_credit += scsbp->credit; } } } } else { if( cb->cinfo.cstate != CS_DISCONN_SNT ) { event_code = SE_BADCSTATE; } } break; } case SCS_CREDIT_RSP: if( cb->cinfo.cstate != CS_OPEN && cb->cinfo.cstate != CS_DISCONN_SNT && cb->cinfo.cstate != CS_DISCONN_REC && cb->cinfo.cstate != CS_DISCONN_MTCH ) { event_code = SE_BADCSTATE; } else if( scsbp->credit < 0 ) { event_code = SE_NEGCREDITS; } break; default: event_code = SE_BADSCSMTYPE; } { register void ( *control )(); if( notify_event ) { ( void )scs_init_cmsb( notify_event, status, &cmsb, cb, pb, 0 ); control = cb->control; if( cb->cinfo.cstate == CS_CLOSED ) { Remove_cb( cb, pb ) } else if( semaphore ) { Incr_cbvte_sem( cbvte ) } else if( lcbvte ) { Lock_cbvte( lcbvte ) Incr_cbvte_sem( lcbvte ) Unlock_cbvte( lcbvte ) } } if( cbvte ) { Unlock_cbvte( cbvte ) } if( event_code == 0 ) { if(!( scsbp->mtype & 1 )) { ( void )scs_response( scsbp, pb ); } else { Lock_pb( pb ) if( pb->pinfo.status.sanity ) { Remove_scs_timeoutq( pb ) } else if( pb->pinfo.state != PS_PATH_FAILURE ) { ( void )panic( SCSPANIC_SANITY ); } Unlock_pb( pb ) ( void )scs_request( 0, NULL, pb, scsbp ); } } else { ( void )( *cb->Crash_path )( pccb, pb, event_code, RECEIVE_BUF, scsbp); } Unlock_scadb() if( notify_event ) { ( void )( *control )( notify_event, &cmsb ); if( semaphore ) { Decr_cbvte_sem( cbvte ) } else if( lcbvte ) { Decr_cbvte_sem( lcbvte ) } } }}/* Name: scs_request - Send SCS Sequenced Message Request * * Abstract: This routine initiates the transmission of a SCS request over * a specific path. Five such requests are supported: * * 1. Request establishment of a logical SCS connection. * 2. Request acceptance of a logical SCS connection. * 3. Request rejection of a logical SCS connection. * 4. Request termination of a logical SCS connection. * 5. Request extension of send credits across a logical SCS * connection. * * SCS applies flow control to its own communications on a per * path basis. Only one SCS request may be transmitted across * each path at a given moment. The transmission of all * subsequent requests is postponed until a response to the active * request is received. * * Flow control is provided by allocating for each path a single * message buffer. These buffers are attached to their PBs as SCS * send message buffers when not in use. A SCS request is * immediately transmitted only when the SCS send message buffer * for the path is available. Otherwise, transmission of the * request is postponed by queuing the CB on whose behalf the * request was made to the appropriate PB until the SCS send * message buffer is again available. * * Message buffers containing SCS requests are always added to the * appropriate ports' free message pools following their * transmissions. There they serve as receive message buffers for * their corresponding SCS responses. After receiving and * processing a SCS response its message buffer is used to * transmit the next SCS request pending on the appropriate * path. The message buffer is attached to the PB as its SCS send * message buffer if there are no such requests pending. * * A sanity timer is set on the target path prior to transmission * of a SCS request. SCS assumes the path has failed and * explicitly crash it if this timer expires before the SCS * response to the current SCS request is received. * * There are two ways in which this routine may be invoked. * * 1. The routine may be invoked to process a specific SCS request * on behalf of an explicitly provided connection. Such * invocations never supply the message buffer to contain the * request( scsbp == NULL ). * * 2. The routine may be invoked to resume processing of the next * SCS request pending transmission on the path. Such * invocations never supply the connection on whose behalf the * transmission is to be made( cb == NULL ) or the explicit * request type( request == CB_NOT_WAIT ) but always supply the * message buffer to contain the request. * * Inputs: * * IPL_SCS - Interrupt processor level * cb - Connection Block pointer * request - Request type * pb - Path Block pointer * scsbp - Address of SCS header of message buffer * scs_sanity - SCS sanity timer interval * scs_timeoutq - SCS protocol sequence timeout queue head * * Outputs: * * IPL_SCS - Interrupt processor level * cb - Connection Block pointer * cinfo.cbstate - CB state * cinfo.pend_rec_credit - Number of credits pending extension * cinfo.reason - Rejection/Disconnection reason * cinfo.rec_credit - Send credit held by remote SYSAP * pb - Path Block pointer * pinfo.duetime - SCS response due time( seconds ) * pinfo.status.sanity - 1 * scs_msgbuf - Address of SCS send message buffer * timeout - SCS protocol sequence timeout queue pointers * * SMP: The SCA database is locked( EXTERNALLY ) to guarantee the * validity of PB addresses and to allow for PB insertion onto the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -