毎秒1000リクエスト を捌く超高速CMS「adiary」
2008/02/05(火)skltonシステムで再帰関数
最近書いた、adiary関連のとあるskeltonで必要に迫られて再帰関数を作りました。
再帰関数なスケルトン
<@local(ary, subdir, prefix, depth, header, idx, x)> <@>再帰サブルーチン -------------------------------------------- <$sub = begin)> <$subdir = argv#1> <$prefix = argv#2> <$depth = argv#3> <$header = if(depth, '<img width=' . (9*depth) . #' height="9" src="<@Basepath><@v.album_icons>spacer.gif">')> <$idx = 0> <@forexec(t, argv#0, begin)> <$push(dirlist, t)> <$ary = v.search_folderlist(basedir, t.path, t.pathname)> <$uri_encode(x = t.path)><@>URIエンコード済パス / ""内に書いても安全にする <@ifexec(ary#0, begin, begin)> <@header><a href="#" onClick="return toggleBlock('<@prefix><@idx>');"> <img src="<@Basepath><@v.album_icons>minus.png" id="img_<@prefix><@idx>"></a> -<a href="<@v.myself2><@x>"><@t.name></a><br> <div id="blk_<@prefix><@idx>"."_"> <@exec(sub, ary, "<@t.path>", "<@prefix><@idx>_", depth+1)> </div> <$else> <@header>+-<a href="<@v.myself2><@x>"><@t.name></a><br> <$end> <$idx+=1> <$end> <$end> <@>main --------------------------------------------------------- <$dirlist = argv#0> <$basedir = v.user_dir> <@exec(sub, v.search_folderlist(v.user_dir), "", "blk_", 0)>
ローカル変数宣言に再起関数。ここまでくるとすでにスケルトンではないような気もしますが、viewに関連する部分はプログラム本体には入れたくないので、こんな感じです。
このとおり Satsuki-system はかなり強力ですが、もう少し記述能力をアップさせたいところではあります。
<@x=forexec(t, v.load_folderlist(), begin)>
とかできませんし、ローカル変数宣言もファイル全体に対する宣言となっているにも関わらず、実装は関数単位分離になるため、かなり理解しにくいところがあります。*1
スケルトンの実行コード
ついでに。このスケルトンは次のような実行コード(Perl)にコンパイルされた後、__cache/ ディレクトリ以下に保存されます。
sub { my $Out = shift; my $R = shift; my $Ary = shift; my $v = $R->{v}; $_[1] = \$v; my ($x,$idx,$depth,$header,$prefix,$subdir,$ary); $R->{sub} = $Ary->[1]; $R->{dirlist} = $R->{argv}->[0]; $R->{basedir} = $v->{user_dir}; $_[0]=38; push(@$Out, $R->exec($R->{sub},$v->search_folderlist($v->{user_dir}),"","blk_",0)); $R->{Break} && return; return; } sub { my $Out = shift; my $R = shift; my $Ary = shift; my $v = $R->{v}; $_[1] = \$v; my ($x,$idx,$depth,$header,$prefix,$subdir,$ary); my $subdir = $R->{argv}->[1]; my $prefix = $R->{argv}->[2]; my $depth = $R->{argv}->[3]; my $header = ($depth != 0 && (('<img width=' . (9 * $depth)) . " height=\"9\" src=\"$R->{Basepath}$v->{album_icons}spacer.gif\">")); my $idx = 0; my $X=$R->{argv}->[0]; if (ref($X) ne 'ARRAY') { $X=[]; $R->error_from("line 17 at $R->{__src_file}", '[executor] forexec: data is not array'); }; foreach(@{ $X }) { $R->{t}=$_; $_[0]=18; push(@{$R->{dirlist}},$R->{t}); $_[0]=19; my $ary = $v->search_folderlist($R->{basedir},$R->{t}->{path},$R->{t}->{pathname}); $R->{Break} && return; $_[0]=20; $R->uri_encode(($x = $R->{t}->{path})); $R->{Break} && return; if ($ary->[0]) { push(@$Out, $header); push(@$Out, '<a href="#" onClick="return toggleBlock(\''); push(@$Out, $prefix); push(@$Out, $idx); push(@$Out, '\');"><img src="'); push(@$Out, $R->{Basepath}); push(@$Out, $v->{album_icons}); push(@$Out, 'minus.png" id="img_'); push(@$Out, $prefix); push(@$Out, $idx); push(@$Out, '"></a>-<a href="'); push(@$Out, $v->{myself2}); push(@$Out, $x); push(@$Out, '">'); push(@$Out, $R->{t}->{name}); push(@$Out, '</a><br> <div id="blk_'); push(@$Out, $prefix); push(@$Out, $idx); push(@$Out, '_"> '); $_[0]=24; push(@$Out, $R->exec($R->{sub},$ary,"$R->{t}->{path}",("$prefix$idx" . "_"),($depth + 1))); $R->{Break} && return; push(@$Out, '</div> '); } else { push(@$Out, $header); push(@$Out, '+-<a href="'); push(@$Out, $v->{myself2}); push(@$Out, $x); push(@$Out, '">'); push(@$Out, $R->{t}->{name}); push(@$Out, '</a><br> '); } $idx += 1; } return; }
これはコンパイルログディレクトリ <$Compile_log_dir="xxx"> を設定することで誰でもみることが出来ます。*2
なお出力を文字列連結せずスタックに積んでいくのは、高速化のためです。(コンパイラが)無駄に綺麗なソースを出力するのは単なる趣味です(笑)
2007/12/25(火)adiary@はてなリング
2007/11/06(火)ライセンスについて
adiaryのライセンスをGPLv3に移行することを検討しています。ただ、GPLv3は到底webアプリ向きではないため、独自ライセンスも少しだけ検討しています。
- テーマ類はGPLv3への移行の方針です。*1
WebアプリとしてのGPLv3の不足点は次の通りです。
- 第3者が改変物を公開されたウェブサイトに設置した際、ソースの公開を求める権利が(誰にも)ない。
ご意見やアドバイスなどありましたらコメントください。
追記
クリエイティブ・コモンズという選択もありかも。むしろテーマファイル群はこっちの方がいいかも知れない。リンクに関する規定がないので、不適切(ある意味でGPLよりゆるくなってしまう)。
追記
ネットワークアプリ向けGPLv3として、AGPLv3というのがあるそうです。これで決まりですね。
2007/08/13(月)CD-Rレーベル印刷
というわけで、C72 Special Editonのレーベル印刷。前回はかえでさんに頼んだのですが、今回は自己作業。絵素材も増えてるわけではないし、いっそ前回の鏡像で済ませようかと思いましたが、それもあんまりなので新規作成しました。
なかなかコレっていう感じにならなかったのですが、これ以上悩んでいる場合ではないのでレーベル作業は終了。現在量産中です。*1
無駄な時間1
そもそもレーベル印刷用のプリンタは自分の部屋にないのですが、レーベル作成ソフトがプリンタがつながってないと起動しないというすばらしい仕様で、クラックしたりしてたんですが、レーベル印刷できるプリンタが存在することが前提の処理部が落ちたりして一苦労しました。
でもよくよくよくよく考えてみると、LPTでもなんでも適当なデバイス指定してプリンタドライバインストールすればクラックせずとも使えたんだよね(激汗
無駄な時間2
レーベル印刷のためにプリンタを無断借用借りてきたんですが、今度はドライバが入らない。USBに接続するタイプのプリンタなのですが、誤って先にドライバを入れたのを消そうと、何を血迷ったのか inf/usbprint.inf を消したせいでプリンタドライバがインストールされない(失敗する)。これに気付くのに○時間。
それに気付いたあとも、USB001がなぜかUSBプリンタに接続されない(通信できない*2)。上の問題に対応するときに誤って
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors\USB Monitor] "Driver"="usbmon.dll"
を削除してしまったのが原因で、USB経由のプリンタ(USB印刷ドライバ)の一部が動作していなかったという問題。合わせて8時間ぐらい損したような(汗)
そして肝心の中身ですが
お察しください(自爆
追伸
20枚中、最後の1枚で満足の行く仕上がりになった点について(ぉ
2007/06/26(火)Firebird という RDBMS があるらしい
オープンソースな RDBMS は PostgreSQL, MySQL しか知らなかったのですが、Firebird というのがあることを知りました。見つけてしまったからには対応してみようかなと思うのが人情というもの(?)なんですが、使いたい人がいるのかどうか(^^;
さて、長らくお待たせしました次期新バージョン「adiary1.40」ですが、今月中にリリース予定です。