www.pudn.com > AirAPIF.rar > AirAPIF.cc


// logfile, outlog の初期化終了化
// logfile の lock 処理
#ifndef lint
static char copyright[] = "Copyright (C) FUJITSU LIMITED 1999-2001" ;
static char id[] = "$Id: AirAPIF.cc,v 1.6 2001/03/05 16:01:46 JST age Exp $" ;
#endif
/*
 * $Log: AirAPIF.cc,v $
 * Revision 1.6  2001/03/05 16:01:46 JST  age
 * 古川  AIR_EVENT_SYMBOLPORT 対応
 *
 * Revision 1.5  2000/07/05 15:53:22 JST  age
 * 古川
 *   - AirAPIF::release で終了化の順序を修正
 *
 * Revision 1.4  2000/06/26 15:12:50 JST  age
 * 古川
 *   - AIR_ENVKEY_APIF_TMP, AIR_ENVKEY_APIF_LOG_PREFIX を air_envkey.h
 *     に移動
 *   - コンストラクタに activate_arch の初期化を追加
 *   - AirAPIF::release に activate_arch, arch_list の終了化を追加
 *   - operator<< に arch_list, activate_arch を追加
 *
 * Revision 1.3  2000/05/22 18:53:34 JST  age
 * 古川  get_part_name 引数の型変更
 *
 * Revision 1.2  2000/03/03 17:09:52 JST  age
 * *** empty log message ***
 *
 * $Com: 古川  AIR_EVENT_SYMBOLPORT 対応
 */
//
// AirAPIF
//

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "air_all.h"


// クラス変数の初期化
bool AirAPIF::inhandler_f = false;


//
// MODULE   : AirAPIF::AirAPIF
// ABSTRACT : AirAPIF コンストラクタ
// FUNCTION : 変数の初期化等を行なう。
//
AirAPIF::AirAPIF(void)
    : program_name(NULL_PTR), program_version(NULL_PTR),
      program_date(0), env(NULL_PTR), msg(NULL_PTR),
      logfile(NULL_PTR), noleft_access_f(false), activate_part(NULL_PTR),
      activate_arch(NULL_PTR)
{
    uid = getuid();

    struct passwd* pw = getpwuid(uid);
    if (pw != NULL_PTR) {
        try {
            username = new char[strlen(pw->pw_name) + 1];
            strcpy(username, pw->pw_name);
        }
        catch (...) {
            username = NULL_PTR;
        }
    }
    else {
        username = NULL_PTR;
    }

    struct utsname unam;
    struct hostent *hp;
    struct in_addr in;
    if (uname(&unam) < 0) {
        hostname = NULL_PTR;
        hostip = NULL_PTR;
    }
    else if ((hp = gethostbyname(unam.nodename)) == NULL_PTR) {
        try {
            hostname = new char[strlen(unam.nodename) + 1];
            strcpy(hostname, unam.nodename);
        }
        catch (...) {
            hostname = NULL_PTR;
        }
        hostip = NULL_PTR;
    }
    else {
        try {
            hostname = new char[strlen(hp->h_name) + 1];
            strcpy(hostname, hp->h_name);
        }
        catch (...) {
            hostname = NULL_PTR;
        }
        memcpy(&in.s_addr, hp->h_addr_list[0], sizeof (in.s_addr));
        try {
            char* p = inet_ntoa(in);
            hostip = new char[strlen(p) + 1];
            strcpy(hostip, p);
        }
        catch (...) {
            hostip = NULL_PTR;
        }
    }

    pid = getpid();

    char path[PATH_MAX];
    if (getcwd(path, PATH_MAX) == NULL_PTR) {
        cwd = NULL_PTR;
    }
    else {
        try {
            cwd = new char[strlen(path) + 1];
            strcpy(cwd, path);
        }
        catch (...) {
            cwd = NULL_PTR;
        }
    }
}


//
// MODULE   : AirAPIF::~AirAPIF
// ABSTRACT : AirAPIF デストラクタ
// FUNCTION : 動的に確保した領域の解放を行なう。
//
AirAPIF::~AirAPIF(void)
{
    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::~AirAPIF()" << endl;
    }

    if (username != NULL_PTR) {
        delete[] username;
    }
    if (hostname != NULL_PTR) {
        delete[] hostname;
    }
    if (hostip != NULL_PTR) {
        delete[] hostip;
    }
    if (cwd != NULL_PTR) {
        delete[] cwd;
    }

    release();

}


