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), ×tamp, &(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); }
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); }