codeblogとcode reading
8月10日主査会の発表資料です。
目次
- 自己紹介
- コード読みの経験談と知見
- Apacheのコード
- codeblogの活動
自己紹介
- アリエルネットワーク株式会社
- http://www.ariel-networks.com
- http://dev.ariel-networks.com [ありえるえりあ]
- 2001年4月創業 創業メンバー
- 色々ありましたが、創業から5年経過
- 製品ラインナップ
- AirOne ProjectA: P2Pプロジェクト管理ソフト
- マルスケ(Multi Scheduler): 無料P2Pスケジュール管理ソフト
- ν: エンタープライズ向けポータル(予定)
コード読みの経験談と知見
規模の大きなソースコードを読んできた経験談と、得られたかもしれない知見について
Lotus NotesのUnixクライアントのコード
1996年ごろLotus NotesのUnixクライアントの開発の手伝いをしました。
Mirageというライブラリを利用
- 商用ライブラリ(ソースごとLotusが取得)
- Motif(X Window System)をラップしてMS-Windows APIをエミュレーション
- 大部分のMS-Windows APIをカバー
- 主に国際化まわりのバグ修正(フォントやInput Methodなど)
- コードの規模は覚えていません(今想像すると、5万行以上はあったと思います)
この時の個人的スキル
- XlibとXt(toolkit)のAPIは知っていた
- Motifはまったく知らなかった (fyi; MotifはXlibとXtの上に載るAPI層です)
- MS-Windows APIは少し知っていた
Lotus NotesのUnixクライアントのコード [cont.]
Lotus Notesのコードは初めてでしたが、意外にすんなり作業に入れた(はず)
- XlibのAPIを知っていたのが有利
- テキスト出力であれば、Xlibの該当するAPIでbreakpointを張っておけば良い
- 入力系であれば、該当するXのイベントで探せば良い
- など
- がむしゃらにコードを読んでいたので、
- MotifのAPIも熱心に勉強した => ますますコードが読みやすくなった
- (結果的に)MS-WindowsのAPIもかなり習得した (後につながる)
Lotus NotesのUnixクライアントのコード [cont.2]
- 当時のコードの読み方
- ひたすらデバッグ
- 実行時のコールスタックで処理を把握
知見
- 低レイヤのAPIを把握していることは大きな利点
- ある規模(数万行?)までなら、実行時のコールスタックと気合いがあれば、なんとか把握できる(たぶん)
Lotus Notes本体のコード
2年間、Iris AssociatesでLotus Notes R5開発に参加
- 全体で500万行以上 (R5開発中に600万行を越えたはず)
- メインの担当は国際化および日本からの機能要求の実装
- が、これを機会にNotesのソースコードを把握してやるぞと、気合い充分でした(若かった...)
しかし、
- 500万行のソースコードの壁は高かった
- 周辺のバグ修正はできても、全体の上っ面だけをいじっている感覚
Lotus Notes本体のコード [cont.]
- 当時のコードの読み方
- 実行時のコールスタックを見て、
- 重要そうな処理に当たりをつけて、*処理中心*にコードを読むスタイル
- MS-WindowsのAPIは把握していたので、画面処理周りは比較的把握しやすかった
- メモリ周りやネットワーク周りは階層が深すぎて歯が立たず (mallocやrecv、sendはコールスタックの深い底にあり、その上に多層のAPI => うんざり)
- 当然、Notesのストレージ周り(一種のObject DB)は、全く不明な状態
Lotus Notes本体のコード [cont.2]
徐々に、大規模なコードを読むために、何が足りないのか分かり始める
- APIで切っていく感覚 内部APIも含めて、モジュールやレイヤの境界を意識して「切っていく」感覚
- データ構造を意識する感覚 遅まきながら、処理中心からデータ構造中心にコードを読み始める
- (オブジェクトの)集合に対する感覚 集合および集合に対する操作(列挙など)を意識 (いわゆるコンテナやコレクションなど)
Lotus Notes本体のコード [cont.3]
(コード以外の)メタな情報から高レベルな概念(アーキテクチャ)や用語(コード上の略称)を把握
- 内部スペック文書
- 公開API => 公開APIのサンプルコードは、ムダが無く直接的なので、大きな概念をつかみやすい
- (スクリプト言語用)公開クラスライブラリ => 同上
- コードの読み方の変化
- モジュール(ディレクトリで分けられたコード)が*何であるか*の把握
- モジュール名やAPIのprefixに現れる略称が*何であるか*の把握
- モジュールの境界(内部API)の把握
- モジュール間の「呼ぶ-呼ばれる」の方向性を把握(依存度の把握)
500万行-600万行のコードが全て頭に入った、とは言いませんが、コツはつかみました。
オープンソースのコード
2000年ごろ、GNU/Linux上のデスクトップ環境に夢を抱いて...
- GNOME1.xは、GTK+1.x/GLib1.xを含めて、コードをだいたい把握 (Xlibを知っていたのでだいぶ楽)
- Emacs、Linux(kernel)、小物ツールなど。
- Mozilla0.xはビルドが通っただけで満足。コードはほとんど読んでいません
パッチを送って貢献しようという気持ちより、どう書いているのだろうという好奇心でコードを読んでいました
アリエルネットワークのコード
2001年、AirOne(P2Pコラボレーションツール)の開発開始
(BSD系ライセンスの)オープンソースを活用
初期
- libapr(Apache Portable Runtime): ポータブル層(WindowsとGNU/Linuxの差を吸収)
- (expat): XMLパーサ
- openssl: 暗号化、署名
- xerces: XMLパーサ (C++)
- xalan: XSLTプロセッサ (C++)
アリエルネットワークのコード [cont.]
今
- libapr(Apache Portable Runtime): ポータブル層(WindowsとGNU/Linuxの差を吸収)
- (expat): XMLパーサ
- openssl: 暗号化、署名、SSL
- libxml2: XMLパーサ。xercesがあまりに遅いの置き換え
- libxslt: XSLTプロセッサ。xalanがあまりに遅いので置き換え
- sqlite: ローカルキャッシュDB用
- libpq(postgresql): サーバ上のユーザ管理DBとの通信用
利用オープンソースのコード
- libapr: 初期の頃、パッチやバグ報告を頻繁に行いました。コードはほとんど把握
- openssl: かなりブラックボックス。興味でBIO(chain化できるbuffering IO)辺りのコードは読んだ
- xerces、xalan: JavaからC++に書き換えたコード。ひどいコード
- expat、libxml2、libxslt: 利用範囲内で特に問題がないので、読む機会なし
- sqlite: 最近、興味あり
- libpq(postgresql): 読む時間なし
Apacheのコード
コード規模(apache2.2)
- 全部で約30万行(ヘッダやテストコード込み)
- srclib/ディレクトリ(apr、apr-util、expat、pcre)が約14万行
- modules/ディレクトリが約11万行
- server/ディレクトリが約4万行
- その他
Apacheのコード [cont.]
コードのスタイルの特徴
- コーディングスタイルは一貫しています (一部のモジュールに例外あり)
- libaprにプラットフォーム依存コードを追い出しているので、#ifdefは少ない
- プリプロセッサマクロの使用はほどほど (opensslほどひどくない)
- assert(3)はほとんどありません (理由は不明)
- コメントは多い方?
Apacheのコード [cont.2]
c_count<http://dickey.his.com/c_count/c_count.html>で、コメントとコードの割合(コード1行に対してコメントの行数)を出してみると、
apache2.2 | 0.40 |
gtk+2.8 | 0.17 |
sqlite | 0.63 |
libxml2 | 0.23 |
postgresql | 0.36 |
emacs21 | 0.47 |
linux2.6 | 0.25 |
Apacheのコードの動向
- つい最近、mod_rewriteでセキュリティホールがありました
- HTTP1.1のchunk対応は落ち着いた様子
- authn/authz周りのコードがまた再整理
- apr-utilにmemcachedとの接続APIが追加 (いずれmod_cacheで利用?)
- apr_ssl APIが追加 (opensslのAPIのラッパー。apr_ssl_openssl.cと並んでapr_ssl_winsock.cもある(事実上、中身無しですが))
- mod_proxy、ajp(tomcatとの接続プロトコル)周りが色々騒がしい
- mod_cache周りが色々騒がしい
mod_proxyとmod_cacheは要注意
codeblogの活動
作業の環境
- Emacs
- grep
以上。
初期の頃はgonzuiで検索したりしていましたが => コードの構成が頭に入るとM-x grep-findで事足りてしまう(etagsすら不要)
- {{code "httpd-2.2.0/include/httpd.h", "741-750,975"}}
こう記事に書く時も、手元のソースツリーで行数を調べて書いています。
codeblogの活動 [cont.]
記事で嘘を書かないように、自信がない時は
- gdbで実際の動作を確認
- サンプルコードを書いて動作を確認
しています。
- codeblogのgonzuiではhttpd-2.2.0のソースツリー
- apache-2.2系の最新はhttpd-2.2.3
幸か不幸か、コードに大きな変化はないので、困ってはいません。