//
// MODULE   : AirAPIF::init
// ABSTRACT : APIF環境初期化
// FUNCTION : APIF関数システムの環境初期化を行なう。
// RETURN   : AIR_R_SUCCESS  : 正常終了
//            AIR_R_ALREADY  : 既に初期化済み
//            AIR_R_NOMEM    : new に失敗(メモリ不足等)
//            AIR_R_NOKEY    : メッセージパスの取得に失敗
//
int32_t AirAPIF::init(
    int argc,            // (i) argc
    char* argv[],        // (i) argv
    const char* opt)     // (i) ファイル指示オプション "-f" 等
{
    int32_t rc = AIR_R_SUCCESS;

    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::init( "
               << argc << " , " << argv << " , " << opt << " )" << endl;
    }

    // 環境の初期化
    if (env != NULL_PTR) {
        // 既に初期化されている?
        // エラー
        rc = AIR_R_ALREADY;
        goto last;
    }
    else {
        try {
            if (opt == NULL_PTR) {
                env = new AirCfEnv(argc, argv);
            }
            else {
                env = new AirCfEnv(argc, argv, opt);
            }
        }
        catch (...) {
            // new でエラー
            rc = AIR_R_NOMEM;
            goto last;
        }

        // メッセージ初期化
        char *buf = NULL_PTR;
        int32_t lv = env->get_var(AIR_ENVKEY_MESSAGE_PATHNAME, NULL_PTR, &buf);
        if (lv != AIR_R_SUCCESS) {
            // 取得に失敗
            // エラー
            rc = AIR_R_NOKEY;
            goto last;
        }

        try {
            msg = new AirCfMsg(buf);
        }
        catch (...) {
            // new でエラー
            rc = AIR_R_NOMEM;
            goto last;
        }
        delete[] buf;

        // メッセージの設定
        // スタックの設定等を行なう
        // not implement
    }

last:
    return rc;
}


//
// MODULE   : AirAPIF::release
// ABSTRACT : APIF環境終了化
// FUNCTION : APIF関数システムの環境終了化を行なう。
// RETURN   : AIR_R_SUCCESS  : 正常終了
//
int32_t AirAPIF::release(void)
{
    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::release()" << endl;
    }

    activate_part = NULL_PTR;
    while (! part_list.empty()) {
        part_list.back()->release();
        part_list.pop_back();
    }

    activate_arch = NULL_PTR;
    while (! arch_list.empty()) {
        AirIfArch* p = arch_list.back();
        p->release();
        arch_list.pop_back();
        p->part = NULL_PTR; // 念のため
        delete p;
    }

    logoff();

    if (env != NULL_PTR) {
        delete env;
        env = NULL_PTR;
    }
    if (msg != NULL_PTR) {
        delete msg;
        msg = NULL_PTR;
    }

    if (program_name != NULL_PTR) {
        delete[] program_name;
        program_name = NULL_PTR;
    }
    if (program_version != NULL_PTR) {
        delete[] program_version;
        program_version = NULL_PTR;
    }
    program_date = 0;

    noleft_access_f = false;

    return AIR_R_SUCCESS;
}


//
// MODULE   : AirAPIF::set_program
// ABSTRACT : プログラム設定
// FUNCTION : 実行しているプログラムの名前、バージョン、作成日付を設定する。
//            設定を行なうと、ログファイル等に情報が記載される。
// RETURN   : AIR_R_SUCCESS  : 正常終了
//            AIR_R_ALREADY  : 既に設定済み
//            AIR_R_NOMEM    : new に失敗(メモリ不足等)
//
int32_t AirAPIF::set_program(
    char* name,    // (i) プログラム名
    char* version, // (i) プログラムバージョン
    time_t date)   // (i) プログラム作成日付
{
    int32_t rc = AIR_R_SUCCESS;

    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::set_program( "
               << name << " , " << version << " , " << date << " )" << endl;
    }

    if (name != NULL_PTR) {
        if (program_name == NULL_PTR) {
            try {
                program_name = new char[strlen(name) + 1];
                strcpy(program_name, name);
            }
            catch (...) {
                // メモリ不足
                // not implement
                rc = AIR_R_NOMEM;
            }
        }
        else {
            // 既に設定されている
            // not implement
            rc = AIR_R_ALREADY;
        }
    }
    if (version != NULL_PTR) {
        if (program_version == NULL_PTR) {
            try {
                program_version = new char[strlen(version) + 1];
                strcpy(program_version, version);
            }
            catch (...) {
                // メモリ不足
                // not implement
                rc = AIR_R_NOMEM;
            }
        }
        else {
            // 既に設定されている
            // not implement
            rc = AIR_R_ALREADY;
        }
    }
    if (date != 0) {
        if (program_date == 0) {
            program_date = date;
        }
        else {
            // 既に設定されている
            // not implement
            rc = AIR_R_ALREADY;
        }
    }

    return rc;
}


