まだ重たいCMSをお使いですか?
毎秒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

*1 : <$begin>~<$end>構文には、関数として展開される場合と埋め込みとして直接展開されるパターンがある。元々は関数展開しかなっかたものを、高速化のため部分的に直接展開を取り入れたことが複雑化の原因。

スケルトンの実行コード

ついでに。このスケルトンは次のような実行コード(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

なお出力を文字列連結せずスタックに積んでいくのは、高速化のためです。(コンパイラが)無駄に綺麗なソースを出力するのは単なる趣味です(笑)

*2 : すでにキャッシュされているスケルトンはコンパイルの必要がないためログは出力されません。キャッシュを消すか何かしてください。

2007/11/06(火)ライセンスについて

adiaryのライセンスをGPLv3に移行することを検討しています。ただ、GPLv3は到底webアプリ向きではないため、独自ライセンスも少しだけ検討しています。

  • テーマ類はGPLv3への移行の方針です。*1

WebアプリとしてのGPLv3の不足点は次の通りです。

  • 第3者が改変物を公開されたウェブサイトに設置した際、ソースの公開を求める権利が(誰にも)ない。

ご意見やアドバイスなどありましたらコメントください。

*1 : GPLv3はプログラム以外に対するライセンスとして利用できるようになっているため、GPLよりも馴染みます。対称となるのは satsuki*/ 以下のGPLテーマのみです

追記

クリエイティブ・コモンズという選択もありかも。むしろテーマファイル群はこっちの方がいいかも知れない。リンクに関する規定がないので、不適切(ある意味でGPLよりゆるくなってしまう)。

追記

ネットワークアプリ向けGPLv3として、AGPLv3というのがあるそうです。これで決まりですね。

2007/08/13(月)CD-Rレーベル印刷

というわけで、C72 Special Editonのレーベル印刷。前回はかえでさんに頼んだのですが、今回は自己作業。絵素材も増えてるわけではないし、いっそ前回の鏡像で済ませようかと思いましたが、それもあんまりなので新規作成しました。

adiary_c72_cd.jpg

なかなかコレっていう感じにならなかったのですが、これ以上悩んでいる場合ではないのでレーベル作業は終了。現在量産中です。*1

*1 : 前回のほうがレーベルかっこいいから、前回ほど売れない気がする……生産数20以下にしよう。

無駄な時間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時間ぐらい損したような(汗)

*2 : USB001自体無理矢理作ったものでUSB001というファイルに出力されてしまう。Virtual printer portがでてこない

そして肝心の中身ですが

お察しください(自爆

追伸

20枚中、最後の1枚で満足の行く仕上がりになった点について(ぉ

2007/06/26(火)Firebird という RDBMS があるらしい

オープンソースな RDBMS は PostgreSQL, MySQL しか知らなかったのですが、Firebird というのがあることを知りました。見つけてしまったからには対応してみようかなと思うのが人情というもの(?)なんですが、使いたい人がいるのかどうか(^^;

さて、長らくお待たせしました次期新バージョン「adiary1.40」ですが、今月中にリリース予定です。