bool adu_1monthcheck( char *input, i4 *output) { i4 month; /* month can be an integer, or an alphanumeric code */ if (CVal(input, &month) == OK) { *output = month; return (month < 1 || month > MONTHS_PER_YR); } else { const ADU_DATENAME *d; _VOID_ CVlower(input); d = adu_monthname_lookup(input,STlength(input)); if (d == NULL) { *output = 0; return 1; } *output = d->d_value; return (d->d_class != 'm'); /* TWISTED LOGIC! */ } }
static II_BOOL ns_param_marker( API_PARSE *parse, i4 fld, i4 *index ) { II_BOOL marker = FALSE; i4 value; if ( parse->fields[ fld ][0] == '~' && parse->fields[ fld ][1] == 'V' ) { /* ** Was an explicit parameter index ** included with the marker? */ if ( parse->fields[ fld ][2] && CVal( &parse->fields[ fld ][2], &value ) == OK ) *index = value; /* ** Convert field from text to parameter. */ parse->parameter[ fld ] = *index; /* Parameter index */ parse->fields[ fld ][0] = EOS; /* Parameter value */ (*index)++; /* Next default index */ marker = TRUE; } return( marker ); }
void Quicksort(CaseNo Fp, CaseNo Lp, Attribute Att) /* --------- */ { CaseNo i, Middle, High; ContValue Thresh, Val; if ( Fp < Lp ) { Thresh = CVal(Case[(Fp+Lp) / 2], Att); /* Divide cases into three groups: Fp .. Middle-1: values < Thresh Middle .. High: values = Thresh High+1 .. Lp: values > Thresh */ for ( Middle = Fp ; CVal(Case[Middle], Att) < Thresh ; Middle++ ) ; for ( High = Lp ; CVal(Case[High], Att) > Thresh ; High-- ) ; for ( i = Middle ; i <= High ; ) { if ( (Val = CVal(Case[i], Att)) < Thresh ) { Swap(Middle, i); Middle++; i++; } else if ( Val > Thresh ) { Swap(High, i); High--; } else { i++; } } /* Sort the first and third groups */ Quicksort(Fp, Middle-1, Att); Quicksort(High+1, Lp, Att); } }
void Quicksort(CaseNo Fp, CaseNo Lp, Attribute Att) /* --------- */ { CaseNo i; ForEach(i, Fp, Lp) { Pair[i].C = CVal(Case[i], Att); Pair[i].D = Case[i]; }
/*{ ** Name: CS_map_sys_segment() - Map the system control segment to this process ** ** Description: ** Maps the system control block to this process. This must happen before ** any other action can be taken on shared memory (with the exception of ** CS_create_sys_segment()). ** ** Upon successful exectution of this routine CS may manipulate the system ** control data structure CS_SMCNTRL (taking care to use proper semaphore ** techniques which take into account that the data structure is shared ** across processes). ** ** This call is internal to CS is meant only to be called by CS, and may ** only exist on unix systems supporting shared memory. ** ** Inputs: ** none. ** ** Outputs: ** cssm_segment ptr to the CS_SMCNTRL data structure. ** err_code system dependent error information. ** ** Returns: ** E_DB_OK ** ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 08-Sep-88 (mmm) ** First Version ** 12-jun-89 (rogerk) ** Added allocated_pages argument to MEget_pages calls. ** Changed shared memory key from a LOCATIONN pointer to a character ** string. ** 26-aug-89 (rexl) ** Added calls to protect page allocator. ** 18-oct-1993 (bryanp) ** Issue trace messages in failure cases. Simply returning FAIL doesnt ** help the diagnosis process very much, while the trace messages ** can help (if the caller has done a TRset_file by this point). ** 14-Oct-1998 (jenjo02) ** CS_map_sys_segment(): Don't initialize css_spinlock. That was done ** when the shared segment was created. Reinitializing it may ** effectively destroy a holding process's lock! ** 21-May-2004 (wanfr01) ** INGSRV2835, Bug 112371 ** As per the Jon Jensen's last update, removed the invalid initialize ** of css_spinlock. ** 5-Apr-2006 (kschendel) ** Use generated css version instead of constant. ** 12-aug-2008 (stephenb) ** previous change is too strict if programs not shipped with Ingres ** try to connect to the system segment because the checked version ** goes right down to the build number. allow some latitude using ** II_SYSSEG_VERS. If this is set to the current major Ingres ** version we will allow the connection. This is an interim ** solution to Golden Gate's issue. */ STATUS CS_map_sys_segment(CL_ERR_DESC *err_code) { STATUS status = OK; PTR address; SIZE_TYPE alloc_pages; /* map segment into first available address and then initialize it */ /* Use "sysseg.mem" as shared memory key. */ address = 0; status = MEget_pages(ME_SSHARED_MASK, 0, "sysseg.mem", &address, &alloc_pages, err_code); if (status) { #ifdef xDEBUG TRdisplay("CS_map_sys_segment: unable to attach to sysseg.mem (%x)\n", status); #endif /* Unable to attach allocated shared memory segment. */ /* status = FAIL; This isn't a useful error return code! */ } else { char *segvers; i4 segint; Cs_sm_cb = (CS_SMCNTRL *) address; /* ** check if segment version has been provided, if so we'll ** deem it O.K. if it matches the current major version */ NMgtAt("II_SYSSEG_VERS", &segvers); if (segvers != (char *)NULL && *segvers != EOS && CVal(segvers, &segint) == OK && segint == GV_MAJOR) status = OK; else { i4 id = make_css_version(); if (Cs_sm_cb->css_version != id) { TRdisplay( "CS_map_sys_segment: sysseg.mem is version %x (%d). We need version %x (%d)\n", Cs_sm_cb->css_version, Cs_sm_cb->css_version, id, id); SETCLERR(err_code, 0, 0); status = FAIL; } } } return(status); }
static STATUS my_dynamic_index(i4 msg, PTR cdata, i4 linstance, char *instance, PTR *instdata ) { STATUS stat = OK; i4 ival; char buf[ 20 ]; switch( msg ) { case MO_GET: *instdata = (PTR)instance; break; case MO_GETNEXT: if( *instance == EOS ) ival = 0; stat = CVal( instance, &ival ); /* value is the instance */ if( stat != OK ) break; if( ival > 9 ) /* validate this instance */ stat = MO_NO_INSTANCE; else if( ++ival > 9 ) /* validate next */ stat = MO_NO_NEXT; if( stat != OK ) break; CVla( ival, buf ); /* assumes caller doesn't blast instance before passing it to a get/set method. Otherwise hard to handle, because we don't want to allocate memory here to be freed in the get or set routine. */ *instdata = (PTR)instance; STncpy( instance, buf, linstance ); instance [ linstance ] = EOS; if( STlength( buf ) != STlen ( instance )) stat = MO_INSTANCE_TRUNCATED; break; default: stat = MO_BAD_MSG; } return( stat ); }
static STATUS myintset( i4 offset, i4 luserbuf, char *userbuf, i4 objsize, PTR object ) { STATUS stat; i4 tval; stat = CVal( userbuf, &tval ); if( stat == OK ) private_num = tval; return( stat ); }
/*{ ** Name: get_value() - get value ** ** Description: ** Return value of symbol input. If symbol is not set in the environment ** then return "default_value". ** ** Inputs: ** symbol The string representation of the symbol (ie. "II_SYM") ** default_value An integer default value to be returned if symbol not ** found in the environment. ** Outputs: ** none. ** ** ** Returns: ** value of the symbol if set in environment, else returns ** whatever "default_value" was input. ** ** History: ** 06-apr-92 (mikem) ** Created. */ static i4 get_value(char *symbol, i4 default_value) { i4 value = default_value; char *string; i4 env_value; NMgtAt(symbol, &string); if (string && *string && (!CVal(string, &env_value))) { /* user override of default */ value = env_value; } return(value); }
STATUS gca_ns_init( VOID ) { #ifdef GCF_EMBEDDED_GCN char *ptr, host[ 50 ]; char *pm_default[ PM_MAX_ELEM ]; i4 count; STATUS status = OK; /* ** We do not want to initialize the embedded Name Server ** interface if this is the actual Name Server. The Name ** Server initializes the interface before initializing ** GCA, so check to see if IIGCn_static is initialized, ** indicating that gcn_init() has already been called. */ if ( IIGCn_static.maxsessions ) return( OK ); /* ** Check to see if tracing of Name Server code ** is enabled (for whoever we are) before resetting ** PM for the Name Server. */ gcu_get_tracesym( "II_GCN_TRACE", "!.gcn_trace_level", &ptr ); if ( ptr && *ptr ) CVal( ptr, &IIGCn_static.trace ); /* ** Save current PM defaults and set up for Name Server. */ for( count = 0; count < PM_MAX_ELEM; count++ ) pm_default[ count ] = PMgetDefault( count ); PMsetDefault( 0, SystemCfgPrefix ); /* Name Server defaults */ PMsetDefault( 1, PMhost() ); PMsetDefault( 2, ERx( "gcn" ) ); for( count = 3; count < PM_MAX_ELEM; count++ ) PMsetDefault( count, NULL ); /* ** Initialize embedded Name Server. */ GChostname( host, sizeof( host ) ); if ( gcn_srv_init() != OK || gcn_srv_load( host, NULL ) != OK ) status = E_GC0013_ASSFL_MEM; /* ** Reset PM defaults. */ for( count = 0; count < PM_MAX_ELEM; count++ ) PMsetDefault( count, pm_default[ count ] ); return( status ); #else /* GCA_EMBEDDED_GCN */ return( OK ); #endif /* GCA_EMBEDDED_GCN */ }
static STATUS initialize( i4 argc, char **argv ) { CL_ERR_DESC cl_err; char *instance = ERx("*"); char *env; char name[ 16 ]; i4 i; GCD_global.language = 1; MHsrand( TMsecs() ); for( i = 1; i < argc; i++ ) if ( ! STbcompare( argv[i], 0, ERx("-instance"), 9, TRUE ) ) { if ( argv[i][9] == ERx('=') && argv[i][10] != EOS ) instance = &argv[i][10]; else if ( argv[i][9] == EOS && (i + 1) < argc ) instance = argv[++i]; break; } NMgtAt( ERx("II_INSTALLATION"), &env ); STprintf( name, ERx("II_CHARSET%s"), (env && *env) ? env : "" ); NMgtAt( name, &env ); if ( ! env || ! *env || STlength(env) > CM_MAXATTRNAME) { switch( CMgetDefCS() ) { #if ( !defined(UNIX) && !defined(VMS) ) case CM_IBM : env = "IBMPC850"; break; #endif case CM_DECMULTI : env = "DECMULTI"; break; default : env = "ISO88591"; break; } } GCD_global.charset = STalloc( env ); CVupper( GCD_global.charset ); gcu_read_cset( gcd_cset_id ); if ( CMset_attr( GCD_global.charset, &cl_err) != OK ) { gcu_erlog( 0, GCD_global.language, E_GC0105_GCN_CHAR_INIT, NULL, 0, NULL ); return( E_GC0105_GCN_CHAR_INIT ); } PMinit(); switch( PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)NULL ) ) { case OK: break; case PM_FILE_BAD: gcu_erlog( 0, GCD_global.language, E_GC003D_BAD_PMFILE, NULL, 0, NULL ); return( E_GC003D_BAD_PMFILE ); break; default: gcu_erlog( 0, GCD_global.language, E_GC003E_PMLOAD_ERR, NULL, 0, NULL ); return( E_GC003E_PMLOAD_ERR ); break; } PMsetDefault( 0, SystemCfgPrefix ); PMsetDefault( 1, PMhost() ); PMsetDefault( 2, ERx("gcd") ); PMsetDefault( 3, instance ); gcd_tl_services[0] = &gcd_dmtl_service; gcd_tl_services[1] = &gcd_jctl_service; GCD_global.tl_services = gcd_tl_services; GCD_global.tl_srvc_cnt = ARR_SIZE( gcd_tl_services ); QUinit( &GCD_global.pib_q ); QUinit( &GCD_global.rcb_q ); QUinit( &GCD_global.ccb_q ); QUinit( &GCD_global.ccb_free ); for( i = 0; i < ARR_SIZE( GCD_global.cib_free ); i++ ) QUinit( &GCD_global.cib_free[ i ] ); env = NULL; gcu_get_tracesym( NULL, ERx("!.client_max"), &env ); if ( env && *env ) { i4 count; if ( CVal( env, &count ) == OK && count > 0 ) GCD_global.client_max = count; } env = NULL; gcu_get_tracesym( NULL, ERx("!.client_timeout"), &env ); if ( env && *env ) { i4 timeout; if ( CVal( env, &timeout ) == OK && timeout > 0 ) GCD_global.client_idle_limit = timeout * 60; /* Cnvt to seconds */ } env = NULL; gcu_get_tracesym( NULL, ERx("!.connect_pool_status"), &env ); if ( env && *env ) { if ( ! STbcompare( env, 0, "optional", 0, TRUE ) ) GCD_global.client_pooling = TRUE; if ( GCD_global.client_pooling || ! STbcompare( env, 0, "on", 0, TRUE ) ) { env = NULL; gcu_get_tracesym( NULL, ERx("!.connect_pool_size"), &env ); if ( env && *env ) CVal( env, &GCD_global.pool_max ); env = NULL; gcu_get_tracesym( NULL, ERx("!.connect_pool_expire"), &env ); if ( env && *env ) { i4 limit; if ( CVal( env, &limit ) == OK && limit > 0 ) GCD_global.pool_idle_limit = limit * 60; /* Seconds */ } } } env = NULL; gcu_get_tracesym( "II_GCD_TRACE", ERx("!.gcd_trace_level"), &env ); if ( env && *env ) CVal( env, &GCD_global.gcd_trace_level ); env = NULL; gcu_get_tracesym( "II_GCD_LOG", ERx("!.gcd_trace_log"), &env ); if ( env && *env ) TRset_file( TR_F_OPEN, env, (i4)STlength( env ), &cl_err ); return( OK ); }
/*{ ** Name: LGK_initialize() - initialize the lg/lk shared mem segment. ** ** Description: ** This routine is called by the LGinitialize or LKinitialize routine. IT ** assumes that a previous caller has allocated the shared memory segment. ** ** If it discovers that the shared memory segment has not yet been ** initialized, it calls the LG and LK initialize-memory routines to do so. ** ** Inputs: ** flag - bit mask of: ** LOCK_LGK_MEMORY to lock the shared data segment ** LGK_IS_CSP if process is CSP process this node. ** ** Outputs: ** sys_err - place for system-specific error information. ** ** Returns: ** OK - success ** !OK - failure (CS*() routine failure, segment not mapped, ...) ** ** History: ** Summer, 1992 (bryanp) ** Working on the new portable logging and locking system. ** 19-oct-1992 (bryanp) ** Check memory version number when attaching. ** 22-oct-1992 (bryanp) ** Change LGLKDATA.MEM to lglkdata.mem. ** 23-Oct-1992 (daveb) ** name the semaphore too. ** 13-feb-1993 (keving) ** Remove support for II_LGK_MEMORY_SIZE. If II_LG_MEMSIZE ** is not set then calculate memory size from PM values. ** 24-may-1993 (bryanp) ** If the shared memory is the wrong version, don't install the ** at_exit handlers (the rundown routines won't be able to interpret ** the memory properly). ** 26-jul-1993 (jnash) ** Add 'flag' param lock the LGK data segment. ** 20-sep-1993 (bryanp) ** In addition to calling PCatexit, call (on VMS) sys$dclexh, since ** there are some situations (image death and image rundown without ** process rundown) which are caught neither by PCatexit (since ** PCexit isn't run) nor by check-dead threads (since process ** rundown never happened). This fixes a hole where an access- ** violating ckpdb or auditdb command never got cleaned up. ** 31-jan-1994 (bryanp) ** Back out a few "features" which are proving countereffective: ** 1) Don't bother checking mem_creator_pid to see if the previous ** creator of the shared memory has died. This was an attempt to ** gracefully re-use sticky shared memory following a system crash, ** but it is suspected as being the culprit in a series of system ** failures by re-initializing the shared memory at inopportune ** times. ** 2) Don't complain if the shared memory already exists but is of a ** different size than you expected. Just go ahead and try to use ** it anyway. ** 21-feb-1994 (bryanp) ** Reverse item (1) of the above 31-jan-1994 change and re-enable the ** graceful re-use of shared memory. People weren't happy with ** having to run ipcclean and csinstall all the time. ** 23-may-1994 (bryanp) ** On VMS, disable ^Y for LG/LK-aware processes. We don't want to allow ** ^Y because you might interrupt the process right in the middle ** of an LG or LK operation, while holding the shared memory ** semaphore, and this would then wedge the whole installation. ** ** 17-May-1994 (daveb) 59127 ** Attach lgk_mem semaphore if we're attaching to the segment. ** 30-jan-1995 (lawst01) bug 61984 ** Use memory needed calculation from the 'lgk_calculate_size' ** function to determine the size of the shared memory pool for ** locking and locking. If the II_LG_MEMSIZE variable is specified ** with a value larger than needed use the supplied value. If ** lgk_calculate_size is unable to calculate a size then use the ** magic number of 400000. In addition issue a warning message ** and continue executing in the event the number of pages ** allocated is less than the number requested. ** 24-apr-1997 (nanpr01) ** Reinstate Bryanp's change. In the process of fixing bug 61984 ** by Steve Lawrence and subsequent undo of Steve's fix by Nick ** Ireland on 25-jun-96 (nick) caused the if 0 code removed. ** Part of the Steve's change was not reinstated such as not returning ** the status and exit and continue. ** 1. Don't complain if the shared memory already exists but is of a ** different size than you expected. Just go ahead and try to use ** it. ** 18-aug-1998 (hweho01) ** Reclaim the kernel resource if LG/LK shared memory segment is ** reinitialized. If the shared segment is re-used (the previous creator ** of the shared segment has died), the cross-process semaphores get ** initialized more than once at the same locations. That cause the ** kernel resource leaks on DG/UX (OS release 4.11MU04). To fix the ** problem, CS_cp_sem_cleanup() is called to destroy all the ** semaphores before LG/LK shraed segment get recreated. ** CS_cp_sem_cleanup() is made dependent on xCL_NEED_SEM_CLEANUP and ** OS_THREADS_USED, it returns immediately for most platforms. ** 27-Mar-2000 (jenjo02) ** Added test for crossed thread types, refuse connection ** to LGK memory with E_DMA811_LGK_MT_MISMATCH. ** 18-apr-2001 (devjo01) ** s103715 (Portable cluster support) ** - Add CX mem requirement calculations. ** - Add LGK_IS_CSP flag to indicate that LGK memory is being ** initialized for a CSP process. ** - Add basic CX initialization. ** 19-sep-2002 (devjo01) ** If running NUMA clustered allocate memory out of local RAD. ** 30-Apr-2003 (jenjo02) ** Rearchitected to silence long-tolerated race conditions. ** BUG 110121. ** 27-feb-2004 (devjo01) ** Rework allocation of CX shared memory to be compatible ** with race condition fix introduced for bug 110121. ** 29-Dec-2008 (jonj) ** If lgk_calculate_size() returns FAIL, the total memory ** needed exceeds MAX_SIZE_TYPE and we can't continue, but ** tell what we can about the needs of the various bits of ** memory before quitting. ** 06-Aug-2009 (wanfr01) ** Bug 122418 - Return E_DMA812 if LOCK_LGK_MUST_ATTACH is ** is passed in and memory segment does not exist ** 20-Nov-2009 (maspa05) bug 122642 ** In order to synchronize creation of UUIDs across servers added ** a semaphore and a 'last time' variable into LGK memory. ** 14-Dec-2009 (maspa05) bug 122642 ** #ifdef out the above change for Windows. The rest of the change ** does not apply to Windows so the variables aren't defined. */ STATUS LGK_initialize( i4 flag, CL_ERR_DESC *sys_err, char *lgk_info) { PTR ptr; SIZE_TYPE memleft; SIZE_TYPE size; STATUS ret_val; STATUS mem_exists; char mem_name[15]; SIZE_TYPE allocated_pages; i4 me_flags; i4 me_locked_flag; SIZE_TYPE memory_needed; char *nm_string; SIZE_TYPE pages; LGK_MEM *lgk_mem; i4 err_code; SIZE_TYPE min_memory; i4 retries; i4 i; i4 attached; PID *my_pid_slot; i4 clustered; u_i4 nodes; SIZE_TYPE cxmemreq; PTR pcxmem; LGLK_INFO lgkcount; char instid[4]; CL_CLEAR_ERR(sys_err); /* ** if LGK_base is set then this routine has already been called. It is ** set up so that both LGiniitalize and LKinitialize calls it, but only ** the first call does anything. */ if (LGK_base.lgk_mem_ptr) return(OK); PCpid( &LGK_my_pid ); memory_needed = 0; NMgtAt("II_LG_MEMSIZE", &nm_string); if (nm_string && *nm_string) #if defined(LP64) if (CVal8(nm_string, (long*)&memory_needed)) #else if (CVal(nm_string, (i4 *)&memory_needed)) #endif /* LP64 */ memory_needed = 0; /* Always calculate memory needed from PM resource settings */ /* and compare with supplied value, if supplied value is less */ /* than minimum then use minimum */ min_memory = 0; if ( OK == lgk_get_counts(&lgkcount, FALSE)) { if ( lgk_calculate_size(FALSE, &lgkcount, &min_memory) ) { /* ** Memory exceeds MAX_SIZE_TYPE, can't continue. ** ** Do calculation again, this time with "wordy" ** so user can see allocation bits, then quit. */ lgk_calculate_size(TRUE, &lgkcount, &min_memory); return (E_DMA802_LGKINIT_ERROR); } } if (min_memory) memory_needed = (memory_needed < min_memory) ? min_memory : memory_needed; else memory_needed = (memory_needed < 400000 ) ? 400000 : memory_needed; clustered = (i4)CXcluster_enabled(); cxmemreq = 0; if ( clustered ) { if ( OK != CXcluster_nodes( &nodes, NULL ) ) nodes = 0; cxmemreq = CXshm_required( 0, nodes, lgkcount.lgk_max_xacts, lgkcount.lgk_max_locks, lgkcount.lgk_max_resources ); if ( MAX_SIZE_TYPE - memory_needed < cxmemreq ) { /* ** Memory exceeds MAX_SIZE_TYPE, can't continue. ** ** Do calculation again, this time with "wordy" ** so user can see allocation bits, then quit. */ SIprintf("Total LG/LK/CX allocation exceeds max of %lu bytes by %lu\n" "Adjust logging/locking configuration values and try again\n", MAX_SIZE_TYPE, cxmemreq - (MAX_SIZE_TYPE - memory_needed)); lgk_calculate_size(TRUE, &lgkcount, &min_memory); return (E_DMA802_LGKINIT_ERROR); } memory_needed += cxmemreq; } if ( memory_needed < MAX_SIZE_TYPE - ME_MPAGESIZE ) pages = (memory_needed + ME_MPAGESIZE - 1) / ME_MPAGESIZE; else pages = memory_needed / ME_MPAGESIZE; /* ** Lock the LGK segment if requested to do so */ if (flag & LOCK_LGK_MEMORY) me_locked_flag = ME_LOCKED_MASK; else me_locked_flag = 0; me_flags = (me_locked_flag | ME_MSHARED_MASK | ME_IO_MASK | ME_CREATE_MASK | ME_NOTPERM_MASK | ME_MZERO_MASK); if (CXnuma_user_rad()) me_flags |= ME_LOCAL_RAD; STcopy("lglkdata.mem", mem_name); /* ** In general, we just want to attach to the shared memory and detect if ** we are the first process to do so. However, there are ugly race ** conditions to consider, as well as complications because the shared ** memory may be left around following a system crash. ** ** First we attempt to create the shared memory. Usually it already exists, ** so we check for and handle the case of "already exists". */ /* ** (jenjo02) ** ** Restructured to better handle all those ugly race conditions ** which are easily reproduced by running two scripts, one that ** continuously executes "lockstat" while the other is starting ** and stopping Ingres. ** ** For example, ** ** lockstat A acquires and init's the memory ** RCP attaches to "A" memory ** lockstat A terminates normally ** lockstat B attaches to "A" memory, sees that ** "A"s pid is no longer alive, and ** reinitializes the memory, much to ** the RCP's chagrin. ** or (more commonly) ** ** lockstat A acquires and begins to init the mem ** RCP attaches to "A" memory which is ** still being zero-filled by lockstat, ** checks the version number (zero), ** and fails with a E_DMA434 mismatch. ** ** The fix utilizes the mem_ext_sem to synchronize multiple ** processes; if the semaphore hasn't been initialized or ** if mem_version_no is zero, we'll wait one second and retry, ** up to 60 seconds before giving up. This gives the creating ** process time to complete initialization of the memory. ** ** Up to LGK_MAX_PIDS are allowed to attach to the shared ** memory. When a process attaches it sets its PID in the ** first vacant slot in lgk_mem->mem_pid[]; if there are ** no vacant slots, the attach is refused. When the process ** terminates normally by calling LGK_rundown(), it zeroes ** its PID slot. ** ** When attaching to an existing segment, we check if ** there are any live processes still using the memory; ** if so, we can't destroy it (no matter who created it). ** If there are no live processes attached to the memory, ** we destroy and reallocate it (based on current config.dat ** settings). */ for ( retries = 0; ;retries++ ) { LGK_base.lgk_mem_ptr = (PTR)NULL; /* Give up if unable to get memory in one minute */ #if defined(conf_CLUSTER_BUILD) if (retries > 1) #else if ( retries ) #endif { if ( retries < 60 ) PCsleep(1000); else { /* Another process has it blocked way too long */ uleFormat(NULL, E_DMA800_LGKINIT_GETMEM, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); /* Unable to attach allocated shared memory segment. */ return (E_DMA802_LGKINIT_ERROR); } } ret_val = MEget_pages(me_flags, pages, mem_name, (PTR*)&lgk_mem, &allocated_pages, sys_err); if ( mem_exists = ret_val ) { if (ret_val == ME_ALREADY_EXISTS) { ret_val = MEget_pages((me_locked_flag | ME_MSHARED_MASK | ME_IO_MASK), pages, mem_name, (PTR*)&lgk_mem, &allocated_pages, sys_err); #if defined(conf_CLUSTER_BUILD) if (ret_val && !retries) continue; /* try one more time */ #endif } if (ret_val) { uleFormat(NULL, ret_val, sys_err, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); uleFormat(NULL, E_DMA800_LGKINIT_GETMEM, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); /* Unable to attach allocated shared memory segment. */ return (E_DMA802_LGKINIT_ERROR); } } else if (flag & LOCK_LGK_MUST_ATTACH) { /* Do not use the shared segment you just allocated */ MEfree_pages((PTR)lgk_mem, allocated_pages, sys_err); return (E_DMA812_LGK_NO_SEGMENT); } size = allocated_pages * ME_MPAGESIZE; /* Expose this process to the memory */ LGK_base.lgk_mem_ptr = (PTR)lgk_mem; if ( mem_exists ) { /* ** Memory exists. ** ** Try to acquire the semaphore. If it's ** uninitialzed, retry from the top. ** ** If the version is zero, then another ** process is initializing the memory; ** keep retrying until the version is ** filled in. ** */ if ( ret_val = CSp_semaphore(1, &lgk_mem->mem_ext_sem) ) { if ( ret_val != E_CS000A_NO_SEMAPHORE ) { uleFormat(NULL, ret_val, sys_err, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); ret_val = E_DMA802_LGKINIT_ERROR; break; } continue; } /* Retry if still being init'd by another process */ if ( !lgk_mem->mem_version_no ) { CSv_semaphore(&lgk_mem->mem_ext_sem); continue; } /* ** Check pids which appear to be attached to ** the memory: ** ** If any process is still alive, then we ** assume the memory is consistent and use it. ** ** If a process is now dead, it terminated ** without going through LGK_rundown ** to zero its PID slot, zero it now. ** ** If there are no live PIDs attached to ** the memory, we destroy and recreate it. */ my_pid_slot = (PID*)NULL; attached = 0; for ( i = 0; i < LGK_MAX_PIDS; i++ ) { if ( lgk_mem->mem_pid[i] && PCis_alive(lgk_mem->mem_pid[i]) ) { attached++; } else { /* Vacate the slot */ if (lgk_mem->mem_pid[i]) { uleFormat(NULL, E_DMA499_DEAD_PROCESS_INFO, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 2, 0, lgk_mem->mem_pid[i], 0, lgk_mem->mem_info[i].info_txt); } lgk_mem->mem_pid[i] = (PID)0; lgk_mem->mem_info[i].info_txt[0] = EOS; /* Use first vacant slot for this process */ if ( !my_pid_slot ) { my_pid_slot = &lgk_mem->mem_pid[i]; LGK_base.lgk_pid_slot = i; } } /* Quit when both questions answered */ if ( attached && my_pid_slot ) break; } /* If no living pids attached, destroy/reallocate */ if ( !attached ) { CSv_semaphore(&lgk_mem->mem_ext_sem); if ( LGK_destroy(allocated_pages, sys_err) ) { ret_val = E_DMA802_LGKINIT_ERROR; break; } continue; } /* All attached pids alive? */ if ( !my_pid_slot ) { /* ... then there's no room for this process */ uleFormat(NULL, E_DMA80A_LGK_ATTACH_LIMIT, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 1, 0, attached); ret_val = E_DMA802_LGKINIT_ERROR; } else if (lgk_mem->mem_version_no != LGK_MEM_VERSION_CURRENT) { uleFormat(NULL, E_DMA434_LGK_VERSION_MISMATCH, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 2, 0, lgk_mem->mem_version_no, 0, LGK_MEM_VERSION_CURRENT); ret_val = E_DMA435_WRONG_LGKMEM_VERSION; } /* ** Don't allow mixed connections of MT/non-MT processes. ** Among other things, the mutexing mechanisms are ** incompatible! */ else if ( (CS_is_mt() && (lgk_mem->mem_status & LGK_IS_MT) == 0) || (!CS_is_mt() && lgk_mem->mem_status & LGK_IS_MT) ) { uleFormat(NULL, E_DMA811_LGK_MT_MISMATCH, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 2, 0, (lgk_mem->mem_status & LGK_IS_MT) ? "OS" : "INTERNAL", 0, (CS_is_mt()) ? "OS" : "INTERNAL"); ret_val = E_DMA802_LGKINIT_ERROR; } else { /* ** CX memory (if any) will lie immediately past LGK header. */ pcxmem = (PTR)(lgk_mem + 1); pcxmem = (PTR)ME_ALIGN_MACRO(pcxmem, sizeof(ALIGN_RESTRICT)); LGK_base.lgk_lkd_ptr = (char *)LGK_base.lgk_mem_ptr + lgk_mem->mem_lkd; LGK_base.lgk_lgd_ptr = (char *)LGK_base.lgk_mem_ptr + lgk_mem->mem_lgd; /* Stuff our pid in first vacant slot */ *my_pid_slot = LGK_my_pid; STlcopy(lgk_info, lgk_mem->mem_info[i].info_txt, LGK_INFO_SIZE-1); } #if defined(VMS) || defined(UNIX) /* set up pointers to reference the uuid mutex and last time * variable */ if (!ID_uuid_sem_ptr) ID_uuid_sem_ptr=&lgk_mem->id_uuid_sem; if (!ID_uuid_last_time_ptr) ID_uuid_last_time_ptr=&lgk_mem->uuid_last_time; if (!ID_uuid_last_cnt_ptr) ID_uuid_last_cnt_ptr=&lgk_mem->uuid_last_cnt; #endif CSv_semaphore(&lgk_mem->mem_ext_sem); } else { /* Memory did not exist */ /* Zero the version to keep other processes out */ lgk_mem->mem_version_no = 0; #if defined(VMS) || defined(UNIX) /* set up the uuid mutex and last time pointers to * reference the objects in shared memory */ { STATUS id_stat; ID_uuid_sem_ptr=&lgk_mem->id_uuid_sem; ID_uuid_last_time_ptr=&lgk_mem->uuid_last_time; ID_uuid_last_cnt_ptr=&lgk_mem->uuid_last_cnt; *ID_uuid_last_cnt_ptr=0; ID_UUID_SEM_INIT(ID_uuid_sem_ptr,CS_SEM_MULTI,"uuid sem", &id_stat); } #endif /* ... then initialize the mutex */ CSw_semaphore(&lgk_mem->mem_ext_sem, CS_SEM_MULTI, "LGK mem ext sem" ); /* Record if memory created for MT or not */ if ( CS_is_mt() ) lgk_mem->mem_status = LGK_IS_MT; /* ** memory is as follows: ** ** -----------------------------------------------------------| ** | LGK_MEM struct (keep track of this mem) | ** | | ** -----------------------------------------------------------| ** | If a clustered installation memory reserved for CX | ** | | ** ------------------------------------------------------------ ** | LKD - database of info for lk system | ** | | ** ------------------------------------------------------------ ** | LGD - database of info for lg system | ** | | ** ------------------------------------------------------------ ** | memory manipulated by LGKm_* routines for structures used | ** | by both the lk and lg systems. | ** | | ** ------------------------------------------------------------ */ /* put the LGK_MEM struct at head of segment leaving ptr pointing ** at next aligned piece of memory */ /* ** CX memory (if any) will lie immediately past LGK header. */ pcxmem = (PTR)(lgk_mem + 1); pcxmem = (PTR)ME_ALIGN_MACRO(pcxmem, sizeof(ALIGN_RESTRICT)); LGK_base.lgk_lkd_ptr = pcxmem + cxmemreq; LGK_base.lgk_lkd_ptr = (PTR) ME_ALIGN_MACRO(LGK_base.lgk_lkd_ptr, sizeof(ALIGN_RESTRICT)); lgk_mem->mem_lkd = (i4)((char *)LGK_base.lgk_lkd_ptr - (char *)LGK_base.lgk_mem_ptr); LGK_base.lgk_lgd_ptr = (PTR) ((char *) LGK_base.lgk_lkd_ptr + sizeof(LKD)); LGK_base.lgk_lgd_ptr = (PTR) ME_ALIGN_MACRO(LGK_base.lgk_lgd_ptr, sizeof(ALIGN_RESTRICT)); lgk_mem->mem_lgd = (i4)((char *)LGK_base.lgk_lgd_ptr - (char *)LGK_base.lgk_mem_ptr); /* now initialize the rest of memory for allocation */ /* how much memory is left? */ ptr = ((char *)LGK_base.lgk_lgd_ptr + sizeof(LGD)); memleft = size - (((char *) ptr) - ((char *) LGK_base.lgk_mem_ptr)); if ( (ret_val = lgkm_initialize_mem(memleft, ptr)) == OK && (ret_val = LG_meminit(sys_err)) == OK && (ret_val = LK_meminit(sys_err)) == OK ) { /* Clear array of attached pids and pid info */ for ( i = 0; i < LGK_MAX_PIDS; i++ ) { lgk_mem->mem_pid[i] = (PID)0; lgk_mem->mem_info[i].info_txt[0] = EOS; } /* Set the creator pid */ LGK_base.lgk_pid_slot = 0; lgk_mem->mem_creator_pid = LGK_my_pid; /* Set the version, releasing other processes */ lgk_mem->mem_version_no = LGK_MEM_VERSION_CURRENT; } else { uleFormat(NULL, ret_val, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); ret_val = E_DMA802_LGKINIT_ERROR; /* Destroy the shared memory */ LGK_destroy(allocated_pages, sys_err); } } if ( ret_val == OK ) { PCatexit(LGK_rundown); if ( clustered ) { /* ** Perform preliminary cluster connection and CX memory init. */ /* Get installation code */ NMgtAt("II_INSTALLATION", &nm_string); if ( nm_string ) { instid[0] = *(nm_string); instid[1] = *(nm_string+1); } else { instid[0] = 'A'; instid[1] = 'A'; } instid[2] = '\0'; ret_val = CXinitialize( instid, pcxmem, flag & LGK_IS_CSP ); if ( ret_val ) { /* Report error returned from CX */ uleFormat(NULL, ret_val, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0 ); break; } } #ifdef VMS { static $EXHDEF exit_block; i4 ctrl_y_mask = 0x02000000; /* ** On VMS, programs like the dmfjsp and logstat run as images in ** the shell process. That is, the system doesn't start and stop ** a process for each invocation of the program, it just starts ** and stops an image in the same process. This means that if ** the program should die, the image may be rundown but the process ** will remain, which means that the check-dead threads of other ** processes in the installation will not feel that they need to ** rundown this process, since it's still alive. ** ** By declaring an exit handler, which will get a chance to run ** even if PCexit isn't called, we improve our chances of getting ** to perform rundown processing if we should die unexpectedly. ** ** Furthermore, we ask DCL to disable its ^Y processing, which ** lessens the chance that the user will interrupt us while we ** are holding the semaphore. */ exit_block.exh$g_func = LGK_rundown; exit_block.exh$l_argcount = 1; exit_block.exh$gl_value = &exit_block.exh$l_status; if (sys$dclexh(&exit_block) != SS$_NORMAL) ret_val = FAIL; lib$disable_ctrl(&ctrl_y_mask, 0); } #endif } break; } if ( ret_val ) LGK_base.lgk_mem_ptr = NULL; return(ret_val); }
/* ** Name: main -main routine. ** ** Description: ** This routine is the main control routine for iirundbms. Starting an ** iidbms server consists of: ** 1) Opening and reading the PM data ** 2) Validating server arguments, converting to VMS internal format. ** 3) Creating mailbox for communication with server. ** 4) creating server processing. ** 5) Sending server process its commands. ** 6) Checking whether server startup succeeded or not. ** ** iirundbms command line format is: ** iirundbms <server type> <server flavor> ** where server type is something like "dbms", "recovery", "star", and ** server flavor is something like "public", "nonames", "benchmark". ** ** Inputs: ** argc - number of arguments (should be 1, 2 or 3) ** argv - argument array. ** ** Outputs: ** None ** ** Returns: ** a VMS status code is returned. ** ** History: ** 31-jan-1994 (bryanp) ** Added comment header. ** 21-Jan-1998 (horda03) Bug 68559 ** For GCC servers where a server flavour has been specified, ** command line to start the server must specify the server ** flavour in the form; "-instance=<server_flavor>" in order ** for the GCC to pickup the correct configuration details. ** 22-feb-1998 (chash01) ** RMCMD (Visual DBA backend server) startup takes two VMS CREPRC ** calls, one ihere, one in rmcmd.exe. When RMCMD server starts ** the PID returned by CREPRC in this module is no longer valid. ** WE have to first decode pid in the t_user_data field returned by ** RMCMD server in termination mailbox before print PID and ** server name to terminal. ** 31-Aug-2007 (ashco01) Bug #113490 & Bug #119021. ** Corrected detection of 'instance name' for GCB & GCD. ** 05-Dec-2007 (ashco01) Bug #119561. ** Ensure that all Ingres back-end detached processes define the ** SYS$SCRATCH logical as this is referenced via II_TEMPORARY ** when placing temporary DCL files. ** 10-Dec-2007 (ashco01) Bug #119561 ** Define SYS$SCRATCH within all detached processes. */ main( int argc, char **argv ) { static $DESCALLOC( prcnam ); unsigned int pqlcnt = 0; $DESCALLOC( uicdsc ); char *param; char prcbuf[16]; ACCDEF2 accmsg; unsigned int pid; unsigned short chan; unsigned short term; unsigned int mbxunt; int dviitem; char buf[128], tmp[128]; II_VMS_MASK_LONGWORD efc_state; char *log_start_commands; IOSB iosb; ER_ARGUMENT dummy_arg; i4 i; STATUS status; i4 gcc = 0; i4 gcc_instance = 0; i4 gcb = 0; i4 gcb_instance = 0; i4 gcd = 0; i4 gcd_instance = 0; /* ** setup the type and server_flavor parameters */ if ( argc >= 2 ) { server_type = argv[1]; /* Are we starting a GCB, GCC or GCD ? */ if (STbcompare( server_type, 3, "gcc", 3, TRUE ) == 0) gcc++; if (STbcompare( server_type, 3, "gcb", 3, TRUE ) == 0) gcb++; if (STbcompare( server_type, 3, "gcd", 3, TRUE ) == 0) gcd++; } if ( argc >= 3 ) { server_flavor = argv[2]; /* Need to precede server_flavor with "-instance=" ** if we're starting a GCB, GCC or GCD. */ gcc_instance = gcc; gcb_instance = gcb; gcd_instance = gcd; } /* ** initialize PM routines and setup the default ** search parameters for config.dat */ status = PMinit( ); if (status) { pmerr_func(status, 0, &dummy_arg); return (status); } switch( status = PMload((LOCATION *)NULL, pmerr_func) ) { case OK: /* Loaded sucessfully */ break; case PM_FILE_BAD: /* syntax error */ if (status != FAIL) /* As of Nov 1993, PM.H defines PM_FILE_BAD 1 */ pmerr_func(status, (i4)0, &dummy_arg); return (status); default: /* unable to open file */ if (status != FAIL) /* FAIL is a useless status to report... */ pmerr_func(status, (i4)0, &dummy_arg); return (status); } #ifdef EDBC PMsetDefault( 0, ERx( "ed" ) ); #else PMsetDefault( 0, ERx( "ii" ) ); #endif PMsetDefault( 1, PMhost( ) ); PMsetDefault( 2, server_type ); PMsetDefault( 3, server_flavor ); /* read and process pm parameters */ for ( i = 0; pm_option[i].PM_name != NULL; i++ ) { status = PMget( pm_option[i].PM_name, ¶m ); if ( status != OK ) continue; switch ( pm_option[i].type ) { unsigned int *target; case TYPE_CLRFLG: if ( STbcompare(param, 0, "off", 0, TRUE) != 0 && STbcompare(param, 0, "on", 0, TRUE) != 0 ) { SIprintf("IIRUNDBMS: %s value must be ON or OFF\n", pm_option[i].PM_name); SIflush(stdout); log_errmsg( "Must be ON or OFF", SS$_BADPARAM, 1 ); return (SS$_BADPARAM); } target = (unsigned int *)pm_option[i].target; if ( STbcompare(param, 0, pm_option[i].keyword, 0, TRUE) == 0) *target &= ~(int)pm_option[i].parameter; if ( msg_echo && (STscompare( pm_option[i].PM_name, 0, echo, 0 ) == 0) ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_SETFLG: if ( STbcompare(param, 0, "off", 0, TRUE) != 0 && STbcompare(param, 0, "on", 0, TRUE) != 0 ) { SIprintf("IIRUNDBMS: %s value must be ON or OFF\n", pm_option[i].PM_name); SIflush(stdout); log_errmsg( "Must be ON or OFF", SS$_BADPARAM, 1 ); return (SS$_BADPARAM); } target = (unsigned int *)pm_option[i].target; if ( STbcompare(param, 0, pm_option[i].keyword, 0, TRUE) == 0) *target |= (int)pm_option[i].parameter; if ( msg_echo ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_INT: target = (unsigned int *)pm_option[i].target; status = CVal( param, target ); if (status) { SIprintf("IIRUNDBMS: %s value must be an integer\n", pm_option[i].PM_name); SIflush(stdout); pmerr_func(status, 0, &dummy_arg); return (SS$_BADPARAM); } if ( msg_echo ) { STprintf( buf, "%d", *target ); ERoptlog( pm_option[i].PM_name, buf ); } break; case TYPE_UIC: { $DESCINIT( uicdsc, param ); status = iics_cvtuic( &uicdsc, (char *)pm_option[i].target ); if ( !(status & 1) ) { log_errmsg( "vms_uic invalid", status, 1 ); return (status); /* B56811 */ } if ( msg_echo ) { if ( *(unsigned int *)(pm_option[i].target) != 0 ) { STprintf( buf, "%s [%o,%o]", param, ((uic >> 16) & 0xffff), (uic & 0xffff) ); ERoptlog( pm_option[i].PM_name, buf ); } } break; } case TYPE_STR: if (STlength(param) > MAX_STRING_OPTION_LENGTH) { SIprintf("IIRUNDBMS: Max length for %s is %d\n", pm_option[i].PM_name, MAX_STRING_OPTION_LENGTH); SIflush(stdout); return (SS$_BADPARAM); } STcopy( param, (char *)pm_option[i].target ); if ( msg_echo ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_PQL: /* ** build VMS process quota block */ quota[pqlcnt].name = (char)pm_option[i].parameter; status = CVal( param, "a[pqlcnt].value ); if (status) { SIprintf("IIRUNDBMS: %s value must be an integer\n", pm_option[i].PM_name); SIflush(stdout); pmerr_func(status, 0, &dummy_arg); return (SS$_BADPARAM); } pqlcnt++; if ( msg_echo ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_PRIV: { char prvbuf[512]; char *p, *q; i4 j; /* ** Remove white space then ** convert the string to upper case, then ** remove leading and trailing parens */ if (STlength(param) >= sizeof(prvbuf)) { SIprintf("IIRUNDBMS: vms_privileges are too long\n"); SIprintf(" Actual length (%d) exceeds maximum (%d)\n", STlength(param), sizeof(prvbuf)); SIflush(stdout); return (SS$_BADPARAM); } STcopy( param, prvbuf); STtrmwhite( prvbuf ); CVupper( prvbuf ); /* ** Scan the comma seperated privilege list and set the ** privileges for each privileges keywork in the list. */ for ( p = prvbuf; p != 0 && *p != 0; p = q ) { if ( (q = STindex( p, ERx( "," ), 0 )) != NULL ) *q++ = '\0'; else if ( (q = STindex( p, ERx( ")" ), 0 )) != NULL ) *q++ = '\0'; if ( *p == '(' ) p++; for ( j = 0; prv_table[j].prv_name != NULL; j++ ) { if ( STscompare( p, 4, prv_table[j].prv_name, 4 ) == 0 ) { prvadr[0] |= prv_table[j].prv_code_low; prvadr[1] |= prv_table[j].prv_code_hi; if ( msg_echo ) ERoptlog( pm_option[i].PM_name, prv_table[j].prv_name ); break; } } if (prv_table[j].prv_name == NULL) { /* ** We failed to find privilege "p" in our table */ SIprintf("IIRUNDBMS: Syntax error in privilege list\n"); SIprintf(" Error near byte %d of string %s", p - prvbuf, param); SIflush(stdout); ERoptlog("Unrecognized privilege:", p); return (SS$_BADPARAM); } } break; } default: break; } }
static STATUS ADFmo_fi_index( i4 msg, PTR cdata, i4 linstance, char *instance, PTR *instdata) { ADI_FI_DESC *fi; STATUS status; i4 ix; i4 maxix = Adf_globs->Adi_num_fis; CVal(instance, &ix); switch (msg) { case MO_GET: if (ix < 1 || ix > maxix ) { status = MO_NO_INSTANCE; break; } fi = &Adf_globs->Adi_fis[ix]; if ((fi == NULL) || (fi->adi_finstid < 1)) { status = MO_NO_INSTANCE; break; } *instdata = (PTR)fi; status = OK; break; case MO_GETNEXT: while (++ix <= maxix) { fi = &Adf_globs->Adi_fis[ix]; if ((fi == NULL) || (fi->adi_finstid < 1)) { continue; } else { *instdata = (PTR)fi; status = MOlongout( MO_INSTANCE_TRUNCATED, (i8)ix, linstance, instance); break; } } if (ix > maxix) status = MO_NO_INSTANCE; break; default: status = MO_BAD_MSG; break; } return (status); }
static STATUS ADFmo_op_index( i4 msg, PTR cdata, i4 linstance, char *instance, PTR *instdata) { ADI_OPRATION *op; STATUS status; i4 ix; i4 maxix = (Adf_globs->Adi_op_size) / sizeof(ADI_OPRATION); CVal(instance, &ix); switch(msg) { case MO_GET: if (ix < 1 || ix > maxix ) { status = MO_NO_INSTANCE; break; } op = &Adf_globs->Adi_operations[ix]; if ((op == NULL) || (op->adi_opid < 1)) { status = MO_NO_INSTANCE; break; } *instdata = (PTR)op; status = OK; break; case MO_GETNEXT: while (++ix <= maxix) { op = &Adf_globs->Adi_operations[ix]; if ((op == NULL) || (op->adi_opid < 1)) { continue; } else { *instdata = (PTR)op; status = MOlongout( MO_INSTANCE_TRUNCATED, (i8)ix, linstance, instance); break; } } if (ix > maxix) status = MO_NO_INSTANCE; break; default: status = MO_BAD_MSG; break; } return (status); }
static STATUS ADFmo_dt_index( i4 msg, PTR cdata, i4 linstance, char *instance, PTR *instdata) { ADI_DATATYPE *dt; STATUS status; i4 ix; i4 maxix = (Adf_globs->Adi_dt_size) / sizeof(ADI_DATATYPE); CVal(instance, &ix); switch(msg) { case MO_GET: if (ix < 1 || ix > maxix ) { status = MO_NO_INSTANCE; break; } dt = &Adf_globs->Adi_datatypes[ix]; if ((dt == NULL) || (dt->adi_dtid < 1)) { status = MO_NO_INSTANCE; break; } *instdata = (PTR)dt; status = OK; break; case MO_GETNEXT: while (++ix <= maxix) { dt = &Adf_globs->Adi_datatypes[ix]; if ((dt == NULL) || (dt->adi_dtid < 1)) { continue; } else { *instdata = (PTR)dt; status = MOlongout( MO_INSTANCE_TRUNCATED, (i8)ix, linstance, instance); break; } } if (ix > maxix) status = MO_NO_INSTANCE; break; default: status = MO_BAD_MSG; break; } return (status); }
STATUS ERsend(i4 flag, char *message, i4 msg_length, CL_ERR_DESC *err_code) { # ifdef NT_GENERIC static bool er_init = FALSE; static bool is_w95 = FALSE; # else /* !NT_GENERIC */ static int er_ifi = -2; static int ar_ifi = -2; # endif /* !NT_GENERIC */ STATUS status; char tmp_buf[ER_MAX_LEN]; char* logmsg = message; /* Check for bad paramters. */ CL_CLEAR_ERR( err_code ); if ((message == 0 || msg_length == 0) && flag != ER_AUDIT_MSG) return (ER_BADPARAM); if ((flag != ER_ERROR_MSG) && (flag != ER_AUDIT_MSG) && ( flag != ER_OPER_MSG)) return (ER_BADPARAM); # ifndef NT_GENERIC if (flag & ER_AUDIT_MSG) { key_t msg_key; char *ipc_number; struct { long mtype; char mtext[ER_MAX_LEN]; } msg; if (ar_ifi == -2) { NMgtAt("II_AUDIT_IPC", &ipc_number); if (ipc_number && ipc_number[0]) { CVal(ipc_number, &msg_key); ar_ifi = msgget(msg_key, 0); if (ar_ifi == -1) { SETCLERR(err_code, 0, ER_open); return(ER_NO_AUDIT); } } else { SETCLERR(err_code, 0, ER_open); return(ER_NO_AUDIT); } } /* Handle special case to connect only but not send message. */ if (msg_length == 0 && message == 0) return (OK); MEcopy(message, msg_length, msg.mtext); msg.mtype = 1; if (msgsnd(ar_ifi, &msg, msg_length, 0)) { SETCLERR(err_code, 0, ER_open); return(ER_BADSEND); } return (OK); } else # endif /* ! NT_GENERIC */ if (flag & ER_OPER_MSG) { char hostname[GL_MAXNAME]; STATUS status; message[msg_length] = EOS; TRdisplay("ER Operator:\"%s\"\n",message); if (!ERsysinit) ERinitsyslog(); # ifdef NT_GENERIC { wchar_t *wmessage = NULL; /* ** Update the ReportEvent to report information in the event log. */ if ( ReportEvent( EventLog, (WORD) EVENTLOG_INFORMATION_TYPE, (WORD) 0, /* event category */ (DWORD) I_ING_INFO, /* event identifier */ (PSID) NULL, (WORD) 1, /* number of strings */ (DWORD) 0, &message, NULL ) == FALSE) status = GetLastError(); if ( !er_init ) { char VersionString[256]; FUNC_EXTERN BOOL GVosvers(char *OSVersionString); GVosvers(VersionString); is_w95 = ( STstrindex(VersionString, "Microsoft Windows 9", 0, FALSE) != NULL ) ? TRUE : FALSE; if ( !is_w95 ) /* netapi32 only on NT */ { HANDLE hDll; if ((hDll = LoadLibrary(TEXT("netapi32.dll"))) != NULL) { pNetMessageNameAdd = (NET_API_STATUS (*)(LPCWSTR,LPCWSTR)) GetProcAddress(hDll, TEXT("NetMessageNameAdd")); pNetMessageNameDel = (NET_API_STATUS (*)(LPCWSTR,LPCWSTR)) GetProcAddress(hDll, TEXT("NetMessageNameDel")); pNetMessageBufferSend = (NET_API_STATUS (*)(LPCWSTR,LPCWSTR,LPCWSTR,LPBYTE,DWORD)) GetProcAddress(hDll, TEXT("NetMessageBufferSend")); } /* if any problem, pretend we don't support it */ if ( pNetMessageNameAdd == NULL || pNetMessageNameDel == NULL || pNetMessageBufferSend == NULL ) is_w95 = TRUE; } } if ( !is_w95 ) { /* ** Now, send the message to the server console, ** putting up a message box (if the messenger service ** is running. Everything must be in Unicode. */ if ( whostname[0] == 0 ) { unsigned int len = sizeof(hostname); /* ** get the hostname in Unicode format for use ** by messenger service */ GetComputerName( (char *)hostname, &len ); MultiByteToWideChar( GetACP(), 0, hostname, sizeof(hostname), whostname, sizeof(whostname) ); } /* initialize the messenger service */ status = (*pNetMessageNameAdd)( whostname, msgname ); if ( status != NERR_Success ) status = GetLastError(); /* Allocate a buffer for the Unicode */ wmessage = (wchar_t *) MEreqmem( 0, msg_length * sizeof(wchar_t), TRUE, &status ); if ( wmessage ) { /* copy the message to the Unicode buffer */ MultiByteToWideChar( GetACP(), 0, message, msg_length, wmessage, msg_length * sizeof(wchar_t) ); status = (*pNetMessageBufferSend)( whostname, msgname, NULL, (LPBYTE) wmessage, msg_length*sizeof(wchar_t) ); if ( status != NERR_Success ) status = GetLastError(); MEfree( (PTR)wmessage ); } /* re-initialize the messenger service */ status = (*pNetMessageNameDel)( whostname, msgname ); if ( status != NERR_Success ) status = GetLastError(); } } # elif defined(OS_THREADS_USED) && defined(any_aix) syslog_r( LOG_ALERT|LOG_ERR, message ); # else syslog( LOG_ALERT|LOG_ERR, message ); # endif /* NT_GENERIC */ } if (flag & ER_OPER_MSG) { i4 msglen = 0; char* host = PMhost(); MEfill( ER_MAX_LEN, 0, tmp_buf ); /* ** Format the message string for the event log. As the source is ** not known a fixed string of INGSYSLOG is used. */ TRformat( NULL, 0, tmp_buf, ER_MAX_LEN - 1, "%8.8t::[INGSYSLOG , 00000000]: %@ ", STlength(host), host ); msglen = STlength(tmp_buf); STcat( tmp_buf, message ); /* append original message */ msg_length += msglen; logmsg = tmp_buf; } status = ERlog( logmsg, msg_length, err_code ); return( status ); }
/*{ ** Name: CXcluster_nodes - Retrun information about configured nodes. ** ** Description: ** ** Function will return information about the nodes configured ** in this installation. ** ** Inputs: ** ** pnodecnt - Pointer to u_i4 to hold node count, or NULL. ** ** hconfig - Address of pointer to be filled with pointer ** to an initialized CX_CONFIGURATION, or NULL. ** DO NOT alter the contents of the cached ** CX_CONFIGURATION through the returned address! ** ** Outputs: ** ** *pnodecnt - Filled in with # nodes. ** ** *hconfig - Holds pointer to cached CX_CONFIGURATION. ** ** Returns: ** OK - Normal successful completion. ** FAIL - Problem with configuration found. ** ** Exceptions: ** none ** ** Side Effects: ** none. ** ** History: ** 18-apr-2001 (devjo01) ** Created. (Much of code lifted from DMFCSP) ** 15-Apr-2005 (fanch01) ** Modified cx_nodes array references to be valid from element zero. */ STATUS CXcluster_nodes( u_i4 *pnodecnt, CX_CONFIGURATION **hconfig ) { static i4 config_valid = 0; static CX_CONFIGURATION config = { 0 }; STATUS status = OK; u_i4 nodecnt; PM_SCAN_REC scanrec; char *resname; char *resvalue; char *nodename; i4 nodename_l; i4 clusterid; CX_NODE_INFO *pni; i4 i, rad; char param[80]; if ( !config_valid ) { status = PMinit(); if ( OK == status ) { status = PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)0); } else if ( PM_DUP_INIT == status ) { status = OK; } if ( status == OK ) { nodecnt = 0; /* ** Start the scan */ status = PMscan( "^II\\.[^.]*\\.CONFIG\\.CLUSTER\\.ID$", &scanrec, (char *) NULL, &resname, &resvalue ); while ( status == OK ) { /* ** Extract out node name and convert value to integer */ nodename = PMgetElem( 1, resname ); nodename_l = STlength(nodename); CVal( resvalue, &clusterid ); /* Ignore entries with zero cluster id. */ if ( 0 != clusterid ) { /* ** Check id is withing range */ if ( (clusterid > CX_MAX_NODES) || (clusterid < 0) ) { TRdisplay( ERx( \ "%@ CSP node config: Node %s has an invalid id: %d, valid range (0 - %d)\n"), nodename, clusterid, CX_MAX_NODES ); status = FAIL; break; } /* ** Adjust clusterid so array references are zero based. */ clusterid--; /* ** Check that specified id is not already used. */ if ( config.cx_nodes[clusterid].cx_node_name_l != 0 ) { /* ** Location is already being used issue a message ** accordingly */ if (STxcompare( nodename, nodename_l, config.cx_nodes[clusterid].cx_node_name, config.cx_nodes[clusterid].cx_node_name_l, TRUE, FALSE) == 0) { TRdisplay( ERx("%@ Cluster configuration: Node %~t already exists in correct location.\n"), nodename_l, nodename ); } else { TRdisplay( ERx("%@ Cluster configuration: Node %~t has same id as Node %~t.\n"), nodename_l, nodename, config.cx_nodes[clusterid].cx_node_name_l, config.cx_nodes[clusterid].cx_node_name ); } status = FAIL; break; } /* ** Make sure nodename is unique */ for (i = 1; i <= nodecnt; i++) { if (STxcompare( config.cx_nodes[config.cx_xref[i]].cx_node_name, config.cx_nodes[config.cx_xref[i]].cx_node_name_l, nodename, nodename_l, TRUE, FALSE) == 0) { TRdisplay( ERx("%@ Cluster configuration: Node %s already exists.\n"), nodename ); status = FAIL; break; } } /* ** Add to configuration */ nodecnt++; config.cx_xref[nodecnt] = clusterid; pni = &config.cx_nodes[clusterid]; STmove( nodename, '\0', CX_MAX_NODE_NAME_LEN, pni->cx_node_name ); pni->cx_node_name_l = STnlength(CX_MAX_NODE_NAME_LEN, pni->cx_node_name ); pni->cx_node_number = clusterid + 1; pni->cx_host_name_l = pni->cx_rad_id = 0; STprintf(param,"ii.%s.gcn.local_vnode", nodename); if ( OK == PMget(param, &resvalue) ) { STmove( resvalue, '\0', CX_MAX_HOST_NAME_LEN, pni->cx_host_name ); pni->cx_host_name_l = STnlength( CX_MAX_HOST_NAME_LEN, pni->cx_host_name ); } STprintf(param,"ii.%s.config.numa.rad", nodename); if ( OK == PMget(param, &resvalue) && OK == CVan(resvalue, &rad) && rad > 0 ) { pni->cx_rad_id = rad; } /* ** Find next element */ status = PMscan( (char *) NULL, &scanrec, (char *) NULL, &resname, &resvalue ); } } /* ** End condition */ if ( status == PM_NOT_FOUND ) status = OK; } if (status != OK ) { TRdisplay( ERx("%@ Cluster configuration Error\n") ); return (FAIL); } config.cx_node_cnt = nodecnt; config_valid = 1; } if ( pnodecnt ) *pnodecnt = config.cx_node_cnt; if ( hconfig ) *hconfig = &config; return OK; } /*CXcluster_nodes*/
/****************************************************************************** ** Name: CSoptions() - fetch a pile of options using PMget() ** ** Description: ** Calls PMget() for each option in the option table, converts the ** value appropriately, and distributes the value into the right ** spot in the CS_SYSTEM block. ** ** Note special cruddiness surrounding CSO_SERVER_CLASS: the CL ** fetches this only to set cs_isstar, used by CSinitiate() to ** calculate the file descriptor fluff factors: STAR uses more of 'em. ******************************************************************************/ STATUS CSoptions( CS_SYSTEM *cssb ) { i4 echo = 1; struct CSO_OPTIONS *csopt; i4 failures = 0; for( csopt = cso_opttab; csopt->cso_name; csopt++ ) { char *cs_svalue; i4 cs_value = 0; STATUS status = OK; /* * Get option's value using PMget() */ if( PMget( csopt->cso_name, &cs_svalue ) != OK ) continue; if( echo ) ERoptlog( csopt->cso_name, cs_svalue ); /* * Convert & check the option's value, according to argtype */ switch( csopt->cso_argtype ) { case 'g': /* String option */ break; case 'm': /* numeric option or the word "max" if( !STcompare( cs_svalue, "max" ) ) { cs_value = -1; break; } /* fall through */ case 'o': case 'n': /* set a numeric option */ if( CVal( cs_svalue, &cs_value ) != OK ) { status = E_CS0025_NUMERIC_ARG; } else if( csopt->cso_argtype == 'o' && cs_value < 0 ) { status = E_CS0026_POSITIVE_VALUE; } break; case 't': /* set a switch option: on = true */ if( STbcompare( cs_svalue, 0, "on", 0, TRUE ) ) continue; break; case 'z': /* clear a switch option */ if( !STbcompare( cs_svalue, 0, "on", 0, TRUE ) ) continue; break; } if( status ) { (*cssb->cs_elog)( status, (CL_ERR_DESC *)0, 1, STlength( csopt->cso_name ), csopt->cso_name ); failures++; break; } /* * Distribute option value, according to index */ switch( csopt->cso_index ) { case CSO_ECHO: /* echo: off */ echo = 0; break; case CSO_ACT_SESSION: cssb->cs_max_active = cs_value; break; case CSO_CON_SESSION: cssb->cs_max_sessions = cs_value; break; case CSO_MAXLDB_CON: // cssb->cs_max_ldb_connections = cs_value; break; case CSO_MAX_WS: # if defined( xCL_034_GETRLIMIT_EXISTS) && defined( RLIMIT_RSS ) { struct rlimit rlim; getrlimit( RLIMIT_RSS, &rlim ); rlim.rlim_cur = cs_value; if( cs_value < 0 || cs_value > rlim.rlim_max ) rlim.rlim_cur = rlim.rlim_max; setrlimit( RLIMIT_RSS, &rlim ); } #endif break; case CSO_PRIORITY: /* Process priority */ # ifdef xCL_033_SETPRIORITY_EXISTS // setpriority( PRIO_PROCESS, 0, cs_value ); # else // nice( cs_value ); # endif break; case CSO_QUANTUM: // cssb->cs_quantum = cs_value; break; case CSO_SESS_ACCTNG: cssb->cs_mask |= CS_ACCNTING_MASK; cssb->cs_mask |= CS_CPUSTAT_MASK; break; case CSO_CPUSTATS: cssb->cs_mask |= CS_CPUSTAT_MASK; break; case CSO_STK_SIZE: cssb->cs_stksize = cs_value; break; case CSO_SERVER_CLASS: // cssb->cs_isstar = !STcompare( cs_svalue, "STAR" ); /* cheesy */ break; case CSO_DEFINE: cssb->cs_define = TRUE; break; } } return (OK); }