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; }
void gcd_msg_cursor( GCD_CCB *ccb ) { DAM_ML_CUR cursor; STMT_ID stmt_id; GCD_SCB *scb; GCD_PCB *pcb; STATUS status; u_i2 pos_anchor = MSG_POS_CURRENT; /* Default to NEXT */ i4 pos_offset = 1; u_i4 pre_fetch = 1; bool incomplete = FALSE; bool got_id = FALSE; if ( ! gcd_get_i2( ccb, (u_i1 *)&cursor.cursor_op ) ) { if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD no cursor op specified\n", ccb->id ); gcd_sess_abort( ccb, E_GC480A_PROTOCOL_ERROR ); return; } if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD Cursor operation: %s\n", ccb->id, gcu_lookup( curMap, cursor.cursor_op ) ); if ( ! (pcb = gcd_new_pcb( ccb )) || ! (pcb->rcb = gcd_new_rcb( ccb, -1 )) ) { if ( pcb ) gcd_del_pcb( pcb ); gcd_sess_abort( ccb, E_GC4808_NO_MEMORY ); return; } while( ccb->msg.msg_len ) { DAM_ML_PM cp; u_i1 u_i1_val; u_i2 u_i2_val; u_i4 u_i4_val; incomplete = TRUE; if ( ! gcd_get_i2( ccb, (u_i1 *)&cp.param_id ) ) break; if ( ! gcd_get_i2( ccb, (u_i1 *)&cp.val_len ) ) break; switch( cp.param_id ) { case MSG_CUR_STMT_ID : if ( cp.val_len != (CV_N_I4_SZ * 2) || ! gcd_get_i4( ccb, (u_i1 *)&stmt_id.id_high ) || ! gcd_get_i4( ccb, (u_i1 *)&stmt_id.id_low ) ) break; incomplete = FALSE; got_id = TRUE; break; case MSG_CUR_PRE_FETCH : switch( cp.val_len ) { case 1 : if ( gcd_get_i1( ccb, (u_i1 *)&u_i1_val ) ) { pre_fetch = max( pre_fetch, u_i1_val ); incomplete = FALSE; } break; case 2 : if ( gcd_get_i2( ccb, (u_i1 *)&u_i2_val ) ) { pre_fetch = max( pre_fetch, u_i2_val ); incomplete = FALSE; } break; case 4 : if ( gcd_get_i4( ccb, (u_i1 *)&u_i4_val ) ) { pre_fetch = max( pre_fetch, u_i4_val ); incomplete = FALSE; } break; } break; case MSG_CUR_POS_ANCHOR : switch( cp.val_len ) { case 1 : if ( gcd_get_i1( ccb, (u_i1 *)&u_i1_val ) ) { pos_anchor = (u_i2)u_i1_val; incomplete = FALSE; } break; case 2 : if ( gcd_get_i2( ccb, (u_i1 *)&u_i2_val ) ) { pos_anchor = (u_i2)u_i2_val; incomplete = FALSE; } break; case 4 : if ( gcd_get_i4( ccb, (u_i1 *)&u_i4_val ) ) { pos_anchor = (u_i2)u_i2_val; incomplete = FALSE; } break; } break; case MSG_CUR_POS_OFFSET : if ( cp.val_len != CV_N_I4_SZ || ! gcd_get_i4( ccb, (u_i1 *)&pos_offset ) ) break; incomplete = FALSE; break; default : if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD unkown parameter ID %d\n", ccb->id, cp.param_id ); break; } if ( incomplete ) break; } if ( incomplete ) { if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD unable to read all cursor parameters %d\n", ccb->id ); status = E_GC480A_PROTOCOL_ERROR; } else if ( ! got_id ) { if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD no cursor ID for cursor message\n", ccb->id ); status = E_GC480A_PROTOCOL_ERROR; } else status = OK; if ( status != OK ) { gcd_del_pcb( pcb ); gcd_sess_abort( ccb, status ); return; } if ( ! (scb = gcd_find_stmt( ccb, &stmt_id )) ) { if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD no active statement for cursor ID\n", ccb->id ); gcd_sess_error( ccb, &pcb->rcb, E_GC4811_NO_STMT ); gcd_send_done( ccb, &pcb->rcb, pcb ); gcd_del_pcb( pcb ); gcd_msg_pause( ccb, TRUE ); return; } switch( cursor.cursor_op ) { case MSG_CUR_CLOSE : ccb->sequence = CLOSE_CURSOR; pcb->scb = scb; crsr_close_sm( (PTR)pcb ); break; case MSG_CUR_FETCH : ccb->sequence = FETCH_INIT; ccb->api.stmt = scb->handle; /* Activate statement */ pcb->scb = scb; pcb->data.data.reference = pos_anchor; pcb->data.data.offset = pos_offset; pcb->data.data.max_row = pre_fetch; crsr_fetch_sm( (PTR)pcb ); break; default : if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD invalid cursor op: %d\n", ccb->id, cursor.cursor_op ); gcd_del_pcb( pcb ); gcd_sess_abort( ccb, E_GC480A_PROTOCOL_ERROR ); } return; }