GCD_CIB * gcd_new_cib( u_i2 count ) { GCD_CIB *cib = NULL; u_i2 len = sizeof( GCD_CIB ) + (sizeof(CONN_PARM) * (count - 1)); if ( count < ARR_SIZE( GCD_global.cib_free ) ) if (! (cib = (GCD_CIB *)QUremove(GCD_global.cib_free[count].q_next))) if ( (cib = (GCD_CIB *)MEreqmem( 0, len, FALSE, NULL )) ) cib->id = GCD_global.cib_total++; if ( ! cib ) gcu_erlog(0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL); else { u_i4 id = cib->id; char buff[16]; MEfill( len, 0, (PTR)cib ); cib->id = id; cib->parm_max = count; QUinit( &cib->caps ); MOulongout( 0, (u_i8)cib->id, sizeof( buff ), buff ); MOattach( MO_INSTANCE_VAR, GCD_MIB_DBMS, buff, (PTR)cib ); GCD_global.cib_active++; if ( GCD_global.gcd_trace_level >= 6 ) TRdisplay( "%4d GCD new CIB (%d)\n", -1, cib->id ); } return( cib ); }
STATUS jdbc_gca_init( char *myaddr ) { GCA_PARMLIST parms; STATUS status; MEfill( sizeof(parms), 0, (PTR) &parms); parms.gca_in_parms.gca_local_protocol = JDBC_GCA_PROTO_LVL; parms.gca_in_parms.gca_normal_completion_exit = gca_sm; parms.gca_in_parms.gca_expedited_completion_exit = gca_sm; parms.gca_in_parms.gca_modifiers |= GCA_API_VERSION_SPECD; parms.gca_in_parms.gca_api_version = GCA_API_LEVEL_5; IIGCa_cb_call( &gca_cb, GCA_INITIATE, &parms, GCA_SYNC_FLAG, NULL, -1, &status ); if ( status != OK || (status = parms.gca_in_parms.gca_status) != OK ) { gcu_erlog( 0, JDBC_global.language, status, &parms.gca_in_parms.gca_os_status, 0, NULL ); return( status ); } MEfill( sizeof(parms), 0, (PTR) &parms); parms.gca_rg_parms.gca_srvr_class = JDBC_SRV_CLASS; parms.gca_rg_parms.gca_l_so_vector = 0; parms.gca_rg_parms.gca_served_object_vector = NULL; parms.gca_rg_parms.gca_installn_id = ""; IIGCa_cb_call( &gca_cb, GCA_REGISTER, &parms, GCA_SYNC_FLAG, NULL, -1, &status ); if ( status != OK || (status = parms.gca_rg_parms.gca_status) != OK ) { gcu_erlog( 0, JDBC_global.language, status, &parms.gca_rg_parms.gca_os_status, 0, NULL ); return( status ); } gca_sm( 0 ); STcopy( parms.gca_rg_parms.gca_listen_id, myaddr ); return( OK ); }
bool gcd_alloc_qdesc( QDATA *qdata, u_i2 count, PTR desc ) { qdata->max_rows = 0; qdata->max_cols = count; qdata->col_cnt = 0; qdata->cur_col = 0; qdata->more_segments = FALSE; qdata->desc = NULL; if ( ! qdata->max_cols ) return( FALSE ); if ( desc ) qdata->desc = desc; else { /* ** Expand descriptor array if needed. */ if ( qdata->max_cols > qdata->desc_max ) { if ( qdata->param_desc ) { IIAPI_DESCRIPTOR *desc = (IIAPI_DESCRIPTOR *)qdata->param_desc; u_i2 i; for( i = 0; i < qdata->desc_max; i++ ) if ( desc[i].ds_columnName ) MEfree( desc[i].ds_columnName ); MEfree( qdata->param_desc ); } if ( ! (qdata->param_desc = MEreqmem( 0, sizeof(IIAPI_DESCRIPTOR) * qdata->max_cols, TRUE, NULL )) ) { gcu_erlog( 0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL); return( FALSE ); } qdata->desc_max = qdata->max_cols; } qdata->desc = qdata->param_desc; } return( TRUE ); }
GCD_PCB * gcd_new_pcb( GCD_CCB *ccb ) { GCD_PCB *pcb; if ( ! (pcb = (GCD_PCB *)MEreqmem( 0, sizeof( GCD_PCB ), TRUE, NULL )) ) gcu_erlog(0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL); else { if ( GCD_global.gcd_trace_level >= 6 ) TRdisplay( "%4d GCD new PCB (%p)\n", ccb->id, pcb ); pcb->ccb = ccb; } return( pcb ); }
GCD_CCB * gcd_new_ccb( void ) { GCD_CCB *ccb; if ( ! (ccb = (GCD_CCB *)QUremove( GCD_global.ccb_free.q_next )) ) if ( (ccb = (GCD_CCB *)MEreqmem( 0, sizeof(GCD_CCB), FALSE, NULL )) ) ccb->id = GCD_global.ccb_total++; if ( ! ccb ) gcu_erlog(0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL); else { u_i4 id = ccb->id; MEfill( sizeof( GCD_CCB ), 0, (PTR)ccb ); ccb->id = id; ccb->use_cnt = 1; ccb->max_buff_len = 1 << DAM_TL_PKT_MIN; ccb->tl.proto_lvl = DAM_TL_PROTO_1; ccb->xact.auto_mode = GCD_XACM_DBMS; ccb->api.env = NULL; QUinit( &ccb->q ); QUinit( &ccb->rcb_q ); QUinit( &ccb->gcc.send_q ); QUinit( &ccb->msg.msg_q ); QUinit( &ccb->msg.info_q ); QUinit( &ccb->stmt.stmt_q ); QUinit( &ccb->rqst.rqst_q ); GCD_global.ccb_active++; QUinsert( &ccb->q, &GCD_global.ccb_q ); if ( GCD_global.gcd_trace_level >= 5 ) TRdisplay( "%4d GCD new CCB (%d)\n", ccb->id, ccb->id ); } return( ccb ); }
GCD_RCB * gcd_new_rcb( GCD_CCB *ccb, i2 len ) { GCD_RCB *rcb; /* ** Adjust length to reserve header space. ** ** The majority of RCB allocations are for default ** buffer sizes or no buffers. Re-use free RCB with ** same buffer size if available. */ if ( len == 0 ) rcb = (GCD_RCB *)QUremove( GCD_global.rcb_q.q_next ); else if ( len < 0 ) { /* ** Use the negotiated TL protocol buffer size from ** the CCB (TL header length already included) and ** provide space for the NL header. */ len = ccb->max_buff_len + (u_i2)GCD_global.nl_hdr_sz; rcb = (GCD_RCB *)QUremove( ccb->rcb_q.q_next ); } else { /* ** NL protocol restricts the size of buffers which ** may be sent. Provide space for TL header by ** increasing requested buffer length. Space is ** also provided for the NL header. */ len = min( len + (u_i2)GCD_global.tl_hdr_sz, ccb->max_buff_len ) + (u_i2)GCD_global.nl_hdr_sz; rcb = NULL; /* RCB must be allocated */ } if ( rcb ) MEfill( sizeof( GCD_RCB ), 0, rcb ); else { rcb = (GCD_RCB *)MEreqmem( 0, sizeof( GCD_RCB ) + len, TRUE, NULL ); if ( ! rcb ) { gcu_erlog( 0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL ); return( NULL ); } if ( GCD_global.gcd_trace_level >= 6 ) TRdisplay( "%4d GCD new RCB[%d] (%p)\n", ccb->id, len, rcb ); } rcb->ccb = ccb; if ( len ) { rcb->buffer = (u_i1 *)rcb + sizeof( GCD_RCB ); rcb->buf_max = (u_i2)len; gcd_init_rcb( rcb ); } return( rcb ); }
static bool alloc_qdata( QDATA *qdata, u_i2 max_rows, bool alloc_buffers ) { IIAPI_DESCRIPTOR *desc; IIAPI_DATAVALUE *data; u_i2 row, col, seg_len; u_i4 dv; u_i4 blen, length; u_i4 tot_cols = max_rows * qdata->max_cols; qdata->max_rows = max_rows; qdata->col_cnt = 0; qdata->cur_col = 0; qdata->more_segments = FALSE; if ( ! qdata->max_rows || ! qdata->max_cols ) return( FALSE ); /* ** Expand data value array if needed. */ if ( tot_cols > qdata->data_max ) { if ( qdata->data ) MEfree( qdata->data ); if ( ! (qdata->data = MEreqmem( 0, sizeof( IIAPI_DATAVALUE ) * tot_cols, TRUE, NULL )) ) { gcu_erlog( 0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL); return( FALSE ); } qdata->data_max = tot_cols; } if ( ! alloc_buffers ) return( TRUE ); desc = (IIAPI_DESCRIPTOR *)qdata->desc; data = (IIAPI_DATAVALUE *)qdata->data; for( col = length = seg_len = 0; col < qdata->max_cols; col++ ) switch( desc[ col ].ds_dataType) { case IIAPI_LVCH_TYPE: case IIAPI_LNVCH_TYPE: case IIAPI_LBYTE_TYPE: case IIAPI_GEOM_TYPE: case IIAPI_POINT_TYPE: case IIAPI_MPOINT_TYPE: case IIAPI_LINE_TYPE: case IIAPI_MLINE_TYPE: case IIAPI_POLY_TYPE: case IIAPI_MPOLY_TYPE: case IIAPI_GEOMC_TYPE: { seg_len = max( seg_len, desc[ col ].ds_length ); break; } default: { length += desc[ col ].ds_length; break; } } if ( (blen = (length * qdata->max_rows)) > qdata->db_max ) { if ( qdata->data_buff ) MEfree( qdata->data_buff ); if ( ! (qdata->data_buff = MEreqmem( 0, blen, FALSE, NULL )) ) { gcu_erlog( 0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL); return( FALSE ); } qdata->db_max = blen; } if ( seg_len > qdata->bb_max ) { if ( qdata->blob_buff ) MEfree( qdata->blob_buff ); if ( ! (qdata->blob_buff = MEreqmem( 0, seg_len, FALSE, NULL )) ) { gcu_erlog( 0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL); return( FALSE ); } qdata->bb_max = seg_len; } for( row = dv = length = 0; row < qdata->max_rows; row++ ) for( col = 0; col < qdata->max_cols; col++, dv++ ) switch( desc[ col ].ds_dataType) { case IIAPI_LVCH_TYPE: case IIAPI_LNVCH_TYPE: case IIAPI_LBYTE_TYPE: case IIAPI_GEOM_TYPE: case IIAPI_POINT_TYPE: case IIAPI_MPOINT_TYPE: case IIAPI_LINE_TYPE: case IIAPI_MLINE_TYPE: case IIAPI_POLY_TYPE: case IIAPI_MPOLY_TYPE: case IIAPI_GEOMC_TYPE: { data[ dv ].dv_value = (char *)qdata->blob_buff; break; } default: { data[ dv ].dv_value = (char *)qdata->data_buff + length; length += desc[ col ].ds_length; } } return( TRUE ); }
static STATUS initialize( i4 argc, char **argv ) { CL_ERR_DESC cl_err; char *instance = ERx("*"); char *env; char name[ 16 ]; i4 i; GCD_global.language = 1; MHsrand( TMsecs() ); for( i = 1; i < argc; i++ ) if ( ! STbcompare( argv[i], 0, ERx("-instance"), 9, TRUE ) ) { if ( argv[i][9] == ERx('=') && argv[i][10] != EOS ) instance = &argv[i][10]; else if ( argv[i][9] == EOS && (i + 1) < argc ) instance = argv[++i]; break; } NMgtAt( ERx("II_INSTALLATION"), &env ); STprintf( name, ERx("II_CHARSET%s"), (env && *env) ? env : "" ); NMgtAt( name, &env ); if ( ! env || ! *env || STlength(env) > CM_MAXATTRNAME) { switch( CMgetDefCS() ) { #if ( !defined(UNIX) && !defined(VMS) ) case CM_IBM : env = "IBMPC850"; break; #endif case CM_DECMULTI : env = "DECMULTI"; break; default : env = "ISO88591"; break; } } GCD_global.charset = STalloc( env ); CVupper( GCD_global.charset ); gcu_read_cset( gcd_cset_id ); if ( CMset_attr( GCD_global.charset, &cl_err) != OK ) { gcu_erlog( 0, GCD_global.language, E_GC0105_GCN_CHAR_INIT, NULL, 0, NULL ); return( E_GC0105_GCN_CHAR_INIT ); } PMinit(); switch( PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)NULL ) ) { case OK: break; case PM_FILE_BAD: gcu_erlog( 0, GCD_global.language, E_GC003D_BAD_PMFILE, NULL, 0, NULL ); return( E_GC003D_BAD_PMFILE ); break; default: gcu_erlog( 0, GCD_global.language, E_GC003E_PMLOAD_ERR, NULL, 0, NULL ); return( E_GC003E_PMLOAD_ERR ); break; } PMsetDefault( 0, SystemCfgPrefix ); PMsetDefault( 1, PMhost() ); PMsetDefault( 2, ERx("gcd") ); PMsetDefault( 3, instance ); gcd_tl_services[0] = &gcd_dmtl_service; gcd_tl_services[1] = &gcd_jctl_service; GCD_global.tl_services = gcd_tl_services; GCD_global.tl_srvc_cnt = ARR_SIZE( gcd_tl_services ); QUinit( &GCD_global.pib_q ); QUinit( &GCD_global.rcb_q ); QUinit( &GCD_global.ccb_q ); QUinit( &GCD_global.ccb_free ); for( i = 0; i < ARR_SIZE( GCD_global.cib_free ); i++ ) QUinit( &GCD_global.cib_free[ i ] ); env = NULL; gcu_get_tracesym( NULL, ERx("!.client_max"), &env ); if ( env && *env ) { i4 count; if ( CVal( env, &count ) == OK && count > 0 ) GCD_global.client_max = count; } env = NULL; gcu_get_tracesym( NULL, ERx("!.client_timeout"), &env ); if ( env && *env ) { i4 timeout; if ( CVal( env, &timeout ) == OK && timeout > 0 ) GCD_global.client_idle_limit = timeout * 60; /* Cnvt to seconds */ } env = NULL; gcu_get_tracesym( NULL, ERx("!.connect_pool_status"), &env ); if ( env && *env ) { if ( ! STbcompare( env, 0, "optional", 0, TRUE ) ) GCD_global.client_pooling = TRUE; if ( GCD_global.client_pooling || ! STbcompare( env, 0, "on", 0, TRUE ) ) { env = NULL; gcu_get_tracesym( NULL, ERx("!.connect_pool_size"), &env ); if ( env && *env ) CVal( env, &GCD_global.pool_max ); env = NULL; gcu_get_tracesym( NULL, ERx("!.connect_pool_expire"), &env ); if ( env && *env ) { i4 limit; if ( CVal( env, &limit ) == OK && limit > 0 ) GCD_global.pool_idle_limit = limit * 60; /* Seconds */ } } } env = NULL; gcu_get_tracesym( "II_GCD_TRACE", ERx("!.gcd_trace_level"), &env ); if ( env && *env ) CVal( env, &GCD_global.gcd_trace_level ); env = NULL; gcu_get_tracesym( "II_GCD_LOG", ERx("!.gcd_trace_log"), &env ); if ( env && *env ) TRset_file( TR_F_OPEN, env, (i4)STlength( env ), &cl_err ); return( OK ); }
int main( int argc, char **argv ) { EX_CONTEXT context; char name[ GCC_L_PORT + 1 ]; u_i2 apivers; PTR hndl; #ifdef LNX PCsetpgrp(); #endif MEadvise( ME_INGRES_ALLOC ); if ( EXdeclare( GCX_exit_handler, &context ) != OK ) { gcu_erlog( 0, 1, E_GC480F_EXCEPTION, NULL, 0, NULL ); PCexit( OK ); return( 0 ); } GChostname( GCD_global.host, sizeof( GCD_global.host ) ); gcu_erinit( GCD_global.host, GCD_LOG_ID, "" ); if ( initialize( argc, argv ) != OK ) gcd_exit(); gcd_init_mib(); if ( gcd_gca_init( ) != OK ) gcd_exit(); gcu_erinit( GCD_global.host, GCD_LOG_ID, GCD_global.gcd_lcl_id ); if ( gcd_adm_init() != OK ) gcd_exit(); apivers = gcd_msg_version( MSG_DFLT_PROTO ); if ( gcd_get_env( apivers, &hndl ) != OK ) gcd_exit(); if ( gcd_pool_init() != OK ) gcd_exit(); if ( gcd_gcc_init() != OK ) gcd_exit(); /* ** Log Server startup. */ { char server_flavor[256], server_type[32]; char *tmpbuf = PMgetDefault(3); ER_ARGUMENT erlist[2]; SIstd_write(SI_STD_OUT, "PASS\n"); if ( ! STbcompare( tmpbuf, 0, "*", 0, TRUE ) ) STcopy( "(DEFAULT)", server_flavor ); else STcopy( tmpbuf, server_flavor ); STcopy(PMgetDefault(2), server_type); CVupper(server_type); erlist[0].er_value = server_flavor; erlist[0].er_size = STlength(server_flavor); erlist[1].er_value = server_type; erlist[1].er_size = STlength(server_type); gcu_erlog( 0, GCD_global.language, E_GC4802_LOAD_CONFIG, NULL, 2, (PTR)&erlist ); gcu_erlog( 0, GCD_global.language, E_GC4800_STARTUP, NULL, 0, NULL ); } GCexec(); gcd_gcc_term(); gcd_pool_term(); gcd_rel_env(0); gcd_adm_term(); gcd_gca_term(); gcu_erlog( 0, GCD_global.language, E_GC4801_SHUTDOWN, NULL, 0, NULL ); EXdelete(); PCexit( OK ); return( 0 ); }
static void crsr_cols ( GCD_CCB *ccb, GCD_SCB *scb, GCD_RCB **rcb_ptr, u_i2 row, bool more_segments ) { IIAPI_DESCRIPTOR *desc = (IIAPI_DESCRIPTOR *)scb->column.desc; IIAPI_DATAVALUE *data = &((IIAPI_DATAVALUE *)scb->column.data)[ row * scb->column.max_cols ]; u_i2 end = scb->column.cur_col + scb->column.col_cnt; u_i2 col, len; for( col = scb->column.cur_col; col < end; col++ ) { if ( desc[ col ].ds_nullable && data[ col ].dv_null ) { gcd_put_i1( rcb_ptr, 0 ); /* No data - NULL value */ continue; } /* ** Write the data indicator byte, for BLOBs this is ** only done on the first segment (more_segments is ** saved below once the segment has been processed, ** so the saved value is FALSE on the first segment). */ if ( (desc[ col ].ds_dataType != IIAPI_LVCH_TYPE && desc[ col ].ds_dataType != IIAPI_LNVCH_TYPE && desc[ col ].ds_dataType != IIAPI_LBYTE_TYPE) || ! scb->column.more_segments ) gcd_put_i1( rcb_ptr, 1 ); switch( desc[ col ].ds_dataType ) { case IIAPI_INT_TYPE : switch( desc[ col ].ds_length ) { case 1 : gcd_put_i1p(rcb_ptr, (u_i1 *)data[col].dv_value); break; case 2 : gcd_put_i2p(rcb_ptr, (u_i1 *)data[col].dv_value); break; case 4 : gcd_put_i4p(rcb_ptr, (u_i1 *)data[col].dv_value); break; case 8 : gcd_put_i8p(rcb_ptr, (u_i1 *)data[col].dv_value); break; } break; case IIAPI_FLT_TYPE : switch( desc[ col ].ds_length ) { case 4 : gcd_put_f4p(rcb_ptr, (u_i1 *)data[col].dv_value); break; case 8 : gcd_put_f8p(rcb_ptr, (u_i1 *)data[col].dv_value); break; } break; case IIAPI_MNY_TYPE : { IIAPI_DESCRIPTOR idesc, ddesc; IIAPI_DATAVALUE idata, ddata; STATUS status; char dbuff[ 130 ]; /* varchar(128) */ char dec[ 8 ]; /* ** It would be nice to convert directly to ** varchar, but money formatting is nasty. ** So we first convert to decimal, then to ** varchar. */ idesc.ds_dataType = IIAPI_DEC_TYPE; idesc.ds_nullable = FALSE; idesc.ds_length = sizeof( dec ); idesc.ds_precision = 15; idesc.ds_scale = 2; idata.dv_null = FALSE; idata.dv_length = sizeof( dec ); idata.dv_value = (PTR)&dec; ddesc.ds_dataType = IIAPI_VCH_TYPE; ddesc.ds_nullable = FALSE; ddesc.ds_length = sizeof( dbuff ); ddesc.ds_precision = 0; ddesc.ds_scale = 0; ddata.dv_null = FALSE; ddata.dv_length = sizeof( dbuff ); ddata.dv_value = dbuff; if ( (status = gcd_api_format( ccb, &desc[ col ], &data[ col ], &idesc, &idata )) != OK || (status = gcd_api_format( ccb, &idesc, &idata, &ddesc, &ddata )) != OK ) { /* ** Conversion error. Send a zero-length ** string as error indication and log error. */ gcd_put_i2( rcb_ptr, 0 ); gcu_erlog( 0, GCD_global.language, status, NULL, 0, NULL ); } else { MEcopy( (PTR)dbuff, 2, (PTR)&len ); gcd_put_i2( rcb_ptr, len ); gcd_put_bytes( rcb_ptr, len, (u_i1 *)&dbuff[2] ); } } break; case IIAPI_BOOL_TYPE : gcd_put_i1p( rcb_ptr, (u_i1 *)data[ col ].dv_value ); break; case IIAPI_DEC_TYPE : /* These types are all sent in text format */ case IIAPI_DTE_TYPE : case IIAPI_DATE_TYPE : case IIAPI_TIME_TYPE : case IIAPI_TMWO_TYPE : case IIAPI_TMTZ_TYPE : case IIAPI_TS_TYPE : case IIAPI_TSWO_TYPE : case IIAPI_TSTZ_TYPE : case IIAPI_INTYM_TYPE : case IIAPI_INTDS_TYPE : { IIAPI_DESCRIPTOR ddesc; IIAPI_DATAVALUE ddata; STATUS status; char dbuff[ 130 ]; /* varchar(128) */ ddesc.ds_dataType = IIAPI_VCH_TYPE; ddesc.ds_nullable = FALSE; ddesc.ds_length = sizeof( dbuff ); ddesc.ds_precision = 0; ddesc.ds_scale = 0; ddata.dv_null = FALSE; ddata.dv_length = sizeof( dbuff ); ddata.dv_value = dbuff; status = gcd_api_format( ccb, &desc[ col ], &data[ col ], &ddesc, &ddata ); if ( status != OK ) { /* ** Conversion error. Send a zero-length ** string as error indication and log error. */ gcd_put_i2( rcb_ptr, 0 ); gcu_erlog( 0, GCD_global.language, status, NULL, 0, NULL ); } else { MEcopy( (PTR)dbuff, 2, (PTR)&len ); gcd_put_i2( rcb_ptr, len ); gcd_put_bytes( rcb_ptr, len, (u_i1 *)&dbuff[2] ); } } break; case IIAPI_CHA_TYPE : case IIAPI_CHR_TYPE : case IIAPI_BYTE_TYPE : gcd_put_bytes( rcb_ptr, desc[ col ].ds_length, (u_i1 *)data[ col ].dv_value ); break; case IIAPI_NCHA_TYPE : gcd_put_ucs2( rcb_ptr, desc[ col ].ds_length / sizeof( UCS2 ), (u_i1 *)data[ col ].dv_value ); break; case IIAPI_TXT_TYPE : case IIAPI_LTXT_TYPE : case IIAPI_VCH_TYPE : case IIAPI_VBYTE_TYPE : MEcopy( data[ col ].dv_value, 2, (PTR)&len ); gcd_put_i2( rcb_ptr, len ); gcd_put_bytes( rcb_ptr, len, (u_i1 *)data[ col ].dv_value + 2 ); break; case IIAPI_NVCH_TYPE : MEcopy( data[ col ].dv_value, 2, (PTR)&len ); gcd_put_i2( rcb_ptr, len ); gcd_put_ucs2( rcb_ptr, len, (u_i1 *)data[ col ].dv_value + 2 ); break; case IIAPI_LCLOC_TYPE : case IIAPI_LNLOC_TYPE : case IIAPI_LBLOC_TYPE : gcd_put_i4p( rcb_ptr, (u_i1 *)data[ col ].dv_value ); break; case IIAPI_LVCH_TYPE : case IIAPI_LNVCH_TYPE : case IIAPI_LBYTE_TYPE : { u_i1 *ptr; u_i2 seg_len, chrs, char_size = sizeof( char ); bool ucs2 = FALSE; if ( desc[ col ].ds_dataType == IIAPI_LNVCH_TYPE ) { ucs2 = TRUE; char_size = sizeof( UCS2 ); } if ( data[ col ].dv_length < 2 ) seg_len = 0; else { MEcopy( data[ col ].dv_value, 2, (PTR)&seg_len ); ptr = (u_i1 *)data[ col ].dv_value + 2; seg_len *= char_size; /* convert array len to byte len */ } /* ** Output data as long as there is sufficient ** data to fill the current message. Any data ** remaining is saved until additional data is ** received or the end of the BLOB is reached. ** ** We actually make sure that room for the ** segment (length indicator and data) and an ** end-of-segments indicator is left in the ** message buffer. This way the end-of-BLOB ** processing below does not need to worry ** about splitting the message. ** ** The test against the save buffer size is ** redundent since the buffer should be at ** least as big as a message buffer, but we ** make the test just to be safe. */ while( (seg_len + scb->seg_len + 4) > RCB_AVAIL(*rcb_ptr) || (seg_len + scb->seg_len) > scb->seg_max ) { /* ** Can a valid data segment be placed in the buffer? */ if ( RCB_AVAIL(*rcb_ptr) >= (2 + char_size) && (seg_len + scb->seg_len) >= char_size ) { len = min( seg_len + scb->seg_len, RCB_AVAIL( *rcb_ptr ) - 2 ); chrs = len / char_size; len = chrs * char_size; gcd_put_i2( rcb_ptr, chrs ); if ( GCD_global.gcd_trace_level >= 5 ) TRdisplay( "%4d GCD send segment: %d (%d,%d)\n", ccb->id, len, scb->seg_len, seg_len ); /* ** First, send saved data. */ if ( scb->seg_len >= char_size ) { len = min( scb->seg_len, RCB_AVAIL( *rcb_ptr ) ); chrs = len / char_size; len = chrs * char_size; if ( ! ucs2 ) gcd_put_bytes( rcb_ptr, len, scb->seg_buff ); else gcd_put_ucs2( rcb_ptr, chrs, scb->seg_buff ); scb->seg_len -= len; if ( scb->seg_len ) MEcopy( (PTR)(scb->seg_buff + len), scb->seg_len, (PTR)scb->seg_buff ); } /* ** Now send data from current segment. */ if ( seg_len >= char_size && RCB_AVAIL( *rcb_ptr ) >= char_size ) { len = min( seg_len, RCB_AVAIL( *rcb_ptr ) ); chrs = len / char_size; len = chrs * char_size; if ( ! ucs2 ) gcd_put_bytes( rcb_ptr, len, ptr ); else gcd_put_ucs2( rcb_ptr, chrs, ptr ); ptr += len; seg_len -= len; } } gcd_msg_end( rcb_ptr, FALSE ); gcd_msg_begin( ccb, rcb_ptr, MSG_DATA, 0 ); } /* ** Save any data left in the current segment. ** The preceding loop makes sure there is room ** in the buffer for the remainder of the ** current segment. */ if ( seg_len ) { if ( ! scb->seg_buff ) { scb->seg_buff = (u_i1 *)MEreqmem( 0, scb->seg_max, FALSE, NULL ); if ( ! scb->seg_buff ) { if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD alloc fail seg: %d\n", ccb->id, scb->seg_max ); gcu_erlog( 0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL ); gcd_sess_abort( ccb, E_GC4808_NO_MEMORY ); return; } } if ( GCD_global.gcd_trace_level >= 5 ) TRdisplay( "%4d GCD save segment: %d (total %d) \n", ccb->id, seg_len, scb->seg_len + seg_len ); MEcopy( (PTR)ptr, seg_len, (PTR)(scb->seg_buff + scb->seg_len) ); scb->seg_len += seg_len; } /* ** When the BLOB is complete, write the last ** segment and end-of-segments indicator. */ if ( ! (scb->column.more_segments = more_segments) ) { /* ** The processing loop above makes sure there ** is room for the last segment. */ if ( scb->seg_len ) { if ( GCD_global.gcd_trace_level >= 5 ) TRdisplay( "%4d GCD send segment: %d \n", ccb->id, scb->seg_len ); chrs = scb->seg_len / char_size; len = chrs * char_size; scb->seg_len = 0; gcd_put_i2( rcb_ptr, chrs ); if ( ! ucs2 ) gcd_put_bytes( rcb_ptr, len, scb->seg_buff ); else gcd_put_ucs2( rcb_ptr, chrs, scb->seg_buff ); } if ( GCD_global.gcd_trace_level >= 5 ) TRdisplay( "%4d GCD send end-of-segments\n", ccb->id ); gcd_put_i2( rcb_ptr, 0 ); } } break; default : /* Should not happen since checked in send_desc() */ if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD invalid datatype: %d\n", ccb->id, desc[ col ].ds_dataType ); gcd_sess_abort( ccb, E_GC4812_UNSUPP_SQL_TYPE ); return; } } return; }
STATUS gcd_api_init( u_i2 api_ver, PTR *env ) { IIAPI_INITPARM init; IIAPI_SETENVPRMPARM set; bool done; STATUS status = OK; init.in_timeout = -1; init.in_version = api_ver; IIapi_initialize( &init ); if ( init.in_status != IIAPI_ST_SUCCESS && GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD Error initializing API: %s\n", -1, gcu_lookup( apiMap, init.in_status ) ); switch( init.in_status ) { case IIAPI_ST_SUCCESS : *env = init.in_envHandle; break; case IIAPI_ST_OUT_OF_MEMORY : status = E_GC4808_NO_MEMORY; break; default : status = E_GC4809_INTERNAL_ERROR; break; } for( done = (status != OK); ! done; done = TRUE ) { II_LONG value; set.se_envHandle = *env; set.se_paramID = IIAPI_EP_TRACE_FUNC; set.se_paramValue = (II_PTR)gcd_api_trace; IIapi_setEnvParam( &set ); if ( (status = set.se_status) != OK ) break; if( api_ver >= IIAPI_VERSION_6 ) { set.se_paramID = IIAPI_EP_DATE_ALIAS; set.se_paramValue = IIAPI_EPV_INGDATE; IIapi_setEnvParam( &set ); if ( (status = set.se_status) != OK ) break; } set.se_paramID = IIAPI_EP_DATE_FORMAT; value = IIAPI_EPV_DFRMT_FINNISH; set.se_paramValue = (II_PTR)&value; IIapi_setEnvParam( &set ); if ( (status = set.se_status) != OK ) break; set.se_paramID = IIAPI_EP_TIMEZONE; set.se_paramValue = "gmt"; IIapi_setEnvParam( &set ); if ( (status = set.se_status) != OK ) break; set.se_paramID = IIAPI_EP_MAX_SEGMENT_LEN; value = 8192; set.se_paramValue = (II_PTR)&value; IIapi_setEnvParam( &set ); if ( (status = set.se_status) != OK ) break; set.se_paramID = IIAPI_EP_DECIMAL_CHAR; set.se_paramValue = "."; IIapi_setEnvParam( &set ); if ( (status = set.se_status) != OK ) break; set.se_paramID = IIAPI_EP_MONEY_SIGN ; set.se_paramValue = "$"; IIapi_setEnvParam( &set ); if ( (status = set.se_status) != OK ) break; set.se_paramID = IIAPI_EP_MONEY_LORT ; value = IIAPI_EPV_MONEY_LEAD_SIGN; set.se_paramValue = (II_PTR)&value; IIapi_setEnvParam( &set ); if ( (status = set.se_status) != OK ) break; set.se_paramID = IIAPI_EP_MONEY_PRECISION ; value = 2; set.se_paramValue = (II_PTR)&value; IIapi_setEnvParam( &set ); if ( (status = set.se_status) != OK ) break; } if ( status != OK ) gcu_erlog( 0, GCD_global.language, status, NULL, 0, NULL ); return( status ); }
static void gca_sm( i4 sid ) { GCA_LCB *lcb = &gca_lcb_tab[ sid ]; bool branch = FALSE; top: if ( JDBC_global.trace_level >= 5 && lsn_states[ lcb->state ].action != LSA_LABEL && lsn_states[ lcb->state ].action != LSA_GOTO ) TRdisplay( "%4d JDBC %s status 0x%x %s\n", sid, lsn_sa_names[ lsn_states[ lcb->state ].action ], lcb->statusp ? *lcb->statusp : OK, branch ? " (branch)" : "" ); branch = FALSE; switch( lsn_states[ lcb->state++ ].action ) { case LSA_INIT : /* Initialize, branch if listening */ branch = listening; lcb->sp = 0; lcb->flags = 0; if ( ! labels[ 1 ] ) { i4 i; for( i = 0; i < ARR_SIZE( lsn_states ); i++ ) if ( lsn_states[ i ].action == LSA_LABEL ) labels[ lsn_states[ i ].label ] = i + 1; } break; case LSA_GOTO : /* Branch unconditionally */ branch = TRUE; break; case LSA_GOSUB : /* Call subroutine */ lcb->ss[ lcb->sp++ ] = lcb->state; branch = TRUE; break; case LSA_RETURN : /* Return from subroutine */ lcb->state = lcb->ss[ --lcb->sp ]; break; case LSA_EXIT : /* Terminate thread */ lcb->state = 0; /* Initialize state */ /* ** Exit if there shutting down or there is an ** active listen. Otherwise, the current ** thread continues as the new listen thread. */ if ( lcb->flags & LCB_SHUTDOWN || listening ) return; break; case LSA_IF_RESUME : /* Branch if INCOMPLETE */ branch = (*lcb->statusp == E_GCFFFE_INCOMPLETE); break; case LSA_IF_TIMEOUT : /* Branch if TIMEOUT */ branch = (*lcb->statusp == E_GC0020_TIME_OUT); break; case LSA_IF_ERROR : /* Branch if status not OK */ branch = (*lcb->statusp != OK); break; case LSA_IF_SHUT : /* Branch if SHUTDOWN requested */ branch = (lcb->flags & LCB_SHUTDOWN) ? TRUE : FALSE; break; case LSA_SET_SHUT: /* Prepare to shutdown server */ GCshut(); lcb->stat = E_GC0040_CS_OK; lcb->statusp = &lcb->stat; break; case LSA_CLEAR_ERR : /* Set status to OK */ lcb->stat = OK; lcb->statusp = &lcb->stat; break; case LSA_LOG : /* Log an error */ if ( *lcb->statusp != OK && *lcb->statusp != FAIL && *lcb->statusp != E_GC0032_NO_PEER ) gcu_erlog( 0, JDBC_global.language, *lcb->statusp, NULL, 0, NULL ); break; case LSA_CHECK : /* Background checks */ jdbc_idle_check(); jdbc_pool_check(); break; case LSA_LISTEN: /* Post a listen */ { i4 timeout = -1; SYSTIME now; MEfill( sizeof(lcb->parms), 0, (PTR) &lcb->parms ); lcb->statusp = &lcb->parms.gca_ls_parms.gca_status; listening = TRUE; TMnow( &now ); if ( JDBC_global.client_idle_limit ) { i4 secs; if ( JDBC_global.client_check.TM_secs <= 0 ) secs = JDBC_global.client_idle_limit; else if ( TMcmp( &now, &JDBC_global.client_check ) < 0 ) secs = JDBC_global.client_check.TM_secs - now.TM_secs; else secs = JDBC_global.client_idle_limit / 2; if ( timeout <= 0 || secs < timeout ) timeout = secs; } if ( JDBC_global.pool_idle_limit ) { i4 secs; if ( JDBC_global.pool_check.TM_secs <= 0 ) secs = JDBC_global.pool_idle_limit; else if ( TMcmp( &now, &JDBC_global.pool_check ) < 0 ) secs = JDBC_global.pool_check.TM_secs - now.TM_secs; else secs = JDBC_global.pool_idle_limit / 2; if ( timeout <= 0 || secs < timeout ) timeout = secs; } /* ** If there is a timeout, leave some ** lee-way to ensure we actually pass ** the target check time. Also, convert ** seconds to milli-seconds. */ if ( timeout >= 0 ) timeout = (timeout + 10) * 1000; IIGCa_cb_call( &gca_cb, GCA_LISTEN, &lcb->parms, GCA_ASYNC_FLAG, (PTR)sid, timeout, &lcb->stat ); if ( lcb->stat != OK ) break; } return; case LSA_LS_RESUME : /* Resume a listen */ IIGCa_cb_call( &gca_cb, GCA_LISTEN, &lcb->parms, GCA_RESUME, (PTR)sid, -1, &lcb->stat ); if ( lcb->stat != OK ) break; return; case LSA_REPOST: /* Repost a listen */ { i4 id; listening = FALSE; for( id = 0; id < LCB_MAX; id++ ) if ( ! gca_lcb_tab[ id ].state ) { gca_sm( id ); break; } } break; case LSA_LS_DONE : /* Listen request has completed */ lcb->assoc_id = lcb->parms.gca_ls_parms.gca_assoc_id; break; case LSA_NEGOTIATE : /* Validate client */ lcb->protocol = min( lcb->parms.gca_ls_parms.gca_partner_protocol, JDBC_GCA_PROTO_LVL ); /* ** Check for shutdown/quiesce request. */ while( lcb->parms.gca_ls_parms.gca_l_aux_data > 0 ) { GCA_AUX_DATA aux_hdr; char *aux_data; i4 aux_len; MEcopy( lcb->parms.gca_ls_parms.gca_aux_data, sizeof( aux_hdr ), (PTR)&aux_hdr ); aux_data = (char *)lcb->parms.gca_ls_parms.gca_aux_data + sizeof( aux_hdr ); aux_len = aux_hdr.len_aux_data - sizeof( aux_hdr ); switch( aux_hdr.type_aux_data ) { case GCA_ID_QUIESCE : case GCA_ID_SHUTDOWN : lcb->flags |= LCB_SHUTDOWN; break; } lcb->parms.gca_ls_parms.gca_aux_data = (PTR)(aux_data + aux_len); lcb->parms.gca_ls_parms.gca_l_aux_data -= aux_hdr.len_aux_data; } break; case LSA_REJECT : /* Reject a client request */ lcb->stat = E_JD010B_NO_CLIENTS; lcb->statusp = &lcb->stat; break; case LSA_RQRESP : /* Respond to client request */ MEfill( sizeof(lcb->parms), 0, (PTR) &lcb->parms); lcb->parms.gca_rr_parms.gca_assoc_id = lcb->assoc_id; lcb->parms.gca_rr_parms.gca_request_status = *lcb->statusp; lcb->parms.gca_rr_parms.gca_local_protocol = lcb->protocol; lcb->statusp = &lcb->parms.gca_rr_parms.gca_status; IIGCa_cb_call( &gca_cb, GCA_RQRESP, &lcb->parms, GCA_ASYNC_FLAG, (PTR)sid, -1, &lcb->stat ); if ( lcb->stat != OK ) break; return; case LSA_DISASSOC : /* Disconnect association */ MEfill( sizeof(lcb->parms), 0, (PTR) &lcb->parms ); lcb->parms.gca_da_parms.gca_association_id = lcb->assoc_id; lcb->statusp = &lcb->parms.gca_da_parms.gca_status; IIGCa_cb_call( &gca_cb, GCA_DISASSOC, &lcb->parms, GCA_ASYNC_FLAG, (PTR)sid, -1, &lcb->stat ); if ( lcb->stat != OK ) break; return; case LSA_DA_RESUME : /* Resume disassociate */ IIGCa_cb_call( &gca_cb, GCA_DISASSOC, &lcb->parms, GCA_RESUME, (PTR)sid, -1, &lcb->stat ); if ( lcb->stat != OK ) break; return; } if ( branch ) lcb->state = labels[ lsn_states[ lcb->state - 1 ].label ]; goto top; }