ラベル プログラミング の投稿を表示しています。 すべての投稿を表示
ラベル プログラミング の投稿を表示しています。 すべての投稿を表示

2010/03/04

竹内先生の最終講義を拝聴しました

幸いにも、竹内郁雄先生の最終講義を拝聴することが出来ました。講義題目は「研究・開発は楽しく」でしたが、竹下先生の講義それ自体が楽しく、実り多い時間でした。どうも有難うございました。

有り難い事に、講義の様子は@hoimeiさんなどが、Twitterなどを通じて公開してくださっています。講義の最後のスライドで語られていた次の言葉は、「目的」の概念を深く考えさせられました(http://twitter.com/hoimei/status/9916983479より)。

真の創造者は目的をもたない
しかしまさのそのことにより
すべての目的を見事に果たす

講義終了後、恐れ多くも「初めての人のためのLISP」へサインを頂くことが出来ました。10代の頃に衝撃を受けた書籍であり、当時は作者の方へお会いする機会を得られようとは夢にも思っていなかっただけに、深い感謝と感慨とを感じています。

東京大学退職後のより一層のご活躍を楽しみにしております。

2010/01/07

git リポジトリを HTTP で公開する設定でハマリました

私の関係しているプロジェクトで、空 git リポジトリを作成し、HTTP 経由でアクセス出来るように設定する必要がありました。

git リポジトリ HTTP 経由でアクセスできるように公開する設定方法に関しては、「Setting up a git repository which can be pushed into and pulled from over HTTP(S).が大変参考になります。また、ありがたい事に、このドキュメントは、Yuanyingさんによって日本語訳も公開されています。

既に過去何回か行った案件であり、且つドキュメントが整備されているにも関わらず、情けないことに再びハマってしまったので、いくつかポイントを整理しておこうと思います。

まずサーバ側の設定作業ですが、setup-git-server-over-http.txtに書かれている通り、概要は次のような手順になります。

1. HTTP サーバを用意する
2. 認証を含めた WebDav の設定を行う
3. リポジトリを準備する

「リポジトリを準備する」は、コマンドライン的にはこんな感じです。

% su
# cd /var/www  # HTTPサーバで設定したリポジトリの公開場所
# mkdir sample_rep.git
# cd sample_rep.git
# git init --bare
Initialized empty Git repository in /var/www/sample_rep.git/
# git update-server-info
# chown -R www . # HTTPサーバを動作させる user が www である場合

ポイントは「git update-server-info を実行すること」「パーミッションを正しく設定しておくこと」の2点で、非常にシンプルです。

このリポジトリを pull/push するクライアント側の設定手順は、以下の通りです。ここで、git クライアントは MacOS X 上の 1.6.6 を想定していますが、特に OS 依存の箇所はないかと思います。またサーバとクライアントの間には firewall は存在しないことを仮定しています。
  1. ~/.netrc を適切に設定する
  2. ユーザ名の含まれていない URL を用いて、リポジトリを clone する
  3. ローカルリポジトリへファイルを commit する
  4. リモート側のリポジトリとローカル側の参照を指定して push する
以下、これらの作業に関係して、私がハマってしまった事例とともにを説明します。

1. ~/.netrc を使うのであれば、URL へユーザ名を埋め込んではならない

認証の必要な http URL へ git でアクセスするには2つの指定方法があります。1つは、ユーザ名をURL内へ埋め込む方法で、もう1つは curl経由でのアクセスを利用し curl が参照する .netrc へ認証情報を書いておく方法です。

前者は、例えば、こんな感じになります。

% git clone http://username:password@server.example.com/sample_rep.git

とはいえ、URLへパスワードを直接書いてしまう方法は好ましい方法ではなく、あまり現実には使われないかと思います。

パスワードを埋め込まない指定も可能です。

% git clone http://username@server.example.com/sample_rep.git

この場合、別途パスワードの入力が求められます。

% git clone http://username@server.example.com/sample_rep.git
Initialized empty Git repository in /users/n-miyo/p/sample_rep/.git/
Password: 

この方式の問題は、頻繁にパスワードの入力を求められることです。何度もパスワードを入力することは、危機意識が薄くなるので、あまり好ましいことではありません。

一方、ホームディレクトリへ .netrc というファイルを作成し、その中に認証情報を書いておく、という方式も利用可能です。HTTP アクセスで利用される libcurl がこの情報を参照し、適切に認証情報を送り出してくれます。

.netrc の記述方法に関しては、MacOS X では ftp(1) のマニュアルページに詳しいですが、基本的には、machine 行へ該当ホスト情報、login へユーザ名、password へパスワードを書いておきます。

% cat ~/.netrc
machine server.example.com
login n-miyo
password PASSWORD

このファイルが読まれてしまわないよう、パーミッションを 600 へ設定するなど、十分気を付けましょう。

.netrc を使う方法であれば、URL へユーザ名やパスワードを埋め込む必要はありません。

% git clone http://server.example.com/sample_rep.git
Initialized empty Git repository in /users/n-miyo/p/sample_rep/.git/
% 

さて、~/.netrc が適切に設定されている状態で、前者の様に URL 内へユーザ名を埋め込んだ場合はどうなるのでしょうか。この場合、まずはパスワードの入力が求められることになります。もし、return を空打ちするなどにより、パスワードへ空文字が入力された場合には .netrc の設定が使われることになります(パスワードを入力した場合には、そのパスワードが利用されます)。

私は、はじめにユーザ名付きの URL でサーバへの接続性を確認をし、その後、~/.netrc を設定する、という手順を踏んでしまったため、どんなに正しく ~/.netrc を設定しても Password 入力プロンプトが表示され続けてしまうことになり、悩んでしまいました。

もし、.netrc を適切に設定したにも関わらず、Password を求められる状況になった場合には、リモートリポジトリの URL を確認してみてください。git remote -v で確認できます。

% git remote -v
origin http://server.example.com/sample_rep.git (fetch)
origin http://server.example.com/sample_rep.git (push)


2. 空リポジトリから clone した場合、初回 git push へは引数指定が必要

既に commit の存在する git リポジトリを clone した場合、この clone 元へローカルの変更を push する場合、特に引数を指定する必要はありません。

% git push
Fetching remote heads...
refs/
...

一方、今回のように、空の git リポジトリから clone により作成したリポジトリへ push する場合には、push 先と、push 対象の branch を明示的に指定しなければなりません。例えば、.git/config で「origin」として命名されているリモートリポジトリへ、ローカルの「master」ブランチを push する場合には、次の通りです。

% git push origin master

ただし、もちろん push する前には、ローカルのリポジトリへ何らかの commit が必要です。commit が存在しない場合、push はエラーになります

% git push origin master
error: src refspec master does not match any.
error: failed to push some refs to 'http://server.example.com/sample_rep.git'

私は git push の引数を正しく理解していなかったため、「clone 出来ているのだから、push できない筈はない」と、サーバの認証設定ばかりを疑い、時間をとられてしまいました。

空リポジトリから clone した場合、 git push へ失敗する場合には、push の引数で明示的に push に必要な情報が指定されているか、または、ローカルリポジトリへ commit が存在するかを確認しましょう。


3. 認証の失敗メッセージへ注意する

認証の必要な URL に対して git clone や push を行い、その動作が認証エラーになると、その旨を示すエラーが表示されます。

% git clone http://server.example.com/sample_rep.git
Initialized empty Git repository in /users/n-miyo/p/sample_rep/.git/
error: The requested URL returned error: 401 while accessing http://server.example.com/sample_rep.git/info/refs?service=git-upload-pack

fatal: HTTP request failed

しかし、特定条件では、一見認証エラーなのか、設定エラーなのか戸惑うエラーが表示される場合もあります。

例えば HTTP サーバの WebDAV で「clone は誰でも可能だが push は禁止する」というような、すなわち clone 時には認証は必要ない、という設定がなされていたとします。この状態で、ローカルで行った変更を push しようとした場合、例えば .netrc の認証情報が誤っていると、git push は次のようなエラーを表示します。

% git push origin master
Unable to create branch path http://server.example.com/sample_rep.git/info/
error: cannot lock existing info/refs
fatal: git-http-push failed

先ほどと異なり、HTTP のステータスコードは表示されず、lock の獲得に失敗したことを示すエラーです。一見、HTTPサーバ側でのファイルパーミション設定誤りを疑いたくなりますが、実際パーミションの設定が誤っていた場合のエラーは次のようになります。

% git push origin master
Fetching remote heads...
 refs/
 refs/heads/
 refs/tags/
updating 'refs/heads/master'
 from 0000000000000000000000000000000000000000
 to   94d642b7e985ae90956700855e158d0e885628ba
Unable to lock remote branch refs/heads/master
Updating remote server info
PUT error: curl result=22, HTTP code=403
fatal: git-http-push failed

同じくロックに関するエラーメッセージが表示されていますが、こちらは最後に、HTTPステータスコードの403(Forbidden)も示されています。

私は、「lock が獲得出来ないのは、ファイルのアクセス権が問題だ」と誤った思い込みへ陥り、本来いじる必要のない、サーバ側のパーミション設定と格闘するハメになりました。

HTTPサーバへ Apache を使っている場合、例えば、httpd-access.log を見るとこの両者の判別がつけやすくなります。例えば認証が失敗している場合、MKCOL コマンドに対するステータスコードとして 401 が返ります。

192.168.1.1 - - [07/Jan/2010:21:26:47 +0900] "MKCOL /var/www/sample_rep.git/info/ HTTP/1.1" 401 401 "-" "git/1.6.6"

一方、HTTPサーバの設定を誤って書き込めない場合には、PUT のステータスコードが 403 を示します。

192.168.1.1 - n-miyo [07/Jan/2010:21:27:04 +0900] "PUT /var/www/sample_rep.git/info/refs HTTP/1.1" 403 234 "-" "git/1.6.6"

この差を頭の片隅に置いておくと、git push でエラーになった場合、原因究明の一助にはなるかもしれません。

一度設定できてしまえば http 経由での git アクセスは、快適に利用することが可能です。
これらの情報がトラブルシュートのお役に立てばと思います。

2009/12/30

FavTun Timer 開発で参考させていただいた書籍群の紹介

先日公開させていただいたiPhone 用タイマーアプリのFavTun Timerですが、皆様のおかげで、AppStore Utilities カテゴリの TOP FREE APPS で86位というランクをいただくことができました!

ダウンロードしてくださった皆様、ご利用くださっている皆様、しかも Review まで投稿してくださった皆様、本当に感謝しております。有難うございました。なんであれ、使ってくださっている方々がいる、ということが大変に嬉しいです。

FavTun Timerは初めて書いた iPhone 用アプリケーションです。「iPhone OS 3.0 で膨大な数のAPIが追加される」という Apple からの説明を受け「どんなAPIが追加されるんだろう」と興味本位でAPIリストを覗いたことが発端でした。リストやドキュメントを見ているうちに「折角 Mac と iPhone を持っているのだから..」と、サンプルコードの改変を進めているうちに、完成された Framework の魅力へと引き釣りこまれていきました。当時は、ともに C で始まるから、という理由だけで Cocoa と Carbon とを混乱しているような初心者っぷりだったように記憶しています。

こんな状態で開発を始めたので、完成までは非常に様々な書籍、ドキュメントへお世話になりました。ここでは、参考になった書籍群の作者様へ感謝しつつ、それらを紹介させていただきたいと思います。なお、私が書籍を購入したのは主に2009年夏位で、まだiPhone OS 3.0に関する書籍が存在していなかった頃です。現在は改版されているものもあるかと思いますので参考にされる際にはご注意ください。またリンク先は、出版社のページです。

まずは、基礎となる Objective-C に関する書籍です。

詳解 Objective-C 2.0(荻原剛志)

Objective-C 2.0に関する包括的な言語解説書であり、リファレンスでもあります。Objective-C に於けるメモリ管理から、リフレクションの利用方法、Foundation ライブラリの概要やネーミング規約、また、2.0で導入された宣言プロパティ/アクセサまで、すべての内容が網羅されています。もしより深い内容を知るために、Appleの言語マニュアルを参照する場合でも信頼の於ける道標として利用できるでしょう。


次に iPhone アプリケーションの概念を学ぶ際に利用させていただいた書籍です。当時は Xcode での新規 Project 作成方法すらわからなかったので、それらの書かれている書籍を探しました。

iPhone SDKの教科書—Cocoa Touchプログラミング、最初の一歩(赤松 正行)

iPhone アプリケーション作成方法の概説を勉強させていただいた書籍です。数時間で読める解りやすい概説書です。Xcode や Interface Builder の概要を知った書籍で、Xcode と IB との連携方法などが実際に参考となりました。

基礎からのiPhone SDK(鶴薗 賢吾)

Cocoa Touch の規約などに関して勉強させていただいた書籍。こちらも数時間で読みこなすことが可能なサイズです。私は、先の本と併せて基本クラスを勉強させていただくとともに、Application Delegate など、各種実際に利用されている Delegate の概要などを学びました。


上記2冊が概念をつかむまでに参考にさせていただいた書籍です。今振り返ると、NSTimerや AVAudioPlayer など、FavTun Timer の基礎となるクラスの使い方は、ここで勉強したのかな、と思います。

アプリケーションへの機能追加など、開発が本格化してきた際にお世話になった書籍が以下の2冊です。

はじめてのiPhoneプログラミング(デイヴ・マーク、ジェフ・ラマーチ(著)/マーク・ダルリンプル(監修)/鮎川 不二雄)

非常に多くのコードが順を追って書かれている実用的な解説書。単一アプリケーション内での MutiView をどのように取り扱うべきか、また iPhone アプリケーションで数多く利用されている UITableView や、UINavigationCtonroller を実際のコードでどのように利用するのか、など、実開発で直ぐに利用可能な情報が数多く散りばめられています。FavTunTimer では3つのタイマーを切り替えていますが、その基礎はここで学びました。米国では OS3.0 対応版が発刊されているためか、現在この書籍は Amazon では入手が困難になっているようです。良い書籍であるだけに大変残念です。

iPhoneアプリケーションプログラミング(新居 雅行) / サポートページ

iPhone OSの基本クラスに関するリファレンス的な書籍。主要クラスを概説し、その使い方をシンプルなコードで説明しています。この本の素晴らしい点は、メモリ管理など、現実の実装で重要となる概念が、非常に詳しく書かれている点です。残念ながら、このあたりの解説が曖昧な書籍が多い中、この本では、例えば、「IB で作られたインスタンスの release 管理はどうすべきか」に関し、その onwer 権限の考え方も踏まえ、詳しく書かれています。Appleのドキュメントに散逸している情報がひとまとめにされており、何度もこの本に助けられました。非常に素晴らしい本であり、大変におすすめしたい書籍です。惜しむらくは、書籍名からは、その素晴らしさがわかりにくいことでしょうか...。


上記刊行書籍以外に参考になったのは、もちろん Apple Developer Connection で公開されているドキュメントとサンプルコードです。Apple のドキュメントは非常に丁寧に整理/維持されており、また、Xcode と緊密に統合されているため、開発途中に於いても、簡単に各種ドキュメントへたどり着くことが可能です。記載内容も、まずは概説のち詳細と順を追って書かれており、ドキュメントの内で説明されているコードは、実行可能なサンプルとして提供されています。PDFとHTMLの両フォーマットで閲覧可能な点もポイントが高く、私は多くのドキュメントを印刷し、通勤中に読んでいました。一部のドキュメントは日本語訳も公開されています

最後に「Google Objective-C スタイルガイド 日本語訳」を紹介します。Google の定めた Obj-C のコーディングルールがまとめられたもので、Takashi Sasaiさんが日本語へ翻訳してくださっています。私はここに書かれている内容を何度も読み砕くことで、ようやく Objective-C で正しいコードを書く糸口を発見できたような気がしました。

以上、私が参考にさせていただいた書籍、ならびにドキュメントです。作者の方々へ感謝しつつ、他デベロッパの方々の参考になれば嬉しく思います。



2009/12/21

FavTun Timer 1.0.0 リリースしました

iPhone 用アプリケーションである FavTun Timer をリリースしました。本日よりAppStore から入手する事ができます。価格は無料です。

アプリケーションとしては、非常にシンプルなタイマーです。




アラーム音に iPod ライブラリに入っている任意の音楽が指定できるのですが、加えて、任意の「フレーズ」を指定できる点が特徴です。



一般的にタイマーのアラーム音は10秒も聴かないと思いますので、任意の曲が指定できたとしても、お気に入りのサビへ到達する前に止めてしまう事が多いのでは、と思います。このアプリケーションでは、アラームとして利用するフレーズを自由に設定できますので、サビをアラームに使える、という点が大きな特徴になっています。

FavTun Timer公開にあわせサポートページを公開しました。細かな特徴なども併記してありますので、あわせてアクセスして頂ければ嬉しいです。

裏話になりますが、当初は、iPhone OSの構造やAPIセットを勉強しようと、小さなサンプルプログラムを幾つか作って遊んでいたのですが、折角なので、ということでアプリケーションという形式にまとめようと考えました。構想は結構前で、当初は、VFD(FLディスプレイ、家電のフロントパネルなどで利用されているもの)を模したデザインの小さなアプリケーションを作る予定だったのですが、絵心が無いため、七転八倒を繰り返し、出来上がった物は、当初とずいぶん違ったものとなりました。参考書籍などは、忘れる前に、追って、まとめていきたいと思っています。

ご意見、ご感想など、お待ちしております。お気軽にご連絡ください。

2009/10/04

HTML5 Tech Talk へ参加してきました

10月2日、HTML5-Developers-jp主催のHTML5 Tech Talkへ参加してきました。

会場は Google 本社。最初、案内メイルに書かれていた「渋谷セルリアンタワー2Fロビー」が分からず、ホテル内をさまよっていたのは内緒。無事10分ほど前に会場入りしたのですが、会場はほぼ満席状態になっていました。

今回の内容は2点で、1点は、HTML5-Developers-jp主催者である、白石@あゆたさんによる「HTML5で作るオフラインWebアプリケーション」。もう1点は、html5.jp運営者である、羽田野@futomiさんによる「Canvasチュートリアル」。

白石さんのスライドならびに羽田野さんのスライドともに Web から閲覧できます。また、今回の公式タグである#html5_dev_jpを Twitter で追いかけると、当時の状況がつかめるかもしれません。

白石さんの主な内容は、マイコミジャーナルへ執筆してくださった内容を実際のデモを交えながら説明してくださる、というものでした。

今回の見所は「Alexing Framework」で、白石さんの言わく「Open Web Architecture に従ったアプリケーションのひな形を数分で作成できます」というもの。基本「クラウド向けRESTfulライブラリ+HTML5 O/Rマッパーライブラリ」であり、「基本的な準備作業は、クラウド上でデータモデルを定義するだけ」、「@OfflineCapable(というアノテーション)を付与するだけ」。

デモも見せて頂きましたが、なるほど、これは、
  • モデル情報の解析結果をもとに、
  • remote/local でのデータベース & テーブル生成
  • ActiveRecord パターンに基づく O/R マッパ生成
  • 両 O/R マッパ間の Proxy オブジェクト生成
  • それらの上に、両データベース間の conflict 検出を備えたsync モジュール生成
を自動で行ってくれるフレームワークのようです。これは素晴らしい! 本年中にオープンソースとして公開してくださるとの事ですので、楽しみに待たせて頂きたいと思います。

羽田野さんのお話は、初心者でも分かる、Developer 向けの Canvas 説明でした。

プレゼン資料が、実コードの示された簡潔な内容であり、また、説明もゆっくり、はっきりとした口調で行ってくださったおかげで、良く理解できました。特に適切なデモを随所に盛り込みながら説明してくださったことで、より深い理解を得る事ができました。

私は Canvas を制御する JavaScript メソッドの詳細を、今回初めて勉強したのですが、基本概念や機能が原則 PostScript 同様であり、個人的に、すんなりと飲み込めました。

説明の中、羽田野さんは「マンデルブロ、集合をこんなにも高速に、しかもブラウザ上で書く事ができるのは、素晴らしい」と感心しきりで語っていましたが、歳の近い私もまさに同感です。凄い世界になりましたねぇ...。

今回、白石さんの「Open Web Architecture」論を伺い、今後のアプリケーションは祖結合を前提とした分散オブジェクトモデルの上に作られるのかもしれないな、と感じました。

或るオブジェクトに対してアクセスが行われると、そのオブジェクトは現在のネットワーク接続状態に応じ、Proxy オブジェクトを通じて、手元/リモートの適切な箇所からデータを返答、両実データは暗黙的に/明示的に sync されてゆく、といった世界です。

さて、このような世界に於いて、アプリケーションの作り様を簡易化する目的で、何層にも重ねられた抽象化モジュールが生みだされると、結局その行く先はORB(object request broker)になるのでは、という思いが...。

Java 黎明期の HORB を、ふと懐かしく思い出しながら、最近のRESTful 台頭までの分散技術が次々と脳内をよぎり、また、メインフレーム時代から昨今のCloudという流行語までも流れて行き、技術の振り子は面白いな、と一人シミジミしてしまったのでした。

Tech Talk 主催の皆様、ならびに、参加者の皆様どうもありがとうございました。

2009/06/02

『Ruby逆引きハンドブック』は大変お薦めです

るびきちさんの書かれた『Ruby逆引きハンドブック』購入しました。

「逆引き本」というと、安易に解答へ飛びつく人向けの本、という印象があり、正直あまり期待していなかったのですが、本屋でパラパラめくったところ、この考えが私の食わず嫌いであったことが、一瞬で分かりました。

この本は解答本などではなく、「目的」をトリガーとして、その背景や原理理解へ深く深く到達する為の手引書なのです。

まず、目的から手繰るため、自身に興味のある分野から端的に入ってゆくことができます。即座に分かりやすく美しいコードが提示され、目的を達成する為の手順を正しく理解することができます。コードには同じ目的を達成する方法や関連する内容なども含まれているため、同時に別の解法を知ることもできます。加えて「ONEPOINT」や「COLUMN」を通じ、より深く、また幅広く関連する知識を学ぶことも出来ます。しかも、何れの項に於いても解説は丁寧であり、十二分な情報が得られます。非常に練り込まれた構成であり、まさに脱帽です。

初めて Ruby へ触れる方は勿論、長年 Ruby を使ってきた方にとっても、間違いなくお薦めの書籍です。私自身も、末永くお世話になりそうだと感じました。

良い書籍の刊行、ありがとうございました。

2009/03/14

Ruby で UPnP サービスを作る

UPnPは主にホームネットワークなど、管理者のいないネットワークで使われることを想定としたプロトコルです。

UPnP を用いることで ad hoc にサービスを提供したり利用したりすることが可能になります。このプトロコルをベースにしたサービスとしては、例えば Windows の ICS 機能(インターネット接続共有機能)のポートマッピングやDLNAなどが有名です。

規格策定から10年ほどが過ぎ、SOAPベースのプロトコルなど、やや古めかしさを感じる点もありますが、サービスの自動発見など、家庭内ネットワークで気軽にサービスを提供するには便利な仕様です。

というわけで、Rubyを使って簡易UPnPデバイス(サービス提供側)とUPnPコントロールポイント(サービス利用側)を作ってみましょう。

UPnPになじみのない方は、UPnP Device Architectureに目を通しておくことをお勧めします(以下のコードは、UPnp DA 1.0に準拠しています)。

今回は簡単に、'/'ファイルシステムがあるディスク容量を得るためのサービスを書いてみます。デバイスを SystemStatServer、そのデバイスが提供するサービスを DiskStat としました。

ここで解説している全コードは、githubから取得できますので、必要に応じてご利用ください。
  % git clone git://github.com/n-miyo/ru-sss.git

Ruby には、非常に優れた UPnP ライブラリが存在します。作者は rdoc のメインテナンスを担当されている Eric Hodel さんで、現在のバージョンは1.1.0です。

例えば UPnP では、サービス提供側のデバイスが SCPD と呼ばれるSOAP アクション一覧を記した XML ファイルを公開することが必須になっています。多くの UPnP 実装では、このXMLは活用していないのですが、Ruby UPnP 実装では、デバイスから SCPD ファイルを取得、解釈し、SOAP アクションを呼び出すメソッドを動的に作成してくれます。このため、クライアントは、該当メソッドを使うコードを書くことに集中できます。

また、サービス提供側でも、提供したいアクションを登録しておくだけでリフレクションにより SCPD XMLファイルを自動的に生成してくれるなど、Ruby の良さを効果的に生かした、大変美しい実装になっ
ています。

まずはこの UPnP ライブラリをインストールします。

幸い gem で公開されているので本来は、gem install で利用準備は終了です。
  % sudo gem install UPnP

ただ、私の環境ではいくつか期待通りに動作しないバグがあり、修正が必要でした。既に patch はtrackerへ登録済みですが、サンプルコードと一緒に公開もしていますので、必要に応じて利用してください(以下のサンプルコードは、このパッチが適用されていることを前提にしています)。

最初にサービス提供側のコードを書いてみます。

基本的には、UPnP::Deviceを継承してデバイスの定義を行い、そのデバイスが提供するサービスをUPnP::Service を継承して書くことになります。

デバイスの基本は、以下の通りです。
  1. 提供したいサービスに ServiceID を付与しておく
  2. UPnP::Device.create を使ってデバイスを作成する
  3. そのデバイスに対し、manufacture などの基本情報を付与する
  4. そのデバイスが提供するServiceIDを登録する
lib/UPnP/device/system_stat_server.rb の self.run がこのコードです。
def self.run(argv = ARGV)
super

device = create 'SystemStatServer', @options[:name] do |s|
s.manufacturer = 'Tempus.ORG'
s.manufacturer_url = 'http://www.tempus.org'

s.model_description = "Disk Stat version #{s.class::VERSION}"
s.model_name = 'Disk Stat'
s.model_url = 'http://www.tempus.org/'
s.model_number = UPnP::Device::SystemStatServer::VERSION

s.add_service 'DiskStat'
end

device.run
end

次に提供するサービスを実装しましょう。ディスク容量を取得するには、RubyForge で公開されている sys-filesystem を使いましょう。これも gem でインストールするだけです。
  % sudo gem install sys-filesystem

BSDや MacOS X を使っている人はバージョンに注意してください。

サービスの定義では、サービス名称とIN/OUTの種別、ならびに結びつけるstate変数を指定します。ここでは、アクション名称をGetDiskFreeSpace とし、取得したパスと単位を指定できるようにしてみました。lib/UPnP/service/disk_stat.rb が該当のコードです。
add_action 'GetDiskFreeSpace',
[IN, 'FileSystem', 'A_ARG_TYPE_FileSystem'],
[IN, 'Unit', 'A_ARG_TYPE_Unit'],

[OUT, 'FreeSpace', 'A_ARG_TYPE_FreeSpace']

add_variable では、UPnP 上でのstate変数と型とを結びつけています。今回は GENA イベントを利用しないので、非常にシンプルな定義です。
add_variable 'A_ARG_TYPE_FileSystem', 'string'
add_variable 'A_ARG_TYPE_Unit', 'string'
add_variable 'A_ARG_TYPE_FreeSpace', 'i4'

あとは該当サービスの内容を実装するだけです。戻り値の第一要素には RETVAL を指定しますが、今回のサービスでは利用しないので nil を指定しています。
def GetDiskFreeSpace(file_system, unit)
result = 0

begin
stat = Sys::Filesystem.stat(file_system)

s = stat.blocks_available * stat.fragment_size
case unit
when 'G', 'g'
result = s / (1024 * 1024 * 1024)
when 'M', 'm'
result = s / (1024 * 1024)
when 'K', 'k'
result = s / 1024
else
result = s
end
rescue
result = 0
end

[nil, result]
end

最後にデバイスの実行コードを定義しましょう。基本はこれだけです。bin/upnp_system_stat_server が該当コードです。
UPnP::Device::SystemStatServer.run

次に呼び出し側であるコントロールポイントの実装です。

こちらもデバイスと同様、UPnP::Control::Device とUPnP::Control::Service を継承して作成します。

まずはサービスから実装します。と言っても、この1行で完成です。
URN_1 = [UPnP::SERVICE_SCHEMA_PREFIX, name.split(':').last, 1].join ':'

次に利用したいサービスのインスタンスを取得するコードを書きます。今回のデバイスでは単一サービスしか提供していませんが、複数のサービスを提供するデバイスもありますから、適切なサービスを選択するようにしましょう。
def disk_stat
@ds ||= services.find do |service|
service.type == UPnP::Control::Service::DiskStat::URN_1
end

@ds
end

alias ds disk_stat

これでサービスを利用する準備が整いました。

最も大事な、このサービスの GetDiskFreeSpace アクションを利用するコードを書きます。単純に該当アクション名を method として実行するだけでサービスを利用できます。
def print_free_size(path = '/', unit = 'm')
puts "server: #{friendly_name || presentation_url}"
size = ds.GetDiskFreeSpace path, unit
puts "free size: #{size} #{unit.upcase} bytes."
end

最後に、デバイスの VERSION と URN を定義します。

VERSION = '1.0.0'

URN_1 = [UPnP::DEVICE_SCHEMA_PREFIX, name.split(':').last, 1].join ':'

基本的に、サービス利用側が書く必要のあるコードはこれだけです。その他必要なコードはすべてライブラリが必要に応じて動的に生成してくれます。

早速作ったコードを試してみましょう。

FreeBSD と Ubuntu の上ででデバイスを稼働させます。
  freebsd% RUBYLIB=lib bin/upnp_system_stat_server -n freebsd
ubuntu% RUBYLIB=lib bin/upnp_system_stat_server -n ubuntu

デバイスが立ち上がったのを確認して、MacOS X 上で コントロールポイントを実行します。
  macosx% ruby -I ../../UPnP-1.1.0/lib -I../lib upnp_sss
server: ubuntu
free size: 25698 M bytes.
server: freebsd
free size: 134 M bytes.
macosx%

無事、動的に機器発見を行い、サービスを利用して情報を取得することができました。

この実装で書いたコード行は、デバイスで100行、コントロールポイントにいたっては、安心を見越したコードでありながらわずか48行です。Rubyの強力さとUPnPライブラリの洗練さとを十分に感じることが出来ます。

なお、このライブラリではデバイス側とコントロールポイントを同じホストマシン上で動作させることができないようになっています。同一ホストマシン上でデバイスとコントロールポイントを動かしたい場合には、サンプルコードに同梱してあるパッチを試してみてください。

是非、Ruby UPnPライブラリを用いて、ホームネットワークでのサービスを試してみてはいかがでしょうか?

大変有益なライブラリを公開してくださり、また、サンプルコードの参考となった IGD や MediaServer を公開してくださったEric さんに、改めて感謝いたします。

Ruby の sys-filesystem が BSD をサポート

Ruby で OS の差を気にすることなくファイルシステムの情報を取得したい場合、sys-filesystem ライブラリを使うと便利です。

残念ながら 0.2.0 では BSD がサポートされていなかったので、小さな patch をお送りしたところ、早速採用して頂いた上、0.3.0 としてリリースして頂けました。感謝です。

BSDや MacOS X を利用されていて、sys-filesystem が利用できなかった方は、是非、試してみてください。

2009/02/25

『プログラミング言語 Ruby』購入しました

『プログラミング言語 Ruby』を購入しました。

Rubyは比較的長く使わせていただいているのですが、印刷された書籍をまともに読んだのは、『オブジェクト指向スクリプト言語Ruby』以来かもしれません。

この書籍は、適切なボリュームでありながら、大変丁寧に分かりやすく、それでいて深い点まで解説されている為、初めて言語を学ぼうとする方には真面目な解説書として、また、実開発でRubyを常用されている方には言語リファレンスとして、利用が可能です。

例えば、1.9.1がリリースされた今だからこそ大変役に立つと思われる「1.8と1.9との差」に関しても随所で説明が行われており、これに目を通しておくことで、無用な混乱に頭を悩ます心配が少なくなると思います。一方で、動的プログラミングで遊びたい、と考えている方々には、リフレクションの解説などに興味くすぐられる筈です。

私は、この本のお陰で、頭の中でごちゃごちゃつながっていた理解の線を、奇麗に筋道立てて整理整頓することが出来ました。

常に手元へ置いておきたいという気にさせる一冊です。Rubyを使われる方は是非。

広告
プログラミング言語 Ruby
プログラミング言語 Ruby...
卜部 昌平 (監訳), 長尾 ...

2009/01/25

Javaで StackTrace を Log へ書き込む方法

Android上でJavaコードを追いかけていて、StackTrace を Log クラスへ書き込みたいな、と思いました。

「古のまま止まっている Java の知識によれば、確か printStackTrace() があった筈だから、それを Stream に流して、文字列を作って...」などと考えていたら、J2SE 1.4以降では、Throwable.getStackTrace()という大変メソッドのあることがCodeZineの記事で分かりました。

というわけで、こんな簡単なコードで要求が満たせました(正しくは、getLineNumber() がマイナス値の場合などを考えるべきです)。
Throwable t = new Throwable();
for (StackTraceElement ste: t.getStackTrace()) {
    Log.v(TAG, "at " + ste.getClassName()
        + "." + ste.getMethodName()
        + "(" + ste.getFileName()
        + ":" + ste.getLineNumber()
        + ")");
}
分かりやすい記事を公開してくださっているartonさん、どうもありがとうございました。

2009/01/17

Developers Summit 2009参加登録開始

Developers summit 2009参加登録が開始されました。

開催日は、2月12日、13日の2日間で、場所は去年同様、目黒雅叙園です。

残念ながら私は別のセッションとの関係で参加できなかったのですが、去年は、Joel Spolskyさんの講演があり、大好評だったと伺っています。

さて今年は、とプログラムを見てみると、Google が OpenSocialHackathonを行うみたいです。私はOpenSocialには馴染みがないのですが、面白そうですね。

時間の都合をつけて、是非今年も参加してみたいと思っています。

2008/11/12

Visual C++はSTLのStrict Weak Orderingルールを検査してくれます

STLの比較関数には、等しい値が渡されたときには、falseを返さなければならない、というルールがあります。

これは、「Strict Weak Orderingルール」と呼ばれ、例えば、SGI のStandard Template Library Programmer's Guideにも、Strict Weak Orderingという専用のページが存在しています。また、Effective STLでは、第21項に「等しい値に対して比較関数が常にfalseを返すようにしよう」という、そのものズバリの項目があります。

にも関わらず、私は、この件をすっかり忘れており、自分のコードの比較関数で、等しい値に対して true を返していました...。

この間違いが発覚したのは、問題のコードをWindowsのVisual C++ 2005でコンパイルして実行した時。普段はgccを使っていますが、マルチプラットフォーム対応の一環で、自分のコードをWindows上でも動作するようにしました。

すると、なんと Visual C++ では、debug モードが有効になっている場合、STLの比較関数呼び出し実行時、引数の前後を入れ替え、必ずどちらかが false になることを調べてくれるのです! 私のコードでは、何れに於いても true を返すことになりますから、このチェックに引っかかり、無事に問題を発見することが出来ました。

Visual C++を(少しだけ)見直した瞬間でした。感謝。

...べ、べつに、VC++に惚れたわけじゃ、ないんだからねっ!



広告
Effective STL―STLを効果的に使いこなす50の鉄則

2008/09/07

MacOS X 英語環境で Flash を日本語モードで使う

最近iMacの言語設定を英語優先にして使っています。具体的には、「System Preferences」の「International」にある「Languge」のリストで「English」を一番上に持ってきて使う、ということになります。

ただこう設定すると、Browserが利用しているAdobe Flash Player(ver.9.x)で日本語が上手く表示されなくなり(恐らく、日本語が1バイト系文字として解釈されているような感じ)困っていました。

検索してみたところ、「聖アンドレアスの失敗」さんのページに、そのものズバリの解法が書いてありました。元ネタは「リンゴが好きでぃす♪」さんのページのようです。皆さん有り難うございます!

要は、
  • Carbonアプリは言語設定情報を__CF_USER_TEXT_ENCODING環境変数から取得する
  • ~/.CFUserTextEncodingファイルが存在する場合には、__CF_USER_TEXT_ENCODING環境変数の設定値にはその値が用いられる。
  • 言語設定を変更すると、~/.CFUserTextEncodingファイル値が変更される。
という流れのようです。

__CF_USER_TEXT_ENCODING の正式なフォーマットは見つけられなかったのですが、どうも、UID:CFStringEncoding:RegionCode という形式になっているようです。RegionCodeの実体値は、deprecatedになっているけどScript Manager Referenceなどを見ることになるのかな?

今回の「Flashを日本語環境で使いたい」という要求を満たすためには、~/.CFUserTextEncodingへ1:14と書いておくのが良いみたいです。
% echo -n 1:14 > ~/.CFUserTextEncoding

最初の値は「kCFStringEncodingMacJapanese」で後者は「verJapan」を意味しているものと思われます。

Carbon周りの調査は、歴史が詰まっていて、面白くもあり、苦しくもあり (^^;

2008/08/10

C++でクラステンプレートを使った既定クラスへのメンバアクセス

次のようなコードを書きました。
template<typename T>
class B {
public:
int _i;
};

template<typename T>
class D : public B<T> {
public:
void f(const int i) {_i = i;}
};

int
main()
{
D<int> aD;
aD.f(5);
return 0;
}
これをg++ 3.4.6でコンパイルしようとしたら、
baz.cc: In member function `void D::f(int)':
baz.cc:10: error: `_i' was not declared in this scope
と言われて、悩みました。クラステンプレートを使わなければ問題ないのになぁ、と。

同じことではまっていたNão Aqui!さんのBlogを通じて最終的に、C++FAQ liteの該当章へたどり着きました。うえー、確かに nondependent name だけどさー。

正しくは、
  • this->で修飾してdependent nameにする
  • using B::_i;でlook upを明確化する
  • B::_i;にする。が、関数の場合仮想選択機構が働かなくなるので、注意
とのことです。

ISO/IEC 14882draft(June 2008)の「14.6 Name resolution」も読んでみましたが「いや、確かにそう読めるけど...」という感じで、これを頭に叩き込んでいたととしても、実際にはまってみるまでは、気がつかなかったと思います。

やっぱりC++は難しいな。くー。

2008/08/03

C++とSTL

久方ぶりに、業務上、短期間でC++とSTLでコードをガリガリ書く機会がありました。C++もSTLも久しぶり。ここまで日常生活が、コード書きに追いまくられるのも久しぶり。

vectorへの push_back() で、メモリ割り当てがこま切れに発生するのは嫌だから、reserve() しておこう、と考えたのは良いのですが、vector が適切に初期化される前に reserve() してしまい、場合によっては push_back() が落ちる、という羽目に。しかも、stack を壊されて、しばしはまりました。

分かってしまえばなんてことないんですが、暫く遠ざかっていたので勘が働きません。なんか、衰えたなぁ、と流石に少し凹み気味。

2008/07/13

Amazon ECS で CD アーティスト名を取る

あれ、以前は「creator」フィールドで CD の「アーティスト」が取れていたのに、取れなくなってるなぁ。

ひとまず「artist」で取れるようなので、「creator」が空の時には、そちらを使うようにしてみましょう。API更新されたのかな?

2008/06/30

『C++の設計と進化』読み終わりました

『C++の設計と進化』をようやく、読み終わりました。

ほぼ発売と同時に購入した気がしますが、少し読んでは他の本に浮気、読み直しては別の本へ浮気、とちっとも進みませんでした。

内容は、C++の歴史と考え方が分かって面白い本です。この機能の実装にあたり、なぜこう考えたのか、というのが分かるのは、大変楽しい驚きです。ARMをパラパラ眺めて(読んでいたとはおこがましい)、いちいち感心していた頃を思い出しました。

一方で、C++という言語が、かくも難解になってしまったのは、設計者の真面目さ故なのかも、と感じる本でもあります。なんというか、メインフレーム時代のプログラマが携えていた(であろう)気品を感じるというか...。この真面目さが、なかなか読み進めなかった原因なのかも知れません。

まつもとさんが書かれているように「低レベルを切り捨てることができなかった」故にC++が人気の無い言語になってしまった、というのは確かに一理あるなぁ、と感じて、その「切り捨てることができなかった」理由が、設計者の真面目さにあるような気がして、そして、それがなかなか上手くかみ合っていない、また、受け入れられていない気がしていて、少し悲しくなるのでした。

とは言え、この真面目さは、書籍としての完成度を高めるためには、大変有効に機能しています。(私がそうだったから、というわけではないですが)ゆっくり、著者の考えに浸りながら読まれると面白いかな、と思いました。

広告

C++の設計と進化
C++の設計と進化...
επιστημη, 岩谷 宏...

2008/06/13

Google Developer Day 参加

2008/6/10 に Google Developer Day へ行ってきました。



前回はGoogle Gear(現在の名前は、ただのGear)が発表された東京での開催ですが、今回は少し前に開催されたGoogle I/Oに沿った内容で、特に新しいAPIの発表といったものはありませんでした。

今回の目玉をあげるとすれば「日本語ドキュメントが大幅拡充」というもの。一見地味ですが、今回のイベントで「開発者ではない方にもGoogleのサービスを自身のWebやBlogサイト上で使って頂きたい」という発言があった通り、Googleサービスへの取っかかりの敷居を下げることを狙っているのでは、と思います。

実際、Google執行役員の辻野さんは「このようなイベントに来る方々は英語のドキュメントでも問題ないだろうけど、多くの方に使っていただく為に、ローカライゼーションへ力を入れて行く」といった内容の説明をされており、広く開発者を募る為に力を注ぐ姿勢は、上昇気流に乗っていた頃のマイクロソフトを彷彿させました(API Expert認定というあたりは、微妙な方向性の似方ですが...)

何はともあれ、私は日本語のドキュメントの方が斜め読みしやすいので、有り難い限りです (^^;

さて、会場の様子ですが、20代後半から30代前半が大半、という感じでしょうか? 多くの人がノートPCを持っており、また Mac 比率が高いのが印象的でした(MacBook Air比率も高くてうらやましい...)。また、セッション中のプレゼン資料をデジカメで撮る人が多いのですが、デジ一を持ってきているひとが多かったのには、びっくりしました。気合い入ってるなぁ(でも、AFのフォーカス合焦音は消してね)。

Developer Eventということで、午後のセッションはコード中心です。例えば、Google App Engine のセッションでは、その場でコードを書きながら機能説明がなされました(別のセッションでは、実際にGoogle開発者と一緒に App Engine を使ったアプリケーションを書く、というのもあります)。このコードを書きながら、というのが、速い速い。何度もプレゼンしているので暗記している、というのはあるのでしょうが、それでも、瞬間的にコードを紡いで行く姿は感動です。

私が興味ひかれたのは(というか、参加の目的は)、やっぱりAndroid と Gear、そして App Engine。何れも(PCではなく)コンスーマ製品との関わりを考えると、いろいろな未来が見えてきてわくわくします。

若者のパワーを感じられた、という点でも、非常に楽しい1日でした。また来年も行きたいな。

なお、発表資料は公開され始めていますから、興味ある方はご覧になるとよいかと思います。

P.S.
全然関係ないけど、プロカメラマンが年季の入ったDomke F-1Xを持っていて、かっこよかった...。

2008/05/12

SubversionのリポジトリをNFS上で

Subversion の repository を NAS 上へと移行させ、その領域を NFS として export し、FreeBSD で NFS mount して運用することにしてみました。勿論、Subversion のバックエンドは FSFSです(BerkeleyDB で NFS は危険だよ)。

可動実験として commit を試してみたところ、
svn: Can't get exclusive lock on file '/foo/bar/reps/db/transactions/0-1.txn/rev-lock': Operation not supported
というメッセージが。しばし、悩んでしまいました。

原因は、FreeBSD側で lockd/statd をあげていなかったこと。今まで、この NFS サーバは、暫定的試用でしか使っていなかったため、設定が漏れていたようです。うーん、間抜けだ。lockd に頼るのは危険、とは分かっていますが、意味なく完全 disable はマズイでしょう...。

/etc/rc.conf に
rpc_lockd_enable="YES"
rpc_statd_enable="YES"
と書いたところ、無事 commit 出来るようになりました。良かった、良かった。

ちなみに FreeBSD で、該当ファイルシステム上に exclusivelock 付きのファイルが作れるかどうかは、lockf(1) を使うのが簡単です。

lockf(1) では、open(2) にO_EXLOCK つけて lock の確認を行っています(rev 1.11.8.1)。apr-1.2.8 では、HAVE_FCNTL_H がenable されていれば、exclusive lock は fcntl(2) の F_WRLCKで行いますから、結果、同じになる、というわけです。

例えば上の状況だと、
% cd /foo/bar
% lockf foo test
lockf: cannot open foo: Operation not supported
という感じになりますから、あぁ、lockd 問題か、と簡単に気がつくことが出来ました。便利便利。

2008/05/08

Rietveldが来る!

Google内部で使われている、非常に有名なコードレビューツールMondrian。このツールは、Google社内の技術を積極的に有効活用している為、社外への公開は難しいとされてきました。

それが、作者じきじきの手によりGoogle AppEngine向けOpen Sourceとして書き起こされ、Rietveldという名前で公開されるそうです! やったー!

Mondiranは、数年前Googleの方に存在を教えて頂き「凄く便利。Google Videoに紹介動画があるから見てみな」と教えて頂いて、そのビデオを見てから、ずっと興味を持っていたので、本当に本当に嬉しいなぁ。

Mondrianには、例えば「Google社内では、各自のホームディレクトリがNFS共有なのを利用して、他人の手元に置かれているコードを自由にレビュー対象にする」など、いろいろなワザが実装されていると聞きました。その辺りも、どのように実現されているか楽しみです。わくわく。

というわけで(至る所に貼られている)Mondrianの紹介ビデオです。