新 WikiEngine の開発にははいったけれども、稼働するのはずっと後になりそうなので、今使用している engine もまだまだ手を入れて遊びます。
WikiName と違って[[, ]]で区切るページ名は DanglingLink の時に「どこまでが名前かわからない」かなと思い、 CSS で破線をつけるようしてみる。
今までは CGI スクリプトの最初で必ず exclusive lock をかけるというバカ lock だった。 これだと WantedPages のような時間のかかる処理のあるページにアクセスがあると、他のページの read が軒並み sleep させられてしまう。
なので、書き込みのないアクセス時には shared lock で flock するように修正。 これで read vs read でのアクセスが待たされたくなったはず。 それでも時間のかかる shared lock なアクセスがあると write 系のアクセスはやっぱりしばらく待たされてしまうのだけれど、write 系は頻度が低いから……。
結局flock 問題は、File::Flock モジュールを使う事にする。 $^O eq 'solaris' な時は File::Flock::lock を使うようにコードを修正。
それから、RCS まわりでも問題。
Warning: missing newline at end of file /tmp/...
といった感じの警告が出て期待した結果が得られない。 調べてみると rcsdiff の呼び出しで警告。 実際には diff が吐いている。 Sun の diff と GNU diff ではファイル末処理が違うようだ。 ということで、こちらは diffutils-2.8.1 と rcs-5.7 を home の下に入れて解決。
ふう、これで WiKicker は
で動く事を確認。都合5つ(SunOS は一つのホストで2個動かしている)。 今の所の注意点は
といったところか。
WiKicker / DiKicker の Log::Log4perl 対応作業。
ということで、warn -> Apache のエラーログに流れている警告メッセージも、Log::Log4perl の方に流して、好きに消せるようにしておくことにする。
SpeedyCGI 下で動かす事を想定して初期化は、init_once で行うようにする。 可能な限り早く初期化すべきなので、設定ファイル名/設定文字列はプロパティファイルに記述しておくのではなく、CGI プログラムで最初に生成する Controller オブジェクトの初期化パラメータで指定するように。
$SIG{__WARN__}を設定して、warn のメッセージを Log::Log4perl に送る。 最初はほぼ FAQ の例のまま、以下のように記述。
use Log::Log4perl qw(:easy); BEGIN { $::SIG{__WARN__} = sub { local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 1; WARN(@_); }; }
しかし期待していた通りに動かず悩む。原因は前述する init_once との絡み。 use Log::Log4perl qw(:easy) した時点でデフォルトの初期化が行われてしまうため、初期化済みになってしまって init_once での設定処理がスキップされていたのが問題。
use Log::Log4perl; BEGIN { $::SIG{__WARN__} = sub { local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 1; if (Log::Log4perl->initialized) { Log::Log4perl->get_logger->warn(@_); } }; }
と修正。 get_logger も暗黙的に初期化を行うので、init_once する前に warn されるとやはりデフォルトの初期化がおこってしまう。 それではまずいので initialized が真(=初期化済み)の時のみロギングするようにする。 ただしこれだと init_once する前の warn メッセージが失なわれる(STDERR あたりに print するようにすればいいかもしれない)。
CGI::Carp も $SIG{__WARN__} を上書きするので同時に使えない。 以前に use していたのが残っていてはまる。
NaneyOrgWiki、nDiki でロギングしはじめたところ、CGI プログラムの処理はきちんと成功しているもののその後(?) speedy_backend が core dump してしまう事があるようだ。 最初は $::SIG{__WARN__} の設定あたりに問題があるのかと思ったが、Log::Log4perl::Appender::Synchronized を使わないようにしたところ core を吐かなくなった。
IPC::Shareable、IPC::Semaphoreなんて使っているしやっぱりこれが怪しい。 とりあえず外しておくことにする。
しかし何らかの方法でシンクロしておかないとログファイルが壊れるはずだから、本当はどうにかしなければならないな。 もっと簡単に flock とかで排他制御する Appender とか無いのかな。 自分で書くしかない?
Apache::Session 1.6 を使おうかと思ったら Windows XP + ActivePerl 5.6.1 だと make test が通らない。flock まわりの既知の問題らしい。
ということでやっぱり CGI::Session を使う事にする。 expire の処理などもこちらの方が良さそげ。
t/complex_ds.t、t/db_file.t、t/file.t でそれぞれ CGI::Session::File、CGI::Session::DB_File、CGI::Session::File の new メソッドが見つからなくて失敗する。 use base でうまく require されていない? それぞれ別途 use でロードするようにテストを修正すると通過。
ちょっと気持ち悪いが動くことは動く。
数日前、プロジェクトの一つで使っている WiKicker が突然動かなくなっている事に気がつく。アクセスしてもレスポンスが返ってこない。 チェックしてみると知らない間にサーバがリプレースされている様子。
どちらも SunOS 5.6 で、バイナリ互換な環境。 管理者いわく「ひととおりWebページ等は移行できているようですが」。
でチェックしてみると新サーバへの移行に際し、ホームディレクトリはまだ旧サーバのものを NFS でマウントしている様子。 どうやら flock まわりの問題か。ホームディレクトリの下だと WiKicker の make test が通らないし (/tmp の下などだと通る)。
WiKicker の修正もちょっと大変だし、このままホームディレクトリが NFS 下にあるなら /usr/local か /var のどっかに WiKicker 用のデータベースを書かせてもらうようにしないといけないな。
WiKicker をベースにちょっとしたWebアプリケーションを作ろうという話になったのだが、そういえば Win32 対応していない。
ということで ActivePerl で動くように手を入れる。 まずは make test が通るようになるまで修正。
あたりを修正してだいたい対応できたようだ。 同梱している DiKicker の方は DB_File::Lock の make test が通らないので、とりあえず使用不可ということで。 WiKicker の方も flock まわりがきちんと動いているか確認する必要があるな。
WiKicker の Win32 対応のために、ファイル処理まわりや flock を使っているところを中心としたテスト・修正作業。
これでようやく Win32 で動くようになったかな。 まだ一部警告が出るけど。
しかし ThinkPad X31 (2672-PHJ、Pentium M 1.60GHz [Banias]) の上での QEMU + Windows 2000 は、やっぱり遅すぎて動作検証には使いづらい。WiKicker で1ページの処理に10秒以上かかったりするし。 結局 VNC を使って、別のPCで作業を行った。
Naney (なにい)です。株式会社ミクシィで SNS 事業の部長をしています。
※本サイトの内容は個人的見解であり所属組織とは関係ありません。