Int32 CmpISPFuncs::RegFuncs( const char* procName, //null terminated SP_COMPILE_FUNCPTR compileFunc, SP_INPUTFORMAT_FUNCPTR inFormatFunc, SP_PARSE_FUNCPTR parseFunc, SP_NUM_OUTPUTFIELDS_FUNCPTR outNumFormatFunc, SP_OUTPUTFORMAT_FUNCPTR outFormatFunc, SP_PROCESS_FUNCPTR procFunc, SP_HANDLE spHandle, const char* version) { if ( strcmp(version, CMPISPVERSION) != 0 ) { ABORT ( "arkcmp: The ISP interface version is not compatible" ); NAExit(1); } procFuncsArray_.insert(ProcFuncsStruct(procName, compileFunc, inFormatFunc, parseFunc, outNumFormatFunc, outFormatFunc, procFunc, spHandle)); return 1; }
void UdrGuaControlConnection::actOnSystemMessage( short messageNum, IpcMessageBufferPtr sysMsg, IpcMessageObjSize sysMsgLen, short clientFileNumber, const GuaProcessHandle &clientPhandle, GuaConnectionToClient *connection) { const char * moduleName = "UdrGuaControlConnection::actOnSystemMessage"; switch (messageNum) { case ZSYS_VAL_SMSG_OPEN: { if (udrGlob_->verbose_ && udrGlob_->traceLevel_ >= TRACE_IPMS && udrGlob_->showMain_) { ServerDebug( "[UdrServ (%s)] A new connection %p is opened to the Server.", moduleName, connection); } // Create a new message stream. Link the connection. // Then call receive on it to bring it into receiving mode. UdrServerControlStream *newControlStream = new (udrGlob_->getIpcHeap()) UdrServerControlStream(udrGlob_->getIpcEnvironment(), udrGlob_, UDR_STREAM_SERVER_CONTROL, UdrServerControlStreamVersionNumber); newControlStream->addRecipient(connection); newControlStream->receive(FALSE); } break; default: // do nothing for all other kinds of system messages break; } // switch // The parent class already handles the job of closing all connections // who lost their client process by failed processes, failed CPUs and // failed systems or networks. Check here that we die if all our // requestors go away, but don't die if the first system message is // something other than an OPEN message. if (getNumRequestors() == 0 AND initialized_) { NAExit(0); } else if (NOT initialized_ AND getNumRequestors() > 0) { // the first requestor came in initialized_ = TRUE; } } // UdrGuaControlConnection::actOnSystemMessage()
void EspGuaControlConnection::actOnSystemMessage( short messageNum, IpcMessageBufferPtr sysMsg, IpcMessageObjSize sysMsgLen, short clientFileNumber, const GuaProcessHandle &clientPhandle, GuaConnectionToClient *connection) { switch (messageNum) { case ZSYS_VAL_SMSG_OPEN: if (initialized_) { // This an OPEN message for a connection that isn't the // initial control connection. Create a new message stream and // attach it to the newly created connection. EspNewIncomingConnectionStream *newStream = new(getEnv()->getHeap()) EspNewIncomingConnectionStream(getEnv(),espFragInstanceDir_); ex_assert(connection != NULL, "Must create connection for open sys msg"); newStream->addRecipient(connection); newStream->receive(FALSE); // now abandon the new object, it will find its way to the right // send bottom TCB on its own // (a memory leak would result if the client would open our $RECEIVE // w/o sending corresponding ESP level open requests) } break; case ZSYS_VAL_SMSG_CPUDOWN: case ZSYS_VAL_SMSG_REMOTECPUDOWN: case ZSYS_VAL_SMSG_CLOSE: case ZSYS_VAL_SMSG_NODEDOWN: // Somebody closed us or went down. Was it master executor? // Note that GuaReceiveControlConnection::getConnection returns // the master executor connection. if (getConnection() == connection) { // Master is gone, stop this process and let the OS cleanup. if (getEnv()->getLogEspGotCloseMsg()) { /* Coverage notes: to test this code in a dev regression requires changing $TRAF_VAR/ms.env, so I made a manual test on May 11, 2012 to verify this code. */ char myName[20]; memset(myName, '\0', sizeof(myName)); getEnv()->getMyOwnProcessId(IPC_DOM_GUA_PHANDLE).toAscii( myName, sizeof(myName)); char buf[500]; char *sysMsgName = NULL; switch (messageNum) { case ZSYS_VAL_SMSG_CPUDOWN: sysMsgName = (char *) "CPUDOWN"; break; case ZSYS_VAL_SMSG_REMOTECPUDOWN: sysMsgName = (char *) "REMOTECPUDOWN"; break; case ZSYS_VAL_SMSG_CLOSE: sysMsgName = (char *) "CLOSE"; break; case ZSYS_VAL_SMSG_NODEDOWN: sysMsgName = (char *) "NODEDOWN"; break; } str_sprintf(buf, "System %s message causes %s to exit.", sysMsgName, myName); SQLMXLoggingArea::logExecRtInfo(__FILE__, __LINE__, buf, 0); } getEnv()->stopIpcEnvironment(); } // Otherwise, do a search thru all // downloaded fragment entries and check whether their // client is still using them. The IPC layer will wake // up the scheduler so the actual release can take place. espFragInstanceDir_->releaseOrphanEntries(); break; default: // do nothing for all other kinds of system messages break; } // switch // The parent class already handles the job of closing all connections // who lost their client process by failed processes, failed CPUs and // failed systems or networks. Check here that we die if all our // requestors go away, but don't die if the first system message is // something other than an OPEN message. if (getNumRequestors() == 0 AND initialized_) { // ABORT("Lost connection to client"); // losing the client is not a reason to panic, the client may // have voluntarily decided to exit without freeing its resources NAExit(0); } else if (NOT initialized_ AND getNumRequestors() > 0) { // the first requestor came in initialized_ = TRUE; } }
void DoEspStartup(Int32 argc, char **argv, IpcEnvironment &env, ExEspFragInstanceDir &fragInstanceDir, GuaReceiveFastStart *guaReceiveFastStart) { // make the compiler happy by using fragInstanceDir for something if (fragInstanceDir.getNumEntries() < 0) {} // interpret command line arguments IpcServerAllocationMethod allocMethod = IPC_ALLOC_DONT_CARE; Int32 currArg = 1; Int32 socketArg = 0; Int32 portArg = 0; while (currArg < argc) { if (strcmp("-fork", argv[currArg]) == 0) { allocMethod = IPC_POSIX_FORK_EXEC; } else if (strcmp("-service", argv[currArg]) == 0) { // /etc/inetd.conf should be configured such that the "-service" // command line option is given allocMethod = IPC_INETD; } else if (strcmp("-guardian", argv[currArg]) == 0) { allocMethod = IPC_LAUNCH_GUARDIAN_PROCESS; } else if (strcmp("-noespfaststart", argv[currArg]) == 0) ; else if (strcmp("-debug", argv[currArg]) == 0) { NADebug(); } else { // bad arguments, die NAExit(-1); } currArg++; } // create control connection (open $RECEIVE in Tandemese) switch (allocMethod) { case IPC_LAUNCH_GUARDIAN_PROCESS: case IPC_SPAWN_OSS_PROCESS: { // open $RECEIVE with a receive depth of 4000 GuaReceiveControlConnection *cc = new(&env) EspGuaControlConnection(&env, &fragInstanceDir, 4000, guaReceiveFastStart); env.setControlConnection(cc); // wait for the first open message to come in cc->waitForMaster(); // set initial timeout in case the master never send first plan message env.setIdleTimestamp(); } break; case IPC_INETD: case IPC_POSIX_FORK_EXEC: env.setControlConnection( new(&env) EspSockControlConnection(&env,&fragInstanceDir)); break; // NEEDS PORT (12/16/96) // handle the local NT process case without NSK-like case IPC_LAUNCH_NT_PROCESS: //debugging code - figure out later // the name of this machine on which this process is executing char myMachine[IpcNodeNameMaxLength]; char errorLine[64]; Int32 result; // who am I? result = gethostname(myMachine,IpcNodeNameMaxLength); if (!result) { sprintf(errorLine," DoEspStartup : gethostname : error %d",result); ABORT(errorLine); }; // end debugging code env.setControlConnection( new(&env) EspSockControlConnection( &env,&fragInstanceDir,socketArg, portArg)); break; default: // bad command line arguments again NAExit(-1); } }
Int32 runESP(Int32 argc, char** argv, GuaReceiveFastStart *guaReceiveFastStart) { // initialize ESP global data StatsGlobals * statsGlobals; XCONTROLMESSAGESYSTEM(XCTLMSGSYS_SETRECVLIMIT, XMAX_SETTABLE_RECVLIMIT_H); CliGlobals *cliGlobals = NULL; cliGlobals = CliGlobals::createCliGlobals(TRUE); // TRUE indicates a non-master process (WAIT on LREC) if (cliGlobals == NULL) // Sanity check NAExit(1); // Abend Int32 shmid; statsGlobals = shareStatsSegment(shmid); cliGlobals->setSharedMemId(shmid); //Lng32 numCliCalls = cliGlobals->incrNumOfCliCalls(); cliGlobals->setIsESPProcess(TRUE); NAHeap *espExecutorHeap = cliGlobals->getExecutorMemory(); // must create default context after set IpcEnvironment in CliGlobals first // because context's ExSqlComp object needs IpcEnvironment cliGlobals->initiateDefaultContext(); NAHeap *espIpcHeap = cliGlobals->getIpcHeap(); IpcEnvironment *ipcEnvPtr = cliGlobals->getEnvironment(); if (statsGlobals != NULL) cliGlobals->setMemoryMonitor(statsGlobals->getMemoryMonitor()); else { // Start the memory monitor for dynamic memory management Lng32 memMonitorWindowSize = 10; Lng32 memMonitorSampleInterval = 10; MemoryMonitor *memMonitor = new (espExecutorHeap) MemoryMonitor(memMonitorWindowSize, memMonitorSampleInterval, espExecutorHeap); cliGlobals->setMemoryMonitor(memMonitor); } // After CLI globals are initialized but before we begin ESP message // processing, have the CLI context set its user identity based on // the OS user identity. ContextCli *context = cliGlobals->currContext(); ex_assert(context, "Invalid context pointer"); context->initializeUserInfoFromOS(); ExEspFragInstanceDir espFragInstanceDir(cliGlobals, espExecutorHeap, (StatsGlobals *)statsGlobals); ExEspControlMessage espIpcControlMessage(&espFragInstanceDir, ipcEnvPtr, espIpcHeap); // handle startup (command line args, control connection) DoEspStartup(argc,argv,*ipcEnvPtr,espFragInstanceDir,guaReceiveFastStart); // the control message stream talks through the control connection espIpcControlMessage.addRecipient( ipcEnvPtr->getControlConnection()->getConnection()); // start the first receive operation espIpcControlMessage.receive(FALSE); NABoolean timeout; Int64 prevWaitTime = 0; // while there are requesters while (espFragInstanceDir.getNumMasters() > 0) { // ----------------------------------------------------------------- // The ESPs most important line of code: DO THE WORK // ----------------------------------------------------------------- espFragInstanceDir.work(prevWaitTime); // ----------------------------------------------------------------- // After we have done work, it's necessary to wait for some I/O // (the frag instance dir work procedure works until it is blocked). // ----------------------------------------------------------------- ipcEnvPtr->getAllConnections()-> waitOnAll(IpcInfiniteTimeout, TRUE, &timeout, &prevWaitTime); // TRUE means: Called by ESP main } // nobody wants us anymore, right now that means that we stop return 0; }
void runServer(Int32 argc, char **argv) { Int32 shmid; jmp_buf sscpJmpBuf; StatsGlobals *statsGlobals = NULL; void *statsGlobalsAddr; NABoolean createStatsGlobals = FALSE; CliGlobals *cliGlobals = CliGlobals::createCliGlobals(FALSE); char tmbuf[64]; time_t now; struct tm *nowtm; long maxSegSize = STATS_MAX_SEG_SIZE; char *envSegSize = getenv("MX_RTS_STATS_SEG_SIZE"); if (envSegSize) { maxSegSize = (long) str_atoi(envSegSize, str_len(envSegSize)); if (maxSegSize < 32) maxSegSize = 32; else if (maxSegSize > 256) maxSegSize = 256; maxSegSize *= 1024 * 1024; } long enableHugePages = 0; int shmFlag = RMS_SHMFLAGS; char *envShmHugePages = getenv("SQ_RMS_ENABLE_HUGEPAGES"); if (envShmHugePages != NULL) { enableHugePages = (long) str_atoi(envShmHugePages, str_len(envShmHugePages)); if (enableHugePages > 0) shmFlag = shmFlag | SHM_HUGETLB; } now = time(NULL); nowtm = localtime(&now); strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S ", nowtm); if ((shmid = shmget((key_t)getStatsSegmentId(), 0, // size doesn't matter unless we are creating. shmFlag)) == -1) { if (errno == ENOENT) { // Normal case, segment does not exist yet. Try to create. bool didCreate = true; if ((shmid = shmget((key_t)getStatsSegmentId(), maxSegSize, shmFlag | IPC_CREAT)) == -1) { if (enableHugePages > 0) { enableHugePages = 0; // try again withouf hugepages shmFlag = shmFlag & ~SHM_HUGETLB; if ((shmid = shmget((key_t)getStatsSegmentId(), maxSegSize, shmFlag | IPC_CREAT)) == -1) didCreate = false; } else didCreate = false; } if (didCreate) { cout << tmbuf << " RMS Shared segment id = " << shmid << ", key = " << (key_t)getStatsSegmentId() ; if (enableHugePages > 0) cout << ", created with huge pages support." << endl; else cout << ", created without huge pages support." << endl; createStatsGlobals = TRUE; } else { cout << tmbuf << " Shmget failed, key = " << getStatsSegmentId() <<", Error code: " << errno << " (" << strerror(errno) << ")" << endl; exit(errno); } } // if ENOENT (i.e., attempting creation.) } else { cout << tmbuf << " RMS Shared segment exists, attaching to it, shmid="<< shmid << ", key=" << (key_t)getStatsSegmentId() << "\n"; } if ((statsGlobalsAddr = shmat(shmid, getRmsSharedMemoryAddr(), 0)) == (void *)-1) { cout << tmbuf << "Shmat failed, shmid=" <<shmid << ", key=" << (key_t) getStatsSegmentId() << ", Error code : " << errno << "(" << strerror(errno) << ")\n"; exit(errno); } char *statsGlobalsStartAddr = (char *)statsGlobalsAddr; if (createStatsGlobals) { short envType = StatsGlobals::RTS_GLOBAL_ENV; statsGlobals = new (statsGlobalsStartAddr) StatsGlobals((void *)statsGlobalsAddr, envType, maxSegSize); cliGlobals->setSharedMemId(shmid); // We really should not squirrel the statsGlobals pointer away like // this until the StatsGloblas is initialized, but // statsGlobals->init() needs it ...... cliGlobals->setStatsGlobals(statsGlobals); statsGlobals->init(); } else { statsGlobals = (StatsGlobals *)statsGlobalsAddr; cliGlobals->setSharedMemId(shmid); cliGlobals->setStatsGlobals(statsGlobals); } XPROCESSHANDLE_GETMINE_(statsGlobals->getSscpProcHandle()); NAHeap *sscpHeap = cliGlobals->getExecutorMemory(); cliGlobals->setJmpBufPtr(&sscpJmpBuf); if (setjmp(sscpJmpBuf)) NAExit(1); // Abend IpcEnvironment *sscpIpcEnv = new (sscpHeap) IpcEnvironment(sscpHeap, cliGlobals->getEventConsumed(), FALSE, IPC_SQLSSCP_SERVER, FALSE, TRUE); SscpGlobals *sscpGlobals = NULL; sscpGlobals = new (sscpHeap) SscpGlobals(sscpHeap, statsGlobals); // Currently open $RECEIVE with 256 SscpGuaReceiveControlConnection *cc = new(sscpHeap) SscpGuaReceiveControlConnection(sscpIpcEnv, sscpGlobals, 256); sscpIpcEnv->setControlConnection(cc); while (TRUE) { while (cc->getConnection() == NULL) cc->wait(IpcInfiniteTimeout); #ifdef _DEBUG_RTS cerr << "No. of Requesters-1 " << cc->getNumRequestors() << " \n"; #endif while (cc->getNumRequestors() > 0) { sscpIpcEnv->getAllConnections()->waitOnAll(IpcInfiniteTimeout); } // Inner while } } // runServer
// myNAExit(status) does mxcmp finalization before calling NAExit(status) static void myNAExit(Int32 status) { CURRENTQCACHE->finalize("Dynamic "); NAExit(status); }