SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

ApacheModuleでWebアプリケーションをつくろう

コーディングでApacheModuleの開発プロセスをまなぶ

  • このエントリーをはてなブックマークに追加

7.mod_dbdのデータベースコネクションプールを使用したApacheモジュール

 さて、Apache ModuleによるWebアプリケーション作成の最終ステップです。今度はmod_dbdを利用した形にコードを修正します。現時点では画面表示用の文言をコード内に固定で持っていますが、これをデータベースから取得するように作り変えましょう。

 この章では以下の手順で作業を進めます。

  1. データベースの準備
  2. mod_dbdの導入確認
  3. httpd.confの修正
  4. Apache Moduleの修正
  5. Apache Moduleの動作確認

テスト用データの作成

 まずは、Apache Moduleからアクセスするための試験用データベースを準備しておきましょう。

データベースの作成
initdb --encoding=UTF-8 --no-locale
postmaster&
createdb hoge

 データベース作成後、自ホスト以外からもデータベースにアクセスできるようPostgreSQLの設定ファイルを変更します。「pg_hba.conf(74行目付近)」と「postgresql.conf(56行目付近)」にそれぞれ以下の内容で追記してください(※この例では 192.168.0.0/16 のネットワークに接続されている全ての端末からのアクセスを許可しています)。

/usr/local/postgres825/data/pg_hba.confへの追記内容
host    all         all         192.168.0.0/16        trust
/usr/local/postgres825/data/postgresql.confへの追記内容
listen_addresses = '*'

 設定ファイルを修正し終えたらPostgreSQLの再起動を行います。

PostgreSQLの再起動
pg_ctl stop
pg_ctl start

 データベースが無事起動したことを確認した後、PostgreSQLのGUIツール等(pgAdmin3)を使用してテーブルの作成とデータの登録を行ってください。

テーブルの作成とデータの登録
create table addrbook (name varchar(50),
                       telno varchar(50), email varchar(50));
insert into addrbook values('FOO',  '090-0000-****','aaaaa@hoge.com');
insert into addrbook values('BAR',  '080-0000-****','bbbbb@hoge.com');
insert into addrbook values('HOGE', '070-0000-****','ccccc@hoge.com');
insert into addrbook values('MONA', '060-0000-****','ddddd@hoge.com');

mod_dbdの導入確認

 Apache Moduleの作成を行う前に、mod_dbdが導入されていることも確認しておきましょう。下記に示すコマンドで、現在使用しているApache HTTP Serverにmod_dbdが組み込まれているか確認することができます。

httpd -M

 コマンド実行後、「dbd_module (shared)」が表示されていればmod_dbdは組み込まれています。表示されていない場合は付録を参考にインストールしなおして下さい。

httpd.confの修正

 次にmod_dbdを有効にするために「/usr/local/apache22/conf/httpd.conf」の最終行付近に以下の内容を追記し、Apache HTTP Serverを再起動します(※mod_dbdの詳細は「Apache Module mod_dbd」を参照ください)。

httpd.conf
DBDriver pgsql
DBDParams "dbname=hoge user=postgres password=postgres"
DBDMin  5
DBDKeep 5
DBDMax  10
DBDExptime 60

Apache Moduleの修正

 ここまで準備が済んだところでApache Moduleの修正を行いましょう。表示用データをPostgreSQLから取得するように変更します。

