SRS之SrsServer::cycle()

1. SrsServer 相关类定义

1.1 SrsServer 类定义

/**
 * SRS RTMP server, initialize and listen,
 * start connection service thread, destroy client.
 */
class SrsServer : virtual public ISrsReloadHandler 
    , virtual public ISrsSourceHandler
    , virtual public IConnectionManager
{
private:
#ifdef SRS_AUTO_HTTP_API
    // TODO: FIXME: rename to http_api
    SrsHttpServeMux* http_api_mux;
#endif
#ifdef SRS_AUTO_HTTP_SERVER
    SrsHttpServer* http_server;
#endif
#ifdef SRS_AUTO_HTTP_CORE
    SrsHttpHeartbeat* http_heartbeat;
#endif
#ifdef SRS_AUTO_INGEST
    SrsIngester* ingester;
#endif
private:
    /**
     * the pid file fd, lock the file write when server is running.
     * @remark the init.d script should cleanup the pid file, when stop service,
     *         for the server never delete the file; when system startup, the pid
     *         in pid file maybe valid but the process is not SRS, the init.d script 
     *         will never start server.
     */
    int pid_fd;
    /**
     * all connections, connection manager
     */
    std::vector<SrsConnection*> conns;
    /**
     * all listeners, listener manager.
     */
    std::vector<SrsListener*> listeners;
    /**
     * signal manager which convert signal to io message.
     */
    SrsSignalManager* signal_manager;
    /**
     * handle in server cycle.
     */
    ISrsServerCycle* handler;
    /**
     * user send the signal, convert to variable.
     */
    bool signal_reload;
    bool signal_gmc_stop;
    bool signal_gracefully_quit;
    /* parent pid for asprocess. */
    int ppid;
public:
    SrsServer();
    virtual ~SrsServer();
private:
    /**
     * the destroy is for gmc to analysis the memory leak,
     * if not destroy global/static data, the gmc will will warning memory leak.
     * in service, server never destroy, directly exit when restart.
     */
    virtual void destroy();
    /**
     * when SIGTERM, SRS should do cleanup, for example,
     * to stop all ingesters, cleanup HLS and dvr.
     */
    virtual void dispose();
// server startup workflow, @see run_master()
public:
    /**
     * initialize server with callback handler.
     * @remark user must free the cycle handler.
     */
    virtual int initialize(ISrsServerCycle* cycle_handler);
    virtual int initialize_st();
    virtual int initialize_signal();
    virtual int acquire_pid_file();
    virtual int listen();
    virtual int register_signal();
    virtual int http_handle();
    virtual int ingest();
    virtual int cycle();
// IConnectionManager
public:
    /**
     * callback for connection to remove itself.
     * when connection thread cycle terminatedk, callback this to delete connection.
     * @see SrsConnection.on_thread_stop().
     */
    virtual void remove(SrsConnection* conn);
// server utilities.
public:
    /**
     * callback for signal manager got a signal.
     * the signal manager convert signal to io message,
     * whatever, we will got the signo like the orignal signal(int signo) handler.
     * @remark, directly exit for SIGTERM.
     * @remark, do reload for SIGNAL_RELOAD.
     * @remark, for SIGINT and SIGUSR2:
     *       no gmc, directly exit.
     *       for gmc, set the variable signal_gmc_stop, the cycle will return 
     *       and cleanup for gmc.
     */
    virtual void on_signal(int signo);
private:
    /**
     * the server thread main cycle,
     * update the global static data, for instance, the current time,
     * the cpu/mem/network statistic.
     */
    virtual int do_cycle();
    /**
     * listen at specified protocol.
     */
    virtual int listen_rtmp();
    virtual int listen_http_api();
    virtual int listen_http_stream();
    virtual int listen_stream_caster();
    /**
     * close the listeners for specified type,
     * remove the listen object from manager.
     */
    virtual void close_listeners(SrsListenerType type);
    /**
     * resample the server kbs.
     */
    virtual void resample_kbps();
// internal only
public:
    /**
     * when listener got a fd, notice server to accept it.
     * @param type, the client type, used to create concreate connection,
     *        for instance RTMP connection to server client.
     * @param client_stfd, the client fd in st boxed, the underlayer fd.
     */
    virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
// interface ISrsReloadHandler.
public:
    virtual int on_reload_listen();
    virtual int on_reload_pid();
    virtual int on_reload_vhost_added(std::string vhost);
    virtual int on_reload_vhost_removed(std::string vhost);
    virtual int on_reload_http_api_enabled();
    virtual int on_reload_http_api_disabled();
    virtual int on_reload_http_stream_enabled();
    virtual int on_reload_http_stream_disabled();
    virtual int on_reload_http_stream_updated();
// interface ISrsSourceHandler
public:
    virtual int on_publish(SrsSource* s, SrsRequest* r);
    virtual void on_unpublish(SrsSource* s, SrsRequest* r);
};

