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 ); }
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 ); }
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 ); }
/* ** Name: cleanup_queues ** ** Description: ** Empty reamaining info in the merge and GCN queues. ** ** Input: ** ** Output: ** ** Returns: ** VOID ** ** History: ** 15-Nov-2010 (Ralph Loen) ** Created. */ void cleanup_queues() { QUEUE *q; /* ** Empty information remaining in queues, if any. */ for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = gcn_qhead.q_prev) { QUremove(q); MEfree((PTR)q); } for (q = merge_qhead.q_prev; q != &merge_qhead; q = merge_qhead.q_prev) { QUremove(q); MEfree((PTR)q); } }
void gcadm_free_scb( GCADM_SCB *scb ) { /* remove scb from queue before free */ QUremove( &scb->q); if ( scb->buffer ) (*GCADM_global.dealloc_rtn)( (PTR)scb->buffer ); if ( scb ) (*GCADM_global.dealloc_rtn)( (PTR)scb ); 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 ); }
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 ); }
static void gcadm_event( GCADM_RCB *rcb ) { GCADM_SCB *scb=rcb->scb; if ( gcadm_active ) { if ( GCADM_global.gcadm_trace_level >= 5 ) TRdisplay( "%4d GCADM event: queueing event %s \n", scb->aid, events[ rcb->event ]); QUinsert( &rcb->q, GCADM_global.rcb_q.q_prev); return; } gcadm_active = TRUE; gcadm_sm( rcb ); while( ( rcb = (GCADM_RCB *)QUremove( GCADM_global.rcb_q.q_next )) ) { if ( GCADM_global.gcadm_state != GCADM_ACTIVE ) { if ( GCADM_global.gcadm_trace_level >= 1 ) TRdisplay( "%4d GCADM event: ADM not active\n", -1 ); gcadm_free_rcb ( rcb ); } else { if( GCADM_global.gcadm_trace_level >= 5 ) TRdisplay( "%4d GCADM event: processing queued event %s \n", scb->aid, events[ rcb->event ]); gcadm_sm( rcb ); } } gcadm_active = FALSE; return; }
/****************************************************************************** ** Name: ** MEfree.c ** ** Function: ** MEfree ** ** Arguments: ** void * block; ** ** Result: ** Frees the block of memory pointed to by 'block'. ** ** Removes the block from the tag queue if appropriate. ** ** Returns: ** STATUS: OK, ME_00_FREE, ME_FREE_FIRST ** ** Side Effects: ** None ** ** History: ** 21-mar-1996 (canor01) ** Free memory from calling process's heap. Compact the ** heap after every several frees. ** 03-jun-1996 (canor01) ** Internally, store the tag as an i4 instead of an i2. This makes ** for more efficient code on byte-aligned platforms that do fixups. ** 08-aug-1999 (mcgem01) ** Changed longnat to i4. ** 08-feb-2001 (somsa01) ** Changed types of i_meactual and i_meuser to be SIZE_TYPE. ** 21-jun-2002 (somsa01) ** Sync'ed up with UNIX. Rely on ME_NODE rather than a ptr UNION. ** Also, removed call to HeapCompact() logic. ** 05-Jul-2005 (drivi01) ** Replaced HeapFree call with free. ** 11-May-2009 (kschendel) b122041 ** Change pointer arg to void *, more appropriate. ** 23-Sep-2009 (wonst02) Bug 122427 ** Fix possibly trashing memory (alloc'd by tag) by using taglist mutex ** ******************************************************************************/ STATUS MEfree(void *block) { register ME_NODE *this; STATUS rv = OK; if ( block == NULL ) rv = ME_00_FREE; else { this = (ME_NODE *)((char *)block - sizeof(ME_NODE)); /* ** assume block is legit if the node looks like it points to an ** allocated block. */ if (this->MEaskedfor == 0) rv = ME_NO_FREE; if (rv == OK) { i_meactual -= this->MEsize; i_meuser -= this->MEaskedfor; if (this->MEtag) { CS_synch_lock(&MEtaglist_mutex); QUremove((QUEUE *)this); CS_synch_unlock(&MEtaglist_mutex); } free((char *)this); } } return(rv); }
void gcd_del_cib( GCD_CIB *cib ) { GCD_CAPS *caps; char buff[16]; u_i2 i; GCD_global.cib_active--; MOulongout( 0, (u_i8)cib->id, sizeof( buff ), buff ); MOdetach( GCD_MIB_DBMS, buff ); while( (caps = (GCD_CAPS *)QUremove( cib->caps.q_next )) ) { MEfree( caps->data ); MEfree( (PTR)caps ); } if ( cib->database ) MEfree( (PTR)cib->database ); if ( cib->username ) MEfree( (PTR)cib->username ); if ( cib->password ) MEfree( (PTR)cib->password ); for( i = 0; i < cib->parm_cnt; i++ ) MEfree( (PTR)cib->parms[i].value ); if ( GCD_global.gcd_trace_level >= 6 ) TRdisplay( "%4d GCD del CIB (%d)\n", -1, cib->id ); if ( cib->parm_max < ARR_SIZE( GCD_global.cib_free ) ) QUinsert( &cib->q, GCD_global.cib_free[ cib->parm_max ].q_prev ); else { MEfree( (PTR)cib ); GCD_global.cib_total--; } return; }
PTR MEreqmem( u_i2 tag, SIZE_TYPE size, bool zero, STATUS *status) { PTR block=NULL; register ME_NODE *node; /* the node to return */ register ME_NODE *start; /* for searching free list */ register ME_NODE *this; /* block to get node from */ register ME_NODE *frag; /* fragment block */ ME_NODE *tmp; /* not register for MEadd */ SIZE_TYPE nsize; /* nsize node to obtain */ SIZE_TYPE fsize; /* size of 'this' fragment block */ SIZE_TYPE newstuff; /* size to add to process, or 0 */ SIZE_TYPE prev_actual; /* rescan free list? */ SIZE_TYPE alloc_pages; CL_ERR_DESC err_code; STATUS MEstatus = OK; i_meuser += size; if (!size) MEstatus = ME_NO_ALLOC; if( !MEsetup ) MEinitLists(); /* ** Try to do the allocation. */ if( MEstatus == OK ) { nsize = SIZE_ROUND( size ); /* ** Get memory with malloc(). */ if( MEadvice == ME_USER_ALLOC ) { if( (node = (ME_NODE *)malloc( nsize )) == NULL ) MEstatus = ME_GONE; } /* ** Get block from private free list. */ else { # ifdef OS_THREADS_USED CS_synch_lock( &MEfreelist_mutex ); # endif /* OS_THREADS_USED */ /* ** Look on free list for 1st block big enough ** to hold request. This linear search can be slow. */ start = (ME_NODE *)&MEfreelist; this = MEfreelist.MEfirst; while ( this != NULL && this != start && this->MEsize < nsize ) this = this->MEnext; if( this == NULL ) MEstatus = ME_CORRUPTED; /* ** At this point, we are in one of three states: ** 1) Corrupted memory; MEstatus != OK ** 2) this is good node, this != start ** 3) No good node; this == start; */ if ( MEstatus == OK ) { /* ** If nothing on free list is big enough ** get one or more standard blocks from system, ** take what is needed and add remainder ** to free list. */ if (this != start) { /* take right off the free list */ newstuff = 0; } else /* this == start */ { /* * Expand the free list by calling getpages * newstuff holds the number of pages needed */ newstuff = (nsize + ME_MPAGESIZE-1)/ME_MPAGESIZE; /* if first time allocation, get enough for MO overhead */ if ( (prev_actual = i_meactual) == (SIZE_TYPE) 0 ) newstuff += 4; # ifdef OS_THREADS_USED CS_synch_unlock( &MEfreelist_mutex ); # endif /* OS_THREADS_USED */ MEstatus = MEget_pages(ME_SPARSE_MASK, newstuff, NULL, (PTR *)&tmp, &alloc_pages, &err_code); # ifdef OS_THREADS_USED CS_synch_lock( &MEfreelist_mutex ); # endif /* OS_THREADS_USED */ if (MEstatus == OK) { /* now we need to find where to put this new memory on the sorted free list - we search in reverse */ tmp->MEsize = newstuff * ME_MPAGESIZE; this = MEfreelist.MElast; while (start != this && this != NULL && this > tmp) this = this->MEprev; if (this != start && NEXT_NODE(this) == tmp) { this->MEsize += tmp->MEsize; } else { (void)QUinsert( (QUEUE *) tmp, (QUEUE *)this ); this = tmp; } if (this->MEnext != start && NEXT_NODE(this) == this->MEnext) { this->MEsize += this->MEnext->MEsize; (void)QUremove( (QUEUE *) this->MEnext); } /* ** While the free list mutex was released, another ** thread may have freed up a big enough piece of ** memory for our needs, or may have extended the ** free list. ** If that's the case, research the free list; ** we'll find either a right-sized node or ** the new memory we just added to the free list. */ if ( prev_actual != i_meactual ) { this = MEfreelist.MEfirst; while ( this != NULL && this != start && this->MEsize < nsize ) this = this->MEnext; if( this == NULL ) MEstatus = ME_CORRUPTED; } } else if (MEstatus == ME_OUT_OF_MEM) MEstatus = ME_GONE; } /* ** At this point, we can be in two states. ** 1) Corrupted memory, MEstatus != OK ** 2) 'this' is an OK node from the free list. */ if ( MEstatus == OK ) { node = this; /* ** if this is correct size or would ** leave useless block in chain ** just move block to allocated list ** else ** grab what is needed from 'this' ** block and then update 'this' */ fsize = node->MEsize - nsize; if ( fsize <= sizeof(ME_NODE) ) { (void)QUremove( (QUEUE *) node ); /* fudge size in node to eat leftover amount. */ fsize = 0; nsize = node->MEsize; } else /* make fragment block */ { /* ** Make a leftover block after the ** allocated space in node, in 'this' */ frag = (ME_NODE *)((char *) node + nsize ); frag->MEsize = fsize; frag->MEtag = 0; /* remove node, add fragment to free list */ (void)QUremove( (QUEUE *) node ); MEstatus = MEfadd( frag, FALSE ); } /* fragment left over */ /* Increment meactual while mutex held */ i_meactual += nsize; } /* Got a node */ } /* free list search OK */ # ifdef OS_THREADS_USED CS_synch_unlock( &MEfreelist_mutex ); # endif /* OS_THREADS_USED */ } /* ME_USER_ALLOC */ /* ** At this point we are in one of two states: ** 1. Corrupted, MEstatus != OK. ** 2. Have a 'node' to use, from freelist or malloc. ** The freelist is consistant, but the allocated list is ** not setup for the node. "nsize" is the actual size of "node". */ if( MEstatus == OK ) { /* splice into allocated object queue */ if (0 == tag) { # ifdef OS_THREADS_USED CS_synch_lock( &MElist_mutex ); # endif /* OS_THREADS_USED */ (void)QUinsert( (QUEUE *) node, (QUEUE *) MElist.MElast ); # ifdef OS_THREADS_USED CS_synch_unlock( &MElist_mutex ); # endif /* OS_THREADS_USED */ } else { IIME_atAddTag(tag, node); } /* Set values in block to be returned */ node->MEtag = tag; node->MEsize = nsize; node->MEaskedfor = size; /* Fill in the returned pointer */ block = (PTR)((char *)node + sizeof(ME_NODE)); if (zero) MEfill( (nsize - sizeof(ME_NODE)), 0, block); } /* got node OK */ } if (status != NULL) *status = MEstatus; if (MEstatus != OK) return((PTR)NULL); else return(block); }
II_EXTERN II_BOOL IIapi_termAPI( IIAPI_ENVHNDL *envHndl ) { IIAPI_ENVHNDL *defEnvHndl; II_BOOL last_term = FALSE; if ( ! IIapi_static ) return( TRUE ); defEnvHndl = IIapi_defaultEnvHndl(); if ( envHndl ) { /* ** Free the environment handle. */ MUp_semaphore( &IIapi_static->api_semaphore ); QUremove( (QUEUE *)envHndl ); MUv_semaphore( &IIapi_static->api_semaphore ); IIapi_deleteEnvHndl( envHndl ); } else { /* ** Decrement the usage counter in ** the default environment handle. */ MUp_semaphore( &defEnvHndl->en_semaphore ); defEnvHndl->en_initCount = max( 0, defEnvHndl->en_initCount - 1 ); MUv_semaphore( &defEnvHndl->en_semaphore ); } /* ** Shutdown API when all version 1 initializers have terminated ** and there are no active version 2 environments. */ if ( ! defEnvHndl->en_initCount && IIapi_isQueEmpty( &IIapi_static->api_env_q ) ) { QUEUE *q; IIAPI_TRACE( IIAPI_TR_TRACE ) ( "IIapi_termAPI: shutting down API completely.\n" ); /* ** Free the default environment. */ IIapi_deleteEnvHndl( (IIAPI_ENVHNDL *)IIapi_static->api_env_default ); IIapi_static->api_env_default = NULL; /* ** Shutdown sub-systems. */ IIapi_termGCA(); IIapi_termADF(); IIAPI_TRACE( IIAPI_TR_INFO )( "IIapi_termAPI: API shutdown.\n" ); IIAPI_TERMTRACE(); /* ** Free the remaining global resources. */ if (IIapi_static->api_ucode_ctbl) MEfree (IIapi_static->api_ucode_ctbl); if (IIapi_static->api_ucode_cvtbl) MEfree (IIapi_static->api_ucode_cvtbl); MEtls_destroy( &IIapi_static->api_thread, MEfree ); MUr_semaphore( &IIapi_static->api_semaphore ); MEfree( (PTR)IIapi_static ); IIapi_static = NULL; last_term = TRUE; } return( last_term ); }
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 ); }
void IIodbc_timeOutThread() { QUEUE *q, *p, *pq; pENV penv; pDBC pdbc; RETCODE rc; SYSTIME expire_time; TM_STAMP stamp; char stampStr[TM_SIZE_STAMP]; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread() with timeout %d\n", IIodbc_cb.timeout); while(TRUE) { /* ** Search the pool every thirty seconds and check for expired ** connections. Force disconnect and free from the pool ** if the connection handle has passed the expiration time. ** Note that the CLI and driver connection handles are not ** freed. */ PCsleep(30000); TMget_stamp(&stamp); TMstamp_str(&stamp, stampStr); ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread woke up at %s\n", stampStr); TMnow(&expire_time); if (IIodbc_cb.pooling == DRIVER_POOL) { applyLock(SQL_HANDLE_IIODBC_CB, NULL); for (q = IIodbc_cb.pool_q.q_prev; q!= &IIodbc_cb.pool_q; q = p) { ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: driver pool count is %d\n", IIodbc_cb.pool_count); p = q->q_prev; pdbc = (pDBC)((pPOOL)q)->pdbc; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: found conn handle %p with time diff %d\n",pdbc, expire_time.TM_secs - pdbc->expire_time.TM_secs); if (expire_time.TM_secs - pdbc->expire_time.TM_secs > IIodbc_cb.timeout) { /* ** Note that the connection handle is not freed, only ** removed from the pool. */ ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: EXPIRED. pdbc time is %d vs %d\n", pdbc->expire_time.TM_secs, expire_time.TM_secs); rc = IIDisconnect(pdbc->hdr.driverHandle); QUremove(q); MEfree((PTR)q); IIodbc_cb.pool_count -= 1; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("new pool count is %d\n",IIodbc_cb.pool_count); applyLock(SQL_HANDLE_DBC, pdbc); pdbc->hdr.state = C2; releaseLock(SQL_HANDLE_DBC, pdbc); } } releaseLock(SQL_HANDLE_IIODBC_CB, NULL); } else { for (q = IIodbc_cb.env_q.q_prev; q!= &IIodbc_cb.env_q; q = q->q_prev) { penv = (pENV)q; TRdisplay("Found env handle %p\n",penv); applyLock(SQL_HANDLE_ENV, penv); for (pq = penv->pool_q.q_prev; pq != &penv->pool_q; pq = p) { ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("Env pool count is %d\n",penv->pool_count); p = q->q_prev; pdbc = (pDBC)((pPOOL)pq)->pdbc; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_TimeOutThread: Found conn handle %p with time diff %d\n",pdbc, expire_time.TM_secs - pdbc->expire_time.TM_secs); if (expire_time.TM_secs - pdbc->expire_time.TM_secs > 1) { ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: EXPIRED. pdbc time is %d vs %d\n", pdbc->expire_time.TM_secs, expire_time.TM_secs); rc = IIDisconnect(pdbc->hdr.driverHandle); QUremove(q); MEfree((PTR)q); penv->pool_count -= 1; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: new pool count is %d\n", penv->pool_count); } } releaseLock(SQL_HANDLE_ENV, penv); } /* for (q = IIodbc_cb.env_q.q_prev; q!= &IIodbc_cb.env_q; q = q->q_prev) */ } /* if (IIodbc_cb.pooling == DRIVER_POOL) */ } /* while (TRUE) */ }
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 II_BOOL sm_execute ( IIAPI_ACTION action, IIAPI_HNDL *ev_hndl, IIAPI_HNDL *sm_hndl, II_PTR parmBlock ) { IIAPI_TRANHNDL *tranHndl = (IIAPI_TRANHNDL *)sm_hndl; IIAPI_SAVEPTHNDL *savePtHndl; IIAPI_SAVEPTPARM *savePtParm; IIAPI_STATUS status = OK; II_BOOL success = TRUE; char queryText[ 64 ]; switch( action ) { case NS_TA_REMC : /* ** Remember callback. */ tranHndl->th_callback = TRUE; tranHndl->th_parm = (IIAPI_GENPARM *)parmBlock; break; case NS_TA_DELH : /* ** Mark handle for deletion. */ QUremove( (QUEUE *)tranHndl ); sm_hndl->hd_delete = TRUE; break; case NS_TA_CBOK : /* ** Callback with success. Note that ** this will pick up the most severe ** status from the errors associated ** with the event handle. */ if ( tranHndl->th_callback ) { IIapi_appCallback(tranHndl->th_parm, sm_hndl, IIAPI_ST_SUCCESS); tranHndl->th_callback = FALSE; } break; case NS_TA_CBIF : /* ** API function called in wrong state. */ if ( ! IIapi_localError( sm_hndl, E_AP0006_INVALID_SEQUENCE, II_SS5000R_RUN_TIME_LOGICAL_ERROR, IIAPI_ST_FAILURE ) ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIAPI_ST_FAILURE; /* ** This may not have been a transaction ** related function, and we may have a ** callback saved on the transaction ** handle, so we carefully make the ** callback to the caller making sure ** not to disturb the transaction handle. */ IIapi_appCallback( (IIAPI_GENPARM *)parmBlock, sm_hndl, status ); /* ** We must return the failure here rather ** than following the normal exit route ** to ensure that the transaction handle ** callback does not get made. */ return( FALSE ); case NS_TA_RCVE : /* ** Receive error. ** ** We have received an invalid message. ** Since the connection state machine ** may ignore this particular message ** type, convert to a type which will ** ensure the proper handling in all ** state machines. */ IIapi_liDispatch( IIAPI_EV_UNEXPECTED_RCVD, sm_hndl, NULL, NULL ); return( FALSE ); } /* ** If we couldn't complete the action, callback with failure. */ if ( ! success && tranHndl->th_callback ) { IIapi_appCallback( tranHndl->th_parm, sm_hndl, status ); tranHndl->th_callback = FALSE; } return( success ); }
STATUS MEfadd( ME_NODE *block, i4 releasep) { register ME_NODE *this; register ME_NODE *start; register ME_NODE *nextblk; /* 1st address after end of 'block' */ STATUS MEstatus; MEstatus = OK; if ( block == NULL ) { MEstatus = ME_00_PTR; } else if ( OUT_OF_DATASPACE(block) ) { MEstatus = ME_OUT_OF_RANGE; } else { nextblk = NEXT_NODE(block); /* ** The freelist IS sorted. We might be able to take ** advantage of this to speed up this linear search. ** In practice the freelist is usually much ** smaller than the allocated list, so it might not ** really matter (daveb). */ /* adding inside existing freelist */ start = (ME_NODE *)&MEfreelist; this = MEfreelist.MEfirst; while ( this != NULL && this != start && this < nextblk ) this = this->MEnext; if( this == NULL ) MEstatus = ME_CORRUPTED; /* ** this->MEprev points to free node before 'block', the one ** to free. this points to the block in the free ** list following 'block' to free. */ if ( MEstatus == OK ) { block->MEaskedfor = 0; (void)QUinsert( (QUEUE *) block, (QUEUE *) this->MEprev ); /* Coalesce backwards until this is the start of the queue */ this = block; while( this->MEprev != start && this->MEprev != this && NEXT_NODE(this->MEprev) == this ) { block = this->MEprev; block->MEsize += this->MEsize; (void)QUremove( (QUEUE *) this ); this = block; } /* Coalesce forwards until the queue goes back to the start */ while( this->MEnext != start && NEXT_NODE(this) == this->MEnext ) { this->MEsize += this->MEnext->MEsize; (void)QUremove( (QUEUE *) this->MEnext ); } } } return(MEstatus); }
/*{ ** Name: IIME_ftFreeTag - Free all allocated memory for a tag. ** ** Description: ** This routine is called by MEtfree to free all the allocated ** memory for a tag. ** ** It works by finding the METAGNODE for the tag in the hash table ** and then traversing the QUEUE of allocated blocks freeing ** each block. ** ** Inputs: ** tag The tag whose memory is to be freed. ** ** Outputs: ** Returns: ** OK if all the allocated memory for the tag was freed. ** ME_NO_TFREE if the tag does not have a record in the hash table. ** other failure status if the nodes can't be freed. ** ** Side Effects: ** Will return the METAGNODE for the tag to freelist. ** ** History: ** 5-dec-1989 (Joe) ** First Written ** 30-May-96 (stial01) ** New advice ME_TUXEDO_ALLOC should behave like ME_INGRES_ALLOC ** 12-feb-1997 (canor01) ** Initialize local MEstatus. ** 27-Jan-1999 (fanra01) ** Add thread alloc case for tag free. Otherwise our memory is ** returned to the system heap causing wonderfully esoteric execution. */ STATUS IIME_ftFreeTag( i4 tag ) { register METAGNODE **first; STATUS MEstatus = OK; # ifdef OS_THREADS_USED CS_synch_lock( &MEtaglist_mutex ); # endif /* OS_THREADS_USED */ for (first = &(htab[tag%256]); *first != NULL; first = &((*first)->met_hash)) { if ((*first)->met_tag == tag) { register ME_NODE *this; register ME_NODE *next; register METAGNODE *freenode; for (this = (*first)->met_list.MEfirst; this != NULL && this != (ME_NODE *) &((*first)->met_list);) { next = this->MEnext; if ( MEstatus == OK ) { i_meactual -= this->MEsize; i_meuser -= this->MEaskedfor; (void)QUremove( (QUEUE *) this ); if( (MEadvice == ME_INGRES_ALLOC ) || (MEadvice == ME_INGRES_THREAD_ALLOC) || (MEadvice == ME_TUXEDO_ALLOC) ) { # ifdef OS_THREADS_USED CS_synch_lock( &MEfreelist_mutex ); # endif /* OS_THREADS_USED */ MEstatus = MEfadd(this, TRUE); # ifdef OS_THREADS_USED CS_synch_unlock( &MEfreelist_mutex ); # endif /* OS_THREADS_USED */ } else free( (char *)this ); } if (MEstatus == OK) this = next; else break; } freenode = *first; *first = freenode->met_hash; freenode->met_hash = freelist; freelist = freenode; # ifdef OS_THREADS_USED CS_synch_unlock( &MEtaglist_mutex ); # endif /* OS_THREADS_USED */ return MEstatus; } } # ifdef OS_THREADS_USED CS_synch_unlock( &MEtaglist_mutex ); # endif /* OS_THREADS_USED */ return ME_NO_TFREE; }
static II_BOOL sm_execute ( IIAPI_ACTION action, IIAPI_HNDL *ev_hndl, IIAPI_HNDL *sm_hndl, II_PTR parmBlock ) { IIAPI_TRANHNDL *tranHndl = (IIAPI_TRANHNDL *)sm_hndl; IIAPI_MSG_BUFF *msgBuff; IIAPI_STATUS status; II_BOOL success = TRUE; char queryText[ 64 ]; switch( action ) { case SQL_TA_REMC : /* ** Remember callback. */ tranHndl->th_callback = TRUE; tranHndl->th_parm = (IIAPI_GENPARM *)parmBlock; break; case SQL_TA_RECV : { /* ** Issue receive message request. */ IIAPI_MSG_BUFF *msgBuff = IIapi_allocMsgBuffer( sm_hndl ); if ( ! msgBuff ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIapi_rcvNormalGCA( sm_hndl, msgBuff, (II_LONG)(-1) ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; } case SQL_TA_SCOM : /* ** Format and send GCA_COMMIT message. */ if ( ! (msgBuff = IIapi_allocMsgBuffer( sm_hndl )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } msgBuff->msgType = GCA_COMMIT; msgBuff->flags = IIAPI_MSG_EOD; status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SRB : /* ** Format and send GCA_ROLLBACK message. */ if ( ! (msgBuff = IIapi_allocMsgBuffer( sm_hndl )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } msgBuff->msgType = GCA_ROLLBACK; msgBuff->flags = IIAPI_MSG_EOD; status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SSP : { /* ** Create savepoint handle. Format and ** send GCA_QUERY message 'savepoint <sp>'. */ IIAPI_SAVEPTHNDL *savePtHndl; IIAPI_SAVEPTPARM *savePtParm = (IIAPI_SAVEPTPARM *)parmBlock; if ( ! IIapi_createSavePtHndl( savePtParm ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } savePtHndl = savePtParm->sp_savePointHandle; STprintf( queryText, "savepoint %s\n", savePtHndl->sp_savePtName ); if ( ! (msgBuff = IIapi_createMsgQuery( sm_hndl, queryText )) ) { IIapi_deleteSavePtHndl( savePtHndl ); savePtParm->sp_savePointHandle = NULL; status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) { IIapi_deleteSavePtHndl( savePtHndl ); savePtParm->sp_savePointHandle = NULL; success = FALSE; } break; } case SQL_TA_SRBS : { /* ** Format and send GCA_QUERY message 'rollback to <savepoint>'. */ IIAPI_ROLLBACKPARM *rollParm = (IIAPI_ROLLBACKPARM *)parmBlock; IIAPI_SAVEPTHNDL *savePtHndl = rollParm->rb_savePointHandle; STprintf(queryText, "rollback to %s\n", savePtHndl->sp_savePtName); if ( ! (msgBuff = IIapi_createMsgQuery( sm_hndl, queryText )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; } case SQL_TA_SAON : /* ** Format and send GCA_QUERY message 'set autocommit on'. */ if ( ! (msgBuff = IIapi_createMsgQuery( sm_hndl, "set autocommit on" )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SAOF : /* ** Format and send GCA_QUERY message 'set autocommit off'. */ if ( ! (msgBuff = IIapi_createMsgQuery( sm_hndl, "set autocommit off" )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SSEC : /* ** Format and send GCA_SECURE message. */ if ( ! ( msgBuff = IIapi_createMsgSecure( tranHndl ) ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SXAS : { /* ** Send XA Start message. */ IIAPI_XASTARTPARM *startParm = (IIAPI_XASTARTPARM *)parmBlock; if ( ! (msgBuff = IIapi_createMsgXA( sm_hndl, GCA_XA_START, &startParm->xs_tranID.ti_value.xaXID, startParm->xs_flags )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; } case SQL_TA_SXAE : { /* ** Send XA End message. */ IIAPI_XAENDPARM *endParm = (IIAPI_XAENDPARM *)parmBlock; if ( ! (msgBuff = IIapi_createMsgXA( sm_hndl, GCA_XA_END, &endParm->xe_tranID.ti_value.xaXID, endParm->xe_flags )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; } case SQL_TA_PEND : /* ** Return transaction aborted to all pending operations. */ { IIAPI_STMTHNDL *stmtHndl; for( stmtHndl = (IIAPI_STMTHNDL *)tranHndl-> th_stmtHndlList.q_next; stmtHndl != (IIAPI_STMTHNDL *)&tranHndl->th_stmtHndlList; stmtHndl = (IIAPI_STMTHNDL *)stmtHndl-> sh_header.hd_id.hi_queue.q_next ) IIapi_abortStmtHndl( stmtHndl, E_AP0002_TRANSACTION_ABORTED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ); } break; case SQL_TA_DELH : /* ** Mark handle for deletion. */ QUremove( (QUEUE *)tranHndl ); sm_hndl->hd_delete = TRUE; /* ** If this was a distributed transaction, ** the associated distributed transaction ** name should be releasable during the ** callback. Since the transaction handle ** has not actually been deleted, it is ** still associated with the distributed ** transaction name. Normally, cases such ** as this are serialized by the dispatch ** operations queue, but IIapi_releaseXID() ** is not a dispatched request. So we need ** to drop the association prior to making ** the callback. */ if ( tranHndl->th_tranName ) { QUremove( &tranHndl->th_tranNameQue ); tranHndl->th_tranName = NULL; } break; case SQL_TA_DELX : /* ** Free associated transaction name handle. */ if ( tranHndl->th_tranName ) /* Should never be NULL */ { QUremove( &tranHndl->th_tranNameQue ); IIapi_deleteTranName( tranHndl->th_tranName ); tranHndl->th_tranName = NULL; } /* ** Mark handle for deletion. */ QUremove( (QUEUE *)tranHndl ); sm_hndl->hd_delete = TRUE; break; case SQL_TA_ERAB : /* ** Transaction Aborted. */ IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s: Transaction aborted\n", sql_tran_sm.sm_id ); if ( ! IIapi_localError( sm_hndl, E_AP0002_TRANSACTION_ABORTED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; } break; case SQL_TA_ERCF : /* ** Commit failed. */ IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s: transaction commit failed\n", sql_tran_sm.sm_id ); if ( ! IIapi_localError( sm_hndl, E_AP000B_COMMIT_FAILED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; } break; case SQL_TA_ERPC : /* ** Prepare-to-commit failed. */ IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s: transaction prepare failed\n", sql_tran_sm.sm_id ); if ( ! IIapi_localError( sm_hndl, E_AP000C_2PC_REFUSED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; } break; case SQL_TA_RRSP : { /* ** Read response message. */ IIAPI_MSG_BUFF *msgBuff = (IIAPI_MSG_BUFF *)parmBlock; GCA_RE_DATA respData; if ( (status = IIapi_readMsgResponse( msgBuff, &respData, TRUE )) != IIAPI_ST_SUCCESS ) { success = FALSE; break; } /* ** Check for XA error */ if ( respData.gca_rqstatus & GCA_XA_ERROR_MASK && respData.gca_errd5 && ! IIapi_xaError( sm_hndl, respData.gca_errd5 ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } break; } case SQL_TA_RXAR : { /* ** Read XA response message. */ IIAPI_MSG_BUFF *msgBuff = (IIAPI_MSG_BUFF *)parmBlock; GCA_RE_DATA respData; if ( (status = IIapi_readMsgResponse( msgBuff, &respData, TRUE )) != IIAPI_ST_SUCCESS ) { success = FALSE; break; } /* ** If no XA error is returned, generate generic XA error. */ if ( ! (respData.gca_rqstatus & GCA_XA_ERROR_MASK) || ! respData.gca_errd5 ) respData.gca_errd5 = IIAPI_XAER_RMERR; if ( ! IIapi_xaError( sm_hndl, respData.gca_errd5 ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } break; } case SQL_TA_CBOK : /* ** Callback with success. Note that ** this will pick up the most severe ** status from the errors associated ** with the event handle. */ if ( tranHndl->th_callback ) { IIapi_appCallback(tranHndl->th_parm, sm_hndl, IIAPI_ST_SUCCESS); tranHndl->th_callback = FALSE; } break; case SQL_TA_CBFL : /* ** Callback with failure. */ if ( tranHndl->th_callback ) { IIapi_appCallback(tranHndl->th_parm, sm_hndl, IIAPI_ST_FAILURE); tranHndl->th_callback = FALSE; } break; case SQL_TA_CBIF : /* ** API function called in wrong state. */ if ( ! IIapi_localError( sm_hndl, E_AP0006_INVALID_SEQUENCE, II_SS5000R_RUN_TIME_LOGICAL_ERROR, IIAPI_ST_FAILURE ) ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIAPI_ST_FAILURE; /* ** This may not have been a transaction ** related function, and we may have a ** callback saved on the transaction ** handle, so we carefully make the ** callback to the caller making sure ** not to disturb the transaction handle. */ IIapi_appCallback( (IIAPI_GENPARM *)parmBlock, sm_hndl, status ); break; case SQL_TA_CBAB : /* ** Callback with transaction abort. */ if ( tranHndl->th_callback ) { if ( ! IIapi_localError( sm_hndl, E_AP0002_TRANSACTION_ABORTED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ) ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIAPI_ST_FAILURE; IIapi_appCallback( tranHndl->th_parm, sm_hndl, status ); tranHndl->th_callback = FALSE; } break; case SQL_TA_CBABX : /* ** Callback with XA transaction abort. */ if ( tranHndl->th_callback ) { if ( ! IIapi_xaError( sm_hndl, IIAPI_XA_RBROLLBACK ) ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIAPI_ST_FAILURE; IIapi_appCallback( tranHndl->th_parm, sm_hndl, status ); tranHndl->th_callback = FALSE; } break; case SQL_TA_RCVE : /* ** Receive error. ** ** We have received an invalid message. ** Since the connection state machine ** may ignore this particular message ** type, convert to a type which will ** ensure the proper handling in all ** state machines. */ IIapi_liDispatch( IIAPI_EV_UNEXPECTED_RCVD, sm_hndl, NULL, NULL ); break; case SQL_TA_HALT : /* ** Halt state machine execution. */ return( FALSE ); } /* ** If we couldn't complete the action, callback with failure. */ if ( ! success && tranHndl->th_callback ) { IIapi_appCallback( tranHndl->th_parm, sm_hndl, status ); tranHndl->th_callback = FALSE; } return( success ); }