//
// MODULE   : AirAPIF::logging
// ABSTRACT : ログファイルの設定
// FUNCTION : APIF関数システム起動中の処理経過を記録する。
//            ログファイルの設定を行なった場合、APIF関数(AirAPIF, AirPart,
//            AirArch, AirSeq, AirViewer の public メンバ関数) が呼ばれる毎に
//            ファイルに記録する。
// RETURN   : AIR_R_SUCCESS  : 正常終了
//            AIR_R_ALREADY  : 既に記録中
//            AIR_R_NOMEM    : new に失敗(メモリ不足等)
//            AIR_R_NOKEY    : ログファイル名の取得に失敗
//            AIR_R_NACCESS  : ファイル open に失敗
//
int32_t AirAPIF::logging(
    const char* file) // (i) 実行log出力ファイル名。
                      // NULL_PTR の時は、/tmp の下に
                      // "air_log_プロセスID" で作成する。
{
    int32_t rc = AIR_R_SUCCESS;
    char *buf = NULL_PTR;
    char *buf2 = NULL_PTR;

    if (outlog.is_open()) {
        // 既に開いている
        rc = AIR_R_ALREADY;
        goto last;
    }

    if (file != NULL_PTR) {
        try {
            logfile = new char[strlen(file) + 1];
            strcpy(logfile, file);
        }
        catch (...) {
            rc = AIR_R_NOMEM;
            goto last;
        }
    }
    else {
        // ファイル名の作成
        int32_t lv = env->get_var(AIR_ENVKEY_APIF_TMP, NULL_PTR, &buf);
        if (lv != AIR_R_SUCCESS) {
            // 取得に失敗
            // エラー
            rc = AIR_R_NOKEY;
            goto last;
        }
        lv = env->get_var(AIR_ENVKEY_APIF_LOG_PREFIX, NULL_PTR, &buf2);
        if (lv != AIR_R_SUCCESS) {
            // 取得に失敗
            // エラー
            rc = AIR_R_NOKEY;
            goto last;
        }

        try {
            logfile = new char[strlen(buf) + strlen(buf2) + 16];

            ostringstream str;
            str << buf << "/" << buf2 << pid;
            strcpy(logfile, str.str().c_str());
        }
        catch (...) {
            rc = AIR_R_NOMEM;
            goto last;
        }
    }

    outlog.open(logfile);
    if (outlog.fail()) {
        // オープンに失敗
        rc = AIR_R_NOACCESS;
        goto last;
    }

    // 実行ログファイルヘッダの出力
    outlog << "# " << program_name << " " << program_version << " "
           << air_cf_date << " begin" << endl;

last:
    if (buf != NULL_PTR) {
        delete[] buf;
    }
    if (buf2 != NULL_PTR) {
        delete[] buf2;
    }
    return rc;
}


//
// MODULE   : AirAPIF::logoff
// ABSTRACT : 実行ログ記録の終了
// FUNCTION : APIF関数システム起動中の処理経過を記録を終了する。
// RETURN   : AIR_R_SUCCESS  : 正常終了
//
int32_t AirAPIF::logoff(void)
{
    int32_t rc = AIR_R_SUCCESS;

    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::logoff()" << endl;
    }

    if (outlog.is_open()) {
        // 実行ログファイルフッタの出力
        outlog << "# " << program_name << " " << program_version << " "
               << air_cf_date << " end"<< endl;
        outlog.close();
    }
    else {
        // 実はログを開始していなかった
        // not implement
    }

    if (logfile != NULL_PTR) {
        delete[] logfile;
        logfile = NULL_PTR;
    }

    return rc;
}


