bool gcd_skip( GCD_CCB *ccb, u_i2 length ) { if ( length <= ccb->msg.msg_len ) while( length ) { GCD_RCB *rcb = (GCD_RCB *)ccb->msg.msg_q.q_next; u_i2 len; if ( (len = min( length, rcb->msg.msg_len )) ) { rcb->buf_ptr += len; rcb->buf_len -= len; rcb->msg.msg_len -= len; ccb->msg.msg_len -= len; length -= len; } if ( ! rcb->msg.msg_len ) { QUremove( &rcb->q ); gcd_del_rcb( rcb ); } } return( ! length ); }
bool gcd_get_bytes( GCD_CCB *ccb, u_i2 length, u_i1 *ptr ) { if ( length <= ccb->msg.msg_len ) while( length ) { GCD_RCB *rcb = (GCD_RCB *)ccb->msg.msg_q.q_next; u_i2 len; if ( (len = min( length, rcb->msg.msg_len )) ) { MEcopy( (PTR)rcb->buf_ptr, len, (PTR)ptr ); rcb->buf_ptr += len; rcb->buf_len -= len; rcb->msg.msg_len -= len; ccb->msg.msg_len -= len; ptr += len; length -= len; } if ( ! rcb->msg.msg_len ) { QUremove( &rcb->q ); gcd_del_rcb( rcb ); } } return( ! length ); }
static void dmtl_send( GCD_RCB *rcb ) { DAM_TL_HDR hdr; GCD_CCB *ccb = rcb->ccb; /* ** Consume RCB if we can't pass to GCC, */ if ( ! ccb->tl.gcc_service ) gcd_del_rcb( rcb ); else { if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL sending data\n", ccb->id ); /* ** Build TL Data packet header and send. */ hdr.tl_id = ccb->tl.packet_id; hdr.msg_id = DAM_TL_DT; build_hdr( rcb, &hdr ); (*ccb->tl.gcc_service->send)( rcb ); } return; }
void gcd_del_pcb( GCD_PCB *pcb ) { if ( GCD_global.gcd_trace_level >= 6 ) TRdisplay( "%4d GCD del PCB (%p)\n", pcb->ccb->id, pcb ); if ( pcb->rcb ) gcd_del_rcb( pcb->rcb ); MEfree( (PTR)pcb ); return; }
static bool copy_atom ( GCD_CCB *ccb, u_i2 length, void (*func)( u_i1 *, u_i1 * ), u_i1 *ptr ) { if ( length <= ccb->msg.msg_len ) while( length ) { GCD_RCB *rcb = (GCD_RCB *)ccb->msg.msg_q.q_next; if ( rcb->msg.msg_len ) if ( length > rcb->msg.msg_len ) { /* ** Atomic values must not be split. */ break; } else { (*func)( rcb->buf_ptr, ptr ); rcb->buf_ptr += length; rcb->buf_len -= length; rcb->msg.msg_len -= length; ccb->msg.msg_len -= length; length = 0; } if ( ! rcb->msg.msg_len ) { QUremove( &rcb->q ); gcd_del_rcb( rcb ); } } return( ! length ); }
static void dmtl_shutdown( GCD_CCB *ccb, GCD_RCB *rcb, STATUS status ) { /* ** Terminate the MSG service. */ if ( ccb->tl.msg_service ) { (*ccb->tl.msg_service->abort)( ccb ); ccb->tl.msg_service = NULL; } /* ** Terminate the GCC service. */ if ( ccb->tl.gcc_service ) { if ( status != OK ) { /* ** Abort the connection. */ send_dr( ccb, rcb, status ); rcb = NULL; /* Passed to GCC */ } (*ccb->tl.gcc_service->disc)( ccb ); ccb->tl.gcc_service = NULL; } /* ** Free RCB if not used above since we are ** expected to consume the RCB. */ if ( rcb ) gcd_del_rcb( rcb ); return; }
void gcd_del_ccb( GCD_CCB *ccb ) { if ( ccb->use_cnt ) ccb->use_cnt--; if ( ccb->use_cnt ) { if ( GCD_global.gcd_trace_level >= 5 ) TRdisplay( "%4d GCD del CCB (use count %d)\n", ccb->id, ccb->use_cnt ); } else { GCD_RCB *rcb; GCD_SCB *scb; QUEUE *q; QUremove( &ccb->q ); GCD_global.ccb_active--; if ( ccb->qry.crsr_name ) MEfree( (PTR)ccb->qry.crsr_name ); if ( ccb->qry.schema_name ) MEfree( (PTR)ccb->qry.schema_name ); if ( ccb->qry.proc_name ) MEfree( (PTR)ccb->qry.proc_name ); if ( ccb->qry.qtxt_max ) MEfree( (PTR)ccb->qry.qtxt ); if ( ccb->rqst.rqst_id0 ) MEfree( (PTR)ccb->rqst.rqst_id0 ); if ( ccb->rqst.rqst_id1 ) MEfree( (PTR)ccb->rqst.rqst_id1 ); if ( ccb->client_user ) MEfree( (PTR)ccb->client_user ); if ( ccb->client_host ) MEfree( (PTR)ccb->client_host ); if ( ccb->client_addr ) MEfree( (PTR)ccb->client_addr ); gcd_free_qdata( &ccb->qry.svc_parms ); gcd_free_qdata( &ccb->qry.qry_parms ); gcd_free_qdata( &ccb->qry.all_parms ); /* ** Free control blocks and request queues. */ if ( ccb->cib ) gcd_del_cib( ccb->cib ); if ( ccb->xact.savepoints ) gcd_release_sp( ccb, NULL ); if ( ccb->msg.xoff_pcb ) gcd_del_pcb( (GCD_PCB *)ccb->msg.xoff_pcb ); if ( ccb->gcc.abort_rcb ) gcd_del_rcb( (GCD_RCB *)ccb->gcc.abort_rcb ); while( (scb = (GCD_SCB *)QUremove( ccb->stmt.stmt_q.q_next )) ) { gcd_free_qdata( &scb->column ); MEfree( (PTR)scb ); } while( (rcb = (GCD_RCB *)QUremove( ccb->gcc.send_q.q_next )) ) gcd_del_rcb( rcb ); while( (rcb = (GCD_RCB *)QUremove( ccb->msg.msg_q.q_next )) ) gcd_del_rcb( rcb ); while( (rcb = (GCD_RCB *)QUremove( ccb->msg.info_q.q_next )) ) gcd_del_rcb( rcb ); /* Free RCB must be physically freed */ while( (rcb = (GCD_RCB *)QUremove( ccb->rcb_q.q_next )) ) gcd_free_rcb( rcb ); while( (q = QUremove( ccb->rqst.rqst_q.q_next )) ) MEfree( (PTR)q ); /* ** Save CCB on free queue. */ QUinsert( &ccb->q, GCD_global.ccb_free.q_prev ); if ( GCD_global.gcd_trace_level >= 5 ) TRdisplay( "%4d GCD del CCB (%d)\n", ccb->id, ccb->id ); } return; }
static void send_dr( GCD_CCB *ccb, GCD_RCB *rcb, STATUS error ) { DAM_TL_HDR hdr; if ( ! ccb->tl.gcc_service ) /* Already shutdown? */ { /* ** Consume RCB if provided. */ if ( rcb ) gcd_del_rcb( rcb ); return; } if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL aborting connection: 0x%x\n", ccb->id, error ); /* ** If RCB provided, initialize since it may ** have contained data. Allocate otherwise. ** Allow room for error parameter. */ if ( rcb ) gcd_init_rcb( rcb ); else if ( ! (rcb = gcd_new_rcb( ccb, (CV_N_I1_SZ * 2) + CV_N_I4_SZ )) ) return; /* ** Return error code to client when provided. */ if ( error != OK && error != FAIL ) { DAM_TL_PARAM param; STATUS status; param.param_id = DAM_TL_DP_ERR; CV2N_I1_MACRO( ¶m.param_id, &rcb->buf_ptr[ rcb->buf_len ], &status ); rcb->buf_len += CV_N_I1_SZ; param.pl1 = CV_N_I4_SZ; CV2N_I1_MACRO( ¶m.pl1, &rcb->buf_ptr[ rcb->buf_len ], &status ); rcb->buf_len += CV_N_I1_SZ; CV2N_I4_MACRO( &error, &rcb->buf_ptr[ rcb->buf_len ], &status ); rcb->buf_len += CV_N_I4_SZ; } /* ** Add TL packet header and send packet. */ hdr.tl_id = ccb->tl.packet_id; hdr.msg_id = DAM_TL_DR; build_hdr( rcb, &hdr ); (*ccb->tl.gcc_service->send)( rcb ); return; }
static void dmtl_data( GCD_RCB *rcb ) { GCD_CCB *ccb = rcb->ccb; DAM_TL_HDR hdr; STATUS status = E_GC480A_PROTOCOL_ERROR; u_i2 pkt_type; /* ** Breaking from the switch will shutdown the connection. ** If status is not changed, connection will be aborted ** with protocol error (set to OK for simple shutdown). ** Set the rcb to NULL if not used for new request. ** ** Return directly in the switch for any other result ** (but make sure RCB is used or freed). */ switch( (pkt_type = read_hdr( rcb, &hdr )) ) { case DAM_TL_CR : case DAM_TL_CC : case DAM_TL_DC : /* ** The Connection Request packet is expected only ** initially and should be passed to dmtl_accept(). ** ** The Connection Confirm packet is never expected. ** ** We only send a Disconnect Request when aborting ** the connection and we don't wait for a response, ** so we don't expect a Disconnect Confirmation. */ if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD unexpected DMTL packet: 0x%x\n", ccb->id, pkt_type ); break; case DAM_TL_DT : /* Data */ if ( ccb->tl.msg_service ) { if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL received data\n", ccb->id ); /* ** Pass to MSG Layer and exit successfully. */ (*ccb->tl.msg_service->data)( rcb ); return; } break; case DAM_TL_INT: /* Interrupt */ if ( ccb->tl.msg_service ) { if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL interrupt\n", ccb->id ); /* ** Notify MSG Layer and exit successfully. ** Need to free RCB as we are expected to ** consume the RCB. */ gcd_del_rcb( rcb ); (*ccb->tl.msg_service->intr)( ccb ); return; } break; case DAM_TL_DR : /* Disconnect */ if ( ccb->tl.gcc_service ) { if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL disconnecting\n", ccb->id ); gcd_init_rcb( rcb ); hdr.msg_id = DAM_TL_DC; build_hdr( rcb, &hdr ); (*ccb->tl.gcc_service->send)( rcb ); rcb = NULL; /* Passed to GCC */ status = OK; /* Shutdown, don't abort */ } break; default : if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD invalid DMTL packet: ID=0x%x Type=0x%x\n", ccb->id, hdr.tl_id, hdr.msg_id ); break; } dmtl_shutdown( ccb, rcb, status ); return; }