1.2 ISrsReloadHandler 类定义

/**
 * the handler for config reload.
 * when reload callback, the config is updated yet.
 * 
 * features not support reload, 
 * @see: https://github.com/ossrs/srs/wiki/v1_CN_Reload#notsupportedfeatures
 */
class ISrsReloadHandler
{
public:
    ISrsReloadHandler();
    virtual ~ISrsReloadHandler();
public:
    virtual int on_reload_utc_time();
    virtual int on_reload_max_conns();
    virtual int on_reload_listen();
    virtual int on_reload_pid();
    virtual int on_reload_log_tank();
    virtual int on_reload_log_level();
    virtual int on_reload_log_file();
    virtual int on_reload_pithy_print();
    virtual int on_reload_http_api_enabled();
    virtual int on_reload_http_api_disabled();
    virtual int on_reload_http_stream_enabled();
    virtual int on_reload_http_stream_disabled();
    virtual int on_reload_http_stream_updated();
public:
    // TODO: FIXME: should rename to http_static
    virtual int on_reload_vhost_http_updated();
    virtual int on_reload_vhost_http_remux_updated(std::string vhost);
    virtual int on_reload_vhost_added(std::string vhost);
    virtual int on_reload_vhost_removed(std::string vhost);
    virtual int on_reload_vhost_atc(std::string vhost);
    virtual int on_reload_vhost_gop_cache(std::string vhost);
    virtual int on_reload_vhost_queue_length(std::string vhost);
    virtual int on_reload_vhost_time_jitter(std::string vhost);
    virtual int on_reload_vhost_mix_correct(std::string vhost);
    virtual int on_reload_vhost_forward(std::string vhost);
    virtual int on_reload_vhost_hls(std::string vhost);
    virtual int on_reload_vhost_hds(std::string vhost);
    virtual int on_reload_vhost_dvr(std::string vhost);
    virtual int on_reload_vhost_mr(std::string vhost);
    virtual int on_reload_vhost_mw(std::string vhost);
    virtual int on_reload_vhost_smi(std::string vhost);
    virtual int on_reload_vhost_tcp_nodelay(std::string vhost);
    virtual int on_reload_vhost_realtime(std::string vhost);
    virtual int on_reload_vhost_p1stpt(std::string vhost);
    virtual int on_reload_vhost_pnt(std::string vhost);
    virtual int on_reload_vhost_chunk_size(std::string vhost);
    virtual int on_reload_vhost_transcode(std::string vhost);
    virtual int on_reload_ingest_removed(std::string vhost, std::string ingest_id);
    virtual int on_reload_ingest_added(std::string vhost, std::string ingest_id);
    virtual int on_reload_ingest_updated(std::string vhost, std::string ingest_id);
    virtual int on_reload_user_info();
};

1.3 ISrsSourceHandler 类定义

/**
 * the handler to handle the event of srs source.
 * for example, the http flv streaming module handle the event and 
 * mount http when rtmp start publishing.
 */
class ISrsSourceHandler
{
public:
    ISrsSourceHandler();
    virtual ~ISrsSourceHandler();
public:
    /**
    * when stream start publish, mount stream.
    */
    virtual int on_publish(SrsSource* s, SrsRequest* r) = 0;
    /**
    * when stream stop publish, unmount stream.
    */
    virtual void on_unpublish(SrsSource* s, SrsRequest* r) = 0;
};

1.4 IConnectionManager

/**
 * the manager for connection.
 */
class IConnectionManager
{
public:
    IConnectionManager();
    virtual ~IConnectionManager();
public:
    /**
     * remove the specified connection.
     */
    virtual void remove(SrsConnection* c) = 0;
};
SrsServer 和 ISrsReloadHandler、ISrsSourceHandler 以及 IConnectionManager 之间的关系(继承)

2. int SrsServer::cycle

位于 srs_app_server.cpp:

int SrsServer::cycle()
{
    int ret = ERROR_SUCCESS;
    
    /* 开始进入 SRS 的主循环 */
    ret = do_cycle();
    
#ifdef SRS_AUTO_GPERF_MC
    destroy();
    
    // remark, for gmc, never invoke the exit().
    srs_warn("sleep a long time for system st-threads to cleanup.");
    st_usleep(3 * 1000 * 1000);
    srs_warn("system quit");
#else
    // normally quit with neccessary cleanup by dispost().
    srs_warn("main cycle terminated, system quit normally.");
    dispose();
    srs_trace("srs terminated");
    
    // for valgrind to detect.
    srs_freep(_srs_config);
    srs_freep(_srs_log);
    
    exit(0);
#endif

    return ret;
}