//
// MODULE   : AirAPIF::add_handler
// ABSTRACT : event handler の追加
// FUNCTION : event handler を追加する。
// RETURN   : AIR_R_SUCCESS  : 正常終了
// NOTE     : 登録する関数内部では、APDB を参照することはできるが、追加、
//            削除、変更することは禁止する。
//
int32_t AirAPIF::add_handler(
    AirEventHandler handler, // (i) 登録する関数。関数の型は、
                             // int32_t function(AirArch* arch, AirDBKind kind, AirDBAnyRef obj)
                             // となっていなければならない。kind には要素の種類
                             // obj には、要素のテーブル番号が入る。
    AirEventKind kind,       // (i) どの操作に関するイベントかを指示する。
                             // AIR_EVENT_APIF      : システム関係
                             // AIR_EVENT_PART      : パート関係
                             // AIR_EVENT_ARCH      : ARCH 関係
                             // AIR_EVENT_BLOCK     : ブロック関係
                             // AIR_EVENT_PORT      : ポート関係
                             // AIR_EVENT_NET       : ネット関係
                             // AIR_EVENT_PAGE      : ページ関係
                             // AIR_EVENT_GROUP     : グループ関係
                             // AIR_EVENT_COMPONENT : コンポーネント関係
                             // AIR_EVENT_COMPONENTPORT : コンポーネントポート関係
                             // AIR_EVENT_SYMBOL    : シンボル関係
                             // AIR_EVENT_SYMBOLPORT : シンボルポート関係
                             // AIR_EVENT_APPL      : APPL 定義関係
    AirEventType type,       // (i) どのイベントの時に handler を実行するかを
                             // 指示する。
                             // AIR_EVENT_ADD  : kind を追加・作成する時
                             // AIR_EVENT_DEL  : kind が削除する時
                             // AIR_EVENT_MOD  : kind が変更・更新する時
                             // AIR_EVENT_SEQ  : kind が sequential read する時

    AirEventMode mode,       // (i) handler を実行するタイミングを指示する。
                             // AIR_EVENT_BEFORE    : type が起きる直前に実行
                             // AIR_EVENT_AFTER     : type が起きた直後に実行
    AirEventOrder order)     // (i) 複数 handler が登録されている時、その実行
                             // 順序を指定する。
                             // AIR_EVENT_FIRST     : 最初に実行
                             // AIR_EVENT_LAST      : 最後に実行
{
    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::add_handler( "
               << handler << " , " << kind << " , " << type << " , "
               << mode << " , " << order << " )" << endl;
    }

    if (order == AIR_EVENT_FIRST) {
        event[kind][type][mode].push_front(handler);
    }
    else {
        event[kind][type][mode].push_back(handler);
    }


    return AIR_R_SUCCESS;
}


//
// MODULE   : AirAPIF::del_handler
// ABSTRACT : event handler の削除
// FUNCTION : event handler を削除する。
// RETURN   : AIR_R_SUCCESS  : 正常終了
//            AIR_R_NOEXIST  : event handler が存在しない
//
int32_t AirAPIF::del_handler(
    AirEventHandler handler, // (i) 削除する関数。
    AirEventKind kind,       // (i) どの操作に関するイベントかを指示する。
    AirEventType type,       // (i) どのイベントの時に handler を実行するかを
                             // 指示する。
    AirEventMode mode)       // (i) handler を実行するタイミングを指示する。
{
    int32_t rc = AIR_R_SUCCESS;

    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::del_handler( "
               << handler << " , " << kind << " , " << type << " , "
               << mode << " )" << endl;
    }

#if 0
    for (deque::iterator iter
             = event[kind][type][mode].begin();
         iter != event[kind][type][mode].end(); ++iter) {
        if (*iter == handler) {
            event[kind][type][mode].erase(iter);
            break;
        }
    }
#else
    deque::iterator iter;
    iter = find(event[kind][type][mode].begin(),
                event[kind][type][mode].end(),
                handler);
    if (iter != event[kind][type][mode].end()) {
        event[kind][type][mode].erase(iter);
    }
    else {
        rc = AIR_R_NOEXIST;
    }
#endif

    return rc;
}


