2008/09/04(木)
認識されなくなった PowerMac G5 のディスクだが、無事Data Rescue IIでほとんどのデータを救出できた。感謝、感謝。
で、やっぱりちゃんとバックアップはとっとかんといかんな、というわけで、次のようなスクリプトを cron で1日1回走らせることにした。/etc/daily.local というシェルスクリプトを作り、その中から呼び出せばよい。
#!/bin/sh # Backup the directory to a local (external) hard drive # 2008.09.04. Toshi Nagata echo "rsync_backup start at `date`" src_dir=/Volumes/Common dst_dir=/Volumes/Backup_1/Common_Backups back_dir=`date +_%Y%m%d_%H%M%S_` for src in $src_dir do rsync -a -v --delete --backup --backup-dir=$back_dir $src $dst_dir done cd $dst_dir perl -e '@f = sort { -M $a <=> -M $b } <_*_>; splice(@f, 0, 30); exec "rm -rf @f" if $#f >= 0; ' echo "rsync_backup end at `date`"
--backup-dir オプションを使って、古いファイルを日付・時刻のついたディレクトリに退避させている。--link-dest を使うと、Time Machine と同じような履歴管理ができるはずだけど、HFS+ でハードリンクを扱うのが少々不安で、今回は見送った。なお、下の方にある Perl スクリプトは、退避ディレクトリを30個を上限として古い方から削除するもの。
2008/08/31(日)
ワミーでトーラスを作ってみた(ワミー・ギャラリー:トーラス1、トーラス2)。右の大きいやつは、レイみたいに首にかけることができます。人間輪投げでも遊べる。閉曲面で「端」や「縁」がないので、不用意に投げて当たってしまっても全然痛くない。
円筒を作るのはそれほど難しくないのだが、自然に曲げるのはけっこう難しい。ここに載せた2種類のトーラスは、筒の太さは同じで、曲率を変化させてある。作り方はこちら。筒はいろいろな造形に使えるので、これの作り方は応用範囲が広そう。
ところで、ワミーの新色、カラフルセット・蓄光セットというのが出るそうです。10/15 発売予定。たぶん買います。色は絶対多い方がいいもんね。まあ、僕はあんまり色使いのセンスないんですが。
2008/08/29(金)
見たことないぐらい大変な雨でした。深夜の2時頃窓から外を見たら、側溝から水が湧き出して道路が川になっていた。車が何台もハザードを出して止まっている。朝になってもそのまま放置されている車もあった。研究室に行くと、あらゆる装置が停電で異常停止しているので、立ち上げて回った。うちで一番被害が大きかったのは、数値計算に使っている PowerMac G5 のクラスタで、共有ディスクが認識されなくなったので全く使えない。データも一番重要なもの以外はバックアップをとっていなかったので少々痛かった。だめもとで Data Rescue II の体験版を使ってみると、ラッキーにも復旧できそうな感じなので、作業用のディスクと正式版を発注して、来週作業する予定。まあ、ほとんどは使い捨てのデータなので復旧できなくても諦めはつくのだが、やっぱり毎日のバックアップは重要。こんな作業をしている時間がもったいないものね。
2008/08/25(月)
もくろぐ 8/20 分、「讃歌 by 篠田節子」。これ新聞連載の時にけっこう面白く読んだんだけど、えーとどんな話だっけ、とアマゾンの書評を見て思い出した。ヴィオラ奏者が主人公なのであるが、現実世界のあんなピアニストやあんな作曲家の名前が浮かんだりもするが
…あーあの人とかあの人とかのことかしらん。
アマゾンの書評を読みながらふと思い出したのだが、クラシック音楽を「クラッシック音楽」と表記する人って、クラシック音楽をちょっと斜めから、多少の悪意を込めて見ていることが多いような気がする。これはかなり以前から感じているのだけど、理由は未だによくわからない。そもそも、この表記の根拠が僕にはわからない。「クラッシック」の方が英語の classic の発音により近いわけでもないし。
2008/08/24(日)
北京オリンピック、あんまり盛り上がらないなあと思いつつ、何となくテレビを見てしまっています。ソフトボールの金メダルはすばらしかったね。3決のオーストラリア戦が凄かった。平成の鉄腕・上野。この人日本リーグでもルネサス高崎の全試合に先発して全部勝ってるよ。なんちゅうスタミナや。ところで、女子ソフトボールの親会社って、地味な技術系の企業が多いのはどうしてだろう。豊田自動織機とかデンソーとか太陽誘電とか、なんか「通好み」だよな。4年後のロンドンでは世界選手権をやって、オリンピック復活をアピールするそうです。ソフトボールは野球よりはるかにとっつきやすいスポーツなので、もっと世界に普及させれば復活の芽はありそうだね。
野球は残念でした。結果はしょうがないと思うんだけど、なんかプレーが自信なさげだった。歯車が狂ったまんま、最後まで修正できなかったんだろうな。星野監督が「(選手の力は)こんなもんじゃない」と力を込めて言っていたけど、それはその通りだと思う。でもさあ、プロがいったん引き受けた仕事はちゃんとプロらしくやらんといかんやろ。審判のせいにするとか、みっともないことはやめてほしいな。ストライクゾーンが不安定なんだったら、投手は空振り三振をとれよ。打者はボールくさい球をヒットにしろよ。それを見せてこそプロだろうが。故障を抱えた選手が異常に多かったのも納得がいかない。故障している選手を無理に招集する監督も、それを承諾する選手も、プロとしての状況判断が甘かったんじゃないか。
2008/08/05(火)
ワミーで射影平面、の続き。今度はけっこうそれらしくできたよ。作り方も公開。
ワミー・ギャラリーというページを作りました。
2008/07/29(火)
GigaStudio 開発中止、と報道されてます。まあ、登場当時と比べると競争相手も増えたし、役割は終えたというところだろうか。これを受けて、"Life After Giga: A Call for Open Source Sampling Development" という記事も出ている。LinuxSampler はオープンソースのサンプラーとしてはまあまあのレベルに達していると思うのだが、この記事の筆者は「商用ソフトのコピーではなくて、『新しい』ものを!」と気勢を上げている。うーん、LinuxSampler のメーリングリストでも一時議論になってたんだけど、これだけの規模で一応動いているコードを一旦全部捨てて完全にゼロから書き直すというのは、そりゃうまくいけば美しい結果を生み出すんだろうけど、気の遠くなるほど膨大な作業なんだよね。この記事とコメント欄で「アイデア」を熱く語っている人たち、どうも「自分はこんな素晴らしいアイデアがあるから誰かコーディングしてくれぇ」と言いたいみたいだけど、オープンソースの開発者は「自分のアイデアを具体化する」ことに熱意を持ってコーディングするのであって、他人のアイデアに乗ってくれる人はあんまりいないんじゃないかしら。
2008/07/28(月)
組み込み Ruby の件の続き。どうやら、キー割り込みの監視用スレッドと実行本体を別々の rb_eval_string コールで実行したのでは安定して動作しないみたい。考えてみたら当然という気もするのだが、逆に動くこともあるのが不思議と言えば不思議。そこで、実行したい内容を「レシーバ・メソッド・引数(の配列)」にまとめて、「チェック用スレッドと目的のメソッド呼び出しを同時に実行し、終わったらチェック用スレッドを止める」という内容の Proc に渡すようにしてみた。
static int s_interrupt_var_initialized = 0; static VALUE s_interrupt_thread = Qnil; static VALUE s_interrupt_proc = Qnil; static VALUE s_interrupt_lock = Qnil; static VALUE s_interrupt_flag = Qfalse; /* rb_protect 用の補助関数 */ static VALUE s_Ruby_CallMethod(VALUE val) { void **ptr = (void **)val; VALUE receiver = (VALUE)ptr[0]; ID method_id = (ID)ptr[1]; VALUE args = (VALUE)ptr[2]; return rb_funcall(s_interrupt_proc, rb_intern("call"), 3, receiver, ID2SYM(method_id), args); } /* 割り込みチェック付きでメソッドを呼び出す */ VALUE Ruby_CallMethodWithInterrupt(VALUE receiver, ID method_id, VALUE args, int *status) { void *ptr[3]; VALUE retval; if (s_interrupt_var_initialized == 0) { rb_define_variable("$interrupt_thread", &s_interrupt_thread); rb_define_variable("$interrupt_proc", &s_interrupt_proc); rb_define_variable("$interrupt_lock", &s_interrupt_lock); rb_define_variable("$interrupt_flag", &s_interrupt_flag); rb_eval_string_protect("require 'thread'; $interrupt_lock = Mutex.new", status); if (*status != 0) return Qnil; s_interrupt_proc = rb_eval_string_protect( "Proc.new { |rec, method, args| ¥n" /* 監視用スレッドがすでに走っていれば止める */ " runflag = set_interrupt_flag(false) ¥n" /* 現在の監視用スレッドを退避 */ " thread_save = $interrupt_thread ¥n" /* 新しい監視用スレッドを作る */ " $interrupt_thread = Thread.new { ¥n" " while 1 ¥n" " 10.times { Thread.pass; Thread.stop if !get_interrupt_flag } ¥n" " if check_interrupt > 0 ¥n" /* "raise Interrupt" は Ruby1.8.6 ではエラーになる */ " Thread.main.raise Interrupt.new(nil) ¥n" " end ¥n" " end ¥n" " } ¥n" /* 割り込みチェックを開始する */ " set_interrupt_flag(true) ¥n" " begin ¥n" /* メソッド呼び出し本体 */ " rec.send(method, *args) ¥n" " ensure ¥n" /* 後始末 */ /* 監視用スレッドを止める */ " $interrupt_thread.kill ¥n" /* 以前の監視用スレッドを復帰 */ " $interrupt_thread = thread_save ¥n" /* 監視用スレッドが走っていたなら再開 */ " set_interrupt_flag(runflag) ¥n" " end ¥n" "}", status); if (*status != 0) return Qnil; s_interrupt_var_initialized = 1; } ptr[0] = (void *)receiver; ptr[1] = (void *)method_id; ptr[2] = (void *)args; retval = rb_protect(s_Ruby_CallMethod, (VALUE)ptr, status); return retval; }
set_interrupt_flag, get_interrupt_flag は次のように実装している。
static VALUE s_SetInterruptFlag(VALUE self, VALUE val) { VALUE oldval; /* 値を true/false に揃える */ if (val != Qundef) val = ((val == Qfalse || val == Qnil) ? Qfalse : Qtrue); /* 同期制御 */ if (s_interrupt_lock != Qnil) rb_funcall(s_interrupt_lock, rb_intern("lock"), 0); oldval = s_interrupt_flag; if (val != Qundef) s_interrupt_flag = val; if (s_interrupt_lock != Qnil) rb_funcall(s_interrupt_lock, rb_intern("unlock"), 0); if (s_interrupt_thread != Qnil) { if (val == Qtrue) /* 監視用スレッドを再開する */ rb_funcall(s_interrupt_thread, rb_intern("wakeup"), 0); else if (val == Qfalse) /* 監視用スレッドが止まるまで待つ */ rb_eval_string("while $interrupt_thread.status == ¥"run¥"; end"); } return oldval; } static VALUE s_GetInterruptFlag(VALUE self) { return s_SetInterruptFlag(self, Qundef); }
肝心の check_interrupt はだいたいこんな感じ。
static VALUE s_CheckInterrupt(VALUE self) { if (s_GetInterruptFlag(self) == Qfalse) return INT2NUM(-1); else { /* AppKit (Objective-C) code */ NSEvent *event = [NSApp nextEventMatchingMask: NSKeyDownMask untilDate: nil inMode: NSEventTrackingRunLoopMode dequeue: YES]; if (event != nil) { NSString *s = [event charactersIgnoringModifiers]; unsigned int flags = [event modifierFlags]; if ([s isEqualToString: @"."] && (flags & NSCommandKeyMask) != 0) return INT2NUM(1); } return INT2NUM(0); } }
今のところ 10.4 (Ruby 1.8.2), 10.5 (Ruby 1.8.6) どちらでも動いているようです。まだ細かい問題はいろいろありそうだが、なんとか峠は越えたかな。
2008/07/25(金)
7/1 に書いた組み込み Ruby とキースキャンの件のつづき。手元の PowerBook G4 (10.4) では一応動いているのに、MacBook (10.5) に持って行くと落ちまくって使い物にならない。いろいろ調べて気がついたこと(全部が今回のバグに関係あるとは限らない):
- 落ちるのは Ruby の
Thread.newで作ったスレッドの中からnextEventMatchingMask:untilDate:inMode:dequeue:を呼び出したとき。 - Ruby の Thread は pthread を使わず、スタックを丸ごと書き換えるという方法で実装されている。サブスレッドの中から Objective C のメソッドを呼んだ時に、システムが期待しているスタックの中身と整合性がとれなくなっているのでは?
- Ruby の Thread を使わずに、NSThread で別スレッドを立てて、そこからキースキャンをやってみた。しかし、
nextEventMatchingMask:untilDate:inMode:dequeue:を呼んでも nil が帰ってくるだけで、イベントを取得できない。Cocoa のドキュメントには「Secondary thread の中でイベントを処理することはできる」と書いてあるのだが、どうやったらイベントを取得できるのかわからない。 - Ruby を 1.8.6 に揃えて
rb_add_event_hook()(先日rb_set_event_hook()と書いたのは勘違いだった)を使うことも考えたが、10.4 では Ruby.framework を自前で作って組み込むことになり、どうも気に入らない。
解決案として、Thread.new で監視用スレッドを作るのと、実際にスクリプトを走らせるのを、同じ Objective-C 関数の中からやるようにしてみた。これなら、Ruby 側でコンテキストが切り替わっても、Objective-C に関係するスタックの中身は変わらないだろう、という読み。これでダメだったら rb_add_event_hook() を使うしかないかなあ。
2008/07/21(月)
またワミーで遊んでみた。

