OpenRTMFP/Cumulus Primer(5)CumulusServer启动流程分析(续1)
2012-09-29 17:32
716 查看
作者:柳大·Poechant(钟超)
博客:Blog.CSDN.net/Poechant
邮箱:zhongchao.ustc#gmail.com (# -> @)
日期:April 14th, 2012
ServerApplication 对其子类有如下要求:
Subsystems must be registered in the constructor.
All non-trivial initializations must be made in the initialize() method.
At the end of the main() method, waitForTerminationRequest() should be called.
Application 对其子类的要求是,如下这些成员函数必须被覆盖:
initialize() (the one-argument, protected variant):上一篇已介绍过。
uninitialize():下面会介绍,Application 的 run() 函数会在调用 main() 函数后调用 uninitialize() 函数。
reinitialize()
defineOptions():定义命令行启动选项。
handleOption():响应相应的命令行选项。
main():
设定日志级别(0 - 8,默认是 6,表示 info 级别)。
其他一些选项:
显示帮助信息的选项:
Sets whether the option is required (flag == true) or optional (flag == false).
Returns true if the option can be specified more than once, or false if at most once.
当需要显示帮助信息时,调用如下函数:
setCommand(): Sets the command name.
setUsage(): Sets the usage string.
setHeader(): Sets the header string.
format(): Writes the formatted help text to the given stream.
参数是选项名和选项值。
如果选项是帮助:
如果是
如果选项是
如果选项是
如果选项是
先加一个作用域锁,然后再向日志流写数据。
调用 manageLogFile,主要做一些日志大小超出限制的处理。
先判断是否超过日志文件的大小上线,
1 MB)。
打开新日志文件:
如果该文件已经存在,则先删除:
在
作用域锁:
如果是命令行交互模式(即不是 daemon 模式):
向日志流输出一句日志:
日志文件的善后处理(主要处理文件大小限制可能产生的问题):
-
转载请注明来自柳大的CSDN博客:Blog.CSDN.net/Poechant
-
博客:Blog.CSDN.net/Poechant
邮箱:zhongchao.ustc#gmail.com (# -> @)
日期:April 14th, 2012
1 CumulusServer 是 ServerApplication 的子类
ServerApplication 对其子类有如下要求:Subsystems must be registered in the constructor.
All non-trivial initializations must be made in the initialize() method.
At the end of the main() method, waitForTerminationRequest() should be called.
2 ServerApplication 是 Application 的子类
Application 对其子类的要求是,如下这些成员函数必须被覆盖:initialize() (the one-argument, protected variant):上一篇已介绍过。
uninitialize():下面会介绍,Application 的 run() 函数会在调用 main() 函数后调用 uninitialize() 函数。
reinitialize()
defineOptions():定义命令行启动选项。
handleOption():响应相应的命令行选项。
main():
3 反初始化
CumulusServer是继承
ServerApplication的,
ServerApplication是继承
Application的。
Application的
run()函数会先调用
initialize(),然后调用
main(),最后调用
uninitialize。最后这个反初始化过程,在
CumulusServer就是直接调用父类的
uninitialize函数。
void uninitialize() { ServerApplication::uninitialize(); }
4 命令行选项设定
CumulusServer的命令行选项有:
log(l)、
dump(d)、
cirrus(c)、
middle(m)、
help(h)。
void defineOptions(OptionSet& options) { ServerApplication::defineOptions(options);
设定日志级别(0 - 8,默认是 6,表示 info 级别)。
options.addOption( Option("log", "l", "Log level argument, must be beetween 0 and 8 : \ nothing, fatal, critic, error, warn, note, info, debug, trace. \ Default value is 6 (info), all logs until info level are displayed.") .required(false) .argument("level") .repeatable(false));
其他一些选项:
options.addOption( Option("dump", "d", "Enables packet traces in logs. Optional arguments \ are 'middle' or 'all' respectively to displays just middle packet \ process or all packet process. If no argument is given, just outside \ packet process will be dumped.",false,"middle|all",false) .repeatable(false)); options.addOption( Option("cirrus", "c", "Cirrus address to activate a 'man-in-the-middle' \ developer mode in bypassing flash packets to the official cirrus \ server of your choice, it's a instable mode to help Cumulus developers, \ \"p2p.rtmfp.net:10000\" for example. By adding the 'dump' argument, \ you will able to display Cirrus/Flash packet exchange in your logs \ (see 'dump' argument).",false,"address",true) .repeatable(false)); options.addOption( Option("middle", "m","Enables a 'man-in-the-middle' developer mode \ between two peers. It's a instable mode to help Cumulus developers. \ By adding the 'dump' argument, you will able to display Flash/Flash \ packet exchange in your logs (see 'dump' argument).") .repeatable(false));
显示帮助信息的选项:
options.addOption( Option("help", "h", "Displays help information about command-line usage.") .required(false) .repeatable(false)); }
OptionSet是
Poco::Util::OptionSet,调用
addOption可以向其中增加选项
Option。其中
required和
repeatable表示:
Sets whether the option is required (flag == true) or optional (flag == false).
Returns true if the option can be specified more than once, or false if at most once.
当需要显示帮助信息时,调用如下函数:
void displayHelp() { HelpFormatter helpFormatter(options()); helpFormatter.setCommand(commandName()); helpFormatter.setUsage("OPTIONS"); helpFormatter.setHeader("CumulusServer, open source RTMFP server"); helpFormatter.format(cout); }
setCommand(): Sets the command name.
setUsage(): Sets the usage string.
setHeader(): Sets the header string.
format(): Writes the formatted help text to the given stream.
5 处理命令行选项
参数是选项名和选项值。void handleOption(const std::string& name, const std::string& value) { ServerApplication::handleOption(name, value);
如果选项是帮助:
if (name == "help") _helpRequested = true;
如果是
cirrus,即该服务的 IP 和端口号,Poco::URI 中有协议名(Scheme)、IP 地址(Host)、端口号(Port)、查询串(Query)等等。
else if (name == "cirrus") { try { URI uri("rtmfp://"+value); _pCirrus = new SocketAddress(uri.getHost(),uri.getPort()); NOTE("Mode 'man in the middle' : the exchange will bypass to '%s'",value.c_str()); } catch(Exception& ex) { ERROR("Mode 'man in the middle' error : %s",ex.message().c_str()); }
如果选项是
dump日志:
} else if (name == "dump") { if(value == "all") Logs::SetDump(Logs::ALL); else if(value == "middle") Logs::SetDump(Logs::MIDDLE); else Logs::SetDump(Logs::EXTERNAL);
如果选项是
middle:
} else if (name == "middle") _middle = true;
如果选项是
log,表示设定日志级别:
else if (name == "log") Logs::SetLevel(atoi(value.c_str())); }
6 Dump logs
先加一个作用域锁,然后再向日志流写数据。void dumpHandler(const UInt8* data,UInt32 size) { ScopedLock<FastMutex> lock(_logMutex); cout.write((const char*)data, size); _logStream.write((const char*)data,size); manageLogFile(); }
调用 manageLogFile,主要做一些日志大小超出限制的处理。
void manageLogFile() {
先判断是否超过日志文件的大小上线,
LOG_SIZE是
1000000字节(即约
1 MB)。
if(_pLogFile->getSize() > LOG_SIZE) { _logStream.close(); int num = 10;
打开新日志文件:
File file(_logPath + "10");
如果该文件已经存在,则先删除:
if (file.exists()) file.remove(); while (--num >= 0) { file = _logPath + NumberFormatter::format(num); if (file.exists()) file.renameTo(_logPath + NumberFormatter::format(num + 1)); } _logStream.open(_pLogFile->path(), ios::in | ios::ate); } }
7 停止运行
CumulusServer继承了
ApplicationKiller,该类中有纯虚函数
kill()需要被实现,于是有:
void kill() { terminate(); }
ApplicationKiller的定义在
ApplicationKiller.h中,如下:
class ApplicationKiller { public: ApplicationKiller(){} virtual ~ApplicationKiller(){} virtual void kill()=0; };
8 载入配置
在initialize()函数中调用,上一篇已提到过。
void loadConfiguration(const string& path) { try { ServerApplication::loadConfiguration(path); } catch(...) { } }
9 处理日志
void logHandler(Thread::TID threadId, const std::string& threadName, Priority priority, const char *filePath, long line, const char *text) {
作用域锁:
ScopedLock<FastMutex> lock(_logMutex); Path path(filePath); string file; if (path.getExtension() == "lua") file += path.directory(path.depth()-1) + "/";
如果是命令行交互模式(即不是 daemon 模式):
if (_isInteractive) printf("%s %s[%ld] %s\n", g_logPriorities[priority - 1], (file + path.getBaseName()).c_str(), line, text);
向日志流输出一句日志:
_logStream << DateTimeFormatter::format(LocalDateTime(),"%d/%m %H:%M:%S.%c ") << g_logPriorities[priority-1] << '\t' << threadName << '(' << threadId << ")\t" << (file + path.getFileName()) << '[' << line << "] " << text << std::endl; _logStream.flush();
日志文件的善后处理(主要处理文件大小限制可能产生的问题):
manageLogFile(); }
-
转载请注明来自柳大的CSDN博客:Blog.CSDN.net/Poechant
-
相关文章推荐
- OpenRTMFP/Cumulus Primer(7)CumulusServer 启动流程分析(续3)
- OpenRTMFP/Cumulus Primer(6)CumulusServer启动流程分析(续2)
- OpenRTMFP/Cumulus Primer(4)CumulusServer启动流程分析
- OpenRTMFP/Cumulus Primer(7)CumulusServer启动流程分析(续3)
- OpenRTMFP/Cumulus Primer(5)CumulusServer启动流程分析(续1)
- OpenRTMFP/Cumulus Primer(4)CumulusServer启动流程分析
- OpenRTMFP/Cumulus Primer(6)CumulusServer启动流程分析(续2)
- OpenRTMFP/Cumulus Primer(22)线程逻辑分析之一:RTMFPServer线程的启动和等待
- OpenRTMFP/Cumulus Primer(8)CumulusServer主进程主循环分析
- OpenRTMFP/Cumulus Primer(23)线程逻辑分析之二:RTMFPManager对RTMFPServer的影响
- OpenRTMFP/Cumulus Primer(8)CumulusServer主进程主循环分析
- OpenRTMFP/Cumulus Primer(21)经由服务器的发布/订阅流程的关键点
- OpenRTMFP/Cumulus Primer(20)Cumulus的一个线程启动 Bug
- OpenRTMFP/Cumulus Primer(2)用Lua编写HelloWorld应用扩展CumulusServer
- OpenRTMFP/Cumulus Primer(2)用Lua编写HelloWorld应用扩展CumulusServer
- OpenRTMFP/Cumulus Primer(14)AMF解析之PacketReader/Writer
- SystemServer启动流程之WatchDog分析(四)
- netty5笔记-总体流程分析1-ServerBootstrap启动
- OpenRTMFP/Cumulus Primer(1)入门介绍与部署CumulusServer
- OpenRTMFP/Cumulus Primer(3)图解CumulusEdge原理