// MODULE   : AirAPIF::line_editor
// ABSTRACT : 言語入力 (未サポート)
// FUNCTION : 言語入力の API。言語入力により APDB の作成を行なう
// RETURN   : AIR_R_SUCCESS  : 正常終了
//
int32_t AirAPIF::line_editor(
    const char* inputstring) // (i) 言語
{
    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::line_editor( "
               << inputstring << " )" << endl;
    }

    return AIR_R_SUCCESS;
}


//
// MODULE   : AirAPIF::get_part_num
// ABSTRACT : パート数の獲得
// FUNCTION : あるディレクトリ内にある、パートの数を得る。
// RETURN   : >=0            : パート数
//            AIR_R_NODIR    : ディレクトリが開けない
//
int32_t AirAPIF::get_part_num(
    const char* dirname) // (i) ディレクトリ名
{
    int32_t rc = 0;
    size_t d_name_len;
    char path[PATH_MAX];
    int32_t n_part = 0;

    DIR* dirp = NULL_PTR;
    struct dirent* direntp;
    struct stat buf;

    size_t part_suffix_len = strlen(AIR_FILE_PART_SUFFIX);
    size_t ignore_prefix_len = strlen(AIR_FILE_IGNORE_PREFIX);

    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::get_part_num( "
               << dirname << " )" << endl;
    }

    if ((dirp = opendir(dirname)) == NULL_PTR) {
        // ディレクトリが open できない
        rc = AIR_R_NODIR;
        goto last;
    }

    while ((direntp = readdir(dirp)) != NULL_PTR) {
        if (strncmp(direntp->d_name, AIR_FILE_IGNORE_PREFIX,
                    ignore_prefix_len) == 0) {
            // 先頭 . は除外
            continue;
        }

        d_name_len = strlen(direntp->d_name);
        if (strcmp(&(direntp->d_name[d_name_len - part_suffix_len]),
                   AIR_FILE_PART_SUFFIX) == 0) {
            // サフィックスが一致

            strcpy(path, dirname);
            strcat(path, "/");
            strcat(path, direntp->d_name);
            strcat(path, "/");
            strcat(path, AIR_FILE_ENV_NAME);
            strcat(path, AIR_FILE_DB_SUFFIX);
            if (stat(path, &buf) == 0 && S_ISREG(buf.st_mode)) {
                // env.db がある
                n_part++;
            }
        }
    }
    closedir(dirp);
    rc = n_part;

last:
    return rc;
}


//
// MODULE   : AirAPIF::get_part_name
// ABSTRACT : パート名の獲得
// FUNCTION : あるディレクトリ内にある、パートの名前をすべて得る。
// RETURN   : AIR_R_SUCCESS  : 正常終了
//            AIR_R_NODIR    : ディレクトリが開けない
//            AIR_R_NOMEM    : new に失敗(メモリ不足等)
// NOTE     : partname の領域が使いおわったら、"delete" で削除すること。
//            例) for (i = 0; i < partname_num; i++) {
//                    delete[] partname[i];
//                }
//                delete[] partname;
//
int32_t AirAPIF::get_part_name(
    const char* dirname,   // (i) ディレクトリ名
    char**& partname,      // (o) パート名の配列
    int32_t& partname_num) // (o) partname の配列の大きさ
{
    int32_t rc = AIR_R_SUCCESS;
    size_t d_name_len;
    char path[PATH_MAX];
    int32_t n_part = 0;
    int32_t i_part = 0;

    DIR* dirp = NULL_PTR;
    struct dirent* direntp;
    struct stat buf;

    size_t part_suffix_len = strlen(AIR_FILE_PART_SUFFIX);
    size_t ignore_prefix_len = strlen(AIR_FILE_IGNORE_PREFIX);

    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::get_part_name( "
               << dirname << " , " << partname << " , " << partname_num
               << " )" << endl;
    }

    n_part = get_part_num(dirname);
    if (n_part < 0) {
        // パート数獲得に失敗
        rc = n_part;
        goto last;
    }

    try {
        partname = new char*[n_part];
    }
    catch (...) {
        rc = AIR_R_NOMEM;
        goto last;
    }

    if ((dirp = opendir(dirname)) == NULL_PTR) {
        // ディレクトリが open できない
        rc = AIR_R_NODIR;
        goto last;
    }

    while ((direntp = readdir(dirp)) != NULL_PTR) {
        if (strncmp(direntp->d_name, AIR_FILE_IGNORE_PREFIX,
                    ignore_prefix_len) == 0) {
            // 先頭 . は除外
            continue;
        }

        d_name_len = strlen(direntp->d_name);
        if (strcmp(&(direntp->d_name[d_name_len - part_suffix_len]),
                   AIR_FILE_PART_SUFFIX) == 0) {
            // サフィックスが一致

            strcpy(path, dirname);
            strcat(path, "/");
            strcat(path, direntp->d_name);
            strcat(path, "/");
            strcat(path, AIR_FILE_ENV_NAME);
            strcat(path, AIR_FILE_DB_SUFFIX);
            if (stat(path, &buf) == 0 && S_ISREG(buf.st_mode)) {
                // env.db がある

                // パート名を格納する
                try {
                    partname[i_part] = new char[d_name_len - part_suffix_len + 1];
                    memcpy(partname[i_part], direntp->d_name,
                           d_name_len - part_suffix_len);
                    partname[i_part][d_name_len - part_suffix_len] = '\0';
                }
                catch (...) {
                    closedir(dirp);
                    rc = AIR_R_NOMEM;
                    goto last;
                }

                i_part++;
            }
        }
    }
    closedir(dirp);

last:
    return rc;
}