対応するサンプルコード
  1 #define ap_psprintf apr_psprintf
  2
  3 #include "httpd.h"
  4 #include "http_config.h"
  5 #include "http_protocol.h"
  6 #include "ap_config.h"
  7 #include "ClearSilver.h"
  8
    /*mod_dbdに必要なヘッダファイルの読込*/
  9 #include "apr_dbd.h"
 10 #include "mod_dbd.h"
 11 #include "apr_strings.h"
 12
 13
 14 static NEOERR *render_cb(void *obj, char *s)
 15 {
 16     request_rec *r = (request_rec *)obj;
 17     ap_rputs(s, r);
 18     return STATUS_OK;
 19 }
 20
 21 static void output_handler(request_rec *r)
 22 {
 23     HDF *hdf;
 24     CSPARSE *cs;
 25
 26     int i=0;
 27     hdf_init(&hdf);
 28
 29     
 30     
        /*DBからデータを取得した際の状態を保持する変数*/
 31     apr_status_t rv;
        /*検索の結果セットを保持する変数*/
 32     apr_dbd_results_t *res = NULL;
        /*結果セットの行情報を保持する変数*/
 33     apr_dbd_row_t *row = NULL;
        /*DBに対して実行するSQL文*/
 34     char stmt[]  = "select name,telno,email from addrbook";
 35
        /*mod_dbdコネクションプールからコネクション情報を取得*/
 36     ap_dbd_t *dbd = ap_dbd_acquire(r);
 37     if (dbd == NULL) {
      /*失敗時は処理を中止*/
 38         return;
 39     }
 40
    /*検索処理の実行*/
 41     if (apr_dbd_select
                (dbd->driver, r->pool, dbd->handle, &res, stmt,1) != 0)
 42     {
      /*失敗時は処理を中止*/
 43         return;
 44     }
 45
        /*結果のレコード数分ループ*/
 46     for (rv = apr_dbd_get_row
                    (dbd->driver, r->pool, res, &row, -1);
 47         rv != -1;
 48         rv = apr_dbd_get_row
                    (dbd->driver, r->pool, res, &row, -1)) {
 49
            /*レコードの取得に失敗した場合は処理を中止*/
 50         if (rv != 0) {
 51             return;
 52         }
            /*各カラムの情報を取得するためにAPRを使用してメモリ確保*/
 53         char  *name  = apr_palloc(r->pool,sizeof(char));
            /*カラムの情報をメモリに格納*/
 54         name  = apr_dbd_get_entry(dbd->driver, row, 0);
 55
 56         hdf_set_value(hdf, ap_psprintf( r->pool, 
                            "csdata.%d.arrayname", i ), name );
 57         i++;
 58
 59     }
 60
 61     cs_init(&cs, hdf);
 62     cs_parse_file(cs, "/usr/local/src/modtest/test/test.cs");
 63     cs_render(cs, r, render_cb);
 64     cs_destroy(&cs);
 65     hdf_destroy(&hdf);
 66 }
 67
 68
 69
 70 /* The sample content handler */
 71 static int test_handler(request_rec *r)
 72 {
 73
 74     if (strcmp(r->handler, "test")) {
 75         return DECLINED;
 76     }
 77
 78     r->content_type = "text/html";
 79
 80     if (!r->header_only)
 81         output_handler(r);
 82     return OK;
 83 }
 84
 85 static void test_register_hooks(apr_pool_t *p)
 86 {
 87     ap_hook_handler(test_handler, NULL, NULL, APR_HOOK_MIDDLE);
 88 }
 89
 90 /* Dispatch list for API hooks */
 91 module test_module = {
 92     STANDARD20_MODULE_STUFF,
 93     NULL,                /* create per-dir    config structures */
 94     NULL,                /* merge  per-dir    config structures */
 95     NULL,                /* create per-server config structures */
 96     NULL,                /* merge  per-server config structures */
 97     NULL,                /* table of config file commands       */
 98     test_register_hooks  /* register hooks                      */
 99 };
100
 ※左側に番号の無い行のコメント表記は、説明の便宜上記載しています。

 ところで、53行目で確保したメモリの廃棄が、その後行われていないことに気づいたでしょうか?

 APRは実行環境の隠蔽を行いますが、これは開発時のメモリ管理に関するコーディングについても当てはまります。今回の場合は、メモリはRequestオブジェクトから取得を行い、このRequestオブジェクトが破棄されるときに同時に開放されます。誤解を恐れずに言うと、Javaで言うところのガベッジコレクションに似たこと(※1)をメモリ開放の際にAPRは行ってくれるので、C言語でよくある「malloc()した際にはfree()を忘れないこと」をあまり意識しなくてもよくなります。

※1
 APR メモリプールのリソースライフタイムに関する詳細については以下を参照して下さい。
 The Apache Module Book :3.4.2 APR Pools(61ページ)
 井上の日誌 -Apacheの話- :https://www.codeblog.org/blog/inoue/200602.html

 ちなみに上記コードには記載していませんが、「http_log.h」をインクルードした上で、54行目の記載を下記のように変更すると、ログに検索結果の件数とカラム数が記録されます(※「ap_log_rerror」のAPIは「http_log.h」を参照のこと)。

検索結果の件数とカラム数出力のためのコード
int rows = apr_dbd_num_tuples(dbd->driver,res);
int cols = apr_dbd_num_cols(dbd->driver,res);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
    0, r,"row count =  %d, col count = %d ",rows,cols);
ログへの出力例
[debug] mod_test.c(49): [client xxx.xxx.xxx.xxx] row count =  50, col count = 3

Apache Moduleの動作確認

 ここでまでの作業が済んだら動作確認を行いましょう。Apache停止、mod_testのコンパイル・インストール、Apache再起動という流れで作業を行います。なお、ここでの目的はデータの取得元の変更のみですから、ClearSilverのファイル「test.cs」の修正は行いません。

mod_testのコンパイル・インストール
apachectl stop
make clean
make all install
apachectl start

 ブラウザから「http://(ApahceHTTPサーバが動作しているホスト)/test/」にアクセスし、動作を確認しましょう。結果は以下のようになります。

動作確認結果
動作確認結果

次のページ
8.JNDIのデータベースコネクションプールを使用したJava Webアプリケーション

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

タケル(タケル)

攻殻機動隊の『笑い男』に憧れていて、いつかタチコマには追いつきたいと願うSE

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/2502 2008/06/16 14:30

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング