04562fc3afa06b798b95256108e71b0d38c59b8a
[fms.git] / src / fmsapp.cpp
1 #include "../include/fmsapp.h"\r
2 #include "../include/global.h"\r
3 #include "../include/dbsetup.h"\r
4 #include "../include/optionssetup.h"\r
5 #include "../include/option.h"\r
6 #include "../include/stringfunctions.h"\r
7 #include "../include/http/httpthread.h"\r
8 #include "../include/nntp/nntplistener.h"\r
9 #include "../include/dbmaintenancethread.h"\r
10 #include "../include/freenet/freenetmasterthread.h"\r
11 #include "../include/threadwrapper/threadedexecutor.h"\r
12 \r
13 #include <Poco/Util/HelpFormatter.h>\r
14 #include <Poco/FileChannel.h>\r
15 #include <Poco/ConsoleChannel.h>\r
16 #include <Poco/FormattingChannel.h>\r
17 #include <Poco/PatternFormatter.h>\r
18 #include <iostream>\r
19 \r
20 #ifdef _WIN32\r
21         #include <direct.h>\r
22 #else\r
23         #include <unistd.h>\r
24 #endif\r
25 \r
26 //debug\r
27 #include <Poco/ScopedLock.h>\r
28 #include <Poco/Runnable.h>\r
29 #include <Poco/Thread.h>\r
30 #include <Poco/ThreadPool.h>\r
31 #include "../include/threadwrapper/cancelablerunnable.h"\r
32 #include "../include/threadwrapper/cancelablethread.h"\r
33 \r
34 Poco::FastMutex m1;\r
35 class TestRunner:public CancelableRunnable\r
36 {\r
37 public:\r
38         void run()\r
39         {\r
40                 do\r
41                 {\r
42 \r
43                 }while(!IsCancelled());\r
44         }\r
45 };\r
46 \r
47 FMSApp::FMSApp():m_displayhelp(false),m_logtype("file")\r
48 {\r
49 \r
50 }\r
51 \r
52 void FMSApp::defineOptions(Poco::Util::OptionSet &options)\r
53 {\r
54         ServerApplication::defineOptions(options);\r
55 \r
56         // add command line options here\r
57         options.addOption(Poco::Util::Option("help","?","display help for command line arguments",false).repeatable(false).callback(Poco::Util::OptionCallback<FMSApp>(this,&FMSApp::handleHelp)));\r
58         options.addOption(Poco::Util::Option("log","l","select type of log output (file|stdout|stderr)",false,"type",true).repeatable(false).callback(Poco::Util::OptionCallback<FMSApp>(this,&FMSApp::handleLogOption)));\r
59 }\r
60 \r
61 void FMSApp::displayHelp()\r
62 {\r
63         Poco::Util::HelpFormatter helpFormatter(options());\r
64         helpFormatter.setCommand(commandName());\r
65         helpFormatter.setUsage("OPTIONS");\r
66         helpFormatter.setHeader("The Freenet Message System.");\r
67         helpFormatter.format(std::cout);\r
68 }\r
69 \r
70 void FMSApp::handleHelp(const std::string &name, const std::string &value)\r
71 {\r
72         m_displayhelp=true;\r
73         displayHelp();\r
74         stopOptionsProcessing();\r
75 }\r
76 \r
77 void FMSApp::handleLogOption(const std::string &name, const std::string &value)\r
78 {\r
79         if(value=="file" || value=="stdout" || value=="stderr")\r
80         {\r
81                 m_logtype=value;\r
82         }\r
83 }\r
84 \r
85 void FMSApp::initialize(Poco::Util::Application &self)\r
86 {\r
87         ServerApplication::initialize(self);\r
88 \r
89         // set working directory to program directory\r
90         int rval=chdir(config().getString("application.dir").c_str());\r
91 \r
92         SetupDB();\r
93         SetupDefaultOptions();\r
94         initializeLogger();\r
95         config().setString("application.logger","logfile");\r
96 }\r
97 \r
98 void FMSApp::initializeLogger()\r
99 {\r
100         int initiallevel=Poco::Message::PRIO_TRACE;\r
101 \r
102         std::string tempval="";\r
103         if(Option::Instance()->Get("LogLevel",tempval))\r
104         {\r
105                 StringFunctions::Convert(tempval,initiallevel);\r
106         }\r
107 \r
108         Poco::AutoPtr<Poco::FormattingChannel> formatter=new Poco::FormattingChannel(new Poco::PatternFormatter("%Y-%m-%d %H:%M:%S | %p | %t"));\r
109         \r
110         if(m_logtype=="file")\r
111         {\r
112                 Poco::AutoPtr<Poco::FileChannel> fc=new Poco::FileChannel("fms.log");\r
113                 fc->setProperty("rotation","daily");    // rotate log file daily\r
114                 fc->setProperty("times","utc");                 // utc date/times for log entries\r
115                 fc->setProperty("archive","timestamp"); // add timestamp to old logs\r
116                 fc->setProperty("purgeCount","30");             // purge old logs after 30 logs have accumulated\r
117                 fc->setProperty("compress","true");             // gz compress old log files\r
118                 formatter->setChannel(fc);\r
119         }\r
120         else\r
121         {\r
122                 if(m_logtype=="stdout")\r
123                 {\r
124                         Poco::AutoPtr<Poco::ConsoleChannel> cc=new Poco::ConsoleChannel(std::cout);\r
125                         formatter->setChannel(cc);\r
126                 }\r
127                 else\r
128                 {\r
129                         Poco::AutoPtr<Poco::ConsoleChannel> cc=new Poco::ConsoleChannel(std::cerr);\r
130                         formatter->setChannel(cc);\r
131                 }\r
132         }\r
133         \r
134         setLogger(Poco::Logger::create("logfile",formatter,initiallevel));\r
135 }\r
136 \r
137 int FMSApp::main(const std::vector<std::string> &args)\r
138 {\r
139 \r
140         // running as a daemon would reset the working directory to / before calling main\r
141         // so we need to set the working directory again\r
142         // set working directory to program directory\r
143         int rval=chdir(config().getString("application.dir").c_str());\r
144 \r
145         if(m_displayhelp==false)\r
146         {\r
147                 logger().information("FMS startup v"FMS_VERSION);\r
148 \r
149                 StartThreads();\r
150 \r
151                 if(isInteractive()==true)\r
152                 {\r
153                         std::cout << "FMS has been started." << std::endl << std::endl;\r
154                 }\r
155 \r
156                 waitForTerminationRequest();\r
157 \r
158                 m_threads.Cancel();\r
159                 m_threads.Join();\r
160 \r
161                 logger().information("FMS shutdown");\r
162         }\r
163 \r
164         return FMSApp::EXIT_OK;\r
165 }\r
166 \r
167 void FMSApp::StartThreads()\r
168 {\r
169         std::string tempval="";\r
170 \r
171         // always start the DB maintenance thread\r
172         m_threads.Start(new DBMaintenanceThread());\r
173 \r
174         Option::Instance()->Get("StartHTTP",tempval);\r
175         if(tempval=="true")\r
176         {\r
177                 m_threads.Start(new HTTPThread());\r
178         }\r
179 \r
180         tempval="";\r
181         Option::Instance()->Get("StartNNTP",tempval);\r
182         if(tempval=="true")\r
183         {\r
184                 m_threads.Start(new NNTPListener());\r
185         }\r
186 \r
187         tempval="";\r
188         Option::Instance()->Get("StartFreenetUpdater",tempval);\r
189         if(tempval=="true")\r
190         {\r
191                 m_threads.Start(new FreenetMasterThread());\r
192         }\r
193 \r
194 }\r