//
// MODULE   : AirAPIF::before_event
// ABSTRACT : 実行前 event 実行
// FUNCTION : AIR_EVENT_BEFORE で登録された event handler を実行する。
// RETURN   : exec_event() と同じ
//
int32_t AirAPIF::before_event(
    AirEventKind kind, // (i) どの操作に関するイベントかを指示する。
    AirEventType type, // (i) どのイベントの時に handler を実行するかを指示
                       // する。
    AirDBAnyRef obj)   // (i) 要素のテーブル番号
{
    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::before_event( "
               << kind << " , " << type << " , " << obj << " )" << endl;
    }

    return exec_event(kind, type, AIR_EVENT_BEFORE, obj);
}


//
// MODULE   : AirAPIF::after_event
// ABSTRACT : 実行後 event 実行
// FUNCTION : AIR_EVENT_AFTER で登録された event handler を実行する。
// RETURN   : exec_event() と同じ
//
int32_t AirAPIF::after_event(
    AirEventKind kind, // (i) どの操作に関するイベントかを指示する。
    AirEventType type, // (i) どのイベントの時に handler を実行するかを指示
                       // する。
    AirDBAnyRef obj)   // (i) 要素のテーブル番号
{
    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::after_event( "
               << kind << " , " << type << " , " << obj << " )" << endl;
    }

    return exec_event(kind, type, AIR_EVENT_AFTER, obj);
}


