webgen では、src ディレクトリ下にソースを記述し、webgen コマンドにより output ディレクトリ下に結果を生成する。
まぁ、プログラムのコンパイルと同じで別に悪くはあるまい、と最初は思っていた。そして実際、文章を RD で書くぶんにはとくに問題はは感じない。
が、画像を扱うときには期待したほどにはうまくないことに気がついた。
画像を扱うには以下の手順を繰り返すことになる。
ここで webgen が png を生成するというのは、単にコピーするだけである。
この手順で、webgen コマンドを忘れることが多発した。
ここで、
というわけで、少し考えた結果、webgen でコピーの代わりに output/foo.png から src/foo.png へ symlink する plugin を作ってみた。
これにより、webgen コマンドを起動するという手順を省略でき、src/foo.png を編集してブラウザを reload するだけで済むようになった。
今回は symlink を使ったが、人間の手順を減らすための他の方法もあったかもしれない。
前者は動的生成である。後者は IDE がプログラムをセーブするときに (あるいはセーブしなくても) 自動的にプログラムをコンパイルすることに似ている。
動的生成はローカルにサーバが必要なのが面倒くさい。とはいえ、サーバさえあれば、単なるコピー以外のものも扱えるので、強力ではある。ただ、強力なぶん、そこで問題が発生する可能性が増えるのが難しい所ではある。
IDE みたいな動作を実現するには、画像の編集ツールに手を入れる必要がありそうなのが厄介である。ただ、src directory を監視してどうにかすることもできなくはなさそうである。その場合は監視するサーバが必要になるので面倒くさいが。
関連して、人間の手順のデザインについて考えた。
まず、省略できるものはなくすことにより、全体の手間を減らすというのが基本である。
ただ問題はその先で、手順の中で繰り返される部分をとくに省力化することが重要そうである。
作業 A, B があったとき、順序が決まっているよりも決まっていないほうがいい
順序が決まっていても決まっていなくても失敗しなければトータルの手間は変わらない。しかし、失敗を考えると違ってくる。
A, B の順で行わなければならないとして、B までやった時点で A の失敗が判明すると、B を再度行わなければならず、A, B, A, B という手間がかかる。
しかし、A, B の順序が任意であれば (つまり B が A に依存していなければ) A, B の順でやった後に A の失敗が判明した場合、A だけをやりなおせばよくて、A, B, A で済む。
これは依存関係は浅いのがいいということである。
失敗による手戻りが予期される場合には、(失敗しない場合の少し手間が増えても) 手戻りによる繰り返しの外に作業を移動する
A という作業があって、失敗が予期されているとする。とすると、A, A, A, ... という手順が想定される。
ここで、A の内容を失敗しやすい部分 A1 と、A1 の後で行う失敗しにくい部分 A2 に分割できたとすると、A1, A1, A1, ...., A2 という手順にできる。
こうすると A よりも A1+A2 のほうが作業量が少し多かったとしても、A * n よりは A1 * n + A2 のほうが作業量が小さくなることは十分に期待できる。
これは失敗が早期に判明するのがいいということである。
wiki page とかを cvs/svn のようなインターフェースでいじれるツールをリリースした。
http://www.a-k-r.org/wfo/
CODE blog でいえば、
% mkdir ~/.keyring % cd ~/.keyring % echo TypeKey typekey-username typekey-password | gpg --comment TypeKey -e -a --default-recipient-self > typekey.asc
として TypeKey の認証情報を暗号化して記録しておけば、
% wfo co https://www.codeblog.org/blog/akr/20061002.html % vi 2006-10-02.txt % wfo ci 2006-10-02.txt
として tDiary の日記を書いたり、
% wfo co https://www.codeblog.org/Sandbox.html % vi Sandbox.txt % wfo ci Sandbox.txt
として qwikWeb のページを編集できたりする。
なお、tDiary, qwikWeb 以外に、PukiWiki と Trac の wiki を扱える。
tarball の upload 用の CGI を書く。
気にしたところ:
・ / で始まっているとか、.. が入っているとかパスが怪しくない ・ ディレクトリとふつうのファイルしか入っていない (とくに symlink が気になる) ・ tar が失敗しない
最近、g新部さんとフリーソフトウェア運動について議論していて、いろいろと前提知識が足りないと感じたので、「フリーソフトウェアと自由な社会」を読んだ。
しかし、今度は、倫理とか言論の自由とか経済についての知識が足りないなぁ、と思うようになった。
で、言論の自由について調べると、品切らしい。
upload cgi を動かすことにしたのだが、いくつかの事情があって、新しいマシンのほうで動かすことにした。
で、virtual host の設定をして、suEXEC して、せっかくだから web application 用には別個の UID:GID を与えることにした。
で、気がついたのだが、virtual host で SuexecUserGroup を使って suEXEC すると、 CGI スクリプトの owner:group は SuexecUserGroup で指定した owner, group でなければならない。
しかし、そうすると、スクリプトが動作する UID:GID でそのスクリプトを書き換えることができてしまう。つまり、そのスクリプトに、仮に任意のファイルを書き換えられるというセキュリティホールがあった場合、そのスクリプト自身を書き換えることによって、任意のコードを実行できてしまう。なので UID:GID を別にして実行ファイルは書き換えられないようしておきたいのだが、それができない。
なんでこんな仕様なんだろう、と考えてみると、mod_userdir が前提だからかな。
それでもどうにか、と考えると、Linux なら chattr +i だろうか。
xen で NetBSD を動かしていたマシンを少し違う用途に使いたくなり、運用を変えてみる。NetBSD な domain は運用停止。
メモリをたくさん使いたくなったからなのだが、xen は固定でメモリを割り当てないといけないので、こういうときには都合が悪い。
動かす domain を減らしてひとつの domain のメモリを増やしたわけだが、それでも X が落ちることがある。結局、swap を 4G わりあてた。
動的にやってくるといいのだが、難しいのだろうなぁ。
% google-count ゲ{ラ,リ,ル,レ,ロ}ゲ{ラ,リ,ル,レ,ロ} 895000 ゲラゲラ 0 ゲラゲリ 2 ゲラゲル 4 ゲラゲレ 6 ゲラゲロ 6 ゲリゲラ 842 ゲリゲリ 0 ゲリゲル 0 ゲリゲレ 96 ゲリゲロ 21 ゲルゲラ 42 ゲルゲリ 15300 ゲルゲル 2 ゲルゲレ 6 ゲルゲロ 11 ゲレゲラ 0 ゲレゲリ 2 ゲレゲル 47600 ゲレゲレ 5 ゲレゲロ 6 ゲロゲラ 138 ゲロゲリ 0 ゲロゲル 1 ゲロゲレ 355000 ゲロゲロ
自然が呼んでいる、っていうか、自然が呼び続けているという感じであったのだが、なんとか回復
と、思ったが、充分でなかった
編集可能な対象があったとき、その API にはどのようなデザインが考えられるか。
具体的には wiki のページとかなわけだけど。
まず考えられるのが get と put の対である。get でデータをとってきて、put でデータを設定する。なんともあたりまえなデザインである。
が、考えてみると、get と put だと、複数の更新主体の要求を調停できない。CVS とかでいえば conflict を扱えない。put するまえに get して確認する、ということはできるが、race condition が残る。
API のレベルで race condition が不可避となってしまうのは気に入らない。なので、そういう調停を扱える、なにか他の API が必要である。
他の API としてまず考えられるのは、get と put に加えて、lock, unlock を導入することである。つまり、いきなり put しないで、lock-get-put-unlock という順に行うことにして、get のところで他の人が変更していないことを確認するわけである。
もうひとつ考えられるのは、put のかわりに lock-get-put-unlock というのを基本操作とすることである。lock-get-put-unlock というのは長いので update と呼ぶことにしよう。get と update だけを基本操作として提供するわけである。こうすると、可能性として、lock, unlock, put を単独で使う創意工夫が不可能になるが、deadlock やら unlock しわすれやらその他いやらしいことが起き得なくなるという利点がある。
ここで検討したいのは、既存の wiki に対する wrapper としての実現性である。
その点では、lock, unlock の導入というのは無理がある。そんなことをするには、wiki 自体に lock 機能が必要になる。
wrapper で update を導入するのは、微妙である。衝突検出機能がある wiki では、wiki 自体が update を提供しているわけで、実現に問題はない。しかし、衝突検出機能がない wiki では、読み込んで確認して書き込むというように実現すると、race condition が残る。
もうひとつ検討したいのは、put というプリミティブをなくすのは許容可能かということである。
put のかわりに update があるわけであるが、update では更新前のデータを与える必要がある。get でとってきて与えれば、ユーザから見て put と同等の API を構成することができる。ただ、get と update の間に他の人が書き換えると update が失敗するが、それは成功するまで繰り返す、とする。そうやって update で put を作ることが可能であるとすれば、許容可能ではあるか。
[latest]