DELAEMON BLOG

Live as if you were to die tomorrow. Learn as if you were to live forever.

Apache Module mod_dbd (ubuntu 12.4 apache install)

Apache Moduleからmod_dbdを使ってDBにアクセス、レコードの中身を表示してみる。
mod_dbdはapr(Apache Portable Runtime)を使ってデータベースを操作するもの。
http://httpd.apache.org/docs/2.4/mod/mod_dbd.html
http://apr.apache.org/

ubuntuにはmoduleを有効にするa2enmodと無効にするa2dismodがあるが
そもそもコンパイルに含まれていない関数を使ってる場合はmoduleのコンパイルは通っても

sudo /etc/init.d/apache2 start
 * Starting web server apache2
apache2: Syntax error on line 210 of /etc/apache2/apache2.conf: Syntax error on line 1 of /etc/apache2/mods-enabled/db.load: Cannot load /usr/lib/apache2/modules/mod_db.so into server: /usr/lib/apache2/modules/mod_db.so: undefined symbol: ap_dbd_acquire

undefined symbol: ap_dbd_acquireとなる。
apt-getとかデフォルトで入ってるapacheではたぶんこうなる。

apacheソースコードからビルドする。
apr,apr-utilも最新のものにする。
ubuntu 12.4には/usr/include/apr-1.0/が入ってるが1.2以上じゃないとビルドこけるらしい。

環境

#sakura vps
$ uname -a
Linux www28181ue 3.2.0-36-generic #57-Ubuntu SMP Tue Jan 8 21:44:52 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=12.04
DISTRIB_CODENAME=precise
DISTRIB_DESCRIPTION="Ubuntu 12.04.1 LTS"
$ sudo su - root
% cd /usr/local/src/
% wget http://ftp.jaist.ac.jp/pub/apache//httpd/httpd-2.4.4.tar.gz
% wget http://ftp.tsukuba.wide.ad.jp/software/apache//apr/apr-1.4.6.tar.gz
% wget http://ftp.tsukuba.wide.ad.jp/software/apache//apr/apr-util-1.5.2.tar.gz
% tar xvzf httpd-2.4.4.tar.gz
% tar xvzf apr-1.4.6.tar.gz
% tar xvzf apr-util-1.5.2.tar.gz
% mv apr-1.4.6 httpd-2.4.4/srclib/apr
% mv apr-util-1.5.2 httpd-2.4.4/srclib/apr-util

% cd  httpd-2.4.4/srclib/apr
% ./configure --prefix=/usr/include/apr-httpd/
% make && make install

% cd ../apr-util
% ./configure --prefix=/usr/include/apr-util-httpd/ --with-apr=/usr/include/apr-httpd/ --% with-mysql=/usr/include/mysql
% make && make install

% cd ../../
% ./configure --prefix=/usr/include/apache22 \
% --with-mpm=worker \
% --with-apr=/usr/include/apr-httpd/ \
% --with-apr-util=/usr/include/apr-util-httpd/ \
% --enable-mods-shared=all \
% --enable-modules=all \
% --enable-proxy \
% --enable-cache \
% --enable-disk-cache \
% --enable-mem-cache \
% --enable-ssl
% make && make install

起動。あとでpathを追加。

% /usr/include/apache22/bin/apachectl start

ちょいちょいlogs/error.log吐いたが、とりあえず動かしたいので
conf/httpd.confのslotmem_shmを有効にし、lynxを入れた。そういうログが出てた。

LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
# apt-get install lynx

これで動くようになる。
あとは/usr/include/apache22/bin/apxsでモジュールのひな形を作る。apache再起動でmoduleが有効になる。

$ cd /my/apache_modules
$ /usr/include/apache22/bin/apxs -g -n db
$ sudo /usr/include/apache22/bin/apxs -i -a -c mod_db.c
$ sudo /usr/include/apache22/bin/apachectl restart

mod_db.c ※変更点のみ記載

#include "apr_dbd.h"
#include "mod_dbd.h"
#include "apr_strings.h"


static void execute(request_rec *r)
{
    apr_status_t rv;
    apr_dbd_results_t *res;
    apr_dbd_row_t *row = NULL;
    char stmt[] = "select * from user";
    int rows,cols;

    ap_dbd_t *dbd = ap_dbd_acquire(r);
    if (dbd == NULL) {
        ap_rputs("failed to connect db.", r);
        return;
    }

    int code = apr_dbd_select(dbd->driver, r->pool, dbd->handle, &res, stmt, 0);
    if (code != 0) {
        ap_rprintf(r, "failed. error_code:%d", code);
        return;
    }

    rows = apr_dbd_num_tuples(dbd->driver, res);
    cols = apr_dbd_num_cols(dbd->driver, res);
    ap_rprintf(r, "rows:%d, cols:%d<br>", rows, cols);

    for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
         rv != -1;
         rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
        if (rv != 0) {
            ap_rputs("finish.", r);
            return;
        }
        
        int i;
        for (i = 0; i < cols; i++) {
            char *val = apr_palloc(r->pool, sizeof(char));
            val = apr_dbd_get_entry(dbd->driver, row, i);
            ap_rprintf(r, "%s ", val);
        }
        ap_rputs("<br>", r);
    }
}

/* The sample content handler */
static int db_handler(request_rec *r)
{
    if (strcmp(r->handler, "db")) {
        return DECLINED;
    }
    r->content_type = "text/html";

    if (!r->header_only)
        execute(r);
    return OK;
}

httpd.confにDBの接続情報を追記、moduleとディレクトリの紐付けも

<Location /db>
SetHandler db
</Location>

DBDriver mysql
DBDParams user=delaemon,host=localhost,pass=shizuka,dbname=dekisugi
DBDMin  5
DBDKeep 5
DBDMax  10
DBDExptime 60

mysqlは適当をインストールして、db,user,tableを作っておく。

http://your_host/db
でレコードの中身が画面に表示される。

apr_dbd_num_tuplesは
apr_dbd_select(dbd->driver, r->pool, dbd->handle, &res, stmt, 0);だと-1
apr_dbd_select(dbd->driver, r->pool, dbd->handle, &res, stmt, 1);だとレコード数が返る。

apr_dbd_selectは
成功の場合は0、もしくエラーコード(今回はmysqlのもの)が返される。

その他、apr_dbd_XXX使い方、返り値はソースコードか以下を参照
https://apr.apache.org/docs/apr/trunk/group___a_p_r___util___d_b_d.html

いろいろ調べてたらmod_sample.cを読むと学びがあるらしいので後で読む
http://svn.apache.org/repos/asf/httpd/httpd/branches/2.0.x/modules/experimental/mod_example.c