便利 Acme!
http://search.cpan.org/~kane/Acme-Intraweb-1.01/lib/Acme/Intraweb.pm
サービス[技術・UI・形態]とコンテンツ[実体]
それぞれにおける質と量
Template::Parser
Template::Parserでは、'[%'('%]')をデフォルトデリミタ(※)としてtt2ファイルをparseします。
parseの方針は、
- ファイル先頭もしくは'%]'から、次の'[%'までのテキストを $preとして保存。(プレシーディング部)
- '[%'から'%]'の内部のテキストを $dirとして保存。(ディレクティブ部)
のようです。
こうして順次parseしていき、区切られたもの毎にごにょごにょするわけです。
ごにょごにょ
区切られたものには、$preと$dirがあります。
次は、$dirを tokenize_directiveメソッドを使って、ディレクティブトークンを作成します。
[ ディレクティブ部, ($dir) テンプレート内でディレクティブが存在した行数の番号, ( 12-13 ) tokenise_directive($dir), ]
という配列リファレンスが@tokens(ディレクティブトークン)にpushされていきます。
sub tokenise_directive
[% html_str | html | html_line_break %] $var1 = [ 'IDENT', 'html_str', 'FILTER', '|', 'IDENT', 'html', 'FILTER', '|', 'IDENT', 'html_line_break' ];
[% test_msg1 = 'test1' test_msg2 = 'test2' %] $var1 = [ 'IDENT', 'test_msg1', 'ASSIGN', '=', 'LITERAL', '\'test1\'', 'IDENT', 'test_msg2', 'ASSIGN', '=', 'LITERAL', '\'test2\'', ];
(※)デリミタとして使えるものは、
Template::Parser - LALR(1) parser for compiling template documents - metacpan.org
のTAG_STYLEを参照。
また、TAGSディレクティブでいつでも指定可能です。
(※)ディレクティブのparseデリミタ(デフォルトは'|')に関しては、
http://search.cpan.org/src/ABW/Template-Toolkit-2.15/lib/Template/Parser.pmの
sub tokenise_directive メソッドを参照。
■
デバッグ時に良く使う、Data::Dumper
データ構造をうまく出力してくれて重宝ですが、
コードリファレンスはうまく表示してくれません。
$var1 = sub {"DUMMY"}
とか、出力されてしまいます...
コードリファレンスを表示したい時には、これ! B::Deparse !!
http://search.cpan.org/~nwclark/perl-5.8.8/ext/B/B/Deparse.pm
使い方
use B::Deparse; $deparse = B::Deparse->new("-p", "-sC"); print $deparse->coderef2text(\&func);
とすると、&func内のコードを出力してくれます♪
■
先日、作成中のCatalystアプリにおいてメモリリークが観測されました。
原因は、
use Template::Plugin; use base qw(Template::Plugin); sub new { my ($class, $context, $args) = @_; my $self = { _CONTEXT => $context, _STASH => $context->stash, }; bless $self , $class; }
としているところの、
_STASH => $context->stash
の部分で循環参照となってしまい、リークを起してしまったようです。
この問題によって、Catalyst::View::TTの、sub renderでの $tt->process()
で作成された$output(=画面に出力すべきHTML)が、
リクエスト終了後も開放されず、蓄積されていってしまったのでした。
循環参照の詳しい状況は再度追って報告します。
GTop
今回はGTopモジュールでメモリの推移を把握し、
ボトルネックを突き止めるアプローチを行ないました。
MyApp.pmに以下を追加します。
use GTop; sub prepare { my ( $class, $args) = @_; my $gtop = GTop->new; my $memory_in_start = $gtop->mem($$)->size; my $c = $class->Super::prepare( $args ); $c->stash->{gtop} = $gtop; $c->stash->{memory_in_start} = $memory_in_start; return $c; } sub finalize_body { my ( $class, $c ) = @_; $class->Super::finalize_body( $c ); $c->stash->{memory_in_end} = $c->stash->{gtop}->mem($$)->size; $c->log->debug( "Diff:" . GTop::size( $c->stash->{memory_in_end} - $c->stash->{memory_in_start}) ); }
これで、リクエストに対する処理が終了するまでのメモリの推移が、ログに出力されます。
■
(途中)
ブランチとは
trunk ----A | --B branches ----A----my_A | --B----my_B
いきなりですが、
Subversionは、ブランチを、ブランチとは認識していません。
svn copyコマンドによって作成された、
同じレポジトリ内に共通の履歴を持ったディレクトリのコピーを、
人間がブランチとして認識しているに過ぎないのです。
(後で説明する タグ も全く同じです。)
ですので、ブランチを作るというよりも、
あるリビジョンをBASEとして、ディレクトリ(ファイル)をtrunkから派生させる、
と考えることが重要です。(結局、それはブランチの概念なんですが...w)
ブランチの作成方法
さて、作成方法ですが、2通りあります。
ブランチの作成方法(1)
svn copy trunk/A branches/A/my_A svn ci -m 'create branch of trunk/A'
ブランチの作成方法(2)
svn copy http://repo.com/trunk/A http://repo.com/branches/A/my_A -m 'create ...'
(2)のほうが、svn co(checkout)しなくてよいので効率的です。
既にcheckoutしてある場合には、大した差はありません。
ブランチの運用
ここで、trunk/A/sample.txtと、branches/A/my_A/sample.txt 双方に変更を加え、
それぞれコミットをしたとします。
svn ci trunk/A/sample.text -m 'fix trunk sample.txt' ... revision 3. svn ci branches/A/my_A/sample.text -m 'fix branch my_A/sample.txt' ... revision 4.
そして、以下を実行すると、
svn diff -r 3:4 trunk/A/sample.txt
trunk/A/sample.txtのdiffはbranchとtrunkとの差異の内容を表示してくれます。
このことからも、svn copyで作られたブランチは、
単なるハードリンク的なコピーでしかないことが分かると思います。
ブランチファイルの概念
トランクとブランチは全く同じファイルを参照していると言えます。
では、何が違うのか?
『ファイルのリビジョン管理のストリームが異なる』
__________> branch ________|_________> trunk
あるファイルに、別のリビジョン管理ストリームを作成する。
これが、ブランチを作成する、という意味となります。
これまでの「リビジョン」という概念に、「ストリーム」という概念が加わるわけです。
作成されたストリームには名前が付けれます。
my-branch, release-1.0 などです。
Subversionでは、この名前をディレクトリ名とそのツリーとして実現しています。
また、このストリーム名をキーに、関連するツリーを取得することができます。
svn co http://example.com/branches/my_A
uri エスケープのお話
くえり%,$くえり,"くえり",く&えり,くえる@ ....
これらの文字はすべてuriエスケープ対象となるのでしょうか?
http://www.ietf.org/rfc/rfc2396.txt?number=2396
各モジュールで試してみましょう。
http://example.com/index.cgi?param=くえりー%
'%'がquery stringに含まれると、
400 Bad Requestでエラーになる。
TTであれば、
[% name | uri %]で防げます。