Пример #1
0
void RunServer()
{   
    Bool16 restartServer = false;
    UInt32 loopCount = 0;
    UInt32 debugLevel = 0;
    Bool16 printHeader = false;
    Bool16 printStatus = false;


    //just wait until someone stops the server or a fatal error occurs.
    QTSS_ServerState theServerState = theSver->GetServerState();
    while ((theServerState != qtssShuttingDownState) &&
            (theServerState != qtssFatalErrorState))
    {
#ifdef __sgi__
        OSThread::Sleep(999);
#else
        OSThread::Sleep(1000);
#endif

        if ((theSver->SigIntSet()) || (theSver->SigTermSet()))
        {
            //
            // start the shutdown process
            theServerState = qtssShuttingDownState;
   //         (void)QTSS_SetValue(QTSServerInterface::GetServer(), qtssSvrState, 0, &theServerState, sizeof(theServerState));

            if (theSver->SigIntSet())
                restartServer = true;
        }
    }
        
    //Now, make sure that the server can't do any work
    TaskThreadPool::RemoveThreads();
    
    //now that the server is definitely stopped, it is safe to initate
    //the shutdown process
    delete theSver;
    
    CleanPid(false);
    //ok, we're ready to exit. If we're quitting because of some fatal error
    //while running the server, make sure to let the parent process know by
    //exiting with a nonzero status. Otherwise, exit with a 0 status
    if (theServerState == qtssFatalErrorState || restartServer)
        ::exit (-2);//-2 signals parent process to restart server
}
Пример #2
0
QTSS_ServerState StartServer(XMLPrefsParser* inPrefsSource, PrefsSource* inMessagesSource, UInt16 inPortOverride, int statsUpdateInterval, QTSS_ServerState inInitialState, Bool16 inDontFork, UInt32 debugLevel, UInt32 debugOptions)
{
    //Mark when we are done starting up. If auto-restart is enabled, we want to make sure
    //to always exit with a status of 0 if we encountered a problem WHILE STARTING UP. This
    //will prevent infinite-auto-restart-loop type problems
    Bool16 doneStartingUp = false;
    QTSS_ServerState theServerState = qtssStartingUpState;
    
    sStatusUpdateInterval = statsUpdateInterval;
    
    //Initialize utility classes
    OS::Initialize();
    OSThread::Initialize();

    Socket::Initialize();
    SocketUtils::Initialize(!inDontFork);

#if !MACOSXEVENTQUEUE
    ::select_startevents();//initialize the select() implementation of the event queue
#endif
    
    //start the server
    QTSSDictionaryMap::Initialize();
    QTSServerInterface::Initialize();// this must be called before constructing the server object
    sServer = NEW QTSServer();
    sServer->SetDebugLevel(debugLevel);
    sServer->SetDebugOptions(debugOptions);
    
    // re-parse config file
    inPrefsSource->Parse();

    Bool16 createListeners = true;
    if (qtssShuttingDownState == inInitialState) 
        createListeners = false;
    
    sServer->Initialize(inPrefsSource, inMessagesSource, inPortOverride,createListeners);

    if (inInitialState == qtssShuttingDownState)
    {  
        sServer->InitModules(inInitialState);
        return inInitialState;
    }
    
    OSCharArrayDeleter runGroupName(sServer->GetPrefs()->GetRunGroupName());
    OSCharArrayDeleter runUserName(sServer->GetPrefs()->GetRunUserName());
    OSThread::SetPersonality(runUserName.GetObject(), runGroupName.GetObject());

    if (sServer->GetServerState() != qtssFatalErrorState)
    {
        UInt32 numShortTaskThreads = 0;
        UInt32 numBlockingThreads = 0;
        UInt32 numThreads = 0;
        UInt32 numProcessors = 0;
        
        if (OS::ThreadSafe())
        {
            numShortTaskThreads = sServer->GetPrefs()->GetNumThreads(); // whatever the prefs say
            if (numShortTaskThreads == 0) {
               numProcessors = OS::GetNumProcessors();
                // 1 worker thread per processor, up to 2 threads.
                // Note: Limiting the number of worker threads to 2 on a MacOS X system with > 2 cores
                //     results in better performance on those systems, as of MacOS X 10.5.  Future
                //     improvements should make this limit unnecessary.
                if (numProcessors > 2)
                    numShortTaskThreads = 2;
                else
                    numShortTaskThreads = numProcessors;
            }

            numBlockingThreads = sServer->GetPrefs()->GetNumBlockingThreads(); // whatever the prefs say
            if (numBlockingThreads == 0)
                numBlockingThreads = 1;
                
        }
        if (numShortTaskThreads == 0)
            numShortTaskThreads = 1;

        if (numBlockingThreads == 0)
            numBlockingThreads = 1;

        numThreads = numShortTaskThreads + numBlockingThreads;
        //qtss_printf("Add threads shortask=%lu blocking=%lu\n",numShortTaskThreads, numBlockingThreads);
        TaskThreadPool::SetNumShortTaskThreads(numShortTaskThreads);
        TaskThreadPool::SetNumBlockingTaskThreads(numBlockingThreads);
        TaskThreadPool::AddThreads(numThreads);
		sServer->InitNumThreads(numThreads);
		
    #if DEBUG
        qtss_printf("Number of task threads: %"_U32BITARG_"\n",numThreads);
    #endif
    
        // Start up the server's global tasks, and start listening
        TimeoutTask::Initialize();     // The TimeoutTask mechanism is task based,
                                    // we therefore must do this after adding task threads
                                    // this be done before starting the sockets and server tasks
     }

    //Make sure to do this stuff last. Because these are all the threads that
    //do work in the server, this ensures that no work can go on while the server
    //is in the process of staring up
    if (sServer->GetServerState() != qtssFatalErrorState)
    {
        IdleTask::Initialize();
        Socket::StartThread();
        OSThread::Sleep(1000);
        
        //
        // On Win32, in order to call modwatch the Socket EventQueue thread must be
        // created first. Modules call modwatch from their initializer, and we don't
        // want to prevent them from doing that, so module initialization is separated
        // out from other initialization, and we start the Socket EventQueue thread first.
        // The server is still prevented from doing anything as of yet, because there
        // aren't any TaskThreads yet.
        sServer->InitModules(inInitialState);
        sServer->StartTasks();
        sServer->SetupUDPSockets(); // udp sockets are set up after the rtcp task is instantiated
        theServerState = sServer->GetServerState();
    }

    if (theServerState != qtssFatalErrorState)
    {
        CleanPid(true);
        WritePid(!inDontFork);

        doneStartingUp = true;
        qtss_printf("Streaming Server done starting up\n");
        OSMemory::SetMemoryError(ENOMEM);
    }


    // SWITCH TO RUN USER AND GROUP ID
    //if (!sServer->SwitchPersonality())
    //    theServerState = qtssFatalErrorState;

   //
    // Tell the caller whether the server started up or not
    return theServerState;
}
Пример #3
0
void RunServer()
{   
    Bool16 restartServer = false;
    UInt32 loopCount = 0;
    UInt32 debugLevel = 0;
    Bool16 printHeader = false;
    Bool16 printStatus = false;


    //just wait until someone stops the server or a fatal error occurs.
    QTSS_ServerState theServerState = sServer->GetServerState();
    while ((theServerState != qtssShuttingDownState) &&
            (theServerState != qtssFatalErrorState))
    {
#ifdef __sgi__
        OSThread::Sleep(999);
#else
        OSThread::Sleep(1000);
#endif

        LogStatus(theServerState);

        if (sStatusUpdateInterval)
        {
            debugLevel = sServer->GetDebugLevel();             
            printHeader = PrintHeader(loopCount);
            printStatus = PrintLine(loopCount);
                
            if (printStatus)
            {
                if  (DebugOn(sServer) ) // debug level display or logging is on
                    DebugStatus(debugLevel, printHeader);
                
                if (!DebugDisplayOn(sServer))
                    PrintStatus(printHeader); // default status output
            }
            
            
            loopCount++;

        }
        
        if ((sServer->SigIntSet()) || (sServer->SigTermSet()))
        {
            //
            // start the shutdown process
            theServerState = qtssShuttingDownState;
            (void)QTSS_SetValue(QTSServerInterface::GetServer(), qtssSvrState, 0, &theServerState, sizeof(theServerState));

            if (sServer->SigIntSet())
                restartServer = true;
        }
        
        theServerState = sServer->GetServerState();
        if (theServerState == qtssIdleState)
            sServer->KillAllRTPSessions();
    }
    
    //
    // Kill all the sessions and wait for them to die,
    // but don't wait more than 5 seconds
    sServer->KillAllRTPSessions();
    for (UInt32 shutdownWaitCount = 0; (sServer->GetNumRTPSessions() > 0) && (shutdownWaitCount < 5); shutdownWaitCount++)
        OSThread::Sleep(1000);
        
    //Now, make sure that the server can't do any work
    TaskThreadPool::RemoveThreads();
    
    //now that the server is definitely stopped, it is safe to initate
    //the shutdown process
    delete sServer;
    
    CleanPid(false);
    //ok, we're ready to exit. If we're quitting because of some fatal error
    //while running the server, make sure to let the parent process know by
    //exiting with a nonzero status. Otherwise, exit with a 0 status
    if (theServerState == qtssFatalErrorState || restartServer)
        ::exit (-2);//-2 signals parent process to restart server
}
Пример #4
0
int main(int argc, char * argv[]) 
{
    extern char* optarg;
    
    

    // on write, don't send signal for SIGPIPE, just set errno to EPIPE
    // and return -1
    //signal is a deprecated and potentially dangerous function
    //(void) ::signal(SIGPIPE, SIG_IGN);
    struct sigaction act;
    
#if defined(sun) || defined(i386) || defined(__x86_64__) || defined (__MacOSX__) || defined(__powerpc__) || defined (__osf__) || defined (__sgi_cc__) || defined (__hpux__) || defined (__linux__)
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    act.sa_handler = (void(*)(int))&sigcatcher;
#elif defined(__sgi__) 
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	act.sa_handler = (void(*)(...))&sigcatcher;
#else
    act.sa_mask = 0;
    act.sa_flags = 0;
    act.sa_handler = (void(*)(...))&sigcatcher;
#endif
    (void)::sigaction(SIGPIPE, &act, NULL);
    (void)::sigaction(SIGHUP, &act, NULL);
    (void)::sigaction(SIGINT, &act, NULL);
    (void)::sigaction(SIGTERM, &act, NULL);
    (void)::sigaction(SIGQUIT, &act, NULL);
    (void)::sigaction(SIGALRM, &act, NULL);


#if __solaris__ || __linux__ || __hpux__
    //grow our pool of file descriptors to the max!
    struct rlimit rl;
    
    // set it to the absolute maximum that the operating system allows - have to be superuser to do this
    rl.rlim_cur = RLIM_INFINITY;
    rl.rlim_max = RLIM_INFINITY;
 
    setrlimit (RLIMIT_NOFILE, &rl);
#endif

#if __MacOSX__
    struct rlimit rl;
    getrlimit(RLIMIT_NOFILE,  &rl); //get the default values
    //printf("current open file limit =%"_U32BITARG_"\n", (UInt32) rl.rlim_cur); //leopard returns  256
    //printf("current open file max =%"_U32BITARG_"\n", (UInt32) rl.rlim_max);//leopard returns infinity (-1)
    
    rl. rlim_max = (rlim_t) RLIM_INFINITY -1; //use a big number to find out the real max but do not use RLIM_INFINITY that is not allowed. see man page
    setrlimit (RLIMIT_NOFILE, &rl); //resets the max value stored by limits to the boot config values.
    getrlimit(RLIMIT_NOFILE,  &rl); //now get the real max value
    //printf("current open file limit =%"_U32BITARG_"\n", (UInt32) rl.rlim_cur);
    //printf("current open file max =%"_U32BITARG_"\n", (UInt32) rl.rlim_max);
    
    rl.rlim_cur = (rlim_t) ( (float) rl.rlim_max * 0.9);   //use 90% of the max set in /etc/rc.server and /etc/sysctl.conf.default
    setrlimit (RLIMIT_NOFILE, &rl);  //finally set the current limit 
    
#endif
    
#if 0 // testing
    getrlimit(RLIMIT_NOFILE,  &rl);
    printf("current open file limit =%"_U32BITARG_"\n", (UInt32) rl.rlim_cur);
    printf("current open file max =%"_U32BITARG_"\n", (UInt32) rl.rlim_max);
#endif

#if __MacOSX__ || __FreeBSD__
        //
        // These 2 OSes have problems with large socket buffer sizes. Make sure they allow even
        // ridiculously large ones, because we may need them to receive a large volume of ACK packets
        // from the client
        
        //
        // We raise the limit imposed by the kernel by calling the sysctl system call.
        int mib[CTL_MAXNAME];
        mib[0] = CTL_KERN;
        mib[1] = KERN_IPC;
        mib[2] = KIPC_MAXSOCKBUF;
        mib[3] = 0;

        int maxSocketBufferSizeVal = 2000 * 1024; // Allow up to 2 MB. That is WAY more than we should need
        (void) ::sysctl(mib, 3, 0, 0, &maxSocketBufferSizeVal, sizeof(maxSocketBufferSizeVal));
        //int sysctlErr =  ::sysctl(mib, 3, 0, 0, &maxSocketBufferSizeVal, sizeof(maxSocketBufferSizeVal));
        //qtss_printf("sysctl maxSocketBufferSizeVal=%d err=%d\n",maxSocketBufferSizeVal, sysctlErr);
 #endif
    
    //First thing to do is to read command-line arguments.
    int ch;
    int thePort = 0; //port can be set on the command line
    int statsUpdateInterval = 0;
    QTSS_ServerState theInitialState = qtssRunningState;
    
    Bool16 dontFork = false;
    Bool16 theXMLPrefsExist = true;
    UInt32 debugLevel = 0;
    UInt32 debugOptions = kRunServerDebug_Off;
	static char* sDefaultConfigFilePath = DEFAULTPATHS_ETC_DIR_OLD "easydarwin.conf";
	static char* sDefaultXMLFilePath = DEFAULTPATHS_ETC_DIR "easydarwin.xml";

    char* theConfigFilePath = sDefaultConfigFilePath;
    char* theXMLFilePath = sDefaultXMLFilePath;
    while ((ch = getopt(argc,argv, "vdfxp:DZ:c:o:S:Ih")) != EOF) // opt: means requires option arg
    {
        switch(ch)
        {
            case 'v':
                usage();
                ::exit(0);  
            case 'd':
                dontFork = RunInForeground();
                
                break;                
            case 'D':
               dontFork = RunInForeground();

               debugOptions |= kRunServerDebugDisplay_On;
                
               if (debugLevel == 0)
                    debugLevel = 1;
                    
               if (statsUpdateInterval == 0)
                    statsUpdateInterval = 3;
                    
               break;            
            case 'Z':
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                debugLevel = (UInt32) ::atoi(optarg);
                                
                break;
            case 'f':
				theXMLFilePath  = DEFAULTPATHS_ETC_DIR "easydarwin.xml";
                break;
            case 'p':
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                thePort = ::atoi(optarg);
                break;
            case 'S':
                dontFork = RunInForeground();
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                statsUpdateInterval = ::atoi(optarg);
                break;
            case 'c':
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                theXMLFilePath = optarg;
                break;
            case 'o':
                Assert(optarg != NULL);// this means we didn't declare getopt options correctly or there is a bug in getopt.
                theConfigFilePath = optarg;
                break;
            case 'x':
                theXMLPrefsExist = false; // Force us to generate a new XML prefs file
                theInitialState = qtssShuttingDownState;
                dontFork = true;
                break;
            case 'I':
                theInitialState = qtssIdleState;
                break;
            case 'h':
                usage();
                ::exit(0);
            default:
                break;
        }
    }
    
  
    // Check port
    if (thePort < 0 || thePort > 65535)
    { 
        qtss_printf("Invalid port value = %d max value = 65535\n",thePort);
        exit (-1);
    }

    // Check expiration date
    QTSSExpirationDate::PrintExpirationDate();
    if (QTSSExpirationDate::IsSoftwareExpired())
    {
        qtss_printf("Streaming Server has expired\n");
        ::exit(0);
    }


    XMLPrefsParser theXMLParser(theXMLFilePath);
    
    //
    // Check to see if the XML file exists as a directory. If it does,
    // just bail because we do not want to overwrite a directory
    if (theXMLParser.DoesFileExistAsDirectory())
    {
        qtss_printf("Directory located at location where streaming server prefs file should be.\n");
        exit(-1);
    }
    
    //
    // Check to see if we can write to the file
    if (!theXMLParser.CanWriteFile())
    {
        qtss_printf("Cannot write to the streaming server prefs file.\n");
        exit(-1);
    }

    // If we aren't forced to create a new XML prefs file, whether
    // we do or not depends solely on whether the XML prefs file exists currently.
    if (theXMLPrefsExist)
        theXMLPrefsExist = theXMLParser.DoesFileExist();
    
    if (!theXMLPrefsExist)
    {
        
        //
        // The XML prefs file doesn't exist, so let's create an old-style
        // prefs source in order to generate a fresh XML prefs file.
        
        if (theConfigFilePath != NULL)
        {   
            FilePrefsSource* filePrefsSource = new FilePrefsSource(true); // Allow dups
            
            if ( filePrefsSource->InitFromConfigFile(theConfigFilePath) )
            { 
               qtss_printf("Generating a new prefs file at %s\n", theXMLFilePath);
            }

            if (GenerateAllXMLPrefs(filePrefsSource, &theXMLParser))
            {
                qtss_printf("Fatal Error: Could not create new prefs file at: %s. (%d)\n", theXMLFilePath, OSThread::GetErrno());
                ::exit(-1);
            }
        }
    }

 
    //
    // Parse the configs from the XML file
    int xmlParseErr = theXMLParser.Parse();
    if (xmlParseErr)
    {
        qtss_printf("Fatal Error: Could not load configuration file at %s. (%d)\n", theXMLFilePath, OSThread::GetErrno());
        ::exit(-1);
    }
    
    //Unless the command line option is set, fork & daemonize the process at this point
    if (!dontFork)
    {
#ifdef __sgi__
		// for some reason, this method doesn't work right on IRIX 6.4 unless the first arg
		// is _DF_NOFORK.  if the first arg is 0 (as it should be) the result is a server
		// that is essentially paralized and doesn't respond to much at all.  So for now,
		// leave the first arg as _DF_NOFORK
//		if (_daemonize(_DF_NOFORK, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO) != 0)
        if (_daemonize(0, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO) != 0)
#else
        if (daemon(0,0) != 0)
#endif
        {
#if DEBUG
            qtss_printf("Failed to daemonize process. Error = %d\n", OSThread::GetErrno());
#endif
            exit(-1);
        }
    }
    
    //Construct a Prefs Source object to get server text messages
    FilePrefsSource theMessagesSource;
    theMessagesSource.InitFromConfigFile("qtssmessages.txt");
    

    int status = 0;
    int pid = 0;
    pid_t processID = 0;
	
    if ( !dontFork) // if (fork) 
    {
        //loop until the server exits normally. If the server doesn't exit
        //normally, then restart it.
        // normal exit means the following
        // the child quit 
        do // fork at least once but stop on the status conditions returned by wait or if autoStart pref is false
        {
            processID = fork();
            Assert(processID >= 0);
            if (processID > 0) // this is the parent and we have a child
            {
                sChildPID = processID;
                status = 0;
                while (status == 0) //loop on wait until status is != 0;
                {	
                 	pid =::wait(&status);
                 	SInt8 exitStatus = (SInt8) WEXITSTATUS(status);
                	//qtss_printf("Child Process %d wait exited with pid=%d status=%d exit status=%d\n", processID, pid, status, exitStatus);
                	
					if (WIFEXITED(status) && pid > 0 && status != 0) // child exited with status -2 restart or -1 don't restart 
					{
						//qtss_printf("child exited with status=%d\n", exitStatus);
						
						if ( exitStatus == -1) // child couldn't run don't try again
						{
							qtss_printf("child exited with -1 fatal error so parent is exiting too.\n");
							exit (EXIT_FAILURE); 
						}
						break; // restart the child
							
					}
					
					if (WIFSIGNALED(status)) // child exited on an unhandled signal (maybe a bus error or seg fault)
					{	
						//qtss_printf("child was signalled\n");
						break; // restart the child
					}

                 		
                	if (pid == -1 && status == 0) // parent woken up by a handled signal
                   	{
						//qtss_printf("handled signal continue waiting\n");
                   		continue;
                   	}
                   	
                 	if (pid > 0 && status == 0)
                 	{
                 		//qtss_printf("child exited cleanly so parent is exiting\n");
                 		exit(EXIT_SUCCESS);                		
                	}
                	
                	//qtss_printf("child died for unknown reasons parent is exiting\n");
                	exit (EXIT_FAILURE);
                }
            }
            else if (processID == 0) // must be the child
				break;
            else
            	exit(EXIT_FAILURE);
            	
            	
            //eek. If you auto-restart too fast, you might start the new one before the OS has
            //cleaned up from the old one, resulting in startup errors when you create the new
            //one. Waiting for a second seems to work
            sleep(1);
        } while (RestartServer(theXMLFilePath)); // fork again based on pref if server dies
        if (processID != 0) //the parent is quitting
        	exit(EXIT_SUCCESS);   

        
    }
    sChildPID = 0;
    //we have to do this again for the child process, because sigaction states
    //do not span multiple processes.
    (void)::sigaction(SIGPIPE, &act, NULL);
    (void)::sigaction(SIGHUP, &act, NULL);
    (void)::sigaction(SIGINT, &act, NULL);
    (void)::sigaction(SIGTERM, &act, NULL);
    (void)::sigaction(SIGQUIT, &act, NULL);

#ifdef __hpux__  
	// Set Priority Type to Real Time, timeslice = 100 milliseconds. Change the timeslice upwards as needed. This keeps the server priority above the playlist broadcaster which is a time-share scheduling type.
	char commandStr[64];
	qtss_sprintf(commandStr, "/usr/bin/rtprio -t -%d", (int) getpid()); 
#if DEBUG
	qtss_printf("setting priority to Real Time: %s\n", commandStr);
#endif
	(void) ::system(commandStr);    
#endif
    
#ifdef __solaris__  
    // Set Priority Type to Real Time, timeslice = 100 milliseconds. Change the timeslice upwards as needed. This keeps the server priority above the playlist broadcaster which is a time-share scheduling type.
    char commandStr[64];
    qtss_sprintf(commandStr, "priocntl -s -c RT -t 10 -i pid %d", (int) getpid()); 
    (void) ::system(commandStr);    
#endif

#ifdef __MacOSX__
    (void) ::umask(S_IWGRP|S_IWOTH); // make sure files are opened with default of owner -rw-r-r-
#endif

    //This function starts, runs, and shuts down the server
    if (::StartServer(&theXMLParser, &theMessagesSource, thePort, statsUpdateInterval, theInitialState, dontFork, debugLevel, debugOptions) != qtssFatalErrorState)
    {    ::RunServer();
         CleanPid(false);
         exit (EXIT_SUCCESS);
    }
    else
    	exit(-1); //Cant start server don't try again
}
Пример #5
0
//启动服务
QTSS_ServerState StartServer(XMLPrefsParser* inPrefsSource, PrefsSource* inMessagesSource, UInt16 inPortOverride, int statsUpdateInterval, QTSS_ServerState inInitialState, Bool16 inDontFork, UInt32 debugLevel, UInt32 debugOptions)
{
    //Mark when we are done starting up. If auto-restart is enabled, we want to make sure
    //to always exit with a status of 0 if we encountered a problem WHILE STARTING UP. This
    //will prevent infinite-auto-restart-loop type problems
    Bool16 doneStartingUp = false;
    QTSS_ServerState theServerState = qtssStartingUpState;
    
	//服务单元状态更新间隔
    sStatusUpdateInterval = statsUpdateInterval;
    
    //Initialize utility classes
    OS::Initialize();
    OSThread::Initialize();
	
	//建立网络事件(R/W/E事件)线程,仅建立,But未启动
    Socket::Initialize();
	//获取系统网卡数量sNumIPAddrs及对应的具体ip,存储在sIPAddrInfoArray结构体数组中
    SocketUtils::Initialize(!inDontFork);
/*
#if !MACOSXEVENTQUEUE
    ::select_startevents();//initialize the select() implementation of the event queue
#endif
*/
    #if !MACOSXEVENTQUEUE
#ifndef __Win32__    
    ::epollInit();
#else
    ::select_startevents();//initialize the select() implementation of the event queue        
#endif

#endif
	//初始化系统属性字典
    QTSSDictionaryMap::Initialize();
	//初始化Server对象属性字典,包括其他具有属性字典的类,都要先进行Initialize
    QTSServerInterface::Initialize();//此部分必须在QTSServer对象构造前调用
	sServer = NEW QTSServer();
    sServer->SetDebugLevel(debugLevel);
    sServer->SetDebugOptions(debugOptions);
    
    //重新解析xml配置
    inPrefsSource->Parse();

	//准备开启监听,接收并处理相关事务
    Bool16 createListeners = true;
    if (qtssShuttingDownState == inInitialState) 
		createListeners = false;
    
	//初始化服务实例
    sServer->Initialize(inPrefsSource, inMessagesSource, inPortOverride, createListeners);

    if (inInitialState == qtssShuttingDownState)
    {  
        sServer->InitModules(inInitialState);
        return inInitialState;
    }

    if (sServer->GetServerState() != qtssFatalErrorState)
    {
        UInt32 numShortTaskThreads = 0;
        UInt32 numBlockingThreads = 0;
        UInt32 numThreads = 0;
        UInt32 numProcessors = 0;
        
        if (OS::ThreadSafe())
        {
			//工作线程
            numShortTaskThreads = sServer->GetPrefs()->GetNumThreads(); // whatever the prefs say
            if (numShortTaskThreads == 0) {
               numProcessors = OS::GetNumProcessors();
                // 1 worker thread per processor, up to 2 threads.
                // Note:Limiting the number of worker threads to 2 on a MacOS X system with > 2 cores
                //		results in better performance on those systems, as of MacOS X 10.5.  Future
                //		improvements should make this limit unnecessary.
                if (numProcessors > 2)
                    numShortTaskThreads = 2;
                else
                    numShortTaskThreads = numProcessors;
            }

			//协议处理线程
            numBlockingThreads = sServer->GetPrefs()->GetNumBlockingThreads(); // whatever the prefs say
            if (numBlockingThreads == 0)
                numBlockingThreads = 1;
                
        }
        if (numShortTaskThreads == 0)
            numShortTaskThreads = 1;

        if (numBlockingThreads == 0)
            numBlockingThreads = 1;

        numThreads = numShortTaskThreads + numBlockingThreads;
        //qtss_printf("Add threads shortask=%lu blocking=%lu\n",numShortTaskThreads, numBlockingThreads);
        TaskThreadPool::SetNumShortTaskThreads(numShortTaskThreads);
        TaskThreadPool::SetNumBlockingTaskThreads(numBlockingThreads);
        TaskThreadPool::AddThreads(numThreads);
		sServer->InitNumThreads(numThreads);
		
    #if DEBUG
        qtss_printf("Number of task threads: %" _U32BITARG_ "\n",numThreads);
    #endif
    
        // Start up the server's global tasks, and start listening
		//超时事件处理线程
        TimeoutTask::Initialize();  // The TimeoutTask mechanism is task based,
                                    // we therefore must do this after adding task threads
                                    // this be done before starting the sockets and server tasks
     }

    //Make sure to do this stuff last. Because these are all the threads that
    //do work in the server, this ensures that no work can go on while the server
    //is in the process of staring up
    if (sServer->GetServerState() != qtssFatalErrorState)
    {
		//Idle事务处理线程
        IdleTask::Initialize();
        Socket::StartThread();
        OSThread::Sleep(1000);
        
        //
        // On Win32, in order to call modwatch the Socket EventQueue thread must be
        // created first. Modules call modwatch from their initializer, and we don't
        // want to prevent them from doing that, so module initialization is separated
        // out from other initialization, and we start the Socket EventQueue thread first.
        // The server is still prevented from doing anything as of yet, because there
        // aren't any TaskThreads yet.
        sServer->InitModules(inInitialState);
        sServer->StartTasks();
        theServerState = sServer->GetServerState();
    }

    if (theServerState != qtssFatalErrorState)
    {
        CleanPid(true);
        WritePid(!inDontFork);
        doneStartingUp = true;

		//Log 
		char msgStr[128];
		qtss_snprintf(msgStr, sizeof(msgStr), "EasyCMS Service done starting up");
		QTSServerInterface::LogError(qtssMessageVerbosity, msgStr);

        OSMemory::SetMemoryError(ENOMEM);
    }

    //// SWITCH TO RUN USER AND GROUP ID
    //if (!sServer->SwitchPersonality())
    //    theServerState = qtssFatalErrorState;

    // Tell the caller whether the server started up or not
    return theServerState;
}
Пример #6
0
void RunServer()
{   
    Bool16 restartServer = false;
    UInt32 loopCount = 0;
    UInt32 debugLevel = 0;
    Bool16 printHeader = false;
    Bool16 printStatus = false;

	UInt32 num=0;//add
    //just wait until someone stops the server or a fatal error occurs.
    QTSS_ServerState theServerState = sServer->GetServerState();
    while ((theServerState != qtssShuttingDownState) &&
            (theServerState != qtssFatalErrorState))
    {
#ifdef __sgi__
        OSThread::Sleep(999);
#else
        OSThread::Sleep(1000);
#endif
		//add,redis,定时保活
		num++;
		if(num%5==0)
		{
			num=0;
			UInt32 numModules = QTSServerInterface::GetNumModulesInRole(QTSSModule::kRedisTTLRole);
			for ( UInt32 currentModule=0;currentModule < numModules; currentModule++)
			{
				QTSSModule* theModule = QTSServerInterface::GetModule(QTSSModule::kRedisTTLRole, currentModule);
				(void)theModule->CallDispatch(Easy_RedisTTL_Role, NULL);
			}
		}
		//
        LogStatus(theServerState);

        if (sStatusUpdateInterval)
        {
            debugLevel = sServer->GetDebugLevel();             
            printHeader = PrintHeader(loopCount);
            printStatus = PrintLine(loopCount);
                
            if (printStatus)
            {
                if  (DebugOn(sServer) ) // debug level display or logging is on
                    DebugStatus(debugLevel, printHeader);
                
                if (!DebugDisplayOn(sServer))
                    PrintStatus(printHeader); // default status output
            }
            
            
            loopCount++;

        }
        
        if ((sServer->SigIntSet()) || (sServer->SigTermSet()))
        {
            //
            // start the shutdown process
            theServerState = qtssShuttingDownState;
            (void)QTSS_SetValue(QTSServerInterface::GetServer(), qtssSvrState, 0, &theServerState, sizeof(theServerState));

            if (sServer->SigIntSet())
                restartServer = true;
        }
    }
        
    //Now, make sure that the server can't do any work
    TaskThreadPool::RemoveThreads();
    
    //now that the server is definitely stopped, it is safe to initate
    //the shutdown process
    delete sServer;
    
    CleanPid(false);
    //ok, we're ready to exit. If we're quitting because of some fatal error
    //while running the server, make sure to let the parent process know by
    //exiting with a nonzero status. Otherwise, exit with a 0 status
    if (theServerState == qtssFatalErrorState || restartServer)
        ::exit (-2);//-2 signals parent process to restart server
}