X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/b078cd0fbf7dee4e222fcffffac2ded8a3c9d3a3..ebd170a764ab9660adee464588cda1801c7986b4:/projects/stargazer/main.cpp diff --git a/projects/stargazer/main.cpp b/projects/stargazer/main.cpp index 7cc8eccc..acc826f7 100644 --- a/projects/stargazer/main.cpp +++ b/projects/stargazer/main.cpp @@ -18,547 +18,416 @@ * Author : Boris Mikhailenko */ - /* - $Revision: 1.124 $ - $Date: 2010/10/04 20:19:12 $ - $Author: faust $ - */ - -#include -#include -#include -#include -#include -#include // S_IRUSR -#include // create - -#include -#include -#include -#include // srandom, exit -#include -#include -#include -#include - -#include "stg/user.h" -#include "stg/common.h" -#include "stg/plugin.h" -#include "stg/logger.h" -#include "stg/scriptexecuter.h" -#include "stg/version.h" -#include "stg_timer.h" -#include "settings_impl.h" +#include "store_loader.h" +#include "plugin_mgr.h" +#include "plugin_runner.h" #include "users_impl.h" #include "admins_impl.h" #include "tariffs_impl.h" #include "services_impl.h" #include "corps_impl.h" #include "traffcounter_impl.h" -#include "plugin_runner.h" -#include "store_loader.h" +#include "settings_impl.h" #include "pidfile.h" -#include "eventloop.h" +#include "async_pool.h" +#include "stg_timer.h" -#ifdef DEBUG - #define MAIN_DEBUG (1) - #define NO_DAEMON (1) -#endif +#include "stg/user.h" +#include "stg/common.h" +#include "stg/plugin.h" +#include "stg/logger.h" +#include "stg/scriptexecuter.h" +#include "stg/version.h" + +#include +#include +#include +#include +#include +#include +#include +#include // srandom, exit + +#include +#include +#include +#include +#include +#include // S_IRUSR +#include // create #define START_FILE "/._ST_ART_ED_" +using STG::SettingsImpl; +using STG::AdminsImpl; +using STG::TraffCounterImpl; +using STG::UsersImpl; +using STG::TariffsImpl; +using STG::ServicesImpl; +using STG::CorporationsImpl; +using STG::StoreLoader; + namespace { -std::set executersPid; +std::set executers; -bool StartModCmp(const PLUGIN_RUNNER & lhs, const PLUGIN_RUNNER & rhs); -bool StopModCmp(const PLUGIN_RUNNER & lhs, const PLUGIN_RUNNER & rhs); void StartTimer(); -int StartScriptExecuter(char * procName, int msgKey, int * msgID, SETTINGS_IMPL * settings); -int ForkAndWait(const std::string & confDir); +int StartScriptExecuter(char* procName, int msgKey, int* msgID); +int ForkAndWait(const std::string& confDir); void KillExecuters(); -//----------------------------------------------------------------------------- -bool StartModCmp(const PLUGIN_RUNNER & lhs, const PLUGIN_RUNNER & rhs) -{ -return lhs.GetStartPosition() < rhs.GetStartPosition(); -} -//----------------------------------------------------------------------------- -bool StopModCmp(const PLUGIN_RUNNER & lhs, const PLUGIN_RUNNER & rhs) -{ -return lhs.GetStopPosition() > rhs.GetStopPosition(); -} //----------------------------------------------------------------------------- void StartTimer() { -STG_LOGGER & WriteServLog = GetStgLogger(); + auto& WriteServLog = STG::Logger::get(); -if (RunStgTimer()) + if (RunStgTimer()) { - WriteServLog("Cannot start timer. Fatal."); - //printfd(__FILE__, "Cannot start timer. Fatal.\n"); - exit(1); - } -else - { - WriteServLog("Timer thread started successfully."); - //printfd(__FILE__, "Timer thread started successfully.\n"); + WriteServLog("Cannot start timer. Fatal."); + exit(1); } + else + WriteServLog("Timer thread started successfully."); } //----------------------------------------------------------------------------- #if defined(LINUX) || defined(DARWIN) -int StartScriptExecuter(char * procName, int msgKey, int * msgID, SETTINGS_IMPL * settings) +int StartScriptExecuter(char* procName, int msgKey, int* msgID) #else -int StartScriptExecuter(char *, int msgKey, int * msgID, SETTINGS_IMPL * settings) +int StartScriptExecuter(char*, int msgKey, int* msgID) #endif { -STG_LOGGER & WriteServLog = GetStgLogger(); + auto& WriteServLog = STG::Logger::get(); -if (*msgID == -11) // If msgID == -11 - first call. Create queue + if (*msgID == -11) // If msgID == -11 - first call. Create queue { - for (int i = 0; i < 2; i++) + for (int i = 0; i < 2; i++) { - *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600); + *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600); - if (*msgID == -1) - { - *msgID = msgget(msgKey, 0); if (*msgID == -1) + { + *msgID = msgget(msgKey, 0); + if (*msgID == -1) { - WriteServLog("Message queue not created."); - return -1; - } - else - { - msgctl(*msgID, IPC_RMID, NULL); + WriteServLog("Message queue not created."); + return -1; } + else + msgctl(*msgID, IPC_RMID, NULL); } - else + else { - WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID); - break; + WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID); + break; } } } -pid_t executerPid = fork(); + const auto pid = fork(); -switch (executerPid) + switch (pid) { - case -1: - WriteServLog("Fork error!"); - return -1; + case -1: + WriteServLog("Fork error!"); + return -1; - case 0: - delete settings; + case 0: #if defined(LINUX) || defined(DARWIN) - Executer(*msgID, executerPid, procName); + Executer(*msgID, pid, procName); #else - Executer(*msgID, executerPid); + Executer(*msgID, pid); #endif - return 1; + return 1; - default: - if (executersPid.empty()) { + default: + if (executers.empty()) { #if defined(LINUX) || defined(DARWIN) - Executer(*msgID, executerPid, NULL); + Executer(*msgID, pid, NULL); #else - Executer(*msgID, executerPid); + Executer(*msgID, pid); #endif - } - executersPid.insert(executerPid); + } + executers.insert(pid); } -return 0; + return 0; } //----------------------------------------------------------------------------- -#ifndef NO_DAEMON -int ForkAndWait(const std::string & confDir) -#else -int ForkAndWait(const std::string &) -#endif +int ForkAndWait(const std::string& confDir) { -#ifndef NO_DAEMON -pid_t childPid = fork(); -std::string startFile = confDir + START_FILE; -unlink(startFile.c_str()); + const auto pid = fork(); + const auto startFile = confDir + START_FILE; + unlink(startFile.c_str()); -switch (childPid) + switch (pid) { - case -1: - return -1; - break; + case -1: + return -1; + break; - case 0: - close(1); - close(2); - setsid(); - break; + case 0: + close(1); + close(2); + setsid(); + break; - default: - struct timespec ts = {0, 200000000}; - for (int i = 0; i < 120 * 5; i++) + default: + struct timespec ts = {0, 200000000}; + for (int i = 0; i < 120 * 5; i++) { - if (access(startFile.c_str(), F_OK) == 0) + if (access(startFile.c_str(), F_OK) == 0) { - unlink(startFile.c_str()); - exit(0); + unlink(startFile.c_str()); + exit(0); } - nanosleep(&ts, NULL); + nanosleep(&ts, NULL); } - unlink(startFile.c_str()); - exit(1); - break; + unlink(startFile.c_str()); + exit(1); + break; } -#endif -return 0; + return 0; } + //----------------------------------------------------------------------------- void KillExecuters() { -std::set::iterator pid; -pid = executersPid.begin(); -while (pid != executersPid.end()) + auto pid = executers.begin(); + while (pid != executers.end()) { - printfd(__FILE__, "KillExecuters pid=%d\n", *pid); - kill(*pid, SIGUSR1); - ++pid; + printfd(__FILE__, "KillExecuters pid=%d\n", *pid); + kill(*pid, SIGUSR1); + ++pid; } } + +void PrintHelp(const std::string& programName) +{ + std::cout << "Usage: " << programName << "[-h/--help] [-v/--version] [-f/--foreground] []\n" + << "\t --help, -h - print this help;\n" + << "\t --version, -v - print version;\n" + << "\t --foreground, -f - do not go into background;\n" + << "\t - path to the directory where the configuration file is located.\n"; +} + +void PrintVersion(const std::string& programName) +{ + std::cout << programName << "\n" + << "Stargazer version" << " " << SERVER_VERSION << "\n"; +} //----------------------------------------------------------------------------- } // namespace anonymous //----------------------------------------------------------------------------- -int main(int argc, char * argv[]) +int main(int argc, char* argv[]) { -SETTINGS_IMPL * settings = NULL; -STORE * dataStore = NULL; -TARIFFS_IMPL * tariffs = NULL; -ADMINS_IMPL * admins = NULL; -USERS_IMPL * users = NULL; -TRAFFCOUNTER_IMPL * traffCnt = NULL; -SERVICES_IMPL * services = NULL; -CORPORATIONS_IMPL * corps = NULL; -int msgID = -11; - - { - STG_LOGGER & WriteServLog = GetStgLogger(); - WriteServLog.SetLogFileName("/var/log/stargazer.log"); - } - -std::vector modSettings; -std::list modules; - -std::list::iterator modIter; - -if (getuid()) - { - printf("You must be root. Exit.\n"); - exit(1); - } + int msgID = -11; -if (argc == 2) - settings = new SETTINGS_IMPL(argv[1]); -else - settings = new SETTINGS_IMPL(); + STG::Logger::get().setFileName("/var/log/stargazer.log"); -if (settings->ReadSettings()) + if (getuid()) { - STG_LOGGER & WriteServLog = GetStgLogger(); - - if (settings->GetLogFileName() != "") - WriteServLog.SetLogFileName(settings->GetLogFileName()); - - WriteServLog("ReadSettings error. %s", settings->GetStrError().c_str()); - exit(1); - } -#ifndef NO_DAEMON -std::string startFile(settings->GetConfDir() + START_FILE); -#endif - -if (ForkAndWait(settings->GetConfDir()) < 0) - { - STG_LOGGER & WriteServLog = GetStgLogger(); - WriteServLog("Fork error!"); - exit(1); + printf("You must be root. Exit.\n"); + return 1; } -STG_LOGGER & WriteServLog = GetStgLogger(); -WriteServLog.SetLogFileName(settings->GetLogFileName()); -WriteServLog("Stg v. %s", SERVER_VERSION); + std::string path; + bool noDaemon(false); -for (size_t i = 0; i < settings->GetExecutersNum(); i++) + if (argc == 1) + path = ""; + else { - int ret = StartScriptExecuter(argv[0], settings->GetExecMsgKey(), &msgID, settings); - if (ret < 0) - { - STG_LOGGER & WriteServLog = GetStgLogger(); - WriteServLog("Start Script Executer error!"); - return 1; - } - if (ret == 1) + for (int i = 1; i < argc; ++i) { - // Stopping child - return 0; + const std::string arg(argv[i]); + if (arg == "--help" || arg == "-h") + { + PrintHelp(argv[0]); + return 0; + } + if (arg == "--version" || arg == "-v") + { + PrintVersion(argv[0]); + return 0; + } + if (arg == "--foreground" || arg == "-f") + noDaemon = true; + else + path = arg; } } -PIDFile pidFile(settings->GetPIDFileName()); - -sigset_t signalSet; -sigfillset(&signalSet); -pthread_sigmask(SIG_BLOCK, &signalSet, NULL); + SettingsImpl settings(path); -StartTimer(); -WaitTimer(); -if (!IsStgTimerRunning()) + if (settings.ReadSettings()) { - printfd(__FILE__, "Timer thread not started in 1 sec!\n"); - WriteServLog("Timer thread not started in 1 sec!"); - } + auto& WriteServLog = STG::Logger::get(); -EVENT_LOOP & loop(EVENT_LOOP_SINGLETON::GetInstance()); - -STORE_LOADER storeLoader(*settings); -if (storeLoader.Load()) - { - WriteServLog("Storage plugin: '%s'", storeLoader.GetStrError().c_str()); - goto exitLblNotStarted; - } + if (settings.GetLogFileName() != "") + WriteServLog.setFileName(settings.GetLogFileName()); -if (loop.Start()) - { - WriteServLog("Event loop not started."); - goto exitLblNotStarted; + WriteServLog("ReadSettings error. %s", settings.GetStrError().c_str()); + return -1; } -dataStore = storeLoader.GetStore(); -WriteServLog("Storage plugin: %s. Loading successfull.", dataStore->GetVersion().c_str()); - -tariffs = new TARIFFS_IMPL(dataStore); -admins = new ADMINS_IMPL(dataStore); -users = new USERS_IMPL(settings, dataStore, tariffs, admins->GetSysAdmin()); -traffCnt = new TRAFFCOUNTER_IMPL(users, settings->GetRulesFileName()); -services = new SERVICES_IMPL(dataStore); -corps = new CORPORATIONS_IMPL(dataStore); -traffCnt->SetMonitorDir(settings->GetMonitorDir()); - -modSettings = settings->GetModulesSettings(); - -for (size_t i = 0; i < modSettings.size(); i++) + if (!noDaemon) { - std::string modulePath = settings->GetModulesPath(); - modulePath += "/mod_"; - modulePath += modSettings[i].moduleName; - modulePath += ".so"; - printfd(__FILE__, "Module: %s\n", modulePath.c_str()); - modules.push_back( - PLUGIN_RUNNER(modulePath, - modSettings[i], - admins, - tariffs, - users, - services, - corps, - traffCnt, - dataStore, - settings) - ); + if (ForkAndWait(settings.GetConfDir()) < 0) + { + STG::Logger::get()("Fork error!"); + return -1; + } } -modIter = modules.begin(); + auto& WriteServLog = STG::Logger::get(); + WriteServLog.setFileName(settings.GetLogFileName()); + WriteServLog("Stg v. %s", SERVER_VERSION); -while (modIter != modules.end()) + for (size_t i = 0; i < settings.GetExecutersNum(); i++) { - if (modIter->Load()) + auto ret = StartScriptExecuter(argv[0], settings.GetExecMsgKey(), &msgID); + if (ret < 0) { - WriteServLog("Error loading module '%s': %s", - modIter->GetPlugin()->GetVersion().c_str(), - modIter->GetStrError().c_str()); - goto exitLblNotStarted; + STG::Logger::get()("Start Script Executer error!"); + return -1; } - ++modIter; + if (ret == 1) + return 0; } -if (users->Start()) - { - goto exitLblNotStarted; - } -WriteServLog("Users started successfully."); + PIDFile pidFile(settings.GetPIDFileName()); + + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + sigaction(SIGHUP, &sa, NULL); // Apparently FreeBSD ignores SIGHUP by default when launched from rc.d at bot time. -if (traffCnt->Start()) + sigset_t signalSet; + sigfillset(&signalSet); + pthread_sigmask(SIG_BLOCK, &signalSet, NULL); + + StartTimer(); + WaitTimer(); + if (!IsStgTimerRunning()) { - goto exitLblNotStarted; + printfd(__FILE__, "Timer thread not started in 1 sec!\n"); + WriteServLog("Timer thread not started in 1 sec!"); + return -1; } -WriteServLog("Traffcounter started successfully."); -//Sort by start order -modules.sort(StartModCmp); -modIter = modules.begin(); + STG::AsyncPoolST::start(); -while (modIter != modules.end()) + StoreLoader storeLoader(settings); + if (storeLoader.load()) { - if (modIter->Start()) - { - WriteServLog("Error starting module '%s': %s", - modIter->GetPlugin()->GetVersion().c_str(), - modIter->GetStrError().c_str()); - goto exitLbl; - } - WriteServLog("Module: '%s'. Start successfull.", modIter->GetPlugin()->GetVersion().c_str()); - ++modIter; + printfd(__FILE__, "Storage plugin: '%s'\n", storeLoader.GetStrError().c_str()); + WriteServLog("Storage plugin: '%s'", storeLoader.GetStrError().c_str()); + return -1; } -srandom(static_cast(stgTime)); + auto& store = storeLoader.get(); + WriteServLog("Storage plugin: %s. Loading successfull.", store.GetVersion().c_str()); -WriteServLog("Stg started successfully."); -WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++"); + AdminsImpl admins(store); + TariffsImpl tariffs(&store); + tariffs.ReadTariffs(); + ServicesImpl services(&store); + CorporationsImpl corps(&store); + UsersImpl users(&settings, &store, &tariffs, services, admins.sysAdmin()); + TraffCounterImpl traffCnt(&users, settings.GetRulesFileName()); + traffCnt.SetMonitorDir(settings.GetMonitorDir()); -#ifndef NO_DAEMON -creat(startFile.c_str(), S_IRUSR); -#endif + if (users.Start()) + return -1; -while (true) - { - sigfillset(&signalSet); - int sig = 0; - sigwait(&signalSet, &sig); - bool stop = false; - int status; - pid_t childPid; - std::set::iterator it; - switch (sig) - { - case SIGHUP: - traffCnt->Reload(); - modIter = modules.begin(); - for (; modIter != modules.end(); ++modIter) - { - if (modIter->Reload()) - { - WriteServLog("Error reloading module '%s': '%s'", modIter->GetPlugin()->GetVersion().c_str(), - modIter->GetStrError().c_str()); - printfd(__FILE__, "Error reloading module '%s': '%s'\n", modIter->GetPlugin()->GetVersion().c_str(), - modIter->GetStrError().c_str()); - } - } - break; - case SIGTERM: - stop = true; - break; - case SIGINT: - stop = true; - break; - case SIGPIPE: - WriteServLog("Broken pipe!"); - break; - case SIGCHLD: - childPid = waitpid(-1, &status, WNOHANG); + WriteServLog("Users started successfully."); - it = executersPid.find(childPid); - if (it != executersPid.end()) - { - executersPid.erase(it); - if (executersPid.empty()) - stop = true; - } - break; - default: - WriteServLog("Ignore signel %d", sig); - break; - } - if (stop) - break; - } + if (traffCnt.Start()) + return -1; -exitLbl: + WriteServLog("Traffcounter started successfully."); -WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++"); + STG::PluginManager manager(settings, store, admins, tariffs, services, corps, users, traffCnt); -//Sort by start order -modules.sort(StopModCmp); -modIter = modules.begin(); -while (modIter != modules.end()) - { - std::string name = modIter->GetFileName(); - printfd(__FILE__, "Stopping module '%s'\n", name.c_str()); - if (modIter->Stop()) - { - WriteServLog("Error stopping module '%s': %s", - modIter->GetPlugin()->GetVersion().c_str(), - modIter->GetStrError().c_str()); - printfd(__FILE__, "Error stopping module '%s': '%s'\n", modIter->GetPlugin()->GetVersion().c_str(), modIter->GetStrError().c_str()); - } - else - { - WriteServLog("Module: '%s'. Stop successfull.", modIter->GetPlugin()->GetVersion().c_str()); - } - ++modIter; - } + srandom(static_cast(stgTime)); + + WriteServLog("Stg started successfully."); + WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++"); -if (loop.Stop()) + if (!noDaemon) { - WriteServLog("Event loop not stopped."); + const auto startFile = settings.GetConfDir() + START_FILE; + creat(startFile.c_str(), S_IRUSR); } -exitLblNotStarted: - -modIter = modules.begin(); -while (modIter != modules.end()) + bool running = true; + while (running) { - std::string name = modIter->GetFileName(); - if (modIter->IsRunning()) - { - printfd(__FILE__, "Passing module '%s' `cause it's still running\n", name.c_str()); - } - else + sigfillset(&signalSet); + int sig = 0; + sigwait(&signalSet, &sig); + int status; + switch (sig) { - printfd(__FILE__, "Unloading module '%s'\n", name.c_str()); - if (modIter->Unload()) + case SIGHUP: { - WriteServLog("Error unloading module '%s': '%s'", - modIter->GetPlugin()->GetVersion().c_str(), - modIter->GetStrError().c_str()); - printfd(__FILE__, "Error unloading module '%s': '%s'\n", modIter->GetPlugin()->GetVersion().c_str(), modIter->GetStrError().c_str()); + SettingsImpl newSettings(settings); + if (newSettings.ReadSettings()) + WriteServLog("ReadSettings error. %s", newSettings.GetStrError().c_str()); + else + settings = newSettings; + WriteServLog.setFileName(settings.GetLogFileName()); + traffCnt.Reload(); + manager.reload(settings); + break; } + case SIGTERM: + running = false; + break; + case SIGINT: + running = false; + break; + case SIGPIPE: + WriteServLog("Broken pipe!"); + break; + case SIGCHLD: + executers.erase(waitpid(-1, &status, WNOHANG)); + if (executers.empty()) + running = false; + break; + default: + WriteServLog("Ignore signal %d", sig); + break; } - ++modIter; } -if (traffCnt) - { - traffCnt->Stop(); - WriteServLog("Traffcounter: Stop successfull."); - } + WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++"); -if (users) - { - users->Stop(); - WriteServLog("Users: Stop successfull."); - } + manager.stop(); + + STG::AsyncPoolST::stop(); -sleep(1); -int res = msgctl(msgID, IPC_RMID, NULL); -if (res) - WriteServLog("Queue was not removed. id=%d", msgID); -else - WriteServLog("Queue removed successfully."); + if (!traffCnt.Stop()) + WriteServLog("Traffcounter: Stop successfull."); -KillExecuters(); + if (!users.Stop()) + WriteServLog("Users: Stop successfull."); + + sleep(1); + int res = msgctl(msgID, IPC_RMID, NULL); + if (res) + WriteServLog("Queue was not removed. id=%d", msgID); + else + WriteServLog("Queue removed successfully."); -StopStgTimer(); -WriteServLog("StgTimer: Stop successfull."); + KillExecuters(); -delete corps; -delete services; -delete traffCnt; -delete users; -delete admins; -delete tariffs; -delete settings; + StopStgTimer(); + WriteServLog("StgTimer: Stop successfull."); -WriteServLog("Stg stopped successfully."); -WriteServLog("---------------------------------------------"); + WriteServLog("Stg stopped successfully."); + WriteServLog("---------------------------------------------"); -return 0; + return 0; } //-----------------------------------------------------------------------------