实际工作中,会遇到各种不同的应用程序开发需求,每个应用程序都有很多公共的功能,比如日志操作、配置文件管理、数据库操作、Socket编程等等,每次准备开发一个应用程序的时候如果这些功能都已经整合好,无疑是非常美好的事情;开发人员可以更多的关注业务部分的实现;
近期研究了Poco C++ Library的Poco::Util::Application的实现,其设计方案已经初步实现了上述思想;本篇将系统的整合之前独立的文章和实现类,初步实现上述思想;
本篇的代码带有浓厚的个人使用习惯的色彩,在通用性方面还未投入更多的精力,希望看到该篇文章的coder们交流指导;
对于那些已经独立撰写的文章,这里只提供链接,请各位耐心调阅;
开发环境搭建篇:
1、搭建Oracle 10g Proc+VS2008开发环境:http://blog.csdn.net/ishow99/archive/2009/12/02/4922148.aspx
2、搭建POCO-1.3.6-all+VS2008开发环境:http://blog.csdn.net/ishow99/archive/2009/12/02/4921739.aspx
3、搭建ACE-5.7.4+VS2008开发环境:http://blog.csdn.net/ishow99/archive/2009/11/19/4835161.aspx
功能实现类:
1、常用函数封装:http://blog.csdn.net/ishow99/archive/2010/09/30/5915723.aspx
2、ACE读取配置文件二次封装:http://blog.csdn.net/ishow99/archive/2010/07/09/5723677.aspx
3、ACE实现的轻量级日志系统:http://blog.csdn.net/ishow99/archive/2009/06/13/4266099.aspx
4、ACE实现FTP客户端:http://blog.csdn.net/ishow99/archive/2009/08/12/4439169.aspx
5、PROC++框架:http://blog.csdn.net/ishow99/archive/2009/06/15/4270299.aspx
app_main.h
#ifndef _Application_Main_
#define _Application_Main_
#include <memory>
#include <signal.h>
#include <ace/OS.h>
#include <ace/Reactor.h>
#include <ace/Event_Handler.h>
#include <ace/Thread_Manager.h>
#include <ace/Time_Value.h>
#include "ffcs_common.h"
#include "ffcs_logger.h"
#include "ffcs_config.h"
#include "ffcs_db_proc.h"
#define CONFIG_FILE ACE_TEXT("../config/config.cfg")
class Application : public ACE_Event_Handler
{
public:
Application(Logger& _logger, ConfigUpdate& _config) : active_(false), logger_(_logger), config_(_config)
{
/*ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Application start/n")));*/
}
virtual ~Application()
{
/*ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Application stop/n")));*/
}
/************************************************************************/
virtual int usage(int argc, char* argv[])
{
/*TODO 实现该方法,执行命令行操作*/
return 0;
}
virtual void init()
{
/*TODO 实现该方法,执行程序初始化工作*/
return this->initialize();
}
virtual int run()
{
/*TODO 实现该方法,执行主程序逻辑*/
return this->app_main();
}
virtual void exit()
{
/*TODO 实现该方法,执行程序退出资源回收工作*/
return this->uninitialize();
}
/************************************************************************/
Logger& logger()
{
return logger_;
}
ConfigUpdate& config()
{
return config_;
}
protected:
virtual int handle_timeout(const ACE_Time_Value &_current_time, const void *act = 0)
{
return 0;
}
virtual int handle_signal(int _signum, siginfo_t * = 0, ucontext_t * = 0)
{
this->active_ = false;
this->logger().warn("Receive system signal: %d/n", _signum);
ACE_Reactor::instance ()->end_reactor_event_loop();
return 0;
}
bool active_;
private:
void initialize()
{
/*设置事件处理能力*//*一次handle_events()调用中处理的notify()最大数目*/
ACE_Reactor::instance()->max_notify_iterations(100);
/*注册信号*/
ACE_Reactor::instance()->register_handler (SIGINT, this);
ACE_Reactor::instance()->register_handler (SIGQUIT, this);
ACE_Reactor::instance()->register_handler (SIGABRT, this);
ACE_Reactor::instance()->register_handler (SIGTERM, this);
ACE_Reactor::instance()->register_handler (SIGSEGV, this);
/*启动*/
this->active_ = true;
/*初始化日志系统*/
this->logger().load_config(CONFIG_FILE);
this->logger().open_logger();
/*初始化配置系统*/
this->config().open_config();
/*初始化数据库系统*/
DB_CONNECT::multi_thread();
}
void uninitialize()
{
ACE_Time_Value timeout(3, 0);
/*停止*/
this->active_ = false;
/*关闭配置系统*/
this->config().close_config();
/*关闭日志系统*/
this->logger().close_logger();
/*关闭所有线程*/
ACE_Thread_Manager::instance()->cancel_all();
ACE_Thread_Manager::instance()->wait(&timeout);
ACE_Reactor::instance()->close();
}
int app_main()
{
if (this->active_ == true)
{
ACE_Reactor::instance()->run_reactor_event_loop();
}
return RT_OK;
}
private:
Logger& logger_;
ConfigUpdate& config_;
};
#define FFCS_APP_MAIN(App) /
Logger g_logger; /
ConfigUpdate g_configupdate; /
int ACE_TMAIN(int argc, ACE_TCHAR* argv[]) /
{ /
std::auto_ptr<App> pApp(new App(g_logger, g_configupdate)); /
if (pApp->usage(argc, argv) != 0) return RT_OK; /
try /
{ /
pApp->init(argc, argv); /
pApp->run(); /
} /
catch (std::exception& exc) /
{ /
pApp->logger().error("std::exception:%s/n", exc.what()); /
} /
catch (...) /
{ /
pApp->logger().error("system exception/n"); /
} /
pApp->exit(); /
return RT_OK; /
}
#endif
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <ace/OS.h>
#include <ace/Reactor.h>
#include <ace/Time_Value.h>
#include <ace/Event_Handler.h>
#include <ace/Thread_Manager.h>
#include <ace/Get_Opt.h>
#include <Poco/Timespan.h>
#include <Poco/DateTime.h>
#include <Poco/LocalDateTime.h>
#include <Poco/DateTimeFormatter.h>
#include "ffcs_common.h"
#include "ffcs_logger.h"
#include "ffcs_config.h"
#include "ffcs_db_proc.h"
#include "app_main.h"
class App1: public Application
{
public:
App1(Logger& _logger, ConfigUpdate& _config) : Application(_logger, _config)
{
}
virtual ~App1()
{
}
public:
/*初始化*/
void init(int argc, ACE_TCHAR* argv[])
{
ACE_Time_Value tvDelay(3, 0), tvInterval;
Application::init();
/*参数配置*/
ConfigParameter <int> p_logger_1(CONFIG_FILE, "LOGGER", "LOGMEDIA", FFCS_LOGMEDIA_ALL, this->logger().media_);
ConfigParameter <int> p_logger_2(CONFIG_FILE, "LOGGER", "LOGLEVEL", FFCS_LOGLEVEL_MESSAGE, this->logger().level_);
ConfigParameter <int> p_logger_3(CONFIG_FILE, "LOGGER", "LOGCLEANER", FFCS_LOGCLEANER_OPEN, this->logger().cleaner_switch_);
ConfigParameter <int> p_logger_4(CONFIG_FILE, "LOGGER", "LOGSAVEDMONTH", DEFAULT_SAVED_MONTH, this->logger().saved_month_);
ConfigParameter <int> p_system_1(CONFIG_FILE, "SYSTEM", "SYS_INTERVAL", 15, this->g_iInterval);
ConfigParameter <int> p_system_2(CONFIG_FILE, "SYSTEM", "SYS_NOTIFY_ITERATIONS", 10, this->g_iNotifyIterations);
ConfigParameter<std::string> p_database_1(CONFIG_FILE, "DATABASE", "CONNSTR_0", "NULL", this->g_dbString);
ConfigParameter<std::string> p_database_2(CONFIG_FILE, "DATABASE", "LINKNAME_0", "NULL", this->g_dbName);
this->config().add(p_logger_1);
this->config().add(p_logger_2);
this->config().add(p_logger_3);
this->config().add(p_logger_4);
this->config().add(p_system_1);
this->config().add(p_system_2);
this->config().add(p_database_1);
this->config().add(p_database_2);
/*this->config().dump();*/
/*设置事件处理能力*//*一次handle_events()调用中处理的notify()最大数目*/
ACE_Reactor::instance()->max_notify_iterations(this->g_iNotifyIterations);
/*任务调度*/
tvInterval.sec(this->g_iInterval);
ACE_Reactor::instance()->schedule_timer(this, NULL, tvDelay, tvInterval);
return;
}
/*执行*/
int run()
{
/*
DB_CONNECT conn(svc_dbstring, svc_dbname);
conn.start();
if (conn.connect() == RT_OK)
{
conn.DML_DEMO_1();
conn.DML_DEMO_2(1);
conn.DML_DEMO_2(2);
conn.DML_DEMO_2(3);
conn.DML_DEMO_2(3);
conn.DML_DEMO_2(3);
conn.DML_DEMO_2(4);
conn.DML_DEMO_2(5);
conn.DML_DEMO_3(1);
conn.DML_DEMO_3(3);
}
conn.disconnect();
conn.stop();
*/
ACE_Time_Value tv(0, 100*1000);
struct timespec rqt;
rqt.tv_sec = 0;
rqt.tv_nsec = 100*1000*1000;
while (this->active_ == true)
{
if (ACE_Reactor::instance()->handle_events(tv) == -1) break;
ACE_OS::nanosleep(&rqt);
}
return 0;
/*return Application::run();*/
}
/*退出*/
void exit()
{
return Application::exit();
}
/*参数处理,0:程序继续执行,1:程序中断退出*/
int usage(int argc, char* argv[])
{
int c;
ACE_Get_Opt get_opt(argc, argv, "hv");
while ((c = get_opt ()) != EOF)
{
switch (c)
{
case 'v':
{
Util::fun_copyright();
}
return 1;
case 'h':
default:
{
ACE_OS::printf("/n/n");
ACE_OS::printf("Usage: ./app_main_ace [OPTIONS] /n");
ACE_OS::printf(" -h display this usage message/n");
ACE_OS::printf(" -v display version/n");
ACE_OS::printf("/n/n");
}
return 1;
}
}
return 0;
}
protected:
/*定时任务*/
int handle_timeout(const ACE_Time_Value &_current_time, const void *act = 0)
{
Poco::LocalDateTime ldt_now;
this->logger().debug("心跳正常,程序还活着! 下次看到心跳预计时间:[%s]/n/n", Poco::DateTimeFormatter::format(ldt_now+Poco::Timespan(this->g_iInterval, 0), "%Y-%m-%d %H:%M:%S").c_str());
return 0;
}
private:
int g_iInterval;
int g_iNotifyIterations;
std::string g_dbString, g_dbName;
};
FFCS_APP_MAIN(App1);