void ExExeUtilTcb::deleteServer(IpcServer *ipcServer)
{
  IpcServerClass * sc = ipcServer->getServerClass();
  IpcEnvironment *env = sc->getEnv();

  ipcServer->release();
  NADELETE(sc, IpcServerClass, env->getHeap());
}
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 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);
    }
}
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