はてなキーワード: CACHEとは
やってしまった・・・。
方針:
package SixtyLinesTemplate; use strict; use warnings; our $VERSION = '0.01'; sub convert { return unless defined(my $str = shift); $str =~ s{&}{&}gso; $str =~ s{<}{<}gso; $str =~ s{>}{>}gso; $str =~ s{\"}{"}gso; $str; } sub include_template { my $tmpl = shift; my %c = %{+shift}; eval convert_template($tmpl); die $@ if $@; } sub convert_template { my $tmpl = shift; my $cache = $tmpl.'.cache'; return scalar do { open my ($FH) , $cache; local $/; <$FH> } if ( -f $cache && (stat($tmpl))[9] <= (stat($cache))[9] ); my $out = do { open my ($FH) , $tmpl; local $/; <$FH> }; $out =~ tr/()/\x28\x29/; $out =~ s/\[%\s*(foreach|if|unless|end)\s*(.+?)\s*{?\s*%\]/");".(lc($1) eq 'end' ? '} print q(' : "$1 $2 { print q(")/ige; $out =~ s/\[%(.+?)%\]/);print $1; print q(/g; $out =~ s/\[#(.+?)#\]/);print SixtyLinesTemplate::convert($1); print q(/g; $out = 'print q('.$out.');'; open my ($FH) , '>' , $cache; print $FH $out; $out; } 1;
サンプルコード:
use SixtyLinesTemplate; my $context = { 'title' => 'Example', 'list' => [10,'<A&B>'] }; SixtyLinesTemplate::include_template('template.tmpl',$context);
サンプルテンプレート:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>[# $c{title} #]</title> </head> <body> <h1>[# $c{title} #]</h1> <table> [% foreach my $i (0..@{$c{list}}-1) %] <tr bgcolor="[% $i % 2 ? '#FFCCCC' : '#CCCCFF' %]"> <td>[% $i %]</td> <td>[# $c{list}[$i] #]</td> </tr> [% end %] </table> </body> </html>
出力例:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Example</title> </head> <body> <h1>Example</h1> <table> <tr bgcolor="#CCCCFF"> <td>0</td> <td>10</td> </tr> <tr bgcolor="#FFCCCC"> <td>1</td> <td><A&amp;B></td> </tr> </table> </body> </html>
foreachんところが汚く見えるかもしれませんが、あれは添え字を取ろうとするとああなるんでご勘弁を。
普通にループするだけならforeach my $item (@$c{title}) でいけますゆえ。
あと存在しない変数とか使うと死んだり警告でたりするのでevalの前にno strictとno warningsをやった方がいいかもねぇ。
って何まじめに検証してんだ俺・・・orz
追記:
SixtyじゃなくてFortyだね。恥ずかし!
追追記:
でも&amp;の奴はちゃんと書いてるんだけども投稿すると勝手にエスケープされてしまってるんだよね。何でだろ?
ちなみにこのconvertの処理はCGI::Utilから拝借しました。
方針:
【追記】レイアウト機能を追加してみた
コード:
<?php /* * SixtyLinesTemplate.php - 60行しかないけどSmartyより速いテンプレートエンジン * * 使い方: * require_once('SixtyLinesTemplate.php'); * $TEMPLATE_DIR = 'templates'; // 省略可、パーミッションに注意 * $context = array('title'=>'Example', * 'list'=>array(10,'<A&B>',NULL)); * include_template('template.php', $context); * * ライセンス: public domain (自由に改造してね) */ /* * テンプレートを探すディレクトリ。 */ $TEMPLATE_DIR = NULL; /* * テンプレートを読み込んで実行する。 * $_context は変数名をキー、値を要素とする連想配列。 */ function include_template($_filename, $_context) { $_cachename = convert_template($_filename); extract($_context); include($_cachename); } /* * filename を読み込み、convert_string() で置換してから * filename.cache に書き込む。読み書きのロックは省略。 * (file_{get,put}_contents() はファイルロックできるようにすべきだ。) */ function convert_template($filename) { global $TEMPLATE_DIR; if (! file_exists($filename) && $TEMPLATE_DIR) $filename = "$TEMPLATE_DIR/$filename"; $cachename = $filename . '.cache'; if (! file_exists($cachename) || filemtime($cachename) < filemtime($filename)) { $s = file_get_contents($filename); $s = convert_string($s); file_put_contents($cachename, $s); } return $cachename; } /* * テンプレートの中身を置換する。 * - '#{...}' を 'echo ...;' に置換 * - '%{...}' を 'echo htmlspecialchars(...);' に置換 * - ついでにXML宣言も置換 */ function convert_string($s) { $s = preg_replace('/^<\?xml/', '<<?php ?>?xml', $s); $s = preg_replace('/#\{(.*?)\}/', '<?php echo $1; ?>', $s); $s = preg_replace('/%\{(.*?)\}/', '<?php echo htmlspecialchars($1); ?>', $s); return $s; } ?>
<?php require_once('SixtyLinesTemplate.php'); $TEMPLATE_DIR = 'templates'; // optional $context = array('title'=>'Example', 'list'=>array(10,'<A&B>',NULL)); include_template('template.php', $context); ?>
サンプルテンプレート:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>%{$title}</title> </head> <body> <h1>%{$title}</h1> <table> <?php foreach ($list as $i=>$item): ?> <tr bgcolor="#{$i % 2 ? '#FFCCCC' : '#CCCCFF'}"> <td>#{$i}</td> <td>%{$item}</td> </tr> <?php endforeach ?> </table> </body> </html>
出力例:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Example</title> </head> <body> <h1>Example</h1> <table> <tr bgcolor="#CCCCFF"> <td>0</td> <td>10</td> </tr> <tr bgcolor="#FFCCCC"> <td>1</td> <td><A&B></td> </tr> <tr bgcolor="#CCCCFF"> <td>2</td> <td></td> </tr> </table> </body> </html>
■X-Reproxy-Cache-Clear できる Perlbal プラグインCommentsAdd Star
■[Perl][CPAN][Perlbal] X-REPROXY-CACHE-FORを使いたい人向けショートBK
X-REPROXY-CACHE-FOR ヘッダが Perlbal に(というか Perlbal::Cache に)どのように解釈されるかというと、
1467 sub add_to_reproxy_url_cache {
1468 my Perlbal::Service $self;
1469 my ($reqhd, $reshd);
1470
1471 ($self, $reqhd, $reshd) = @_;
1472
(snip)
1484 my $hostname = $reqhd->header("Host") || '';
1485 my $requri = $reqhd->request_uri || '';
1486 my $key = "$hostname|$requri";
1487
(snip)
1496 $cache->set($key, [$timeout, \@headers, $urls]);
1497 }
こうなってる。ここで、
Perlbal -> mod_perl -> MogileFS
こんな風に、フロントに Perlbal, バックエンドに mod_perl ハンドラでも置いて、その裏の MogileFS とやりとり(をあんまさせたくないので Perlbal に直にキャッシュさせたい)という構成を考える。
この場合、
つまり、
X-REPROXY-CACHE-CLEAR: /artwork/12345
というヘッダを mod_perl から Perlbal に返す必要がある(host は補われる)
この /artwork/12345 というリクエスト URL は、 mod_perl 側から直に参照できない。
mod_perl ハンドラを例えば以下のような conf であてていたとすると、
<Location /example/artwork>
PerlHandler Example::Artwork
</Location>
RewriteEngine On
RewriteRule ^/artwork/(.*) http://127.0.0.1:8080/example/artwork/$1 [P,L]
ここで $r->uri をとると /example/artwork/12345 となり、これをそのまま X-REPROXY-CACHE-CLEAR で返しても Perlbal::Cache がキャッシュした key とは違うものなのでキャッシュを破棄できない。自前で $r->uri を split なりして、 /artwork/12345 を、 Rewrite される前の URL を知る必要がある。当然、どんな RewriteRule かに依存するので一般的な実装はあげられない。 Rewrite しなければもう少し話が簡単になる。
要は、
と、それぞれ意味の違った URL (key になるもの)がいくつか存在して、どれがどれやらわからなくなってしまうので、ハマりどころが多い。ありがちな(というか俺がやった)ミスとしては、 CACHE-FOR でキャッシュした状態で MogileFS からファイル実体を消してしまうと (mogile に突っ込むときの key はまた別に digest とかで作ってあったりすると余計に混乱することうけあい) Mogile にはもう存在せず、したがって mod_perl にはどうしたって知りようがない URL を Perlbal がキャッシュしていて 503 を返しつづける、という状態になってしまう。それから、キャッシュを自発的に消したいときというのはもともとキャッシュしてた URL (Mogile 上でのファイルのありか)が指し示すファイル実体を消したいときなので(実体がないものをいつまでもキャッシュしているのは困る、という理由)当然実体そのものも消すわけだが、
こういう手順でつくらないといけない。この URL は ACL を厳重にしておかないと、全ての artwork に対応するキャッシュ破棄用(つまりファイル削除用) URL を GET されまくってファイルを消されまくってしまうので非常にまずい。
我ながら乱雑で要領を得ない文章だと思うけど、こんなものでもないよりはあったほうがこれから同じことをやろうとする人にとっては多少の助けになると思うので走り書きのままで公開する。こういう、どっかに一言書いてあれば5秒でぐぐって済むことを何時間もかけてやり直すのは人類にとっての時間的損失でばからしいので、適当に間違ってるところとかを修正しつついろんなブログとかに転載しまくって世に広めてください。
証拠隠滅済み
http://www.tvw.co.jp/pofile02.html
(cache) 日本テレワーク株式会社概要-2/会社組織・主要経営陣
http://megalodon.jp/?url=http://www.tvw.co.jp/pofile02.html&date=20070121064247
関連
http://anond.hatelabo.jp/20070121222245
付記
1976年8月20日、社内プロダクション制度が敷かれたフジテレビで「ひらけ!ポンキッキ」と「第三の眼」を担当していたフジテレビ社員ら17名が独立して設立した。担当した番組はそのままフジテレビから日本テレワークに制作が委託され、初代の社長にはフジテレビ編成局長だった武田信敬が就任した。
参照:http://yuichirou.g.hatena.ne.jp/Yuichirou/20060401