2014年4月14日月曜日

apr_skiplist とmod_dialupモジュール

httpd-2.4.7で行われている変更:
Changes with Apache 2.4.7

  *) APR 1.5.0 or later is now required for the event MPM.
これがなぜだろう、というblogを見かけた。

同じblogの記事内に、以下のconfig.logのメッセージが紹介されている。
configure:25866: result: no - APR skiplist is not available

したがって、これは、以下の関係だろうと想像された。
Changes for APR 1.5.0
 :

  *) Add apr_skiplist family. [Jim Jagielski]

blogを書かれた方の意図はともかく、少し調べてみるとこれに関連した 2.4系branch の修正は、次のcommitで行われていた。
http://svn.apache.org/viewvc?view=revision&revision=1542560

http://svn.apache.org/viewvc?view=revision&revision=1543475
ここにある、Jeffのアイデアというのはこれだろう。
http://mail-archives.apache.org/mod_mbox/httpd-dev/201311.mbox/%3CCAKUrXK5n7havg2-6MR6JAt0dQecbH6je6K9ySY8iHNQfN6mv8g%40mail.gmail.com%3E


ちなみに、もともとhttpd側で実装していたのを、APRに引っ越させたらしい。
http://svn.apache.org/viewvc?view=revision&revision=1528438
http://svn.apache.org/viewvc?view=revision&revision=1527536
これはどうでもいいか。



apr_skiplistの利用

もう少し調べてみた。
event.c で次のフック関数 event_register_timed_callback が定義されている。

(httpd-2.4.9/server/mpm/event/event.c)
   3172     ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL,
   3173                                         APR_HOOK_MIDDLE);

event_register_timed_callback() 関数は、 引数にタイムアウトまでの時間、タイムアウト時に実行する関数、処理に依存するデータへのポインタを持つ。
これらの情報を timer_event_t 構造体に格納し、apr_skiplist_insert()を使って、apr_skiplist構造体である timer_skiplist に登録する。
タイムアウトまでの時間は現在時刻に加えられ、タイムアウト予定時刻が計算されている。

登録は、タイムアウト予定時刻順になるが、このための順序関数が、apr_skiplist構造体に登録されている。
2種類存在する。
変数名で書くと、 compare関数と、comparek関数、だ。
いずれも、2値(void *型)を引数にとり、整数を返す。

apr_skiplist_set_compare()関数で登録する。

event MPMでは
compare関数は以下。

   1233 static int indexing_comp(void *a, void *b)
   1234 {
   1235     apr_time_t t1 = (apr_time_t) (((timer_event_t *) a)->when);
   1236     apr_time_t t2 = (apr_time_t) (((timer_event_t *) b)->when);
  :
   1239     return ((t1 < t2) ? -1 : ((t1 > t2) ? 1 : 0));
   1240 }

引数は timer_event_t構造体で、それが持つタイムアウト時刻。
2つのtimer_event_tのタイムアウト時刻を比較し、 aが小さければ、-1、aが大きければ、1、一致すれば、0を返している。

comparek関数は以下。

   1242 static int indexing_compk(void *ac, void *b)
   1243 {
   1244     apr_time_t *t1 = (apr_time_t *) ac;
   1245     apr_time_t t2 = (apr_time_t) (((timer_event_t *) b)->when);
  :
   1247     return ((*t1 < t2) ? -1 : ((*t1 > t2) ? 1 : 0));
   1248 }

この場合は、最初の値はapr_time_t *型の変数。
現在時刻等の時刻情報と比較して、タイムアウト予定時刻を経過しているかどうかの判定に用いるのではないか。
時刻情報が小さければ、-1、時刻情報が大きければ、1、一致すれば、0を返す。

apr_skiplistの実装の方はちゃんと見られてはいない。

このフック関数の呼び出しは、 ap_run_mpm_register_timed_callback()が行う。
それを実行する関数があった。

(httpd-2.4.9/server/mpm_common.c)
    533 AP_DECLARE(apr_status_t) ap_mpm_register_timed_callback(apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton)
    534 {
    535     return ap_run_mpm_register_timed_callback(t, cbfn, baton);
    536 }

これを使っているのは、見たところでは、mod_dialupモジュールだけのようだ。

タイムアウトの処理自体は タイムアウト時刻を過ぎたかどうか、listenerスレッドがチェックし、タイムアウト処理を行う場合、timer_event_t情報をworkerスレッドに通知している。
workerスレッドは、timer_event_t構造体に保持するタイムアウト処理関数を引数に、同じく timer_event_t 構造体が保持する処理依存のデータへのポインタを与えて、実行する。

listenerスレッドが処理するタイムアウト処理自体は、この他にもある。
timeout_queue構造体が管理するイベント処理にかかわるタイムアウトで、4種類存在している。
これは今度調べて書く。

mod_dialupモジュール


mod_dialupモジュールは、静的コンテンツを限定されたレートで送信する。
レートは古いモデムの標準によって定義されている、という。

参考) http://httpd.apache.org/docs/2.4/en/mod/mod_dialup.html

単にダウンロードの送信レートを小さく絞るためのモジュールなのか?
httpd-2.4で追加されたモジュールなので、まだよく分かっていない。
ステータスが Experimentalなので、利用は自己責任らしい。

処理自体は、タイムアウトで実行されるコールバック関数dialup_callback() 内で、一定のデータを送信してflushするdialup_send_pulse関数を実行している。
これをどうやら1秒間隔で実行しているようだ。この1秒というタイムアウト時間で、dialup_callback()を登録していた。

1秒間隔で送信するデータサイズが定義されており、以下のようになっていた、

名前 送信バイト数/秒
V.21 12Bytes
V.26bis 300Bytes
V.32 1200Bytes
V.34 3600Bytes
V.92 7000Bytes
i-was-rich-and-got-a-leased-line 187500Bytes

これを ModemStandard ディレクティブで指定するという仕組みになっていた。


0 件のコメント:

コメントを投稿