OpenRTMFP/Cumulus Primer(6)CumulusServer启动流程分析(续2)
- 作者:柳大·Poechant(钟超)
- 博客:Blog.CSDN.net/Poechant
- 邮箱:zhongchao.ustc#gmail.com (# -> @)
- 日期:April 14th, 2012
1 main.cpp 中的main()
函数中的server
main.cpp 中真正启动的是server
,它继承自Cumulus::RTMFPServer
,而Cumulus::RTMFPServer
又继承自Cumulus::Startable
、Cumulus::Gateway
、Cumulus::Handler
。而Cumulus::Startable
继承自Poco::Runnable
,所以其是一个可以运行的线程。在OpenRTMFP/CumulusServer
中,这是主线程。
Server server(config().getString("application.dir", "./"), *this, config());
server.start(params);
这是CumulusServer/Server.h
中定义的,其构造函数的原型为:
Server(const std::string& root,
ApplicationKiller& applicationKiller,
const Poco::Util::AbstractConfiguration& configurations);
个参数含义如下:
- The Path Root for the Server Application
- Killer for Termanting the Server Application
- Server Configuration
距离来说,在我的 Worksapce 中:
-
root
是/Users/michael/Development/workspace/eclipse/OpenRTMFP-Cumulus/Debug/
构造函数的初始化列表极长:
Server::Server(const std::string& root,
ApplicationKiller& applicationKiller,
const Util::AbstractConfiguration& configurations)
: _blacklist(root + "blacklist", *this),
_applicationKiller(applicationKiller),
_hasOnRealTime(true),
_pService(NULL),
luaMail(_pState=Script::CreateState(),
configurations.getString("smtp.host","localhost"),
configurations.getInt("smtp.port",SMTPSession::SMTP_PORT),
configurations.getInt("smtp.timeout",60)) {
下面调用Poco::File
创建目录:
File((string&)WWWPath = root + "www").createDirectory();
因为roor
是/Users/michael/Development/workspace/eclipse/OpenRTMFP-Cumulus/Debug/
目录,所以WWWPath
就是/Users/michael/Development/workspace/eclipse/OpenRTMFP-Cumulus/Debug/www
目录。然后初始化GlobalTable
,这个GlobalTable
是和 Lua 有关的东东,这里暂不细说,先知道与 Lua 相关就好。
Service::InitGlobalTable(_pState);
下面就涉及到了 Lua script 了:
SCRIPT_BEGIN(_pState)
SCRIPT_CREATE_PERSISTENT_OBJECT(Invoker,LUAInvoker,*this)
readNextConfig(_pState,configurations,"");
lua_setglobal(_pState,"cumulus.configs");
SCRIPT_END
}
其中SCRIPT_BEGIN
、SCRIPT_CREATE_PERSISTENT_OBJECT
和SCRIPT_END
都是宏,其定义在Script.h
文件中,如下:
#define SCRIPT_BEGIN(STATE) \
if (lua_State* __pState = STATE) { \
const char* __error=NULL;
#define SCRIPT_CREATE_PERSISTENT_OBJECT(TYPE,LUATYPE,OBJ) \
Script::WritePersistentObject(__pState,OBJ); \
lua_pop(__pState,1);
#define SCRIPT_END }
SCRIPT_BEGIN
和SCRIPT_END
经常用到,当与 Lua 相关的操作出现时,都会以这两个宏作为开头和结尾。
2 main.cpp 中main()
函数的server.start()
void RTMFPServer::start(RTMFPServerParams& params) {
如果OpenRTMFP/CumulusServer
正在运行,则返回并终止启动。
if(running()) {
ERROR("RTMFPServer server is yet running, call stop method before");
return;
}
设定端口号,如果端口号为 0,则返回并终止启动。
_port = params.port;
if (_port == 0) {
ERROR("RTMFPServer port must have a positive value");
return;
}
设定OpenRTMFP/CumulusEdge
的端口号,如果其端口号与OpenRTMFP/CumulusSever
端口号相同,则返回并终止启动:
_edgesPort = params.edgesPort;
if(_port == _edgesPort) {
ERROR("RTMFPServer port must different than RTMFPServer edges.port");
return;
}
Cirrus:
_freqManage = 2000000; // 2 sec by default
if(params.pCirrus) {
_pCirrus = new Target(*params.pCirrus);
_freqManage = 0; // no waiting, direct process in the middle case!
NOTE("RTMFPServer started in man-in-the-middle mode with server %s \
(unstable debug mode)", _pCirrus->address.toString().c_str());
}
middle:
_middle = params.middle;
if(_middle)
NOTE("RTMFPServer started in man-in-the-middle mode between peers \
(unstable debug mode)");
UDP Buffer:
(UInt32&)udpBufferSize =
params.udpBufferSize==0 ?
_socket.getReceiveBufferSize() : params.udpBufferSize;
_socket.setReceiveBufferSize(udpBufferSize);
_socket.setSendBufferSize(udpBufferSize);
_edgesSocket.setReceiveBufferSize(udpBufferSize);
_edgesSocket.setSendBufferSize(udpBufferSize);
DEBUG("Socket buffer receving/sending size = %u/%u",
udpBufferSize,
udpBufferSize);
(UInt32&)keepAliveServer =
params.keepAliveServer < 5 ? 5000 : params.keepAliveServer * 1000;
(UInt32&)keepAlivePeer =
params.keepAlivePeer < 5 ? 5000 : params.keepAlivePeer * 1000;
(UInt8&)edgesAttemptsBeforeFallback = params.edgesAttemptsBeforeFallback;
setPriority(params.threadPriority);
启动线程,进入循环运行:
Startable::start();
}
上句具体的源码实现为:
void Startable::start() {
if (running())
return;
如果在运行则返回并终止启动。然后加一个局部锁。
ScopedLock lock(_mutex);
如果不得不join()
到主线程中,那就join()
吧
if(_haveToJoin) {
_thread.join();
_haveToJoin=false;
}
然后就运行这个线程吧:
_terminate = false;
_thread.start(*this);
_haveToJoin = true;
}
-
转载请注明来自柳大的CSDN博客:Blog.CSDN.net/Poechant
-