示例#1
0
文件: dmxsecure.c 项目: akdh/Ingres
DB_STATUS
dmx_secure(
DMX_CB    *dmx_cb)
{
    DML_SCB             *scb;
    DMX_CB		*dmx = dmx_cb;
    DML_XCB		*xcb;
    DB_STATUS		status = E_DB_ERROR;
    i4		error,local_error;
    DMP_RCB		*rcb;
    CL_ERR_DESC		sys_err;
    STATUS		cl_stat;
    i4			qnext;
    DMC_REPQ		*repq = (DMC_REPQ *)(Dmc_rep + 1);
    i4			rep_iq_lock;
    i4			rep_maxlocks;
    DB_TAB_TIMESTAMP	timestamp;
    LK_EVENT		lk_event;

    CLRDBERR(&dmx->error);

    for (;;)
    {
	xcb = (DML_XCB *)dmx->dmx_tran_id;
	if (dm0m_check((DM_OBJECT *)xcb, (i4)XCB_CB) != E_DB_OK)
	{
	    SETDBERR(&dmx->error, 0, E_DM003B_BAD_TRAN_ID);
	    break;
	}

	if (dmx->dmx_dis_tran_id.db_dis_tran_id_type == 0)
	{
	    SETDBERR(&dmx->error, 0, E_DM002A_BAD_PARAMETER);
	    break;
	}
	if (xcb->xcb_state & (XCB_STMTABORT | XCB_TRANABORT))
	{
	    SETDBERR(&dmx->error, 0, E_DM0064_USER_ABORT);
	    break;
	}
	if (xcb->xcb_state & XCB_WILLING_COMMIT)
	{
	    SETDBERR(&dmx->error, 0, E_DM0132_ILLEGAL_STMT);
	    break;
	}
        scb = xcb->xcb_scb_ptr;

	/*  Clear user interrupt state in SCB. */

	scb->scb_ui_state &= ~SCB_USER_INTR;

	/* Clear the force abort state of the SCB. */

	if (xcb->xcb_state & XCB_FORCE_ABORT)
	    scb->scb_ui_state &= ~SCB_FORCE_ABORT;

	/*
	** If the transaction has written no Begin Transaction record,
	** then force one to the log file now.
	*/
	if (xcb->xcb_flags & XCB_DELAYBT)
	{
	    status = dmxe_writebt(xcb, TRUE, &dmx->error);
	    if (status != E_DB_OK)
	    {
		xcb->xcb_state |= XCB_TRANABORT;
		break;
	    }
	}

	/*
	** If the database is replicated, the input queue must
	** be processed before putting the transaction in a
	** willing commit state.
	**
	** All of this transaction's tables, including those
	** associated with replication, must be closed and
	** their pages tossed from the cache.
	**
	** This is the same processing as that for a 
	** "normal" commit.
	*/
	if ((xcb->xcb_odcb_ptr->odcb_dcb_ptr->dcb_status & DCB_S_REPLICATE) &&
	    (DMZ_SES_MACRO(32) == 0 || dmd_reptrace() == FALSE) &&
	    ((xcb->xcb_rep_input_q == NULL) || 
		(xcb->xcb_rep_input_q == (DMP_RCB *)-1)))
	{
	    if (dmf_svcb->svcb_rep_iqlock == DMC_C_ROW)
		rep_iq_lock = DM2T_RIX;
	    else if (dmf_svcb->svcb_rep_iqlock == DMC_C_TABLE)
		rep_iq_lock = DM2T_X;
	    else
		rep_iq_lock = DM2T_IX;
 
	    /* allow a minimum maxlocks value of 50 ... */
	    if (dmf_svcb->svcb_rep_dtmaxlock > 50)
		rep_maxlocks = dmf_svcb->svcb_rep_dtmaxlock;
	    /* ...but default to 100 */
	    else if (dmf_svcb->svcb_lk_maxlocks > 100)
		rep_maxlocks = dmf_svcb->svcb_lk_maxlocks;
	    else
		rep_maxlocks = 100;
	    
	    status = dm2t_open(xcb->xcb_odcb_ptr->odcb_dcb_ptr, 
		&xcb->xcb_odcb_ptr->odcb_dcb_ptr->rep_input_q, rep_iq_lock,
                DM2T_UDIRECT, DM2T_A_WRITE, (i4)0, rep_maxlocks,
                (i4)0, xcb->xcb_log_id, xcb->xcb_lk_id, (i4)0, 
		(i4)0, (i4)0, &(xcb->xcb_tran_id), &timestamp, 
		&(xcb->xcb_rep_input_q), (DML_SCB *)0, &dmx->error);
	    if (status != E_DB_OK)
	    {
		xcb->xcb_state |= XCB_TRANABORT;
		break;
	    }
	}
        /*
        ** clean up replication input queue RCB
        */
        if (xcb->xcb_rep_input_q)
        {
	    HRSYSTIME		curtime;
	    bool	list_ok = TRUE;
	    i4		semaphore_status = -1;

	    (VOID)TMhrnow(&curtime);

	    /* If rep_txq_size=0, Dmc_rep will be NULL and we have to
	    ** do the distribution synchronously now (kibro01) b118566
	    */
	    if (Dmc_rep == NULL)
		list_ok = FALSE;

	    /*
	    ** if we had the input queue open, then we need to distribute
	    */
	    if (list_ok)
	    {
	        semaphore_status = CSp_semaphore(TRUE, &Dmc_rep->rep_sem);
		if (semaphore_status == E_DB_OK)
		{
		    qnext = (Dmc_rep->queue_start == Dmc_rep->queue_end &&
			repq[Dmc_rep->queue_start].active == 0 &&
			repq[Dmc_rep->queue_start].tx_id == 0) ?
			  Dmc_rep->queue_end :
			  (Dmc_rep->queue_end + 1) % Dmc_rep->seg_size;
		    if (qnext == Dmc_rep->queue_start && 
			Dmc_rep->queue_start != Dmc_rep->queue_end)
		    {
			list_ok = FALSE;
		    }
		} else
		{
	            TRdisplay("%@ dmxsecure() CSp_semaphore failed %d\n",
                        semaphore_status);

		    /* Error getting the semaphore, can't rely on the list */
		    list_ok = FALSE;
		}
	    }
	    if (!list_ok)
	    {
		/* queue is full, print warning and distribute manually */
		if (semaphore_status == E_DB_OK)
			CSv_semaphore(&Dmc_rep->rep_sem);

		/* If we have a queue and it's full, log that fact */
		if (Dmc_rep)
		{
            	    uleFormat(NULL, W_DM9561_REP_TXQ_FULL, NULL, ULE_LOG, NULL, 
		        (char *)NULL, (i4)0, (i4 *)NULL, &local_error, 0);
		}

		status = dm2rep_qman(xcb->xcb_odcb_ptr->odcb_dcb_ptr,
		    xcb->xcb_rep_remote_tx ? xcb->xcb_rep_remote_tx :
			(i4)xcb->xcb_tran_id.db_low_tran,
		    &curtime, xcb->xcb_rep_input_q, xcb->xcb_lk_id, 
		    &dmx->error, FALSE);
		if (status != E_DB_OK)
		{
		    if (dmx->error.err_code > E_DM004A_INTERNAL_ERROR)
		    {
		        uleFormat( &dmx->error, 0, NULL, ULE_LOG , NULL, 
				    (char * )NULL, 0L, (i4 *)NULL, 
				    &local_error, 0);
			SETDBERR(&dmx->error, 0, E_DM957F_REP_DISTRIB_ERROR);
		    }
		    xcb->xcb_state |= XCB_TRANABORT;
		    break;
		}
	    }
	    else
	    {
	        /* we have mutex and an entry we can use, so fill out entry */
	        /* we assume we are only accessing one db in this tx */
	        STRUCT_ASSIGN_MACRO(xcb->xcb_odcb_ptr->odcb_dcb_ptr->dcb_name,
		    repq[qnext].dbname);
	        /*
	        ** use remote TX if it's set (by the replication server)
	        */
	        if (xcb->xcb_rep_remote_tx)
		    repq[qnext].tx_id = xcb->xcb_rep_remote_tx;
	        else
	            repq[qnext].tx_id = (i4)xcb->xcb_tran_id.db_low_tran;
	        repq[qnext].active = FALSE;
	        MEcopy((char *)&curtime, sizeof(HRSYSTIME), 
		       (char *)&repq[qnext].trans_time);
	        Dmc_rep->queue_end = qnext;
	        CSv_semaphore(&Dmc_rep->rep_sem);
	        /*
	        ** signal the queue management thread(s)
	        */
		lk_event.type_high = REP_READQ;
		lk_event.type_low = 0;
		lk_event.value = REP_READQ_VAL;
		
	        cl_stat = LKevent(LK_E_CLR | LK_E_CROSS_PROCESS, xcb->xcb_lk_id,
		    &lk_event, &sys_err);
                if (cl_stat != OK)
                {
                    uleFormat(NULL, cl_stat, &sys_err, ULE_LOG, NULL,
                        (char *)NULL, (i4)0, (i4 *)NULL, &error, 0);
                    uleFormat(&dmx->error, E_DM904B_BAD_LOCK_EVENT, &sys_err, ULE_LOG, 
			NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 3,
                        0, LK_E_CLR, 0, REP_READQ, 0, xcb->xcb_lk_id);
                    status = E_DB_ERROR;
                    break;
                }
	    }
	    /*
	    ** user updates to the input queue will cause xcb_rep_input_q to
	    ** be set to -1, the table will already be closed by the user in
	    ** this case
	    */
	    if (xcb->xcb_rep_input_q != (DMP_RCB *)-1)
	    {
                status = dm2t_close(xcb->xcb_rep_input_q, (i4)0, &dmx->error);

		if (status != E_DB_OK)
		{
		    if (dmx->error.err_code != E_DM004A_INTERNAL_ERROR)
		    {
			uleFormat( &dmx->error, 0, NULL, ULE_LOG , NULL,
			    (char * )NULL, 0L, (i4 *)NULL,
			    &local_error, 0);
			SETDBERR(&dmx->error, 0, E_DM009A_ERROR_SECURE_TRAN);
		    }
		    xcb->xcb_state |= XCB_TRANABORT;
		    return (status);
		}
		xcb->xcb_rep_input_q = (DMP_RCB*)NULL;
	    }
        }

	/*  Close all open tables and destroy all open temporary tables.    */

	while (xcb->xcb_rq_next != (DMP_RCB*) &xcb->xcb_rq_next)
	{
	    /*	Get next RCB. */

	    rcb = (DMP_RCB *)((char *)xcb->xcb_rq_next -
		(char *)&(((DMP_RCB*)0)->rcb_xq_next));

	    /*	Remove from the XCB. */

	    rcb->rcb_xq_next->rcb_q_prev = rcb->rcb_xq_prev;
	    rcb->rcb_xq_prev->rcb_q_next = rcb->rcb_xq_next;

	    /*	Deallocate the RCB. */

	    status = dm2t_close(rcb, (i4)0, &dmx->error);
	    if (status != E_DB_OK)
	    {
		if (dmx->error.err_code != E_DM004A_INTERNAL_ERROR)
		{
		    uleFormat( &dmx->error, 0, NULL, ULE_LOG , NULL, 
			(char * )NULL, 0L, (i4 *)NULL, 
			&local_error, 0);
		    SETDBERR(&dmx->error, 0, E_DM009A_ERROR_SECURE_TRAN);
		}
		xcb->xcb_state |= XCB_TRANABORT;
		return (status);
	    }
	}

	/*  Now prepare to commit the transaction. */

	STRUCT_ASSIGN_MACRO(dmx->dmx_dis_tran_id, xcb->xcb_dis_tran_id);

	status = dmxe_secure(&xcb->xcb_tran_id, &xcb->xcb_dis_tran_id,
				xcb->xcb_log_id, xcb->xcb_lk_id, &dmx->error);
	if (status != E_DB_OK)
	{
	    if (dmx->error.err_code > E_DM_INTERNAL)
	    {
		uleFormat(&dmx->error, 0, NULL, ULE_LOG, NULL, 
			    (char * )NULL, (i4)0, (i4 *)NULL, &error, 0);
		SETDBERR(&dmx->error, 0, E_DM009A_ERROR_SECURE_TRAN);
	    }

	    xcb->xcb_state |= XCB_TRANABORT;
	    return (E_DB_ERROR);
	}

	/* Mark the state of the transaction in xcb to WILLING COMMIT. */

	xcb->xcb_x_type |= XCB_DISTRIBUTED;
	xcb->xcb_state |= XCB_WILLING_COMMIT;
	return (E_DB_OK);
    }
    return (status);
}
示例#2
0
DB_STATUS
adu_dbconst(
ADF_CB		    *adf_scb,
ADK_MAP		    *kmap,
DB_DATA_VALUE       *rdv)
{
    ADK_CONST_BLK	*k = adf_scb->adf_constants;
    bool		kcalced = FALSE;
    PTR			kptr = NULL;
    DB_ERROR		err;
    ADF_DBMSINFO	*dbi  = kmap->adk_dbi;
    i4			kbit  = kmap->adk_kbit;
    DB_STATUS		db_stat;
    bool		datetimetype = FALSE;
    DB_DT_ID		date_dt;
    u_i4		val;
    /* Beware that some of the dbmsinfo functions care not about
    ** caller lengths and will update the DBV regardless so
    ** we arrange to get the constants written directy and if
    ** need be, we conver on return. */
    DB_DATA_VALUE tmp_rdv = *rdv;
    i8 tmp_buf[1024/sizeof(i8)]; /* Make temporary aligned */

    switch (kbit)	    /* look for datetime constants */
    {
    case ADK_CURR_DATE:		/* _current_date */
	datetimetype = TRUE;
	date_dt = DB_ADTE_TYPE;
	break;

    case ADK_CURR_TIME:		/* _current_time */
	datetimetype = TRUE;
	date_dt = DB_TMW_TYPE;
	break;

    case ADK_CURR_TSTMP:	/* _current_timestamp */
	datetimetype = TRUE;
	date_dt = DB_TSW_TYPE;
	break;

    case ADK_LOCAL_TIME:	/* _local_time*/
	datetimetype = TRUE;
	date_dt = DB_TME_TYPE;
	break;

    case ADK_LOCAL_TSTMP:	/* _local_timestamp */
	datetimetype = TRUE;
	date_dt = DB_TSTMP_TYPE;
	break;
    }

    if (k != NULL)
    {
	switch (kbit)	    /* switch on known query constants */
	{
	  case ADK_BINTIM:	/* _bintim */
	    tmp_rdv.db_data = (PTR) &k->adk_bintim;
	    tmp_rdv.db_length = sizeof(k->adk_bintim);
	    break;

	  case ADK_CPU_MS:	/* _cpu_ms */
	    tmp_rdv.db_data = (PTR) &k->adk_cpu_ms;
	    tmp_rdv.db_length = sizeof(k->adk_cpu_ms);
	    break;

	  case ADK_ET_SEC:	/* _et_sec */
	    tmp_rdv.db_data = (PTR) &k->adk_et_sec;
	    tmp_rdv.db_length = sizeof(k->adk_et_sec);
	    break;

	  case ADK_DIO_CNT:	/* _dio_cnt */
	    tmp_rdv.db_data = (PTR) &k->adk_dio_cnt;
	    tmp_rdv.db_length = sizeof(k->adk_dio_cnt);
	    break;

	  case ADK_BIO_CNT:	/* _bio_cnt */
	    tmp_rdv.db_data = (PTR) &k->adk_bio_cnt;
	    tmp_rdv.db_length = sizeof(k->adk_bio_cnt);
	    break;

	  case ADK_PFAULT_CNT:	/* _pfault_cnt */
	    tmp_rdv.db_data = (PTR) &k->adk_pfault_cnt;
	    tmp_rdv.db_length = sizeof(k->adk_pfault_cnt);
	    break;

	  case ADK_CURR_DATE:	/* _current_date */
	    tmp_rdv.db_data = (PTR) &k->adk_curr_date;
	    tmp_rdv.db_length = sizeof(k->adk_curr_date);
	    break;

	  case ADK_CURR_TIME:	/* _current_time */
	    tmp_rdv.db_data = (PTR) &k->adk_curr_time;
	    tmp_rdv.db_length = sizeof(k->adk_curr_time);
	    break;

	  case ADK_CURR_TSTMP:	/* _current_timestamp */
	    tmp_rdv.db_data = (PTR) &k->adk_curr_tstmp;
	    tmp_rdv.db_length = sizeof(k->adk_curr_tstmp);
	    break;

	  case ADK_LOCAL_TIME:	/* _local_time*/
	    tmp_rdv.db_data = (PTR) &k->adk_local_time;
	    tmp_rdv.db_length = sizeof(k->adk_local_time);
	    break;

	  case ADK_LOCAL_TSTMP:	/* _local_timestamp */
	    tmp_rdv.db_data = (PTR) &k->adk_local_tstmp;
	    tmp_rdv.db_length = sizeof(k->adk_local_tstmp);
	    break;

	  default:
	    return (adu_error (adf_scb, E_AD9998_INTERNAL_ERROR,
		2, 0, "dbmsinfo kbit"));
	}
	
	if (k->adk_set_mask & kbit) /* Has this value been calculated yet? */
	    kcalced = TRUE;
    }
    else
	tmp_rdv.db_data = (PTR)tmp_buf;


    if (!kcalced)
    {
	/* Must calculate value from scratch */

	if (datetimetype)
	{
	    AD_NEWDTNTRNL       dn;
	    struct timevect     tv;
	    DB_STATUS           db_stat;
	    i4			sec_time_zone;
	    HRSYSTIME		hrsystime;

	    TMhrnow(&hrsystime);

	    MEfill ((u_i2) sizeof(i4)*10, NULLCHAR, (PTR) &tv);

	    adu_cvtime((i4) hrsystime.tv_sec, (i4)hrsystime.tv_nsec, &tv);

	    MEfill((u_i2) sizeof(AD_NEWDTNTRNL), NULLCHAR, (PTR) &dn);
	    /* Interpret the time vector */
	    dn.dn_year    = (i2)tv.tm_year + 1900;
	    dn.dn_month   = (i2)tv.tm_mon + 1;
	    dn.dn_day     = tv.tm_mday;
	    dn.dn_seconds = tv.tm_hour * 3600 + tv.tm_min * 60 + tv.tm_sec;
	    dn.dn_nsecond = tv.tm_nsec;
	    dn.dn_dttype  = date_dt;

	    sec_time_zone = TMtz_search(adf_scb->adf_tzcb, TM_TIMETYPE_GMT,
				 (i4) hrsystime.tv_sec);

	    AD_TZ_SETNEW(&dn, sec_time_zone);

	    dn.dn_status = AD_DN_ABSOLUTE;
	    switch (date_dt)
	    {
	    case DB_ADTE_TYPE:	/* _current_date */
		dn.dn_seconds = 0;
		dn.dn_nsecond = 0;
		dn.dn_status2 |= AD_DN2_ADTE_TZ;
		dn.dn_status |= AD_DN_YEARSPEC|AD_DN_MONTHSPEC|AD_DN_DAYSPEC;
		break;

	    case DB_TME_TYPE:	/* _local_time*/
		dn.dn_status2 |= AD_DN2_TZ_OFF_LCL;
		/*FALLTHROUGH*/
	    case DB_TMW_TYPE:	/* _current_time */
		dn.dn_status |= AD_DN_TIMESPEC;
		dn.dn_status2 |= AD_DN2_NO_DATE;
		break;

	    case DB_TSTMP_TYPE:	/* _local_timestamp */
		dn.dn_status2 |= AD_DN2_TZ_OFF_LCL;
		/*FALLTHROUGH*/
	    case DB_TSW_TYPE:	/* _current_timestamp */
		dn.dn_status |= AD_DN_YEARSPEC|AD_DN_MONTHSPEC|AD_DN_DAYSPEC;
		dn.dn_status |= AD_DN_TIMESPEC;
		break;
	    }

	    /* Convert straight into constant data area */
	    if (db_stat = adu_7from_dtntrnl (adf_scb, &tmp_rdv, &dn))
		return (db_stat);
	}
	else if (dbi == NULL  ||  dbi->dbi_func == NULL)
	{
	    /* If no function ptr in dbmsinfo array, set default value */
	    if (db_stat = adc_getempty(adf_scb, &tmp_rdv))
		return (db_stat);
	}
	else
	{
	    /* Get the value from the proper dbmsinfo function */

	    /*
	    ** NOTE: If the dbmsinfo routines ever change the size of
	    ** of the returned object, it will be assumed that the length
	    ** will match the adk_* buffer length. If not, there will
	    ** be a risk of uninitialised data slipping in.
	    */
	    if (db_stat = (*dbi->dbi_func)(dbi, NULL, &tmp_rdv, &err))
		return (db_stat);
	}

	/* We now have the calculated result written directly to the
	** constant buffers if they exist or to the tmp_buf.
	** Either way, we don't need to write the constant again, we just
	** need to convert out to the return buffer/dbv.
	*/

	/* Don't forget to set the `already calculated' bit */
	if (k)
	    k->adk_set_mask |= kbit;
    }

    /* We have the value requested, so just set result and return */
    if (rdv->db_datatype == DB_INT_TYPE)
    {	/* Currently, all query constants are uints or dates */
	u_i8 val;
	switch (tmp_rdv.db_length)
	{
	case 8:
	    val = (u_i8)*(u_i8*)tmp_rdv.db_data;
	    break;
	case 4:
	    val = (u_i8)*(u_i4*)tmp_rdv.db_data;
	    break;
	case 2:
	    val = (u_i8)*(u_i2*)tmp_rdv.db_data;
	    break;
	case 1:
	    val = (u_i8)*(u_i1*)tmp_rdv.db_data;
	    break;
	}
	switch (rdv->db_length)
	{
	case 8:
	    I8ASSIGN_MACRO(val, *(u_i8 *)rdv->db_data);
	    break;
	case 4:
	    {
		u_i4 val4 = (u_i4)val;
		I4ASSIGN_MACRO(val4, *(u_i4 *)rdv->db_data);
	    }
	    break;
	case 2:
	    {
		u_i2 val2 = (u_i2)val;
		I2ASSIGN_MACRO(val2, *(i2*)rdv->db_data);
	    }
	    break;
	case 1:
	    *(u_i1 *)rdv->db_data = (u_i1)val;
	    break;
	default:
	    return (adu_error (adf_scb, E_AD9998_INTERNAL_ERROR,
		2, 0, "dbmsinfo isz"));
	}
    }
    else if (tmp_rdv.db_length != rdv->db_length)
    {
	return (adu_error (adf_scb, E_AD9998_INTERNAL_ERROR,
		2, 0, "dbmsinfo len"));
    }
    else
    {
	MEcopy(tmp_rdv.db_data, rdv->db_length, rdv->db_data);
    }
    return (E_DB_OK);
}