DB操作ツール Emacs DBI を作ってみた
去年からほそぼそと作ってきた、EmacsからDBを操作できるツール Emacs DBI を紹介します。
Emacs DBI の簡単な紹介
このツールの目的は、クロスプラットフォームで便利なDB操作環境を実現することです。 pgAdmin や MySQL Query Browser のようなGUIの良さをCUIで実現してみようとしてみました。すなわち、ぼくのかんがえたさいきょうのDBツールです。ちなみに、このツールにとってEmacsはただの実行環境です。Emacs使わない人でも使うと便利だと思います。
データベース画面
e2wmで3ペインの画面
機能概要
以下のような機能があります。
- EmacsとDB接続可能なPerlが動けばターミナルでも何処でも動く
- DB定義、テーブル定義がすぐ見れる
- auto-complete によるSQL補完
- 接続先DBにからキーワード、型名、テーブル名、カラム名などを補完
- 対応DB(この日記時点)
- SQLite3, MySQL, PostgreSQL, Oracle
簡単に仕組みを説明しますと、EmacsのUIから自前RPC(SWANKっぽいS式のプロトコル)でPerlに接続し、PerlのDBIを使ってDB接続するというものです。
インストール
どちらもパッケージシステムを使うことによって、コマンド一発で入れることが出来るのですが、環境によってはうまく動かないかもしれません。多分そんなに難しくないとは思いますが、EmacsとPerl/CPANの知識があるとスムーズです。
手元での動作確認は、以下の環境で確認しています。
- Gentoo Linux amd64 / perl 5.12.4 / cpanm / Emacs 23.3.5 / SQLite, MySQL, Postgresql
- Windows XP (32bit) / cygwin perl 5.10.1 / cpanm / Emacs 23.3a / SQLite
- Windows XP (32bit) / ActivePerl 5.14.2 / ppm / Emacs 23.3a / SQLite
CPAN
以下のCPANモジュールを入れます。
- RPC::EPC::Service
- DBI
- DBIドライバ(使うDBに応じて)
- DBD::SQLite (SQLite)
- DBD::Pg (Postgresql)
- DBD::mysql (MySQL)
cpan 使うときのコマンド例
cpan RPC::EPC::Service DBI DBD::SQLite DBD::Pg DBD::mysql
自分の所ではシステム全体のCPANと分けるために cpanm を使っています。
LinuxやMacならこれで入ると思います。Windowsで手軽に使うにはActivePerlがいいみたいです。
Cygwinを使っている人は多いと思いますが、Cygwin Perl はPerl以外の依存関係を自力解決する必要があります。
Windows : Cygwin Perl
CygwinのSetup.exeから、Perl や gcc-4 や SQLite などの開発パッケージを入れて、CPANコマンドで入れると入るはずです。CygwinのCPANが遅いのでちょっと時間がかかります。その場合は、 cpanm を使うと速くていいです。CPANでのビルドに失敗した場合は、build.logを見ながら依存ライブラリを追加すると大丈夫みたいです。
Windows : ActivePerl
(2012/03/07 修正)ActivePerlのppmで一発インストールできます!
ppm install RPC-EPC-Service
Marmalade を使ったelispの全自動インストール
Marmalade package システムが入っていれば、 M-x list-package して、「edbi」というパッケージを探してインストール操作するだけです。必要な依存ライブラリやPerlプログラムがすべてインストールされます。あとは設定へ進んでください。
elispの手動インストール
Marmaladeを使わない場合のインストール方法です。
まずは以下の elisp をインストールします。
- deferred.el
- concurrent.el
- ctable.el
- epc.el
- edbi.el
;; auto-installを使う場合 (auto-install-from-url "https://github.com/kiwanami/emacs-deferred/raw/master/deferred.el") (auto-install-from-url "https://github.com/kiwanami/emacs-deferred/raw/master/concurrent.el") (auto-install-from-url "https://github.com/kiwanami/emacs-ctable/raw/master/ctable.el") (auto-install-from-url "https://github.com/kiwanami/emacs-epc/raw/master/epc.el") (auto-install-from-url "https://github.com/kiwanami/emacs-edbi/raw/master/edbi.el")
- 手動ダウンロード
- https://github.com/kiwanami/emacs-deferred/raw/master/deferred.el
- https://github.com/kiwanami/emacs-deferred/raw/master/concurrent.el
- https://github.com/kiwanami/emacs-ctable/raw/master/ctable.el
- https://github.com/kiwanami/emacs-epc/raw/master/epc.el
- https://github.com/kiwanami/emacs-edbi/raw/master/edbi.el
後は perl のプログラムが必要です。
以下のリンクから edbi-bridge.pl をダウンロードして edbi.el と同じ所に置いてください
使い方説明
各画面を簡単に説明します。後で画面遷移についてもまとめます。
接続
M-x edbi:open-db-viewer で接続ダイアログが開きます。
接続ダイアログ
「Data Source」にはDBIで接続するときの書き方で、接続先のDB情報を書きます。以下、書き方の例です。
- sqlite : dbi:SQLite:dbname=/path/to/abcd.sqlite
- postgresql : dbi:Pg:dbname=abcd (※abcd というDBに接続する場合)
- mysql : dbi:mysql:abcd (※abcd というDBに接続する場合)
- 詳細は DBIのドキュメントや各DBDのドキュメントを参照してください。
「User Name」「Auth」には、接続のためのユーザー名とパスワードを入れます。ユーザー名やパスワードが必要ないDBは入力する必要はありません。
一度接続確立したら、Data Source と User Name は履歴に残りますので、次回からは「History」をクリックするかボタンの上でRETすると選択できます。履歴は edbi:ds-history-file に保存されます。(履歴の編集機能は現在ありません。)
接続の際にエラーが発生すると、エラーの内容が上の方に表示されます。接続情報に間違いがなければインストールに問題があるかもしれません。トラブルシューティングの項を参照してください。
DB定義画面
Emacs DBI のホーム的な画面です。接続先のテーブルやビューの一覧が表示されます。
ここから各テーブルの定義やクエリーの内容を表示します。
DB定義画面
主なキーバインドです。
キー | 動作 |
---|---|
j,k,n,p | 選択の上下移動 |
SPC | 選択したテーブルの定義表示 |
RET | 選択したテーブルのデータ表示 |
c | クエリーエディタ開く |
g | 最新の情報に更新 |
q | Emacs DBI 終了 |
(詳しくは edbi:dbview-keymap と ctbl:table-mode-map を参照してください。)
テーブル定義画面
テーブルやビューの定義を表示します。カラムの名前・型・サイズや主キーやNOT NULLなどの情報を見ることができます。
テーブル定義画面
主なキーバインドです。
キー | 動作 |
---|---|
j,k, n,p | 上下移動 |
V | テーブルのデータ表示 |
c | クエリーエディタ開く |
g | 最新の情報に更新 |
q | バッファkill |
(詳しくは edbi:dbview-table-keymap と ctbl:table-mode-map を参照してください。)
クエリーエディタ画面
このバッファでSQLを書きます。C-c C-c でSQL実行、 M-p / M-n で過去に実行したSQLを表示できます。
sql-mode をベースにしたメジャーモードになっていて、適当なシンタックスハイライトと、auto-completeが入っていれば補完が効いて、Emacsのエディタの能力を生かして効率よくSQLを書くことができます。
エディタ画面
主なキーバインドです。
キー | 動作 | |
---|---|---|
C-c C-c | SQL実行 | |
M-p | 履歴もどる | |
M-n | 履歴すすむ | |
C-q q | Emacs DBI 終了 |
(詳しくはedbi:sql-mode-map を参照してください。)
クエリー結果画面
SQLの結果を見やすいテーブルで表示します。
結果画面
主なキーバインドです。
キー | 動作 |
---|---|
j,k,n,p | 上下移動 |
h,l,b,f | 左右移動 |
a,e | 左端、右端移動 |
q | バッファkill |
SELECTでないSQLの場合は、影響を受けた行数が表示されます。
(ただし、DBIドライバの実装によってはなんだかよく分からない値になることがあります。)
画面遷移
これまでの画面の遷移をまとめると以下のようになります。
画面遷移
トラブルシュート
予想されるトラブルと対応方法を簡単にまとめました。
近所に Emacs や Perl のハッカーが一人はいると思いますので、うまく動かない場合は相談されるといいと思います。
- LC_ALLとかLANGのロケールが不明というエラー
- (setenv "LC_ALL" "ja_JP.utf8") とか評価すると動くかもしれません。
- 「file-error Searching for program そのようなファイルやディレクトリはありません perl」
- 「error Server may raise an error : Can't open perl script "〜/edbi-bridge.pl": そのようなファイルやディレクトリはありません (以下略」
- 「error Server may raise an error : Can't locate RPC/EPC/Service.pm in @INC (@INC contains: ...(以下略」
- その他
まだまだ開発途上ですので、バグや不便なところがたくさんあると思います。
カスタマイズ
変数、フック、キーマップ
- テーブル簡易データ表示の LIMIT 件数。デフォルトは50。
- edbi:dbview-show-table-data-default-limit
- 長い文字列の切り捨て文字数。デフォルトは 50。
- edbi:query-result-column-max-width
- 固定ヘッダーか、バッファ内ヘッダーか。デフォルトは t (固定ヘッダー)
- edbi:query-result-fix-header
- 固定だと縦スクロールしてもヘッダーが表示されるが、横スクロールすると切れてしまう
- バッファ内ヘッダーだと横スクロールしても問題ないが、縦スクロールで切れてしまう
- クエリー編集バッファの mode-hook
- edbi:sql-mode-hook
- キーマップ
- ctbl:table-mode-map : テーブルの基本キーマップ
- edbi:dbview-keymap : DB定義画面のキーマップ
- edbi:dbview-table-keymap : テーブル定義画面のキーマップ
- edbi:sql-mode-map : クエリー編集画面のキーマップ
- edbi:dbview-query-result-keymap : クエリー結果画面のキーマップ
e2wmとの連携
e2wmのパースペクティブにすることで、GUIアプリのようにウインドウの構成を固定して使うことができます。
e2wm 画面
利用方法は、以下の elisp を e2wm の後で読み込むように設定します。
- edbi-e2wm.el : https://gist.github.com/1842966
この例では「Super+D」でDB画面になるように設定しています。
キー一発でコードとDB操作を切り替えることができるので、Webアプリ開発のようなコードとDBを頻繁に参照するような開発に威力を発揮します。
別のDBMSへの対応
現在のところ、SQLite, MySQL, Postgresql と、id:buzztaiki さんにパッチをいただいた Oracle に対応しています。これ以外のDBMSについては、PerlのDBD(DBIのドライバ)があれば原理的に対応可能です。ただし、DBDやDBMSによってAPIの仕様や返り値がかなり異なるため、そのままでは動かない可能性が高いです。
他のDBMSへの対応を追加する方法は以下のようです。
- githubの edbi-demo.el をポチポチ実行しながらDBDからの返り値を確認
- 他のDBMSのものを参考にしながら edbi:dbd 構造体を定義
- edbi:dbd-register で登録して接続しなおして動作確認
もし、いい感じに追加対応ができたら、 pull request を送っていただけたら取り込みたいと思います。
今後の展開
以下、自分が現在考えている希望です。実現するかどうかは未定です。
あとがき
そもそも、このツールをつくろうと思ったのは、Linux用の良いDB操作用GUIツールが無かったからです。
開発の時はSQLをたくさん書くので、補完もシンタックスハイライトも欲しいですし、テーブル定義も頻繁に見たいです。コンソールだとそのあたりのサポートが全く無いので不便でした。
Emacs には sql-mode や inferior な sql-interactive-mode もありますが、自分にとっては console がちょっと便利になった程度でしかないので、コンソールに比べてメリットが感じられませんでした。
一方、GUIのアプリは、結果がテーブルの形で表示されるので見やすく、またテーブルの定義情報へのアクセスも容易です。さらに、GUIでテーブルやDBMSの管理が行えたり、Explainの結果を見やすく整形できたり、便利な機能がたくさんあります。
自分が使ったり試したりしたことがあるDB操作のGUIツールには以下のものがあります。
- pgAdmin
- MySQL Query Browser / MySQL Workbench
- http://dev.mysql.com/
- Query Browser は便利だった
- Workbenchになってよく分からなくなった
- SQL Server Management Studio
- http://en.wikipedia.org/wiki/SQL_Server_Management_Studio
- DBに関することは何でも出来る
- 管理、バックアップ、監査、定義、EXPLAIN などなど
- 死ぬほど重いので使いたくない
- phpMySQLAdmin
- http://www.phpmyadmin.net/home_page/
- いろいろ出来る
- このためにWebサーバーやPHPセットアップするのが面倒
- SQLite Browser
- http://sqlitebrowser.sourceforge.net/
- 大体いいけど、他のツールに比べてGUIが適当で細かい所が使いづらい
- SQLite Manager (Firefox plugin)
- https://addons.mozilla.org/ja/firefox/addon/sqlite-manager/
- SQLite Browserよりこっちの方が使いやすいので、専用のFirefoxのプロファイルを用意するといい感じ。
- CSE
- http://www.hi-ho.ne.jp/tsumiki/
- 歴史や動作実績が多く、ODBC経由では現場デファクトらしい
- A5:SQL Mk2
- http://www.wind.sannet.ne.jp/m_matsu/developer/a5m2/
- 個人的に気に入っている
- ODBCやOLEでの接続が豊富
- 定義書出力、SQLの補完も便利
- Eclipse / DBViewer
- http://www.ne.jp/asahi/zigen/home/plugin/dbviewer/about_jp.html
- Eclipseで開発する人向け
- 昔はDBEditとか使ってた
- NetBeans
- http://netbeans.org/features/ide/database.html
- JPAが出た頃から急速にDBとJava開発の融合が進んでる
- JDevelopperも現場の評判いいらしい
Windows にはたくさんGUIツールがあるのですが、Mac版は殆どありません。LinuxはMacよりはましですが、常用できるツールはほとんど無いです。IDE統合のツールはどのOSでも動いて便利そうなのですが、わざわざこのためにIDE起動したくありません。
軽くて、どのOSでも同じように動いて、GUIのツールぐらい便利に使えて、Emacs並にエディタが強力なDB操作ツールが欲しいのです。
ということで、無いなら作ろうという事で、去年の calfw が一段落した後から作り始めました。途中、派生ツールとして epc / ctable などが出来ました。
オライリー:プログラミングC# 第4版 メモ
プログラミングC#―C#2.0/.NET2.0/Visual Studio2005対応
- 作者: ジェシーリバティ,Jesse Liberty,鈴木幸敏,首藤一幸,情報技研
- 出版社/メーカー: オライリージャパン
- 発売日: 2006/02
- メディア: 単行本
- 購入: 1人 クリック: 27回
- この商品を含むブログ (43件) を見る
プログラミング C# 第4版を最近スキャンしたのですが、以前読んだ時の付箋がたくさん貼ってありました。読み返してみたら今でも相当面白かったので、メモを淡々と書いてみます。
現在は第6版なので、以下のメモには現在の仕様と異なっている部分があるかもしれません。ご注意ください。
- p26 値型(value type)と参照型(reference type)の説明
- →地味に各章への伏線がはってある
- p28 スタックとヒープ
- コラムでスタックとヒープについての説明
- p29 組み込み型同士の変換
- "キャストとは「おい!コンパイラ!私は自分が何をやってるのかちゃんとわかってるよ」と伝えること"
- p33 シンボル定数(const)
- シンボル定数という呼び方
- p36 列挙型の変換 cast
- 指定しないと0から始まって1ずつ増える。途中指定するとそこから増える。
- p45 goto / label
- "goto文は、通常別のcaseにジャンプするときに使われる"
- サンプルコードが政治
- p53 空白文字と中括弧
- コラムで空白文字と中括弧のスタイルについて
- 趣味の問題であり、VSの設定で調整可能。
- p55 四則演算演算子
- "C#は、整数の割算をするとき、小学4年生ぐらいの子供が行うように割ります。" → つまり切り捨て
- p67 クラスとオブジェクトについて
- クラスは型であり、同時にカプセル化の手段である
- "クラスとオブジェクトの違いは、犬という概念と足元に座っている特定の犬との間の違いになぞらえることができます。犬とは何なのかという定義を相手にして、これを取ってこいといいつけて遊ぶことはできません。遊び相手にできるのは特定のインスタンスです。"
- "プログラミングに関する古い冗談に「電球を交換するために何人のオブジェクト指向プログラマが必要でしょうか?」、「ひとりも要りません。電球に、自身を交換するように指示すればよいのです」というものがあります(「ひとりも要りません。なぜなら、Microsoftが暗闇というものの基準そのものを変えてしまったからです」という答もあります)。"
- p70 アクセス修飾子
- public, private とかの表。アセンブリも一つの境界になる。
- p71 アクセス修飾子は明示的に書くべき
- "明示的に書いておくと、それは考えた結果の決定であるという事が伝わりますし、自己記述的にも出来ます。"
- p73 VB6 の Dim, New と C# の new
- VB6では Dim と New を同じ行で使うと性能が悪くなるらしい
- p73 単純型の既定値
- char の既定値は '\0'
- p78 C#の「thisポインタ」
- C#では「thisポインタ」は誤解のもとになるので、正しくは「this参照」を使う
- "本書ではthis参照というように使い分けるようにしています。言い間違えた個所があれば、それぞれに25セントの罰金をチャリティに寄付しましょう。"
- p80 staticメソッドはインスタンスから呼べない
- →Javaとは違う
- p80 オブジェクトの名前 = ヒープ上の無名のインスタンスへの参照の値に付けられた名前
- "本書において、オブジェクトの名前という表現をする場合、「ヒープ上の無名のインスタンスへの参照の値につけられた名前」を省略しているということを記憶の隅に置いておいてください。"
- p85 デストラクタの動作
- GCの動きを具体的に書いている
- p87 using文
- try - catch - finally よりも確実
- p93 出力用の out, 参照渡し ref の例
- Javaと同様、基本的に引数は「値渡し」。
- out や ref を使うことで引数で値を返すことが出来る。
- p99 set アクセサ
- value キーワード
- p102 readonly の代入ルール
- コンストラクタ内では代入できる
- p105 クラス階層の説明
- 本文で陥りがちな悪い例を示して、コラムで自分で批判
- →これで分かる人は面白いけど、分からない人は混乱しそう
- p109 overrideキーワード
- オーバーライドするには override って付ける必要がある
- p111 既定コンストラクタ自動生成
- p113 new virtual キーワード
- new virtual を使うと、基本クラスが同名の派生クラスのメソッドを呼ばないように出来る
- 規模が大きくなってメソッド名がぶつかる事故が起きて、意図せず基本クラスの動作を破壊することを防ぐらしい。
- →うーん。余計な迷路を増やしただけにも見えるし、ちょっと気持ち悪い。
- p122 ボックス化とボックス化解除
- p123 C#の入れ子クラス
- p127 比較演算子オーバーライド
- p137 構造体は値渡し、参照にするにはボックス化が必要
- →クラスと構造体の使い分けは難しそう
- p140 構造体はnewしなくても使えるが、推奨されない
- →何のためにあるのか?
- p143 C#ではインタフェースに定数が書けない
- p144 Mix In の話
- 例のアイスクリーム屋の小話
- p147 インタフェースでのアクセサ
- publicしかありえないので、アクセス修飾子を書くとコンパイルエラー
- p159 as演算子。isでチェックしてキャストする
- →cast必要なときは便利そう
- p161 抽象クラスかインタフェースか
- Microsoft社内ではバージョン管理の都合からインタフェースよりも抽象クラスを好む人がいる
- インタフェースはインタフェースと実装クラスの2つが必要。めんどう。抽象クラスであれば virtual 付けるだけでいい。
- "なんということでしょう!"
- p163 キャスト先の型によって動作が変わる!
- インスタンスが同じでも、キャスト先のインタフェースの型によって動作を変えることが出来る
- →サンプルコードは的確で分かりやすく、本文で説明されているメリットは理解できるが、それによるデメリットの方が大きくないのか?ちょっと気持ち悪い。
- p166 インタフェース名を指定して実装するときはアクセス修飾子を付けられない
- インタフェースはpublic以外ありえないから
- p168 インタフェース名を指定して実装することで、インタフェースメンバの選択的公開が出来る、クラスのセマンティクスを守る
- →熟考の上での選択だと思うけど、そんな複雑なことがどうしても必要なことがC#界隈にはあるのだろう。
- p207 IEnumerable
とyield - →見た目かなり違うけど、中身はRubyのyieldっぽい
- p210 ジェネリクスの型の制約
- →型の制約の書き方はどの言語も大変そう
- p233 Dictionaryのキーをオブジェクトにするならキーのオブジェクトを変更してはいけない!
- オブジェクトの中身を変更するとGetHashCodeが変わるので、オブジェクトをハッシュのキーにして変更すると探せなくなる
- →ついやってしまいそう。こわい。
- p236 stringとStringは等価
- stringの内容を変更すると新しいオブジェクトの参照が帰る
- p237 逐語的文字列リテラル
- 基本的にエスケープされないが、ダブルクオートはエスケープする必要がある
- →JavaやEmacs Lispにも欲しい
- p242 case ignore な比較
- "ここでは、1行を短くすることで結果の出力が書籍のページにきちんと収まるように、WriteLine()を2回呼出しています。" ??
- p244 string の == はオーバーライドされているので中身で比較される
- →Javaもそうだったらよかった
- p249 split の params キーワードの例
- 可変長引数
- p263 例外について
- バグとエラーと例外の区別をつけよう
- →いい話
- p267 すべての例外をキャッチする書き方
- p274 finally ブロックの制限
- return, break などのジャンプを使うとエラー
- p311 event キーワード
- イベントハンドラの直接呼び出しの制限
- p316 delegate の匿名メソッド
- lambda
- p318 マルチキャストデリゲートの明示的な実行
- →ここまでくると、わざわざ言語でサポートする必要があったのか疑問
- p321 デリゲートの非同期実行
- →話は面白いけど、多分説明が分かりにくそう
- p341 コラム 亀は続く
- スチーブン・ホーキング氏の小話
- "「あなたはなかなかよくできた子ね。しかし亀は亀の上にいるのですよ。その繰り返しです。」"
- p367 ADO.NET
- p397 UIデザイン
- "筆者はUIを完璧にデザインできるプログラマはいないと考えます。"
- p400 ASP.NET
- IsPostBack でポストされたかどうかの判断
- →うーん。昔だからしょうがないかも。
- p444 アセンブリとセキュリティ境界
- 2つのアセンブリにまたがって型を定義することはできない。型の参照は出来る。
- p452 デフォルトではプライベートアセンブリ
- DLL地獄の解決策
- p480 マーシャリングの説明
- 約1ページに渡って、マーシャリングとチャンネルについてスター・トレックで説明
- "例えば、カーク船長が文明の発展に重大な影響を与えるようなことを伝達しようとするとき、最初のシンクはこれを拒絶します。"
- → Prime Directive の知識が前提!!!!
- p497 RPCのサンプルコードのコメント
- "「ただそこに立ち、待つばかりの者もまた主に使えし者である」(ミルトン)"
- → キリスト教の知識が前提。深い。
- p526 訳者注:デッドロック
- アメリカでは「deadlock」、ヨーロッパでは「deadly embrace」が多い。ただし、embraceは2つのプロセス間の場合のみに使う。
- p553 シングルスレッドでブロックするサーバーソケットのサンプルコードについて
- "電話を目の前にして、鳴り出すのをいつまでも待っているような状態です。このモデルは1週間に2接続程度のサーバーであれば問題ないでしょうが、実際のアプリケーションとしてはほとんど使い物になりません。"
- p612 fixed キーワード
- fixedを使うとGCによって変更されないメモリアドレスのポインタを取得できる
この本はサイ本や詳説正規表現と並んでとても楽しかったです。
C/C++の方面から見るとそんなに不思議ではないけど、Java側から見ると落とし穴が多いと思います。Javaと字面は似てるけど、全く同じのつもりで業務でコード書いてる人(SE PGとかでよく見る)は気を付けた方が良いと思いました。(Lispに比べたら大した違いではないけど。。。)
Emacs で IPC や RPC (Emacs Advent Calendar jp: 2011)
Emacs Advent Calendar jp: 2011 : ATND 6日目の記事のはずでしたが、手違いでかぶってしまい、いろいろあって遅くなってしまいました。
皆様、乱してしまってすみません。
今回の記事では、EmacsでのIPC(Inter-Process Communication)やRPC(Remote Procedure Call)の方法について、自分の知っている範囲でまとめてみます。IPCは、プログラムの間で通信する仕組みです。RPCは、既に起動しているプログラムの一部(関数やサブルーチン)を別のプログラムから呼び出す仕組みです。一般的にIPCの枠にRPCが含まれます。
EmacsにはどんなIPC/RPCの実現方法があるのか、実際の応用例などを5分程度で簡単にまとめてみます。
Emacsの標準IPC手段
以下のようなものがあります。(Emacs 23 以上の場合)
- パイプ
- プロセスを起動してパイプで通信
- ソケット
- D-Bus
- Linux Desktop 環境向けの通信プロトコル
- D-Bus - Wikipedia
- ファイル読み書き
- 排他制御が必要
- emacsclient
- 起動中のEmacsとS式でのやりとり
ひと通り揃っていて、大体色々出来ますし、D-Bus以外はプラットフォーム中立の事を考えて作られています。
しかしながら、本格的なプログラミング環境としては細かい制御が出来ず、悔しい思いをすることが多いです。特に、共有ライブラリにリンクして、高機能・高パフォーマンスな通信手段(DB直接続とかmsgpackとか)を使うことが出来ません。
そのため、一般的には別の中継プログラムを作成して、パイプなどで通信してやりたい機能を実現するということが多いです。このあたりの歴史や状況については、 id:m2ym さんの文書 http://cx4a.org/pub/emacs-is-dead.ja.html が詳しいです。*1
IPC/RPC いろいろ
Emacsで行われている IPC/RPC の手段について簡単に紹介してみます。
コマンド起動
プログラムを起動し、結果を標準出力などからテキスト等で受け取る方式です。
同期的に呼べば簡単に使えますし、外部プログラムだけでデバッグもできるので楽です。
一方で、外部プログラムや設定がOSや環境に依存して動かないこともあります。が、他の方法よりもはるかに問題解決が楽です。
パイプ・ソケット
バックグラウンドで外部プログラムを起動し、パイプやソケットなどで通信する方法です。
非同期プログラミングが大変ですが、常に起動しているため応答の性能も良く、また外部プログラム側も状態を持つことができるので、出来ることが大幅に増えます。
- パイプで通信
- TCPソケットで通信
- SLIME / Swank
- IIIMECF(ATOK)
- ソケットで非同期通信
- キーイベント → 漢字変換、UI更新(非同期)
(2011/12/09 TCPソケットのところにパイプ通信が混じっていたのを修正)
D-Bus
D-Bus は Linux Desktop 上ではかなりデファクトに近いIPC環境になっています。
- D-Bus - Wikipedia (再掲)
1対1の通信だけではなく、必要なプロセスにイベント通知させたり、オブジェクトのシリアライズ、サービスのインスペクションなども出来るため、IPCとしてはかなり高機能です。
- 参考文献
skype.el でも使っていますが、これを積極的に利用したアプリケーションはほとんど無く、正直 D-Bus をEmacsでサポートする必要はなかった(もっと他にやることがあった?)のではないかとか思っています。
emacsclient
起動中のEmacsにファイルをオープンさせるような用途が圧倒的ですが、S式を送り込んで評価させたり出来るため、手軽なRPCとして利用できます。
HTTP / Webサービス
最近はインターネット上のサービスと通信する機会が多くなってきました。REST APIに直接アクセスしたり、XML-RPCなどで機能を手軽に呼び出すことが出来ます。
xml-rpc.el のように、標準のurlパッケージを使ってEmacs単独で通信することも出来ますが、るびきちさんも指摘する通り、細かいバグやSSL・プロキシ経由の通信で問題があるので、自前実装する場合は curl, wget を使う方が堅実だと思います。
Webサービスと通信する場合に問題になるのは認証です。一般的に以下の方法があります。
- OAuth
- Webアプリ向けの OAuth を実装する方法、コスト高い
- Twitterクライアントとかだと必須
- oauthライブラリ : EmacsWiki: O Auth Library
- twittering-mode は自前実装
- API key
- HTTPセッション Cookie
- 認証APIからクッキーを発行してもらって、以降の通信で使う
- 参考 : セッションキーとして出力されるCookieをwgetで保存する: hogepiyo
- あんまり見たこと無い。ページスクレイピング? リファラーとかCSRF対策は?
- BASIC認証
- ユーザーに認証情報を入れてもらう
- パスワードやユーザー情報を wget などに渡す必要がある
今後、Webサービスとの通信は増えてくると思いますので、この辺りの環境が整備されてくると便利になりそうです。
EPC に続く
これまでのIPC/RPCはプリミティブすぎる(パイプとかD-Busとか)か、特定の目的のための専用スタック(pymacsとかel4rとか)なので、別のプログラムを気軽に呼び出して使えるような、汎用のRPCスタックがありません。
例えば、EmacsはDBに直接接続することが出来ませんが、DBに接続して自由にSQLを発行してデータをやり取りできると、大変夢が広がります。さらに、これがPythonやRubyなどの専用スタックではなく、インタフェースは固定のまま、自分の好きな言語で拡張できると大変素敵です。
ということで、現在 EPC(Emacs Procedure Call)なるものをつくっています。YAPC Asia 2011の時にデモしたような、EmacsからPerlを自由に呼んでやりたい放題なことを実現できるようにする予定です。
Emacs - Perl 間はだいたい動くのですが、いきなり CPAN に上げる前に PrePAN でレビューをお願いしたいと思っています。
プロトコルの詳細などのドキュメントが固まり次第、お知らせする予定です。
おわり
本当にすみません。Advent Calendar は小粒なネタで毎日続けることが重要だと思いました。来年も参加するときは気をつけようと思います。
やっぱり1時間ぐらいかかりました。
Nginx Inside Memo (カーネル/VM Advent Calendar)
この記事は http://atnd.org/events/21910 のために書かれたものです。
一つ前の5日目は @sora_h さんの钱柜娱乐_钱柜娱乐平台_钱柜娱乐777(唯一)官方网站でした。明日は、 @master_q さんの予定です。
nginx の内部の仕組みやモジュールの作り方について簡単に紹介してみます。
最近 nginx のコードを読んでハックを試みました。 nginx のコードについてはほとんどドキュメントがなく、日本語でも見かけなかったため(もし書いている人がいたらすみません)、後から続く人にとって多少でも参考になれるようメモをまとめました。(2011/12/06 デバッグについて少し追記)
全部読みきったわけではないので、コードを読む上でのとりかかりぐらいの情報です。もし、間違いがあれば教えてください。
このメモは stable version である Nginx-1.0.10 のコードを対象にしています。
参考情報
- Joshua Zhu's Blog, Nginx Internals (Slides & Video)
- 英語と中国語ですが、大変参考になりました。結構読んだ後に見つけたのですが、プレゼンのスライドなので読まないと分からないことが多かったです。
全体アーキテクチャ
各地で説明されているように、クライアントのリクエストをさばくWorkerプロセスと、Workerプロセスを管理して、全体の起動や終了などを管理するMasterプロセスからなる。
WorkerプロセスとMasterプロセスは、UNIXシグナルや共有メモリ、ドメインソケットなど(環境によって違う)で通信する。
各Workerはシングルプロセス*1のシンプルなイベントドリブンな設計になっている。
nginxが受け取るイベントには、ネットワークのソケットの接続開始・終了や、読み出し・書き込み可能状態の変更、シグナルなどの通知などがある。ひとつのプロセスでIOを多重化し、可能な限り処理を非同期に行うことで、各地で評判の高いスループットが実現している。OS(FreeBSDとか)によってはファイルのIOも非同期に行うことができる。
各OSや実行環境でのイベント操作の抽象化のために ngx_event_actions_t という構造体が定義されている。この構造体のメンバにイベント操作の関数ポインタ入っている。
個別のイベントについては ngx_event_t でイベントの情報と操作がセットで定義されていて、各地の実装で実際のイベント情報が生成される。
コードレイアウトと起動
コードのレイアウトはシンプルで直感的。見たまま。
- src
- core
- event
- http
- misc
- os/unix
エントリポイントは /src/core/nginx.c の main 関数。内容はごく普通のデーモンサーバー。
- 処理流れ
- 引数処理
- デーモン化
- 環境変数設定して worker フォーク
- 各モジュール初期化
- メインループ突入
この中で cycle という単語がよく出てくる。プロセスサイクルの略だと思われる。大体 worker/master プロセスのメインの処理やデータを表す感じ。
高速化の努力
全部読んでないけど、なるほどと思った。
イベントドリブン
全体の設計が徹底的にイベントドリブン。非同期に出来るものであれば、何でもこのアーキテクチャに乗って回すことが出来る。後述のモジュール実装でも出てくる。
独自メモリアロケーション
イベントオブジェクトやバッファなど、各地で細かくメモリの割り当て・開放が行われるので、多分かなり効果ありそう。
Rope的バッファ
バッファをリンクリストで連結。イベントドリブンな仕組みと相性が良さそう。
HTTP処理
処理フェーズ状態遷移
HTTPの細かい処理を状態遷移マシンで抽象化。
- 状態一覧 (ngx_http_init_phase_handlers 周辺で定義)
各状態でやるべき処理が明らかになって見通しが良い。ただし、状態遷移マシンの実装はハック的。
フィルター
よくある出力の抽象化。リンクリストで実装。
設定で柔軟に組み合わせられる。
モジュール
各パーツをモジュールという入れ物に入れて、統一的に扱う仕組み。(ここは抽象度が高くて範囲が広く、いたる所 void* だらけで完全に把握できてない。)
ngx_xxx_module_t が各モジュールごとにあり、そこから各モジュールの設定ファイルの解釈、状態(コンテキスト)にアクセスできる。
設定ファイルの解釈、起動時の初期化、終了時の処理などが統一的に定義されていて、大体どのモジュールも同じような書き方になっている。
モジュールには core, event, http, mail の4種類がある。各モジュールの依存関係の図が欲しい。
モジュール開発について
nginx にはたくさんモジュールがある。が、本家サイトにはモジュール開発の情報がない。
- Joshua Zhu s Blog, Creating a Hello World! Nginx Module
- 上の解説プレゼンの人による最小限のコードによる Hello Module 。なんとなく雰囲気が分かる。
- ただ、これだけでは全然分からないので、下のドキュメントを読む必要がある。
- Emiller's Guide to Nginx Module Development
- Emiller's Advanced Topics In Nginx Module Development
- 上の続き。もう少し細かい話題など。まだ続くらしい。
- NginxでのModuleの作り方 - よねのはてな
- 米林さんの記事。この記事を書いた大分後に見つけました。とても参考になります。(2012/08/28追記)
デバッガ
本体やモジュールが落ちる場合はデバッガを使って原因を調査する。Workerを調査する場合は、追跡しやすくするために worker プロセスは1つにしておくほうが良い。
デバッガを使って本体を起動するか、起動中のPIDを調べてアタッチする。Linuxだとgdbやnemiverを使ってやる感じ。
設定ファイルのパースの状況やモジュールの状態がどうなっているかなどがよく分かる。
gdbで起動させる場合は、フォークしたWorkerプロセスをフォローしてもらうために、以下のコマンドを実行しておく。
set follow-fork-mode child
結局やりたかったこと
これまで業務で DRBD などを用いて大容量冗長化のファイルシステムを用いてきたが、ファイル容量のスケールアップが辛く、また運用のコストも高いので、初期コスト低い・簡単運用・スケールアップ可能な分散ファイルシステムを探している。
最近、 MongoDB の分散FSである GridFS に注目している。
nginx-gridfs というモジュールがあり、これを使うと GridFS に直接つなげることが出来る。単純なローカルファイルへのリクエストとのパフォーマンス比較ではもちろん圧倒的に負ける。
- ベンチマーク結果
しかしながら、他の分散ファイルシステムと比較した場合のパフォーマンスについては自明ではない。そこで、手元で修正したり、ハックしながら調査中。
GridFS との接続が同期通信なので、ここを非同期にするとスループットが上がるのではないかと考えている。もしくはキャッシュをうまくやる。でも C で実装するのは辛いので mighttpd など、他のプランも考えたい。
GlusterFS も調査したい。
その他高速Webサーバー
- Cherokee Web Server | Home
- かわいい。GUI。速いらしい。
- Mighttpd
- Haskell。速いらしい。モジュール作り易いなら乗り換えたい。
まとめ
つかれました。
*1:マルチスレッドで動かすことも出来るみたい
org-mode のリファレンス検索 anything-orgcard
最近ローカルでの開発作業のメモに org-mode を使っています。単なるテキストファイルの延長から始めているので、そんなに高度な機能は使っていません。
- Org mode for Emacs – Your Life in Plain Text
- 最近の Emacs は標準添付。最新は 7.7。
- http://hpcgi1.nifty.com/spen/index.cgi?OrgMode
- 日本語サイト。現在最新ドキュメントを翻訳中。
- Org-mode 翻訳プロジェクト
org-modeは機能が多いのでリファレンスのお世話になることが多いのですが、Emacs上のキーバインドを検索できる神ツール descbinds-anything が全く役に立ちません。
こんな風にバインド先の関数名がキー名の関数なので意味がないです!*1
org-キー名になってうれしくない
そこで、 orgmode.org のサイトにあるリファレンスカードのファイルを使って、anythingで機能からキーバインドを探すことのできるツールを作りました。こんな感じになります。
機能で探すことができる
やっつけ実装なので選択しても実行はしません。ミニバッファに表示しておくので、自分でキーを入力します。
インストールは load-path に置いて (require 'anything-orgcard) してください。
M-x aoc:anything-orgcard で起動しますので、適当なキーバインドに入れておくといいと思います。手元では、以下のように org-mode のキーマップに入れるようにしています。
(eval-after-load "org" '(progn (define-key org-mode-map (kbd "M-4") 'aoc:anything-orgcard) ))
Gentoo派になりました
8月〜9月ごろからメインマシンの X201s の Ubuntu10.10 が急速に不安定になってきました。原因はよく分かりません。最初、排気口が詰まったことによる熱暴走かと思っていましたが、熱の問題を解決しても状況はあまり改善せず、9月末には1日10回以上再起動するような状況になり、とても生活できない状況になったのでOSを入れ替えることにしました。
11.10までのつなぎとしてGentooでも使ってみようと思い、WDの安いハードディスクを買ってきてGentooを入れてみました。結果、相当よかったので今もそのままGentooで使っています。以下、Gentoo導入のメモです。かなりいいかげんで、細かいところはアドリブでやったのであんまり覚えていませんが、何かの参考になるといいですね。
Gentoo インストール
ブートと展開用ファイルだけが入ったCDを準備。手順をひとつひとつ確認しながらすすめるのでかなり時間がかかった。別環境に2回目インストールしたときは再起動まで1時間ぐらい。練習すれば放置してあるPCをGentooにしてしまうのに10分かからないくらいまで行けるのかも。
Xの起動ではまった。結局、自分で xorg.conf 書いてはダメだということと、 /etc/make.conf に INPUT_DEVICES="evdev" が必要だった。これらの情報は日本語ドキュメントと英語ドキュメントで内容が違っていたので、日本語で概要を掴んで英語ドキュメントで詳細を見る方が確実そう。
カーネルコンパイルが楽。すごい楽。FreeBSD 並。10年以上 Linux をやっていて make menuconfig から make modules_install までこけなかったのは初めて。一方で Ubuntu ではカーネルのビルドに成功したことがほとんど無い。 Ubuntu は独自にカーネルを調整してるらしいので独自コンパイルが難しいのかも。
/etc/fstab の /boot のオプションに noauto が入っているのに気がつかずに /boot の内容が反映されずにしばらく grub ではまってた。
あとはひたすら emerge してもとのUbuntuで出来ていた環境に近づけていくだけ。naota先生の資料が大変役に立ちました。
メインメモリは 6GByte あるので /dev/shm の容量は 5GByte にした。大物 LibreOffice のコンパイルが 3GByte ちょっと使うので多めに設定。
途中、libpngの更新ではまった。soライブラリのシンボリックリンクが足りなかったので自分で足した。何というか、 emerge のエラーが親切というかログも素直なので問題解決がしやすい。
WD の IntelliPark 問題
ディスクアクセスの時に2秒くらい固まるのは気のせいかなと思っていたけど、やっぱり気のせいでなかった。
るびきちさんもはまったこのIntelliPark地雷を踏んでしまった。3000円くらいの安物だったので、よく調べずに買ってしまった。ハードディスクの値段というより、Gentooインストールにかけた時間と労力が悔しかったのでなんとか対応した。
方法は、非推奨ツールのwdidle3を使う方法。
USBメモリにDOSブートディスク作成。DOSのブートはいろいろ試したけども、結局 Linux 上の makebootfat を使う方法が一番確実だった。
wdidle3でハードディスクの設定を見てみると4秒アイドルでヘッド退避・回転停止の設定だった。4秒ごとにシステムが2秒固まる設定に殺意を覚えた。すぐにwdidle3/dでタイマーを無効にした。一応普段は固まらなくなったが、バッテリー駆動中に固まる時がある。今後の課題。
ATOK X3 インストール失敗 → ibus/mozc へ
こちらを参考に頑張った。
しかしながら iiim のサーバーが起きない。ダイナミックリンクの問題みたいだけど、2日ぐらいいろいろ頑張ったけどだめだった。あきらめて ibus/mozc にした。全然問題なかった。。。
unzip/file-roller 文字化け
スーツとしては日本語SJISファイル名入りのZIPが扱えないと困る。unzipに自分でパッチするのかと思ったら、unzip の最新 ebuild の mask 外して natspec 入れると解決した。
/etc/portage/package.use =app-arch/unzip-6.0-r2 natspec /etc/portage/package.accept_keywords >=dev-libs/libnatspec-0.2.6 ~amd64 =app-arch/unzip-6.0-r2 ~amd64
GNOME/Compiz
すんなり入った。screenlets もそのまま移行。これでもとのデスクトップ環境がもどった。
そこへ naota 先生から Gentoo の compiz 終了かものニュース。
- Re: desktop-effects herd future
nvidia とか ati とかのボード持ってないので、メインでサポートは出来ないけど、パッケージを単に追従させるとかだったら出来るかもしれない。あとで desktop-effect overlay をチェックしてみる。
VMware → VirtualBox
VMware Server の放置っぷりに困ってたので、この機会に VirtualBox に移行。設定ファイルとイメージを変換するだけで完了。超快適。今までの VMware の速度はなんだったのか。。。
USB2.0の対応は一応出来てはいるけども、iPadの同期はちょっと不安定。ipadなどの同期はWifi経由か、iOSのアップグレードなどのクリティカルな更新はMacを使ったほうが良さそう。
iPad用アドホックルーター
X201sを有線でつないでいるときに、iPadからも無線でアドホック接続してX201sをルータにして外に出たい。
こちらを参考に、dhcpdとiptablesを入れて設定。有線側のDHCPを混乱させないように注意。
電子辞書 EBView の ebuild
Emacs の lookup でもいいのだけど、ウインドウの構成が崩されるのが嫌なので EBView をよく使っている。
Portageに無かったので最初は自前コンパイルしてたけど、 思い切って ebuild 書いてみた。
- prototype030: オレオレGentoo overlayを作ってlaymanで管理する
- http://www.gentoo.org/proj/en/devrel/handbook/handbook.xml
実際には app-dicts/eblook の ebuild を参考に書いた。dpkgよりは楽だった。
GNOME-Do の migemo 化 ebuild
GNOME-Doもパッチ作って migemo の use いれて ebuild 作成。ebuildはまだ自信がないところがあるので、naota先生のebuild読み講座で勉強中。
- 自分のとこの overlay
[perl] YAPC::Asia 2011 参加。LTしました。
以前からすごく参加してみたかったYAPCに、今年やっと行けました。
Perlは言語よりも、やっぱりそのコミュニティにすごい興味がありました。
結果、会場の勢いのあるコミュニティの空気と、素晴らしいスタッフによる運営にとても感動しました。おつかれさまです。ありがとうございました。
こんなイベントを企画運営できると面白いだろううなと思いました。
レポートなどは以下をどうぞ。
- YAPC::Asia Tokyo 2011 1日目レポート[随時更新]:YAPC::Asia Tokyo 2011 スペシャルレポート|gihyo.jp … 技術評論社
- YAPC::Asia Tokyo 2011 2日目レポート[随時更新]:YAPC::Asia Tokyo 2011 スペシャルレポート|gihyo.jp … 技術評論社
- http://app.linknode.net/
- YAPC::Asia 2011 Tokyo 1日目まとめ - Togetter
- YAPC::Asia 2011 Tokyo 2日目まとめ #yapcasia - Togetter
LT : Emacs, Perl and Async
Fukuoka.pm に肩を押されてLTにも挑戦してみました。準備があまり間に合わなくて、とてもいっぱいいっぱいでした。最後のデモは準備不足でUIを省略してミニバッファでやっていたのですが、プロジェクターでは画面の下が切れて見えてなかったので、かなり残念な感じになってしまいました。でも(後続の深町さんと同様)Perlの会でLispをやるというネタだったので、そこは達成できましたと思います!!!
この技術(EPC:Emacs Procedure Call)については後ほど形にして記事にすると思います。
しばらく YAPC 熱にうなされそうです。