これも正十二面体だが、頂点をとんがらせてみた。できあがってしまえばきれいに対称形になるのだが、途中段階ではパーツがこの形に曲がったままではいてくれないので、制作はかなり難しい。

今度は正四面体。少し趣向を変えて、頂点に集まるパーツの色を揃えてある。この方がきれいかな。

一つ前の正四面体を2つ互いに貫通させて組み合わせると、立方体になる。左は3回軸の方向から見た図、右は面の法線方向から見た図。

前回はクラインのびんを作ったので、今回は頑張って射影平面に挑戦。射影平面を3次元に埋め込むやり方はいくつもあるのだが、Boy's surface(Wikipedia 英語版、Mathematisches Forschungsinstitut Oberwolfach)が一番気に入ったので、これを目標にしてみた。残念ながら全然そうは見えないところが悲しい。一応トポロジーは正しい(と思う)し、3回対称も実現できたのだが。

横から見た図。射影平面は円盤とメビウスの帯を貼り合わせた閉曲面だが、図の下半分が円盤、上半分がメビウスの帯になっている。

上半分は、3枚の帯を半回転ひねったものを貼り合わせて作ってある(それで3回対称になる)。そのうちの一枚について、ひねった部分を拡大した写真。

射影平面の3次元埋め込みには欠かせない(?)、面の自己交差の部分。
まあ、ワミーで Boy's surface を作るというのは世界初の試みでしょうな(ちなみに、レゴで制作した例はある)。今回作ったのは上半分がどうもチンチクリンで見栄えがよろしくないので、後日改良版を制作する予定。





