/*{ ** Name: PSF_SESSCB - get session control block. ** ** Description: ** Get the session control block from SCF. ** ** Inputs: ** none ** ** Outputs: ** Returns: ** sess_cb session control block ptr ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 8-oct-86 (daved) ** written ** 14-jul-93 (ed) ** replacing <dbms.h> by <gl.h> <sl.h> <iicommon.h> <dbdbms.h> ** 10-aug-93 (andre) ** removed declaration of scf_call() ** 08-sep-93 (swm) ** Changed sizeof(DB_SESSID) to sizeof(CS_SID) to reflect recent CL ** interface revision. ** 10-Jan-2001 (jenjo02) ** Use (new) GET_PSS_SESBLK macro instead of ** scf_call(SCU_INFORMATION) to return session's ** PSS_SESBLK*. [@history_line@]... [@history_template@]... */ PSS_SESBLK* psf_sesscb(void) { CS_SID sid; CSget_sid(&sid); return(GET_PSS_SESBLK(sid)); }
/* ** Name: AllocConn - Allocate a new connection block ** ** Description: ** Allocate a piece of ME storage to hold the new CM_CONN_BLK ** ** Inputs: ** conn_db - DataBase handle ** conn_userid - Userid handle ** conn_hndl _ Connection handle ** ** Outputs: ** ** Returns: ** The addr(Connection entry) ** ** History: ** 27-Feb-98 (shero03) ** Created. */ P_CM_CONN_BLK ccm_AllocConn(i4 conn_id, i4 conn_flag, PTR conn_DB, PTR conn_Userid, PTR conn_hndl) { CM_CONN_BLK *entry; entry = (CM_CONN_BLK *)HSH_AllocEntry(pCM_cb->cm_used_conn_index, NULL, 0, sizeof(CM_CONN_BLK)); if (entry) { entry->cm_conn_id = conn_id; /* initialize the ID field */ if (pCM_cb->cm_flags & CM_FLAG_MULTITHREADED) CSget_sid(&entry->cm_conn_SID); /* Fill in the SID */ else entry->cm_conn_SID = 1; entry->cm_conn_flags = conn_flag; entry->cm_conn_DB = conn_DB; /* Fill in the DB handle */ entry->cm_conn_User = conn_Userid; /* Fill in the Userid Handle */ entry->cm_conn_hndl = conn_hndl; /* Fill in the Conn Handle */ } return entry; /* return the addr(new entry) */ } /* proc - AllocConn */
/*{ ** Name: rdt_clear_cache - Clear RDf cache ** ** Description: ** This function causes one or more RDF cache(s) to be cleared, as follows: ** Trace Point: Caches Cleared: ** rd1 RELcache ** rd2 RELcache, QTREE cache ** rd3 LDBdesc cache ** rd4 LDBdesc cache, RELcache, QTREE cache ** rd5 Defaults Cache ** rd10 ALL RDF CACHES ** ** Inputs: ** trace_pt value of trace point. ** Outputs: ** none ** ** Returns: ** E_DB_OK Function completed normally. ** E_DB_ERROR Function failed due to error by caller; ** E_DB_FATAL Function failed due to some internal ** problem; ** Exceptions: ** none ** ** Side Effects: ** none. ** ** History: ** (teresa) ** Initial creation -- the original subroutine header section seems ** to have gotten lost, so recreated today (7-jan-91) ** 07-jan-91 (teresa) ** Fix AV caused by uninitialized rdr_types_mask and rdr_2types_mask. ** (bug 41956) ** 23-Jan-92 (teresa) ** SYBIL: change criter for QTREE invalidation from rdi_qthash (which ** is no longer in the structure to setting facility ID to ** PSF to invalidate QTREE hash. ** 16-jul-92 (teresa) ** prototypes ** 16-sep-92 (teresa) ** modify to take trace_pt as argument and handle trace points 3 and 4. ** 07-Mar-2001 (jenjo02) ** Supply session id to rdf_invalidate in RDF_CB. ** 13-May-2009 (kschendel) b122041 ** Compiler warning fixes. */ DB_STATUS rdt_clear_cache(i4 trace_pt) { RDF_GLOBAL global; RDF_CB rdfcb; RDI_FCB fcb; DB_STATUS status; global.rdfcb = &rdfcb; rdfcb.rdf_rb.rdr_fcb = (PTR ) &fcb; rdfcb.rdf_info_blk = NULL; rdfcb.rdf_rb.rdr_db_id = NULL; rdfcb.rdf_rb.rdr_types_mask = 0; rdfcb.rdf_rb.rdr_2types_mask = 0; CSget_sid(&rdfcb.rdf_rb.rdr_session_id); /* trace ** point cache action (call rdf_invalidate with ) ** ------ --------- --------------------- ** RD0001 RELcache rdi_fac_id = DB_RDF_ID, rdr_2types_mask = 0 ** RD0002 RELcache & ** QTREE rdi_fac_id = DB_PSF_ID, rdr_2types_mask = 0 ** RD0003 LDBdesc rdr_2types_mask = RDR2_INVL_LDBDESC ** RD0004 rel,QTREE, rdi_fac_id=DB_PSF_ID, then call a second time with ** LDBdesc rdr_2types_mask=RDR2_INVL_LDBDESC ** RD0005 Defaults rdi_fac_id=DB_RDF_ID, rdr_2types_mask=RDR2_INVL_DEFAULT ** RD0010 ALL Three calls: ** 1 rdi_fac_id=DB_RDF_ID,rdr_2types_mask=RDR2_INVL_LDBDESC ** 2 rdi_fac_id=DB_RDF_ID,rdr_2types_mask=RDR2_INVL_DEFAULT ** 3 rdi_fac_id=DB_PSF_ID,rdr_2types_mask = 0 */ switch (trace_pt) { case RD0001: fcb.rdi_fac_id = fcb.rdi_fac_id = DB_RDF_ID; status = rdf_invalidate(&global, &rdfcb); break; case RD0002: fcb.rdi_fac_id = fcb.rdi_fac_id = DB_PSF_ID; status = rdf_invalidate(&global, &rdfcb); break; case RD0003: fcb.rdi_fac_id = fcb.rdi_fac_id = DB_RDF_ID; rdfcb.rdf_rb.rdr_2types_mask = RDR2_INVL_LDBDESC; status = rdf_invalidate(&global, &rdfcb); break; case RD0004: /* invalidate LDBdesc cache first, then RELcache and QTREE cache */ fcb.rdi_fac_id = fcb.rdi_fac_id = DB_RDF_ID; rdfcb.rdf_rb.rdr_2types_mask = RDR2_INVL_LDBDESC; status = rdf_invalidate(&global, &rdfcb); /* LDBdesc cache */ if (status != E_DB_OK) break; rdfcb.rdf_rb.rdr_2types_mask = 0; fcb.rdi_fac_id = fcb.rdi_fac_id = DB_PSF_ID; status = rdf_invalidate(&global, &rdfcb); /* RELcache, QTREE*/ break; case RD0005: fcb.rdi_fac_id = fcb.rdi_fac_id = DB_RDF_ID; rdfcb.rdf_rb.rdr_2types_mask = RDR2_INVL_DEFAULT; status = rdf_invalidate(&global, &rdfcb); break; case RD0010: /* invalidate LDBdesc cache first, then default cache, then ** RELcache and QTREE cache */ fcb.rdi_fac_id = fcb.rdi_fac_id = DB_RDF_ID; rdfcb.rdf_rb.rdr_2types_mask = RDR2_INVL_LDBDESC; status = rdf_invalidate(&global, &rdfcb); /* LDBdesc cache */ if (status != E_DB_OK) break; fcb.rdi_fac_id = fcb.rdi_fac_id = DB_RDF_ID; rdfcb.rdf_rb.rdr_2types_mask = RDR2_INVL_DEFAULT; status = rdf_invalidate(&global, &rdfcb); /* Default cache */ if (status != E_DB_OK) break; fcb.rdi_fac_id = fcb.rdi_fac_id = DB_PSF_ID; rdfcb.rdf_rb.rdr_2types_mask = 0; status = rdf_invalidate(&global, &rdfcb); /* RELcache, QTREE*/ break; default: /* do nothing if trace_pt is an unexpected value */ break; } return status; }
/*{ ** Name: rdf_trace - Call RDF trace operation. ** ** External call format: status = rdf_trace(&db_debug_cb) ** ** Description: ** This function is the standard entry point to RDF for setting and ** clearing tracepoints(the "set trace point" command). Because RDF ** is a service facility, trace point for RDF can only be set on ** the server basis. There is no session level trace point. ** Db_debug_cb is the tracing control block that contains the trace ** flag information. ** ** See file <rdftrace.h> for a description of all possible ** RDF trace points. ** ** Inputs: ** debug_cb Pointer to a DB_DEBUG_CB ** .db_trswitch What operation to perform ** DB_TR_NOCHANGE None ** DB_TR_ON Turn on a tracepoint ** DB_TR_OFF Turn off a tracepoint ** .db_trace_point Trace point ID(the flag number) ** .db_value_count The number of values specified in ** the value array ** .db_vals[2] Optional values, to be interpreted ** differently for each tracepoint ** Outputs: ** none ** ** Returns: ** E_DB_OK Function completed normally. ** E_DB_ERROR Function failed due to error by caller; ** E_DB_FATAL Function failed due to some internal ** problem; ** Exceptions: ** none ** ** Side Effects: ** The trace vector in the server control block of RDF will be updated ** to contain the trace information. The trace information will be persist ** throughout the life of the server. ** ** History: ** 15-apr-86 (ac) ** written ** 02-mar-87 (puree) ** replace global server control block with global pointer. ** 14-dec-1989 (teg) ** modify to go get svcb from SCF instead of using a global pointer ** to it. ** 16-jul-92 (teresa) ** prototypes ** 16-sep-92 (teresa) ** implement trace points rd3 and rd4 to clear ldbdesc cache. ** 22-apr-94 (teresa) ** added trace points rd11 and rd12 to dump memory statistics or all ** statistics. This is an action trace point -- the dump occurs when ** the trace point is selected rather than during query execution. ** 20-nov-2007 (thaju02) ** If trace point RD0022/RDU_CHECKSUM specified, invalidate ** relcache. Entries need rdr_checksum to be calc/init'd ** otherwise E_RD010D errors may be reported. (B119499) */ DB_STATUS rdf_trace(DB_DEBUG_CB *debug_cb) { i4 flag; i4 firstval; i4 secondval; DB_STATUS status; i4 trace_scope; /* assure flag is legal */ flag = debug_cb->db_trace_point; if (flag >= RDF_NB) { return (E_DB_ERROR); } /* There can be UP TO two values, but maybe they weren't given */ firstval = (debug_cb->db_value_count > 0) ? debug_cb->db_vals[0] : 0L; secondval = (debug_cb->db_value_count > 1) ? debug_cb->db_vals[1] : 0L; /* see if this is an action trace. Action traces require an immediate ** action rather than turning trace flags on/off/etc. */ if ( (debug_cb->db_trswitch==DB_TR_ON) && (flag <= RD_ACT_MAX) ) { /* see which action is requested. Not all actions are implemented ** yet, so its possible that this call may become a no-opt */ switch (flag) { case RD0001: case RD0002: case RD0003: case RD0004: case RD0005: case RD0010: status=rdt_clear_cache(flag); if (DB_FAILURE_MACRO(status)) { return(E_DB_ERROR); } break; case RD0011: /* dump memory info. This trace is used by tech support when ** debugging out of memory errors. */ TRdisplay("\n...............................................\n"); TRdisplay("RDF Cache Memory Available: %d\n",Rdi_svcb->rdv_memleft); TRdisplay("RDF memory cache size : %d\n", Rdi_svcb->rdv_pool_size); TRdisplay("Max number of objects allowed on Cache:\n"); TRdisplay(" RELcache: %d, QTREE Cache: %d, \n", Rdi_svcb->rdv_cnt0_rdesc, Rdi_svcb->rdv_cnt1_qtree); TRdisplay(" LDBDesc Cache %d, DEFAULTS cache: %d\n", Rdi_svcb->rdv_cnt2_dist, Rdi_svcb->rdv_cnt3_default); TRdisplay("Hashids:\n"); TRdisplay(" RELcache: %d, QTREE Cache: %d, \n", Rdi_svcb->rdv_rdesc_hashid, Rdi_svcb->rdv_qtree_hashid); TRdisplay(" LDBDesc Cache %d, DEFAULTS cache: %d\n", Rdi_svcb->rdv_dist_hashid, Rdi_svcb->rdv_def_hashid); TRdisplay("...............................................\n"); break; case RD0012: /* dump all of the RDF statistics */ rdf_report ( &Rdi_svcb->rdvstat ); break; default: break; } } else { /* ** determine if this is a session wide trace or a server wide trace ** and process accordingly */ trace_scope = trace_type(flag); if (trace_scope == SVR_WIDE_TRACE) { /* turn trace on in svcb ** ** Three possible actions: Turn on flag, turn it off, or do nothing. */ switch (debug_cb->db_trswitch) { case DB_TR_ON: if ((flag == RD0022) && !(ult_check_macro(&Rdi_svcb->rdf_trace, flag, &firstval, &secondval))) { /* setting RDU_CHECKSUM */ RDF_GLOBAL global; RDF_CB rdfcb; RDI_FCB fcb; global.rdfcb = &rdfcb; rdfcb.rdf_rb.rdr_fcb = (PTR)&fcb; rdfcb.rdf_info_blk = NULL; rdfcb.rdf_rb.rdr_db_id = NULL; rdfcb.rdf_rb.rdr_types_mask = 0; rdfcb.rdf_rb.rdr_2types_mask = 0; CSget_sid(&rdfcb.rdf_rb.rdr_session_id); fcb.rdi_fac_id = DB_RDF_ID; status = rdf_invalidate(&global, &rdfcb); if (DB_FAILURE_MACRO(status)) return(E_DB_ERROR); } ult_set_macro(&Rdi_svcb->rdf_trace, flag, firstval, secondval); break; case DB_TR_OFF: ult_clear_macro(&Rdi_svcb->rdf_trace, flag); break; case DB_TR_NOCHANGE: /* Do nothing */ break; default: return (E_DB_ERROR); }; } else { CS_SID sid; RDF_SESS_CB *rdf_sess_cb; /* ** this trace point is session specific, so use the session control ** block for this trace point. */ CSget_sid(&sid); rdf_sess_cb = GET_RDF_SESSCB(sid); /* ** Three possible actions: Turn on flag, turn it off, or do nothing. */ switch (debug_cb->db_trswitch) { case DB_TR_ON: ult_set_macro(&rdf_sess_cb->rds_strace, flag, firstval, secondval); break; case DB_TR_OFF: ult_clear_macro(&rdf_sess_cb->rds_strace, flag); break; case DB_TR_NOCHANGE: /* Do nothing */ break; default: return (E_DB_ERROR); } } } return (E_DB_OK); }
/*{ ** Name: GM_gcmsend - make GCa_call for GCM request. ** ** Description: ** Makes the call... ** ** Re-entrancy: ** yes. ** ** Inputs: ** conn the connect block with the prepared message to send. ** ** Outputs: ** conn ** ** Returns: ** E_DB_OK ** E_DB_ERROR ** ** History: ** 8-oct-92 (daveb) ** created. ** 12-Nov-1992 (daveb) ** Need GCA_ALT_EXIT for our completiong routien to be seen. ** Add fs_parms var to simplify debugging. ** 14-Nov-1992 (daveb) ** take *cl_stat to fill in. ** 20-Nov-1992 (daveb) ** Put in more TRdisplay error logging, to fix later. ** 2-Dec-1992 (daveb) ** Check for server failed in quick abort case. Trying to avoid ** lots of errors re-connectiong to non-gcm servers. ** 08-sep-93 (swm) ** Changed sid type from i4 to CS_SID to match recent CL ** interface revision. ** 20-jul-95 (canor01) ** pass the SCB to IIGCa_call() instead of the SID */ static DB_STATUS GM_gcmsend( GM_CONN_BLK *conn, STATUS *cl_stat ) { DB_STATUS db_stat; CS_SID sid; i4 resume = 0; STATUS local_status; GCA_FS_PARMS *fs_parms = &conn->conn_fs_parms; GM_PLACE_BLK *place = conn->conn_place; conn->conn_state = GM_CONN_GCM_WORKING; CSget_sid(&sid); GM_incr( &GM_globals.gwm_stat_sem, &GM_globals.gwm_gcm_sends ); if( place->place_type == GM_PLACE_SRVR && ((place->place_srvr.srvr_flags & GCA_RG_MIB_MASK) == 0 || place->place_srvr.srvr_state == GM_SRVR_FAILED )) { /* nothing can be had from this server. We did a lot of setup work for nothing. FIXME -- move this test higher up? */ conn->conn_rsb->response.err_element = 0; conn->conn_rsb->response.status = *cl_stat = MO_NO_INSTANCE; conn->conn_state = GM_CONN_EMPTIED; return( E_DB_ERROR ); } do { *cl_stat = IIGCa_call(GCA_FASTSELECT, (GCA_PARMLIST *)fs_parms, GCA_ASYNC_FLAG | GCA_ALT_EXIT | resume, (PTR)CS_find_scb(sid), (i4) -1, &local_status ); if (*cl_stat != OK) { /* "GWM Internal error: Error making gcm send to %0c" */ GM_1error( (GWX_RCB *)0, E_GW8042_GCA_CALL, GM_ERR_INTERNAL, 0, (PTR)conn->conn_rsb->request.place ); GM_error( *cl_stat ); conn->conn_state = GM_CONN_ERROR; } else { /* wait for completion routine to wake us */ *cl_stat = CSsuspend(CS_BIO_MASK, 0, 0); if (*cl_stat != OK) { /* "GWM Internal error: CSsuspend problem" */ GM_error( E_GW8043_CS_SUSPEND ); GM_error( *cl_stat ); conn->conn_state = GM_CONN_ERROR; } else /* completion handler called */ { switch ( *cl_stat = conn->conn_fs_parms.gca_status ) { case OK: resume = 0; conn->conn_state = GM_CONN_GCM_DONE; break; case E_GCFFFE_INCOMPLETE: GM_incr( &GM_globals.gwm_stat_sem, &GM_globals.gwm_gcm_reissues ); resume = GCA_RESUME; break; case E_GC0032_NO_PEER: resume = 0; /* "GWM Internal error: Got 'no peer' to %0c (%1c %2x)" */ GM_3error( (GWX_RCB *)0, E_GW8044_NO_PEER, GM_ERR_INTERNAL, 0, place->place_key, 0, place->place_srvr.srvr_class, sizeof(place->place_srvr.srvr_flags), (PTR)&place->place_srvr.srvr_flags ); GM_error( *cl_stat ); conn->conn_state = GM_CONN_ERROR; break; default: resume = 0; /* "GWM Internal error: GCM completion error to %0c (%1c %2x)" */ GM_3error( (GWX_RCB *)0, E_GW8045_GCA_COMPLETION, GM_ERR_INTERNAL, 0, (PTR)place->place_key, 0, (PTR)place->place_srvr.srvr_class, sizeof(place->place_srvr.srvr_flags), (PTR)&place->place_srvr.srvr_flags ); GM_error( *cl_stat ); conn->conn_state = GM_CONN_ERROR; place->place_srvr.srvr_state = GM_SRVR_FAILED; break; } } } } while( resume != 0 ); db_stat = (*cl_stat == OK) ? E_DB_OK : E_DB_ERROR; return( db_stat ); }
STATUS dmf_get_srs( DB_SPATIAL_REF_SYS *db_srs, i4 *errcode) { DMT_SHW_CB srs_show; DMT_TBL_ENTRY srs_table; STATUS status; DML_SCB *scb; CS_SID sid; DMT_CB dmt_cb; DMR_CB dmr_cb; DMR_ATTR_ENTRY key, *kptr = &key; SRS_ROW row; CSget_sid(&sid); scb = GET_DML_SCB(sid); /* ** make sure we are have a transaction */ if (scb->scb_x_ref_count != 1) { *errcode = E_AD5603_NO_TRANSACTION; return E_DB_ERROR; } /* * First we need to grab spatial_ref_sys information */ MEfill(sizeof(DB_OWN_NAME), ' ', &srs_show.dmt_owner); MEfill(sizeof(DB_TAB_NAME), ' ', &srs_show.dmt_name); STncpy(srs_show.dmt_name.db_tab_name, "spatial_ref_sys", STlen("spatial_ref_sys")); STncpy(srs_show.dmt_owner.db_own_name, "$ingres", STlen("$ingres")); srs_show.type = DMT_SH_CB; srs_show.length = sizeof(DMT_SHW_CB); srs_show.dmt_session_id = sid; srs_show.dmt_db_id = (PTR) scb->scb_x_next->xcb_odcb_ptr; srs_show.dmt_flags_mask = DMT_M_NAME | DMT_M_TABLE; srs_show.dmt_char_array.data_address = (PTR) NULL; srs_show.dmt_char_array.data_in_size = 0; srs_show.dmt_char_array.data_out_size = 0; srs_show.dmt_table.data_address = (PTR) &srs_table; srs_show.dmt_table.data_in_size = sizeof(DMT_TBL_ENTRY); status = dmt_show(&srs_show); if(status != E_DB_OK) { //something went wrong *errcode = E_AD5604_SRS_NONEXISTENT; return status; } /* * Next open the spatial_ref_sys table */ MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb); dmt_cb.type = DMT_TABLE_CB; dmt_cb.length = sizeof(DMT_CB); dmt_cb.dmt_db_id = (PTR) scb->scb_x_next->xcb_odcb_ptr; STRUCT_ASSIGN_MACRO(srs_table.tbl_id, dmt_cb.dmt_id); dmt_cb.dmt_flags_mask = 0; dmt_cb.dmt_lock_mode = DMT_IS; dmt_cb.dmt_update_mode = DMT_U_DIRECT; dmt_cb.dmt_mustlock = FALSE; dmt_cb.dmt_access_mode = DMT_A_READ; dmt_cb.dmt_char_array.data_in_size = 0; dmt_cb.dmt_sequence = 0; dmt_cb.dmt_tran_id = (PTR) scb->scb_x_next; status = dmt_open(&dmt_cb); if (status != E_DB_OK) { *errcode = E_AD5601_GEOSPATIAL_INTERNAL; return status; } /* * Let's set up for the actual gets */ dmr_cb.type = DMR_RECORD_CB; dmr_cb.length = sizeof(DMR_CB); dmr_cb.dmr_access_id = dmt_cb.dmt_record_access_id; dmr_cb.dmr_tid = 0; dmr_cb.dmr_q_fcn = NULL; dmr_cb.dmr_position_type = DMR_QUAL; kptr->attr_number = SRS_SRID_COL; kptr->attr_operator = DMR_OP_EQ; kptr->attr_value = (char *) &db_srs->srs_srid; dmr_cb.dmr_attr_desc.ptr_address = (PTR) &kptr; dmr_cb.dmr_attr_desc.ptr_in_count = 1; dmr_cb.dmr_attr_desc.ptr_size = sizeof (DMR_ATTR_ENTRY); dmr_cb.dmr_flags_mask = 0; status = dmr_position(&dmr_cb); if (status != E_DB_OK) { if (dmr_cb.error.err_code == E_DM0055_NONEXT) *errcode = E_AD5605_INVALID_SRID; else *errcode = E_AD5601_GEOSPATIAL_INTERNAL; dmt_close(&dmt_cb); return status; } dmr_cb.dmr_data.data_in_size = SRS_ROW_SIZE; dmr_cb.dmr_data.data_address = row; dmr_cb.dmr_flags_mask = DMR_NEXT; status = dmr_get(&dmr_cb); if (status != E_DB_OK) { if (dmr_cb.error.err_code == E_DM0055_NONEXT) { *errcode = E_AD5605_INVALID_SRID; } else { *errcode = E_AD5601_GEOSPATIAL_INTERNAL; } dmt_close(&dmt_cb); return status; } /* * If we get here we retrieved a row yay! */ MEcopy((row + SRS_AUTH_NAME_OFFSET), sizeof(db_srs->srs_auth_name), db_srs->srs_auth_name); db_srs->srs_auth_name[STlen(db_srs->srs_auth_name)] = '\0'; MEcopy((row + SRS_AUTH_ID_OFFSET), sizeof(i4), &db_srs->srs_auth_id); MEcopy((row + SRS_SRTEXT_OFFSET), sizeof(db_srs->srs_srtext), db_srs->srs_srtext); db_srs->srs_srtext[STlen(db_srs->srs_srtext)] = '\0'; MEcopy((row + SRS_PROJ4TEXT_OFFSET), sizeof(db_srs->srs_proj4text), db_srs->srs_proj4text); db_srs->srs_proj4text[STlen(db_srs->srs_proj4text)] = '\0'; /* * Must close the table when we're done */ status = dmt_close(&dmt_cb); if(status != E_DB_OK) { /* close failed?? */ *errcode = E_AD5601_GEOSPATIAL_INTERNAL; return status; } return E_DB_OK; }
/*{ ** ** Name: dmc_write_behind_common - the guts of a write behind thread ** ** Description: ** ** The dmc_write_behind routine is used for implementing an asynchronous ** write behind thread. It wakes up whenever signaled by an LK event ** and writes dirty pages out of the cache to make room for new pages ** to be read in. ** ** The dmc_write_behind routine should only be called within a special ** session that is dedicated for this purpose. This routine will not ** return under normal circumstances until server shutdown time. ** ** This routine uses two routines in DM0P to drive the write behind ** thread: ** DM0P_BMFLUSH_WAIT waits for a session in the buffer manager ** to signal the event to wake up the write behind threads. This ** is signalled when some specified percent of the buffer manager ** is filled with dirty pages. ** ** DM0P_FLUSH_PAGES goes through the buffer manager modified queue ** in reverse priority order writing pages until some specified ** percentage of the buffer manager is free. ** ** This routine will return only if the event wait in DM0P_BMFLUSH_WAIT ** is cancelled by an interrupt. At server shutdown time, the server ** is expected to interrupt all the write behind threads. ** ** This common code is executed by both Primary and Cloned ** WriteBehind agents. ** ** Inputs: ** i_am_a_clone FALSE if this is the Primary WB Agent, ** TRUE if a Clone. ** cfa Agent's data. ** ** Outputs: ** dmf_err ** .error.err_code One of the following error numbers. ** E_DB_OK ** E_DM004A_INTERNAL_ERROR ** E_DM004B_LOCK_QUOTA_EXCEED ** E_DM0062_TRAN_QUOTA_EXCEED ** E_DM0117_WRITE_BEHIND ** ** Returns: ** E_DB_OK ** E_DB_FATAL ** ** History: ** 30-jun-1988 (rogerk) ** Created for Jupiter. ** 30-Jan-1989 (ac) ** Added arguments to LGbegin(). ** 15-may-1989 (rogerk) ** Return resource errors if resource limit is exceeded. ** 2-oct-1992 (ed) ** Use DB_MAXNAME to replace hard coded numbers ** - also created defines to replace hard coded character strings ** dependent on DB_MAXNAME ** 18-oct-1993 (rogerk) ** Add check for LOGFULL status. We don't execute write behind when ** in logfull to avoid background log forces which wreak havoc on ** the recovery logspace reservation algorithms. ** 10-oct-93 (swm) ** Bug #56438 ** Put LG_DBID into automatic variable lg_dbid rather than overloading ** dmc_cb->dmc_db_id. ** 31-jan-1994 (bryanp) B58380, B58381 ** Log LG/LK status code if LG or LK call fails. ** Check return code from CSsuspend. ** 10-Mar-1998 (jenjo02) ** Support for demand-driven WriteBehind threads. Changed prototype ** to pass a boolean indicating whether this is the primary or ** cloned WB thread and a pointer to DB_ERROR instead of a pointer ** to DMC_CB. ** Made this a common function called by Primary and Cloned threads. */ static DB_STATUS dmc_write_behind_common( i4 i_am_a_clone, char *cfa, DB_ERROR *dmf_err) { DM_SVCB *svcb = dmf_svcb; DB_TRAN_ID tran_id; LG_LXID lx_id; DM0L_ADDDB add_info; TIMERSTAT stat_block; i4 lock_list; i4 len_add_info; i4 event_mask; i4 events, wakeup_event; i4 have_locklist = FALSE; i4 have_transaction = FALSE; i4 lg_added = FALSE; DB_STATUS status = E_DB_OK; i4 wbcount = 0; i4 wait_time = 0; i4 base_time = 0; i4 flush_time, new_time; i4 length; i4 lgd_status; STATUS stat; i4 error; CL_ERR_DESC sys_err; DB_OWN_NAME user_name; LG_DBID lg_dbid; #ifdef xDEBUG CS_SID sid; i4 pid; PCpid(&pid); CSget_sid(&sid); TRdisplay("Starting Write Behind Thread %x in server process %d\n", sid, pid); #endif CLRDBERR(dmf_err); if (status == E_DB_OK) { /* ** Add write behind thread to logging system. ** Write behind thread does not actually open a database, so use ** the LG_NOTDB flag. */ STmove((PTR)DB_WRITEBEHIND_THREAD, ' ', sizeof(add_info.ad_dbname), (PTR) &add_info.ad_dbname); MEcopy((PTR)DB_INGRES_NAME, sizeof(add_info.ad_dbowner), (PTR) &add_info.ad_dbowner); MEcopy((PTR)"None", 4, (PTR) &add_info.ad_root); add_info.ad_dbid = 0; add_info.ad_l_root = 4; len_add_info = sizeof(add_info) - sizeof(add_info.ad_root) + 4; stat = LGadd(dmf_svcb->svcb_lctx_ptr->lctx_lgid, LG_NOTDB, (char *)&add_info, len_add_info, &lg_dbid, &sys_err); if (stat != OK) { uleFormat(NULL, stat, (CL_ERR_DESC *)&sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); uleFormat(NULL, E_DM900A_BAD_LOG_DBADD, &sys_err, ULE_LOG, NULL, (char *)NULL, 0L, (i4 *)NULL, &error, 4, 0, dmf_svcb->svcb_lctx_ptr->lctx_lgid, sizeof(add_info.ad_dbname), (PTR) &add_info.ad_dbname, sizeof(add_info.ad_dbowner), (PTR) &add_info.ad_dbowner, 4, (PTR) &add_info.ad_root); if (stat == LG_EXCEED_LIMIT) SETDBERR(dmf_err, 0, E_DM0062_TRAN_QUOTA_EXCEEDED); else SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); status = E_DB_ERROR; } else lg_added = TRUE; } if (status == E_DB_OK) { /* ** Begin transaction in order to do LG and LK calls. ** Must specify NOPROTECT transaction so that LG won't pick us ** as a force-abort victim. Also, the Log File BOF can be advanced ** past this transaction's position in the log file, which means that ** the Write Behind thread should do no logging nor work that could ** require backout. */ STmove((PTR)DB_WRITEBEHIND_THROWN, ' ', sizeof(DB_OWN_NAME), (PTR) &user_name); stat = LGbegin(LG_NOPROTECT, lg_dbid, &tran_id, &lx_id, sizeof(DB_OWN_NAME), user_name.db_own_name, (DB_DIS_TRAN_ID*)NULL, &sys_err); if (stat != OK) { uleFormat(NULL, stat, (CL_ERR_DESC *)&sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); uleFormat(NULL, E_DM900C_BAD_LOG_BEGIN, &sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 1, 0, lg_dbid); if (stat == LG_EXCEED_LIMIT) SETDBERR(dmf_err, 0, E_DM0062_TRAN_QUOTA_EXCEEDED); else SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); status = E_DB_ERROR; } else have_transaction = TRUE; } if (status == E_DB_OK) { /* ** Create locklist to use to wait for Write Behind event. */ stat = LKcreate_list(LK_NONPROTECT, (i4) 0, (LK_UNIQUE *)&tran_id, (LK_LLID *)&lock_list, (i4)0, &sys_err); if (stat != OK) { uleFormat(NULL, stat, (CL_ERR_DESC *)&sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); uleFormat(NULL, E_DM901A_BAD_LOCK_CREATE, &sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); if (stat == LK_NOLOCKS) SETDBERR(dmf_err, 0, E_DM004B_LOCK_QUOTA_EXCEEDED); else SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); status = E_DB_ERROR; } else have_locklist = TRUE; } if (status == E_DB_OK) { /* ** Now begin loop of waiting for Write Behind event and flushing ** the buffer manager. */ do { if (DMZ_ASY_MACRO(2)) { new_time = TMsecs(); flush_time = new_time - base_time - wait_time; base_time = new_time; /* Write Write Behind thread statistics. */ stat = CSstatistics(&stat_block, 0); TRdisplay("%22*- DMF Write Behind Thread statistics %21*-\n"); TRdisplay(" Write Behind wakeups: %d Cpu : %d Dio : %d\n", wbcount, stat_block.stat_cpu, stat_block.stat_dio); TRdisplay(" Time waiting for event: %d seconds\n", wait_time); TRdisplay(" Time to flush pages: %d seconds\n", flush_time); TRdisplay("%79*-\n"); } /* ** Cloned threads don't wait for a signal, they just ** help flush the cache, then go away. */ if (i_am_a_clone == FALSE) { /* ** Wait for the next signal that the buffer manager needs to have ** pages flushed. ** ** This routine will also clear the event from the previous ** signal. */ status = dm0p_wbflush_wait(cfa, lock_list, dmf_err); if (status != E_DB_OK) { /* ** If warning is returned, that's a signal that ** this thread is to terminate. */ if (status == E_DB_WARN) { status = E_DB_OK; break; } else { if (dmf_err->err_code > E_DM_INTERNAL) { uleFormat(dmf_err, 0, NULL, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); } break; } } } /* ** Check LOGFULL status. We don't execute write behind when in ** logfull to avoid background log forces which wreak havoc on ** the recovery logspace reservation algorithms. */ stat = LGshow(LG_S_LGSTS, (PTR)&lgd_status, sizeof(lgd_status), &length, &sys_err); if (stat != OK) { uleFormat(NULL, stat, (CL_ERR_DESC *)&sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); uleFormat(NULL, E_DM9017_BAD_LOG_SHOW, &sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 1, 0, LG_S_LGSTS); SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); status = E_DB_ERROR; break; } /* ** If logfull, skip the cache flush. */ if (lgd_status & LGD_LOGFULL) { /* ** Pause for a moment since the write-behind event will likely ** be immediately resignaled. We expect that this 5-second ** wait will return with "timed-out"; if it returns with ** "interrupted", then the server is being shut down. If it ** returns with any other return code, something is awry. */ stat = CSsuspend(CS_TIMEOUT_MASK | CS_INTERRUPT_MASK, 5, 0); if (stat == E_CS0008_INTERRUPTED) { status = E_DB_OK; break; } if (stat != E_CS0009_TIMEOUT) { uleFormat(NULL, stat, (CL_ERR_DESC *)&sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); status = E_DB_ERROR; break; } } else { /* ** Flush some dirty pages out of the Buffer Manager. */ if (dmf_svcb->svcb_status & SVCB_IOMASTER) { /* in IOMASTER server use same func as write-along thread */ i4 numforce; u_i4 duty = 0xffffffff; status = dm0p_write_along(lock_list, (i4)lx_id, &numforce, duty, dmf_err); } else status = dm0p_flush_pages(lock_list, (i4)lx_id, cfa, dmf_err); if (status != E_DB_OK) { if (dmf_err->err_code > E_DM_INTERNAL) { uleFormat(dmf_err, 0, NULL, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); } break; } } /* ** If dumping statistics, save time for event to be signaled. */ if (DMZ_ASY_MACRO(2)) wait_time = TMsecs() - base_time; wbcount++; } while (i_am_a_clone == FALSE); } if (i_am_a_clone == FALSE) { /* Write Fast Commit thread statistics. */ stat = CSstatistics(&stat_block, 0); TRdisplay("\n%22*- DMF Write Behind Thread statistics %21*-\n"); TRdisplay(" Write Behind wakeup: %d Cpu : %d Dio : %d\n", wbcount, stat_block.stat_cpu, stat_block.stat_dio); TRdisplay("%79*-\n"); } /* ** Clean up transaction and/or lock list left hanging around. */ if (have_transaction) { stat = LGend(lx_id, 0, &sys_err); if (stat != OK) { uleFormat(NULL, stat, (CL_ERR_DESC *)&sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); uleFormat(NULL, E_DM900E_BAD_LOG_END, &sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 1, 0, lx_id); if ( status == E_DB_OK ) { SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); status = E_DB_ERROR; } } have_transaction = FALSE; } if (have_locklist) { stat = LKrelease(LK_ALL, lock_list, (LK_LKID *)0, (LK_LOCK_KEY *)0, (LK_VALUE *)0, &sys_err); if (stat != OK) { uleFormat(NULL, stat, (CL_ERR_DESC *)&sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); uleFormat(NULL, E_DM901B_BAD_LOCK_RELEASE, &sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 1, 0, lock_list); if ( status == E_DB_OK ) { SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); status = E_DB_ERROR; } } have_locklist = FALSE; } if (lg_added) { stat = LGremove(lg_dbid, &sys_err); if (stat != OK) { uleFormat(NULL, stat, (CL_ERR_DESC *)&sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 0); uleFormat(NULL, E_DM9016_BAD_LOG_REMOVE, &sys_err, ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL, &error, 1, 0, lg_dbid); if ( status == E_DB_OK ) { SETDBERR(dmf_err, 0, E_DM0117_WRITE_BEHIND); status = E_DB_ERROR; } } } return (status); }
/*{ ** Name: SRopen - Opens a file. ** ** Description: ** The SRopen routine is used to open a direct access file. ** It will open the file for write access and will ** place no locks on the file. If the create_flag is set ** it will create it and allocate the amount specified. ** Additional space may be required to accomplish the sort. ** An unlimited number of extensions must be allowed. ** You can specify that nothing should be allocated at ** create time. ** ** SR files are allocated in SR_MIN_INCR-block chunks, ** i.e. (SR_MIN_INCR/2) Kb chunks. Ideally, one reads and ** writes SR files using a constant page size; but, it's ** allowable to read with a larger page size as long as both ** old and new page sizes are a power of 2 no larger than ** (SR_MIN_INCR/2) Kb. Likewise, it's allowable to read an ** existing SR file with a smaller page size as long as it ** divides evenly into the original page size. In general there ** is no burning need to flail around with SR file page sizes... ** ** Inputs: ** f Pointer to the SR file ** context needed to do I/O. ** path Pointer to the directory name ** for the file. ** pathlength Length of path name. ** filename Pointer to file name. ** filelength Length of file name. ** pagesize Value indicating size of page ** in bytes. Must be a multiple of ** the VMS page size of 512 bytes. ** create_flag Value indicating if creation needed. ** Must be SR_IO_CREATE. ** n Value indicating number of pages to ** pre-allocate. ** ** Outputs: ** f Updates the file control block. ** err_code Pointer to a variable used ** to return operating system ** errors. ** Returns: ** OK ** SR_BADDIR Error in path specification. ** SR_BADOPEN Error opening file. ** SR_BADFILE Bad file context. ** SR_PADPARAM Parameter(s) in error. ** SR_EXCEED_LIMIT Too many open files, exceeding disk quota ** or exceeding available disk space. ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 30-sep-85 (jennifer) ** Created new for 5.0. ** 02-apr-86 (jennifer) ** Modified the system error returned from a i4 to ** the type CL_ERR_DESC per CL request. ** 27-jul-87 (rogerk) ** Added return code SR_EXCEED_LIMIT. ** 17-aug-87 (rogerk) ** Save local return status after CSsuspend call before acting on ** its value. We were losing the return status from the allocate ** call by seting the local return status from CSsuspend later on. ** 11-may-98 (kinte01) ** Added page size for 65536 */ STATUS SRopen( SR_IO *f, char *path, u_i4 pathlength, char *filename, u_i4 filelength, i4 pagesize, u_i4 create_flag, i4 n, CL_ERR_DESC *err_code) { IOSB local_iosb; /* Operation return status. */ i4 s; /* Request return status. */ FIBDEF *fib; struct { i4 count; char *pointer; } descriptor; CS_SID sid; CL_CLEAR_ERR(err_code); #ifdef SR_CHECK_RESUME if (SR_check_resume) { SR_check_init(); } #endif /* Page size has to be a multiple of 512. */ if ((pagesize & 511) != 0) return (SR_BADPARAM); /* Initialize file control block. */ MEfill (sizeof(SR_IO), NULL, (PTR)f); f->io_type = SR_IO_ASCII_ID; CSget_sid(&sid); /* Assign a channel for I/O. */ descriptor.count = pathlength; descriptor.pointer = path; s = sys$assign(&descriptor, &f->io_channel, 0, 0); if ((s & 1) == 0) { err_code->error = s; if ((s == SS$_EXQUOTA) || (s == SS$_EXDISKQUOTA) || (s == SS$_NOIOCHAN)) return (SR_EXCEED_LIMIT); return (SR_BADOPEN); } /* Access the file with no locking.*/ fib = (FIBDEF *)f->io_fib; fib->fib$l_acctl = FIB$M_NOLOCK | FIB$M_WRITE; fib->fib$w_nmctl = 0; fib->fib$w_exctl = 0; f->io_fib_desc.str_len = sizeof(f->io_fib); f->io_fib_desc.str_str = f->io_fib; /* Queue the Create call. */ s = sr_qio(EFN$C_ENF, f->io_channel, IO$_CREATE | IO$M_CREATE | IO$M_ACCESS | IO$M_DELETE, &local_iosb, sr_resume_fcn, sid, &f->io_fib_desc, 0, 0, 0, 0, 0); if (s & 1) { /* Successfully queued, wait for completion. */ #ifdef SR_SUSPEND_THREAD SR_SUSPEND_THREAD; #endif s = local_iosb.iosb$w_status; if (local_iosb.iosb$w_status & 1) { /* Successful completion, setup the control block. */ fib->fib$l_acctl = 0; f->io_block_size = pagesize; f->io_blks = pagesize >> 9; /* Don't bother with io_log2_blk, nothing uses it... */ if (n != 0) { /* Preallocate space for the file. */ s = iiSRallocate(f, n, sid, err_code); if (s == OK) return (OK); /* ** If allocate returns an error, stuff the os errcode into ** 's' for processing below. */ s = err_code->error; } else { return (OK); } }
STATUS SRclose( SR_IO *f, i4 delete_flag, CL_ERR_DESC *err_code) { IOSB local_iosb; /* Operation return status. */ int s; /* Request return status. */ CS_SID sid; #ifdef xDEBUG long device_class; long dvi_length; ILE3 itmlst = {4, DVI$_DEVCLASS, &device_class, &dvi_length}; #endif CL_CLEAR_ERR(err_code); /* Check for valid control block. */ if (f->io_type != SR_IO_ASCII_ID) return (SR_BADFILE); /* Check that the file is open. */ if (f->io_channel == 0) return (OK); CSget_sid(&sid); #ifdef xDEBUG /* ** Check that the channel we are deallocating is still connected ** to a disk device. This will trap the errors where we are ** conflicting with GCF on IO channels. */ s = sr_getdvi(EFN$C_ENF, f->io_channel, 0, &itmlst, &local_iosb, sr_resume_fcn, sid, 0); if (s & 1) { #ifdef SR_SUSPEND_THREAD SR_SUSPEND_THREAD; #endif s = local_iosb.iosb$w_status; } if (((s & 1) == 0) || (device_class != DC$_DISK)) { /* ** This io channel is no longer any good, or is not what we ** think it is. Return BADCLOSE and either the system error ** (if one was returned), or SS$_NOTFILEDEV. */ err_code->error = s; if (s & 1) err_code->error = SS$_NOTFILEDEV; return (SR_BADCLOSE); } #endif /* Queue request to close and delete the file. */ s = sr_qio(EFN$C_ENF, f->io_channel, IO$_DEACCESS, &local_iosb, sr_resume_fcn, sid, 0, 0, 0, 0, 0, 0); if (s & 1) { /* Successfully queued, wait for completion. */ #ifdef SR_SUSPEND_THREAD SR_SUSPEND_THREAD; #endif if (local_iosb.iosb$w_status & 1) { /* Deassign the channel. */ s = sys$dassgn(f->io_channel); if (s & 1) { /* Return successful. */ f->io_channel = 0; f->io_type = 0; return (OK); } } else s = local_iosb.iosb$w_status; } err_code->error = s; return (SR_BADCLOSE); }
/* ** Name: scs_check_external_password ** ** Description: ** Check the external password for a role ** ** Inputs: ** scb - SCB ** ** authname - Role/User name being checked ** ** password - Role/User password ** ** auth_role - TRUE if authenticating a role ** ** Returns: ** E_DB_OK - Access is allowed ** ** E_DB_WARN - Access is denied ** ** E_DB_ERROR - Failure determining access ** ** History: ** 9-mar-94 (robf) ** Created ** 11-mar-94 (robf) ** Distinguish between access disallowed and some other ** error. Add SCF activity in case auth. server take a while ** 15-mar-94 (robf) ** Rework to allow for user or role authentication, add ** parameter auth_role. Make routine external, ** name scs_check_external_password, and move to scseauth.c ** 22-mar-1996 (stial01) ** Cast length passed to sc0m_allocate to i4. ** 16-jul-96 (stephenb) ** Add effective user to parameter list and pass to authentication ** server (fix primarily for ICE authentication, but useful ** information for the user anyway). ** 16-Nov-1998 (jenjo02) ** When suspending on BIO read, use CS_BIOR_MASK. */ DB_STATUS scs_check_external_password ( SCD_SCB *scb, DB_OWN_NAME *authname, DB_OWN_NAME *e_authname, DB_PASSWORD *password, bool auth_role ) { DB_STATUS status = E_DB_WARN; STATUS cl_stat; STATUS local_status; char pmname[64]; char *pmvalue; char target[64]; GCA_FS_PARMS fs_parms; SCS_REBUFF *re_buff = NULL; char *work_buff; i4 resume = 0; CS_SID sid; PTR save_data_area; char *q; char *gcmvalue; i4 error_index; i4 error_status; char *act_string; char blank_string[32] = ""; for (;;) { if (auth_role) act_string = "Validating external role password"; else act_string = "Validating external user password"; MEcopy((PTR)act_string, STlength(act_string), scb->scb_sscb.sscb_ics.ics_act1); scb->scb_sscb.sscb_ics.ics_l_act1 = (i4)STlength(act_string); /* ** Find the authentication mechanism for this role */ if (auth_role) { STprintf(pmname, "ii.$.secure.role_auth.%*s", scs_trimwhite(sizeof(*authname), (char*)authname), (char*)authname); } else { STprintf(pmname, "ii.$.secure.user_auth.%*s", scs_trimwhite(sizeof(*authname), (char*)authname), (char*)authname); } cl_stat = PMget(pmname, &pmvalue); if (cl_stat != OK) { sc0e_put(E_SC035A_EXTPWD_NO_AUTH_MECH, 0, 1, scs_trimwhite(sizeof(*authname), (char*)authname), (PTR)authname, 0, (PTR)0, 0, (PTR)0, 0, (PTR)0, 0, (PTR)0, 0, (PTR)0 ); status = E_DB_ERROR; break; } /* ** Now we know the target mechanism, set up target destination ** ** Legal values are either 'value' which maps to value/authsvr ** or @value which is sent untranslated. */ if (*pmvalue != '@') STprintf(target,"%s/authsvr",pmvalue); else STprintf(target,"%s", pmvalue+1); /* ** Allocate buffer for processing the request */ status = sc0m_allocate(SCU_MZERO_MASK, (i4)sizeof(SCS_REBUFF), DB_SCF_ID, (PTR)SCS_MEM, SCRE_TAG, (PTR*)&re_buff); if (status != E_DB_OK) { /* sc0m_allocate puts error codes in return status */ sc0e_0_put(status, 0); status = E_DB_ERROR; break; } work_buff = re_buff->work_buff; gcmvalue = re_buff->gcmvalue; CSget_sid(&sid); save_data_area = work_buff; /* ** Build the fastselect request */ fs_parms.gca_user_name = NULL; fs_parms.gca_password = NULL; fs_parms.gca_account_name = NULL; fs_parms.gca_completion = cep_complete; fs_parms.gca_closure = NULL; fs_parms.gca_peer_protocol = GCA_PROTOCOL_LEVEL_61; fs_parms.gca_partner_name = target; fs_parms.gca_modifiers = GCA_RQ_GCM; fs_parms.gca_buffer = work_buff; fs_parms.gca_b_length = RQ_BUFF_SIZE; fs_parms.gca_message_type = GCM_SET; q = save_data_area; q += sizeof(i4); /* Past error_status */ q += sizeof(i4); /* Past error_index */ q += sizeof(i4); /* Past future[0] */ q += sizeof(i4); /* Past future[1] */ q += gcm_put_int(q, -1);/* Client perms */ q += gcm_put_int(q, 1); /* Row count */ q += gcm_put_int(q, 1); /* Element count */ if (auth_role) q += gcm_put_str(q, "exp.scf.auth_server.role_authenticate"); /* Class id */ else q += gcm_put_str(q, "exp.scf.auth_server.user_authenticate"); /* Class id */ q += gcm_put_str(q, "0"); /* Instance */ /* ** Now build the value. ** This consists of: ** Role: ** flag - 4 byte integer, currently 0 ** real user - 32 byte blank-padded ** effective user - 32 byte blank-padded ** role - 32 byte blank-padded ** password - 24 byte blank-padded ** User: ** flag - 4 byte integer, currently 1 ** real user - 32 byte blank-padded ** effective user - 32 byte blank-padded ** password - 24 byte blank-padded ** These are all padded into a single GCM value. ** Note: This assumes no NULL values in any of the fields. */ if (auth_role) { STprintf(gcmvalue,"%-4.4s%32.32s%32.32s%32.32s%-24.24s", "0", (char*)&scb->scb_sscb.sscb_ics.ics_rusername, e_authname ? (char*)e_authname : blank_string, (char*)authname, (char*)password); } else { STprintf(gcmvalue,"%-4.4s%32.32s%32.32s%-24.24s", "1", (char*)authname, e_authname ? (char*)e_authname : blank_string, (char*)password); } q += gcm_put_str(q, gcmvalue ); /* Value */ fs_parms.gca_msg_length = (i4)(q - save_data_area); break; } /* ** Now do the fastselect */ resume = 0; if (status == E_DB_OK) do { cl_stat = IIGCa_call(GCA_FASTSELECT, (GCA_PARMLIST *)&fs_parms, GCA_ASYNC_FLAG | GCA_ALT_EXIT | resume, (PTR)CS_find_scb(sid), (i4) -1, &local_status); if (cl_stat != OK) { sc0e_0_put(cl_stat, 0); sc0e_0_put(E_SC0357_EXTPWD_GCA_FASTSELECT, 0); status = E_DB_ERROR; break; } else { /* wait for completion routine to wake us */ cl_stat = CSsuspend(CS_BIOR_MASK, 0, 0); if (cl_stat != OK) { sc0e_0_put(cl_stat, 0); sc0e_0_put(E_SC0356_EXTPWD_GCA_CSSUSPEND, 0); status = E_DB_ERROR; resume = 0; break; } else /* completion handler called */ { switch ( cl_stat = fs_parms.gca_status ) { case OK: resume = 0; break; case E_GCFFFE_INCOMPLETE: resume = GCA_RESUME; break; case E_GC0032_NO_PEER: case E_GC0138_GCN_NO_SERVER: case E_GC0139_GCN_NO_DBMS: resume = 0; sc0e_put(E_SC0355_EXTPWD_GCA_NOPEER, 0, 2, scs_trimwhite(sizeof(*authname), (char*)authname), (PTR)authname, (i4)STlength(target), (PTR)target, 0, (PTR)0, 0, (PTR)0, 0, (PTR)0, 0, (PTR)0 ); status = E_DB_ERROR; break; default: resume = 0; sc0e_0_put(cl_stat, 0); sc0e_0_put(E_SC0354_EXTPWD_GCA_COMPLETION, 0); status = E_DB_ERROR; break; } } } } while( resume != 0 ); /* ** Check if select worked OK, if not skip to the end */ if (status == E_DB_OK) { /* ** Got result of fastselect, so unpack and see what happened */ q = save_data_area; q += gcm_get_int(q, &error_status); q += gcm_get_int(q, &error_index); if (error_status != 0) { if (error_index == -1) { sc0e_0_put(error_status, 0); sc0e_0_put(E_SC0359_EXTPWD_GCM_ERROR, 0); status = E_DB_ERROR; } else { /* Access is denied */ status = E_DB_WARN; } } else { /* Access is allowed */ status = E_DB_OK; } } /* Reset activity */ scb->scb_sscb.sscb_ics.ics_l_act1 = 0; /* ** Free buffer if allocated */ if (re_buff) { if (sc0m_deallocate(0, (PTR *) &re_buff) != E_DB_OK) { sc0e_0_put(status, 0); } } return(status); }