2.1 SrsServer::do_cycle

int SrsServer::do_cycle()
{
    int ret = ERROR_SUCCESS;
    
    // find the max loop
    int max = srs_max(0, SRS_SYS_TIME_RESOLUTION_MS_TIMES);

#ifdef SRS_AUTO_STAT
    max = srs_max(max, SRS_SYS_RUSAGE_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_CPU_STAT_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_DISK_STAT_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_MEMINFO_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES);
#endif
    
    // for asprocess.
    bool asprocess = _srs_config->get_asprocess();
    
    // the daemon thread, update the time cache
    while (true) {
        /* 这里 handler 初始化为 NULL,所以忽略 */
        if (handler && (ret = handler->on_cycle((int)conns.size())) != ERROR_SUCCESS) {
            srs_error("cycle handle failed. ret=%d", ret);
            return ret;
        }
        
        // the interval in config.
        int heartbeat_max_resolution = (int)(_srs_config->get_heartbeat_interval() \
                                       / SRS_SYS_CYCLE_INTERVAL);
        
        // dynamic fetch the max.
        int temp_max = max;
        temp_max = srs_max(temp_max, heartbeat_max_resolution);
        
        for (int i = 0; i < temp_max; i++) {
            /* 主线程进入休眠,调度其他线程运行,比如调度 conn 线程,接收
             * 客户端的连接 */
            st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000);
            
            // asprocess check.
            if (asprocess && ::getppid() != ppid) {
                srs_warn("asprocess ppid changed from %d to %d", ppid, ::getppid());
                return ret;
            }
            
            // gracefully quit for SIGINT or SIGTERM.
            if (signal_gracefully_quit) {
                srs_trace("cleanup for gracefully terminate");
                return ret;
            }
            
            // for gperf heap checker,
            // @see: research/gperftools/heap-checker/heap_checker.cc
            // if user interrupt the program, exit to check mem leak.
            // but, if gperf, use reload to ensure main return normally,
            // because directly exit will cause core-dump.
#ifdef SRS_AUTO_GPERF_MC
            if (signal_gmc_stop) {
                srs_warn("gmc got singal to stop server.");
                return ret;
            }
#endif      
            
            // do reload the config.
            if (signal_reload) {
                signal_reload = false;
                srs_info("get signal reload, to reload the config.");
                
                if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
                    srs_error("reload config failed. ret=%d", ret);
                    return ret;
                }
                srs_trace("reload config success.");
            }
            
            // notice the stream sources to cycle.
            if ((ret = SrsSource::cycle_all()) != ERROR_SUCCESS) {
                return ret;
            }
            
            // update the cache time
            if ((i % SRS_SYS_TIME_RESOLUTION_MS_TIMES) == 0) {
                srs_info("update current time cache.");
                srs_update_system_time_ms();
            }
            
#ifdef SRS_AUTO_STAT
            if ((i % SRS_SYS_RUSAGE_RESOLUTION_TIMES) == 0) {
                srs_info("update resource info, rss.");
                srs_update_system_rusage();
            }
            if ((i % SRS_SYS_CPU_STAT_RESOLUTION_TIMES) == 0) {
                srs_info("update cpu info, cpu usage.");
                srs_update_proc_stat();
            }
            if ((i % SRS_SYS_DISK_STAT_RESOLUTION_TIMES) == 0) {
                srs_info("update disk info, disk iops.");
                srs_update_disk_stat();
            }
            if ((i % SRS_SYS_MEMINFO_RESOLUTION_TIMES) == 0) {
                srs_info("update memory info, usage/free.");
                srs_update_meminfo();
            }
            if ((i % SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES) == 0) {
                srs_info("update platform info, uptime/load.");
                srs_update_platform_info();
            }
            if ((i % SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES) == 0) {
                srs_info("update network devices info.");
                srs_update_network_devices();
            }
            if ((i % SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES) == 0) {
                srs_info("update network server kbps info.");
                resample_kbps();
            }
    #ifdef SRS_AUTO_HTTP_CORE
            if (_srs_config->get_heartbeat_enabled()) {
                if ((i % heartbeat_max_resolution) == 0) {
                    srs_info("do http heartbeat, for internal server to report.");
                    http_heartbeat->heartbeat();
                }
            }
    #endif
#endif
            
            srs_info("server main thread loop");
        }
    }
}

在该函数中,该主线程循环进行休眠,以便调度其他线程运行。

posted @ 2018-05-18 15:16  季末的天堂  阅读(970)  评论(0编辑  收藏  举报