//
// MODULE   : AirAPIF::exec_event
// ABSTRACT : 実行前 event 実行
// FUNCTION : event handler を実行する。
//            event handler を実行する時に、inhandler_f が true になり、
//            実行が完了すると、false になる。inhandler_f が true の間は、
//            event handler は実行されない(多重実行なし)。
// RETURN   : AIR_R_SUCCESS  : 正常終了
//            AIR_R_ALREADY  : 既に実行中
//            AIR_R_NOARCH   : アーキテクチャがみつからない
//            AIR_R_ERROR    : event handler 実行中のエラー
//
int32_t AirAPIF::exec_event(
    AirEventKind kind, // (i) どの操作に関するイベントかを指示する。
    AirEventType type, // (i) どのイベントの時に handler を実行するかを指示
                       // する。
    AirEventMode mode, // (i) handler を実行するタイミングを指示する。
    AirDBAnyRef obj)   // (i) 要素のテーブル番号
{
    int32_t rc = AIR_R_SUCCESS;
    int32_t lv;

    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::exec_event( "
               << kind << " , " << type << " , " << mode << " , "
               << obj << " )" << endl;
    }

    // event handler を既に実行しているか?
    if (inhandler_f) {
        // 既に実行中
        rc = AIR_R_ALREADY;
        goto last;
    }

    // 活性化しているArch を探す
    AirArch* a_arch;
    if (activate_arch != NULL_PTR) {
        a_arch = activate_arch;
    }
    else {
        // 活性化している Arch がみつからない
        rc = AIR_R_NOARCH;
        goto last;
    }

    // event handler 実行中
    inhandler_f = true;

    for (deque::iterator iter
             = event[kind][type][mode].begin();
         iter != event[kind][type][mode].end(); ++iter) {
        switch (kind) {
        case AIR_EVENT_BLOCK:
            lv = (*iter)(a_arch, AIR_DB_STACK_TYPE, obj);
            break;
        case AIR_EVENT_PORT:
            lv = (*iter)(a_arch, AIR_DB_PORTINFO_TYPE, obj);
            break;
        case AIR_EVENT_NET:
            lv = (*iter)(a_arch, AIR_DB_NETINFO_TYPE, obj);
            break;
        case AIR_EVENT_PAGE:
            lv = (*iter)(a_arch, AIR_DB_PAGE_TYPE, obj);
            break;
        case AIR_EVENT_GROUP:
            lv = (*iter)(a_arch, AIR_DB_GROUP_TYPE, obj);
            break;
        case AIR_EVENT_COMPONENT:
            lv = (*iter)(a_arch, AIR_DB_COMPONENTINFO_TYPE, obj);
            break;
        case AIR_EVENT_COMPONENTPORT:
            lv = (*iter)(a_arch, AIR_DB_COMPONENTPORTINFO_TYPE, obj);
            break;
        case AIR_EVENT_SYMBOL:
            lv = (*iter)(a_arch, AIR_DB_SYMBOL_TYPE, obj);
            break;
        case AIR_EVENT_SYMBOLPORT:
            lv = (*iter)(a_arch, AIR_DB_SYMBOLPORT_TYPE, obj);
            break;
        case AIR_EVENT_APPL:
            lv = (*iter)(a_arch, AIR_DB_APPLDEF_TYPE, obj);
            break;
        default:
            // エラー
            lv = AIR_R_ERROR;
        }
        if (lv != AIR_R_SUCCESS) {
            rc = AIR_R_ERROR;
        }
    }

    // event handler 終了
    inhandler_f = false;

last:
    return rc;
}



//
// MODULE   : AirAPIF::noleft_access
// ABSTRACT : アクセス記録を残さない
// FUNCTION : これからロードまたは新規作成するアーキテクチャに対して、
//            アクセス記録を残さない。この関数を実行しなければ、アクセス
//            記録は残す。
// RETURN   : AIR_R_SUCCESS  : 正常終了
//
int32_t AirAPIF::noleft_access(
    bool flag) // (i) true ならば残さない、false ならば残す。
               // 省略時は、true となる。
{
    // 実行ログ
    if (outlog.is_open()) {
        outlog << air_cf_date
               << "AirAPIF::noleft_access( "
               << flag << " )" << endl;
    }

    noleft_access_f = flag;

    return AIR_R_SUCCESS;
}



//
// MODULE   : operator<<
// ABSTRACT : AirAPIF の print
// FUNCTION : AirAPIF のオブジェクトの内容を ostream に出力する
// RETURN   : ostream
//
ostream& operator<<(ostream& ostr, const AirAPIF& a)
{
    ostr << "program_name(" << a.program_name << ")  ";
    ostr << "program_version(" << a.program_version << ")  ";
    ostr << "program_date(" << a.program_date << ")  ";
    ostr << "uid(" << a.uid << ")  ";
    ostr << "usename(" << a.username << ")  ";
    ostr << "hostname(" << a.hostname << ")  ";
    ostr << "hostip(" << a.hostip << ")  ";
    ostr << "pid(" << a.pid << ")  ";
    ostr << "cwd(" << a.cwd << ")  ";
    ostr << "logfile(" << a.logfile << ")  ";
    ostr << "event(" << a.event << ")  ";
    ostr << "inhandler_f(" << a.inhandler_f << ")  ";
    ostr << "noleft_access_f(" << a.noleft_access_f << ")  ";
    ostr << "part_list(" << a.part_list << ")  ";
    ostr << "activate_part(" << a.activate_part << ")  ";
    ostr << "arch_list(" << a.arch_list << ")  ";
    ostr << "activate_arch(" << a.activate_arch << ")  ";

    return ostr;
}