/** \mainpage KeywordsIndexCreator service \section usage_section Использование \b keywords_indexcreator --- это модуль, ответственный за построение и обновление индекса библиотеки полнотекстового поиска CLucene. Модуль является фоновым приложением, запускаемым как сервис из /etc/init.d Примеры использования из командной строки (indexator.conf - файл конфигурации, см. ниже): \code keywords_indexcreator indexator.conf \endcode \section settings_section Настройка сервиса keywords_indexcreator для построения индекса использует базу данных mongo, которая содержит описание всех рекламных предложений. Это основная база данных проекта, которую использует пользовательская часть. На уровне приложения регистрируется как база данных по умолчанию (см. DB::addDatabase). Параметры подключения к базе данных хранятся в файле конфигурации. Параметры \c mongo_main_host, \c mongo_main_db содержат адрес (в формате "host[:port]" и названия баз данных. По умолчанию будут использованы следующие параметры: \code mongo_main_host = localhost mongo_main_db = getmyad_db mongo_main_set = '' mongo_main_slave_ok = false \endcode Кроме того, в файле конфигурации хранится переменная \c index_folder, отвечающая за место размещения индекса на физическом диске. По умолчанию будут использованы следующие параметры: \code index_folder = /var/www/index \endcode Пример конфигурационного файла: \code mongo_main_host=213.186.119.121:27017,213.186.119.121:27018,213.186.119.121:27019 mongo_main_set=vsrv mongo_main_db=getmyad_db mongo_main_slave_ok=true index_folder=/var/www/index \endcode */ int main(int argc, char *argv[]) { google::InitGoogleLogging(argv[0]); if (argc ==1) { printf ("Configuration file is needed!\nProcess stoped.....\n"); return 0;} pid_t parpid, sid; parpid = fork(); //создаем дочерний процесс //The parent process should get a non-zero pid from fork //The child process should get 0 if (parpid < 0) //negative indicates error { printf("Error: Start Daemon failed (%s)\n", strerror(errno)); exit(EXIT_FAILURE); } else if (parpid > 0) //parent process, exit success { printf("Demon starting... "); SetPidFile(PID_FILE, parpid); exit(EXIT_SUCCESS); } umask(0);//даем права на работу с фс sid = setsid(); if(sid < 0) { printf("sid<0\n"); exit(EXIT_FAILURE); } if((chdir("/")) < 0) {//выходим в tmp exit(EXIT_FAILURE); } close(STDIN_FILENO); open("/dev/null",O_RDONLY); close(STDOUT_FILENO); open("/dev/null",O_WRONLY); close(STDERR_FILENO); dup(1); return IndexCreatorService(argv[1]).Serve(); }
//следим за потомком int TDaemon::MonitorProc() { int pid; int status; int need_start = 1; sigset_t sigset; siginfo_t siginfo; // настраиваем сигналы которые будем обрабатывать sigemptyset(&sigset); // сигнал остановки процесса пользователем sigaddset(&sigset, SIGQUIT); // сигнал для остановки процесса пользователем с терминала sigaddset(&sigset, SIGINT); // сигнал запроса завершения процесса sigaddset(&sigset, SIGTERM); // сигнал посылаемый при изменении статуса дочернего процесса sigaddset(&sigset, SIGCHLD); // пользовательский сигнал который мы будем использовать для обновления конфига sigaddset(&sigset, SIGHUP); sigprocmask(SIG_BLOCK, &sigset, NULL); // данная функция создаст файл с нашим PID'ом SetPidFile(PID_FILE.c_str()); // бесконечный цикл работы for (;;) { // если необходимо создать потомка if (need_start) { // создаём потомка pid = fork(); } need_start = 1; if (pid == -1) // если произошла ошибка { // запишем в лог сообщение об этом WriteLog("%s [MONITOR] Fork failed (%s)\n",getTime(), strerror(errno)); } else if (!pid) // если мы потомок { // данный код выполняется в потомке // запустим функцию отвечающую за работу демона status = WorkProc(); // завершим процесс exit(status); } else // если мы родитель { // данный код выполняется в родителе // ожидаем поступление сигнала sigwaitinfo(&sigset, &siginfo); // если пришел сигнал от потомка if (siginfo.si_signo == SIGCHLD) { // получаем статус завершение wait(&status); // преобразуем статус в нормальный вид status = WEXITSTATUS(status); // если потомок завершил работу с кодом говорящем о том, что нет нужды дальше работать if (status == CHILD_NEED_TERMINATE) { // запишем в лог сообщени об этом WriteLog("%s [MONITOR] Child stopped\n", getTime()); // прервем цикл break; } else if (status == CHILD_NEED_WORK) // если требуется перезапустить потомка { // запишем в лог данное событие WriteLog("%s [MONITOR] Child restart\n", getTime()); } } else if (siginfo.si_signo == SIGHUP) // если пришел сигнал что необходимо перезагрузить конфиг { kill(pid, SIGHUP); // перешлем его потомку need_start = 0; // установим флаг что нам не надо запускать потомка заново } else // если пришел какой-либо другой ожидаемый сигнал { // запишем в лог информацию о пришедшем сигнале WriteLog("%s [MONITOR] Signal %s\n", getTime(), strsignal(siginfo.si_signo)); // убьем потомка kill(pid, SIGTERM); status = 0; break; } } } // запишем в лог, что мы остановились WriteLog("%s [MONITOR] Stop\n", getTime()); // удалим файл с PID'ом unlink(PID_FILE.c_str()); return status; }