root/CorpusLoaderDaemon.cpp

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. setcordata
  2. main

   1 /* -*- coding: utf-8; mode: c++; -*-
   2  * Concordance to A. S. Pushkin's Works - Corpus Shared Memory Loader
   3  * - 共有メモリに Corpus, TitleDB(作品名データベース) の map を構築する
   4  * - アドレスハンドルを表示する
   5  * - Web 環境からアクセスする場合は,Web server user 権限で実行すること
   6  * $Id: CorpusLoaderDaemon.cpp 49 2014-06-06 15:26:02Z isao $
   7  * Copyright (C) 2012, isao yasuda
   8  */
   9 
  10 #include <boost/timer.hpp>
  11 #include "SharedMemoryCommon.hpp"
  12 #include "DeclareFunctions.hpp"
  13 #include "ConcordanceConfig.hpp"
  14 
  15 // Corpus の位置情報とテクスト本文を切り出す
  16 void setcordata(string& line, string& info, string& text)
  17 {
  18     string::size_type i = line.find(' '); // 位置情報と本文の区切り
  19     info = line.substr(0, i);             // 位置情報セット
  20     text = line.substr(++i);              // 本文セット
  21 }
  22 
  23 // Corpus 共有メモリロード主処理
  24 int main(int argc, char** argv)
  25 {
  26     // 引数チェック
  27     if (argc != 3) {
  28         std::cerr <<  "Usage: " << argv[0] <<
  29                   " Corpus-file TitleDB-file" << std::endl;
  30         exit(8);
  31     }
  32 
  33     //  Daemonize
  34     //  ログファイルをオープンし,標準出力・エラー出力を接続
  35     std::ofstream log(LOGFILE, std::ios::out | std::ios::app);
  36     std::cout.rdbuf(log.rdbuf());
  37     std::cerr.rdbuf(log.rdbuf());
  38 
  39     //  起動済チェック
  40     //  すでに pid ファイルが存在していればただちに終了する
  41     //  pid ファイルが存在しなければ,初期作成し STARTING を書き込む
  42     std::ifstream opidf;
  43     opidf.open(CLPIDF);
  44     if (opidf) {
  45         log << "CorpusLoader already started." << std::endl;
  46         return 1;
  47     }
  48     std::ofstream pidf(CLPIDF);
  49     log << "CorpusLoader starting." << std::endl;
  50     pidf << "STARTING";
  51     pidf.close();
  52 
  53     //  3 端末分離
  54     if (pid_t pid = fork()) {
  55         if (pid > 0) {
  56             // ここは親プロセス。終了しなければならない
  57             exit(0);
  58         } else {
  59             log << "CorpusLoader First fork failed." << std::endl;
  60             log.close();
  61             return 1;
  62         }
  63     }
  64 
  65     // プロセスを新セッションリーダとし,プロセスを端末から切断
  66     setsid();
  67 
  68     // ルートディレクトリに移動
  69     chdir("/");
  70 
  71     // ファイルのパーミションマスクをクリア
  72     umask(0);
  73 
  74     // プロセスが制御端末を捕まえてしまうことのないことを確実化
  75     if (pid_t pid = fork()) {
  76         if (pid > 0) {
  77             exit(0);
  78         } else {
  79             log << "CorpusLoader Second fork failed." << std::endl;
  80             log.close();
  81             return 1;
  82         }
  83     }
  84 
  85     // コーパス,titledb ファイル存在チェック
  86     std::ifstream icf;
  87     icf.open(argv[1]);
  88     if (!icf) {
  89         std::cerr << "CorpusLoader " << argv[1] << " open failed." << std::endl;
  90         remove(CLPIDF);
  91         return 1;
  92     }
  93     std::ifstream itd;
  94     itd.open(argv[2]);
  95     if (!itd) {
  96         std::cerr << "CorpusLoader " << argv[2] << " open failed." << std::endl;
  97         remove(CLPIDF);
  98         return 1;
  99     }
 100 
 101     // 標準入出力をクローズ,起動端末からデーモンを分離
 102     close(0);
 103     close(1);
 104     close(2);
 105 
 106     // デーモン化完了・共有メモリ処理開始メッセージ
 107     pid_t pid = getpid();
 108     log << "CorpusLoader daemon started. PID: " << pid << std::endl;
 109 
 110     // シグナルハンドリング
 111     sigset_t ss;      // signal set
 112     int signo;        // signal number
 113     bool flag = true; // signal wait flag: wait->true; terminate->false;
 114 
 115     // シグナル集合を全シグナルにセット
 116     sigfillset(&ss);
 117     // シグナルをブロック
 118     sigprocmask(SIG_BLOCK, &ss, NULL);
 119 
 120     // 共有メモリを開始前と終了後に削除
 121     shm_corpus_remove remover;
 122 
 123     // 共有メモリを確保し,そのオブジェクトを取得
 124     log << "CorpusLoader Corpus Shared Memory Construction." << std::endl;
 125     log << "CorpusLoader Corpus:  " << argv[1] << std::endl;
 126     log << "CorpusLoader TitleDB: " << argv[2] << std::endl;
 127     managed_shared_memory segment(create_only, SHMCRPS, SHMCRSZ);
 128 
 129     // shared memory allocator
 130     void_allocator valloc (segment.get_segment_manager());
 131 
 132     // 処理時間タイマー
 133     boost::timer t;
 134 
 135     // 共有メモリ上に corpus map を構築
 136     string ldata;
 137     shmmap_type* corpus_map = segment.construct<shmmap_type>
 138                               ("CorpusMap")(std::less<char_string>(), valloc);
 139     string cornum;
 140     string corstr;
 141     int corcnt = 0;
 142     while (icf && getline(icf, ldata)) {
 143         setcordata(ldata, cornum, corstr);
 144         char_string keyinf(cornum.c_str(), valloc);
 145         char_string mapped(corstr.c_str(), valloc);
 146         cormap_type value(keyinf, mapped);
 147         corpus_map->insert(value);
 148         corcnt++;
 149     }
 150     icf.close();
 151     log << "CorpusLoader\tCorpus  " <<
 152         corcnt << " lines constructed." << std::endl;
 153     log << "CorpusLoader\t        " << t.elapsed() <<
 154         " sec elapsed." << std::endl;
 155 
 156     // 共有メモリ上に title database map を構築
 157     t.restart(); // タイマーをリセット
 158     shmmap_type* tdb_map = segment.construct<shmmap_type>
 159                            ("TitleDBMap")(std::less<char_string>(), valloc);
 160     string tdbnum;
 161     string tdbstr;
 162     int tdbcnt = 0;
 163     while (itd && getline(itd, ldata)) {
 164         setcordata(ldata, tdbnum, tdbstr);
 165         char_string keyinf(tdbnum.c_str(), valloc);
 166         char_string mapped(tdbstr.c_str(), valloc);
 167         cormap_type value(keyinf, mapped);
 168         tdb_map->insert(value);
 169         tdbcnt++;
 170     }
 171     itd.close();
 172     log << "CorpusLoader\tTitleDB " << tdbcnt <<
 173         " lines constructed." << std::endl;
 174     log << "CorpusLoader\t        " << t.elapsed() <<
 175         " sec elapsed." << std::endl;
 176 
 177     // map のアドレスをクライアントに連絡するためのハンドル
 178     managed_shared_memory::handle_t handle = 0;
 179     // Config ファイル (すでにあったとしても内容を破棄)
 180     std::ofstream conf(CONFIG, std::ios::out | std::ios::trunc);
 181     // Corpus map
 182     void* mp = static_cast<void*>(corpus_map);
 183     handle = segment.get_handle_from_address(mp);
 184     log << "CorpusLoader\tCorpus handle:  " << handle << std::endl;
 185     conf << "CORPUSHDL=" << handle << std::endl;
 186     // Title DB map
 187     mp = static_cast<void*>(tdb_map);
 188     handle = segment.get_handle_from_address(mp);
 189     log << "CorpusLoader\tTitleDB handle: " << handle << std::endl;
 190     conf << "TITLDBHDL=" << handle << std::endl;
 191     conf.close();
 192 
 193     // PID ファイルに pid を書き込んで,共有メモリ処理完了を示す
 194     pidf.open(CLPIDF);
 195     pidf << pid;
 196     pidf.close();
 197 
 198     // 終了指示シグナルを待つ
 199     log << "CorpusLoader waiting for termination signals: " <<
 200         "SIGINT, SIGTERM, SIGHUP, SIGQUIT." << std::endl;
 201     while (flag) {
 202         if (sigwait(&ss, &signo) == 0) {
 203             switch (signo) {
 204             case SIGINT:
 205             case SIGTERM:
 206             case SIGHUP:
 207             case SIGQUIT:
 208                 log << "CorpusLoader signal " << signo <<
 209                     " accepted." << std::endl;
 210                 flag = false;
 211                 break;
 212             default:
 213                 log << "CorpusLoader signal " << signo <<
 214                     " ignored." << std::endl;
 215                 break;
 216             }
 217         }
 218     }
 219 
 220     // PID ファイル削除
 221     remove(CLPIDF);
 222     log << "CorpusLoader daemon terminated by signal " << signo <<
 223         "." << std::endl;
 224 
 225     return 0;
 226 }

/* [previous][next][first][last][top][bottom][index][help] */