投稿日 2009年8月26日 水曜日 カテゴリ Trac 投稿者 omaeコメント(0) » 

omae です。

今回は Trac のパフォーマンスを上げるためにやっている設定を紹介したいと思います。

1. trac.ini の [trac] htdocs_location を設定し、Apache に静的ファイルを処理させる

この方法は TracCgi Mapping Static Resources に書かれていることでありよく知られているものです。 CGI ではなく mod_python などで実行している場合でも Apache に処理させるようにしたほうが速いです。

2. Trac plugin の静的ファイルを Apache に処理させる

Trac plugin は自身が使うための静的ファイルのディレクトリを ITemplateProvider.get_htdocs_dirs() というインターフェイスから返すことになっています。 このディレクトリへのアクセスも Apache に処理させるようにします。

ここでインストールしている plugin からこのディレクトリを一つ一つ調べてもよいのですが、めんどくさいので次のスクリプトを書きました。 引数に TRACENV のパスを指定すると ITemplateProvider.get_htdocs_dirs() の値を収集して出力します。

#! /usr/bin/python

import sys
try:
    set = set
except NameError:
    from sets import Set as set

from trac.env import open_environment
from trac.web.chrome import Chrome

def print_providers(path):
    try:
        env = open_environment(path)
    except Exception, e:
        print('%s: %s', path, e)

    chrome = Chrome(env)
    container = set()
    for provider in chrome.template_providers:
        dirs = provider.get_htdocs_dirs()
        for dir in dirs:
            container.add(dir)

    container = [v for v in container]
    container.sort()

    print('%s:' % path)
    for prefix, dir in container:
        print('\t%s\t%s' % (prefix, dir))

for arg in sys.argv[1:]:
    print_providers(arg)

これを実行すると以下のような出力が得られます。

/var/lib/trac/opengroove:
        bitten  /usr/share/trac/plugins/Bitten-0.6dev_r641-py2.3.egg/bitten/htdocs
        common  /usr/lib/python2.3/site-packages/trac/htdocs
        customfieldadmin        /usr/share/trac/plugins/TracCustomFieldAdmin-0.2-py2.3.egg/customfieldadmin/htdocs
        iniadmin        /usr/share/trac/plugins/IniAdmin-0.2-py2.3.egg/iniadmin/htdocs
        s5      /usr/share/trac/plugins/S5-0.1-py2.3.egg/s5/htdocs
        site    /var/lib/trac/opengroove/htdocs
        ticketdelete    /usr/share/trac/plugins/TracTicketDelete-2.0-py2.3.egg/ticketdelete/htdocs
        tracfreemind    /usr/share/trac/plugins/TracFreeMind-0.2-py2.3.egg/tracfreemind/htdocs
        tracnav /usr/share/trac/plugins/TracNav-4.0pre7-py2.3.egg/tracnav/htdocs
        tracwysiwyg     /usr/share/trac/plugins/TracWysiwyg-0.2_r4353-py2.3.egg/tracwysiwyg/htdocs
        workfloweditor  /usr/share/trac/plugins/WorkflowEditorPlugin-1.0.1_r5329-py2.3.egg/workfloweditor/htdocs

ここで最初の文字列は get_htdocs_dirs() が返す prefix であり、この値をキーにファイルがどのディレクトリにあるかを Trac は判断しています。 また common に関しては htdocs_location の設定値で URL が変更できるようになっています。 site に関しては $TRACENV/htdocs/ に置いたファイルへアクセスできるようするために Trac 自身が get_htdocs_dirs() で登録してくるようになっています。

この出力から http://localhost/trac/ で複数プロジェクトを処理している場合は以下のような設定を書きます。

AliasMatch ^/trac/[^/]+/chrome/bitten/(.+) /usr/share/trac/plugins/Bitten-0.6dev_r641-py2.3.egg/bitten/htdocs/$1
AliasMatch ^/trac/[^/]+/chrome/customfieldadmin/(.+) /usr/share/trac/plugins/TracCustomFieldAdmin-0.2-py2.3.egg/customfieldadmin/htdocs/$1
AliasMatch ^/trac/[^/]+/chrome/iniadmin/(.+) /usr/share/trac/plugins/IniAdmin-0.2-py2.3.egg/iniadmin/htdocs/$1
AliasMatch ^/trac/[^/]+/chrome/s5/(.+) /usr/share/trac/plugins/S5-0.1-py2.3.egg/s5/htdocs/$1
AliasMatch ^/trac/[^/]+/chrome/ticketdelete/(.+) /usr/share/trac/plugins/TracTicketDelete-2.0-py2.3.egg/ticketdelete/htdocs/$1
AliasMatch ^/trac/[^/]+/chrome/tracfreemind/(.+) /usr/share/trac/plugins/TracFreeMind-0.2-py2.3.egg/tracfreemind/htdocs/$1
AliasMatch ^/trac/[^/]+/chrome/tracnav/(.+) /usr/share/trac/plugins/TracNav-4.0pre7-py2.3.egg/tracnav/htdocs/$1
AliasMatch ^/trac/[^/]+/chrome/tracwysiwyg/(.+) /usr/share/trac/plugins/TracWysiwyg-0.2_r4353-py2.3.egg/tracwysiwyg/htdocs/$1
AliasMatch ^/trac/[^/]+/chrome/workfloweditor/(.+) /usr/share/trac/plugins/WorkflowEditorPlugin-1.0.1_r5329-py2.3.egg/workfloweditor/
AliasMatch ^/trac/([^/]+)/chrome/site/(.+) /var/lib/trac/$1/htdocs/$2

mod_python で運用している場合には上記だけでなく /trac/*/chrome/ へのアクセスが mod_python に処理させてしまわないように SetHandler None が必要になると思います(未確認。mod_rewrite でないとうまくいかないかも知れません)

<Location /trac/*/chrome/>
    SetHandler None
</Location>

これで体感的な速度が上がるかと思います。

更なる速度改善としては添付ファイルへのアクセスを Apache に処理させる…というのが考えられます。 画像を貼りすぎた Wiki ページでは、やはりその分の速度劣化があるので Apache で処理できれば早く表示できるようになります。 ただし Apache に処理させるということは Trac が行う権限チェック(WIKI_VIEW があるかなど)が効かなくなるので、そのあたりは注意が必要です。

投稿日 2009年7月25日 土曜日 カテゴリ Trac, ソフトウェア開発 投稿者 syojiコメントは受け付けていません。 

開発の現場で大きく2種類の声を聞くことが多い。

ひとつは、「バージョン管理は必須で、プロジェクトが始まったらすぐにリポジトリを作成する」という利用者の声。

もうひとつが「まったく使ったことがない」「使いたいけど、教育が・・・」「自分でバージョン管理(フォルダに日付・・・)」などの利用したことがない人の声。

自分が話を聞いたり、見たりした開発の現場では、特にエンタープライズ系の開発においてバージョン管理システムを導入していないところが多かった気がする。

バージョン管理システムとは

バージョン管理システムとは、プログラムを開発するとき、主にプログラムの版(バージョン)を管理するためのツールである。ファイルの階層構造全体はリポジトリと呼ばれる場所(サーバ)に置かれ、ファイルやフォルダに対するすべての追加、変更、削除を記録する。ファイルの中身に対する変更だけでなく、ファイル名、フォルダ名に対する変更も記録する。

リポジトリに記録された履歴は、古いバージョンのソースコードを参照したり、取り出したりすることができる。 これによって、過去のソースコードに対する修正内容、障害対応時の変更理由、リリース後に発生した不具合の調査など開発者にとってとても便利な機能である。

主なバージョン管理システムは、CVS,Subversion,git などのオープンソースから製品版まで多くの種類がある。

最近では、CVS,Subversionといった中央のリポジトリで管理する仕組みから、SVKgit(Linuxカーネルの開発で使用) など分散バージョン管理がはやっているようだ。

プログラム開発で縁の下の力持ち的に力を発揮するバージョン管理システムであるが、どのようなツールでも言えることであるが

  • 利用目的
  • 運用とルール

を決めておくことが重要である。

以前のブログ記事で「バグトラッキングシステムのワークフロー」について説明したが、新機能開発の時/障害対応の時とワークフローを決めておくことが重要である。 バージョン管理システムとバグトラッキングシステムを密に連携させて管理することで、ものすごい恩恵を受けることが出来ると思う。

バージョン管理とバグトラッキング(BTS)

バージョン管理とバグトラッキング(BTS)

「導入するためには上司を納得させないと・・・」「チームメンバーの教育コストが・・・」など障壁はあるかもしれないが、その障壁を乗り越えて余りあるメリットがある。 開発現場のリーダーや開発チームに提案してみようと考えている人はぜひ導入に向けて頑張って欲しいと思う。

参考になるサイト:

投稿日 2009年7月17日 金曜日 カテゴリ Trac 投稿者 omaeコメント(0) » 

omae です。

ブラウザで見てるページを TracWiki ですぐにリンクしたいな…というときに使っている bookmarklet を紹介します。といっても TracLink 形式の文字列を作って window.prompt() で表示するだけのものです。

javascript:(function(t,u){if(/\]|^[%22']/.test(t)){if(!/^%22/.test(t)&&!/"\]/.test(t)){t='%22'+t+'%22'}else%20if(!/'/.test(t)&&!/'\]/.test(t)){t=%22'%22+t+%22'%22}else{t="'"+t.replace(/'/g,'')+"'"}}prompt('copy','['+u+'%20'+t+']')})(document.title.replace(/[\x00-\x1f]+|^\s+|\s+$/g,''),location.href)

適当なページでこの bookmarklet を実行すると TracLink 形式の文字列が window.prompt() で表示されるので、コピーしてください。Firefox では windows.prompt() の代わりに window.alert() でもよいと思います。(選択可能なので)

この bookmarklet の内容ですが、まず TracWiki では [URL label] という形式でリンクを作成することが出来るようになっています。

[ で始まって ] で終わりを表すようになっているわけですので、label に ] を含んでいる場合にはそのまま書くことは出来ません。このような場合には

[http://example.com/ "Apple]["]
[http://example.com/ 'Apple][']

というようにして double-quote もしくは single-quote で囲ってあげることで記述できます。

囲われているかどうかは label 部分が double-quote もしくは single-quote で開始しているかどうかで判断されるので、double-quote で開始しているなら sinlge-quote で囲い、single-quote で開始しているなら double-quote で囲います。

とは言っても label で表現したい文字列が

"'Apple']["

というような場合、囲ったりするだけではどうしようもないのでこの bookmarklet ではそのような場合には single-quote ' を除去して single-quote で囲うようにしてあります。

ちなみにこの場合に bookmarklet から得られる文字列は

[http://example.com/ '"Apple]["']

になります。

投稿日 2009年7月10日 金曜日 カテゴリ MySQL, Trac 投稿者 omaeコメント(0) » 

omae です。 CentOS 5.3 で Trac 0.11 を MySQL を使って実行しようとしたら、以下のようなエラーでしばらく悩んでしまいました。

Traceback (most recent call last):
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/web/main.py", line 467, in _dispatch_request
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/web/main.py", line 234, in dispatch
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/web/chrome.py", line 761, in render_template
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/web/api.py", line 199, in __getattr__
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/util/compat.py", line 72, in newfunc
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/web/chrome.py", line 516, in prepare_request
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/ticket/web_ui.py", line 171, in get_navigation_items
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/perm.py", line 526, in has_permission
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/perm.py", line 539, in _has_permission
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/perm.py", line 427, in check_permission
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/perm.py", line 283, in check_permission
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/perm.py", line 359, in get_user_permissions
  File "/usr/lib/python2.4/site-packages/Trac-0.11.4-py2.4.egg/trac/perm.py", line 183, in get_user_permissions
TypeError: unhashable type

よくよく確認すると4月末ぐらいも同じエラーでしばらく悩んだみたいです。 今回はここにメモを残すことに。

まずはこのエラーで検索。検索するとすぐに trac.edgewall.org にこのエラーそのものが ticket として作成されていることが解りました。

#7481 (Project not work affter successfull initenv) このチケットによれば「MySQL-python を 1.2.2 にアップデートしろ」とあります。

いま入っている MySQL-python を確認すると MySQL-python-1.2.1-1.i386 でした。 CentOS のパッケージをそのままインストールしているだけなのですが、これは修正されないのかなぁ…。 それはともかく 1.2.2 に対応した rpm を自分で作って入れ替えることにしました。

まず MySQL-python の SRPM をとって来る為に次のコマンドを実行。

# yumdownloader --source MySQL-python
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: www.ftp.ne.jp
 * updates: www.ftp.ne.jp
 * addons: www.ftp.ne.jp
 * extras: www.ftp.ne.jp
extras-source                                            |  951 B     00:00
updates-source                                           |  951 B     00:00
base                                                     | 1.1 kB     00:00
updates                                                  |  951 B     00:00
base-source                                              |  951 B     00:00
addons                                                   |  951 B     00:00
extras                                                   | 1.1 kB     00:00
MySQL-python-1.2.1-1.src.rpm                             |  71 kB     00:00

srpm をインストールしてみます。

# rpm -ivv MySQL-python-1.2.1-1.src.rpm
D: ============== MySQL-python-1.2.1-1.src.rpm
D: Expected size:        72317 = lead(96)+sigs(344)+pad(0)+data(71877)
D:   Actual size:        72317
D: opening  db environment /var/lib/rpm/Packages joinenv
D: opening  db index       /var/lib/rpm/Packages rdonly mode=0x0
D: locked   db index       /var/lib/rpm/Packages
D: opening  db index       /var/lib/rpm/Pubkeys rdonly mode=0x0
D:  read h#     346 Header sanity check: OK
D: ========== DSA pubkey id a8a447dc e8562897 (h#346)
D: MySQL-python-1.2.1-1.src.rpm: Header V3 DSA signature: OK, key ID e8562897
D:      added source package [0]
D: found 1 source and 0 binary packages
D: Expected size:        72317 = lead(96)+sigs(344)+pad(0)+data(71877)
D:   Actual size:        72317
D: InstallSourcePackage: Header V3 DSA signature: OK, key ID e8562897
MySQL-python-1.2.1-1
D: ========== Directories not explicitly included in package:
D:          0 /usr/src/redhat/SOURCES/
D:          1 /usr/src/redhat/SPECS/
D: ==========
D: fini      100664  1 ( 500, 500)     64628 /usr/src/redhat/SOURCES/MySQL-python-1.2.1.tar.gz;4a573e54
D: fini      100664  1 ( 500, 500)      4987 /usr/src/redhat/SPECS/MySQL-python.spec;4a573e54
GZDIO:       9 reads,    70004 total bytes in 0.000573 secs
D: closed   db index       /var/lib/rpm/Pubkeys
D: closed   db index       /var/lib/rpm/Packages
D: closed   db environment /var/lib/rpm/Packages
D: May free Score board((nil))

次に MySQL-python-1.2.2 を /usr/src/redhat/SOURCES/ に配置します。

# wget -nd -P /usr/src/redhat/SOURCES http://downloads.sourceforge.net/sourceforge/mysql-python/MySQL-python-1.2.2.tar.gz

tarball と spec ファイルしかないので、spec ファイルのバージョン部分だけを変更することにします。変更は以下のような感じ。

--- SPECS/MySQL-python.spec.orig        2009-07-10 22:15:55.000000000 +0900
+++ SPECS/MySQL-python.spec     2009-07-10 22:16:01.000000000 +0900
@@ -3,8 +3,8 @@

 Summary: An interface to MySQL
 Name: MySQL-python
-Version: 1.2.1
-Release: 1
+Version: 1.2.2
+Release: 0.1
 License: GPL
 Group: Development/Libraries
 Source0: http://prdownloads.sourceforge.net/mysql-python/MySQL-python-%{version}.tar.gz

下準備はそろったので rpmbuild します。

# rpmbuild -ba SPECS/MySQL-python.spec

これで /usr/src/redhat/RPMS/ 配下に rpm が作成されているので、これでアップデートします。

# rpm -Uvh RPMS/i386/MySQL-python-1.2.2-0.1.i386.rpm

これで完了です。無事に Trac が参照できるようになりました。

投稿日 2009年7月5日 日曜日 カテゴリ Trac 投稿者 omaeコメント(0) » 

omae です。Trac 0.11.5 がリリース間近(いまのところ2009/07/07予定)ですね。さっそく 0.11.5rc1 をダウンロードして 社内の Trac 環境に投入してみました。いまのところ特に問題らしいところもなく動いているようです。

ところで TracWiki では Wiki ページの名前に / を用いることで階層構造を表現できるようになっています。そういったページを参照するとページ名に合わせてパンくずリストも表示されます(この機能は 0.11 から)。

SandBox/2009/07/03 というページを作った場合、以下のようなパンくずリストが表示されます。

Wikiページに表示されるパンくずリスト

これはこれでよいのですが、実際には Log/2009Log/2009/07 に対応する Wiki ページはほとんど作りません(少なくとも社内では)。そのため、Log/2009 を参照すると以下のようなそのページを作成するかどうかを聞いてくるようなページになります。

Wikiページがない

この内容にそのページ名の下位ページに対する RecentChangesTitleIndex を表示しておけば、こういうページをその都度作成しておかなくてもよいのではないかと考えました。

まず Wiki ページがないときに使用される template ファイルは trac/wiki/templates/wiki_view.html になります。このファイルを $TRACENV/templates/wiki_view.html にコピーします。このファイルは Trac インストールディレクトリにありますので、そこから持ってきます。

次にコピーした wiki_view.html を編集してページがないときの処理を追加します。変更後、必要なら Web サーバーを再起動してください。

--- wiki_view.html.orig 2009-01-29 04:55:06.000000000 +0900
+++ wiki_view.html    2009-06-24 00:02:57.000000000 +0900
@@ -98,6 +98,7 @@
         </py:if>
       </py:with>

+      <div py:if="not page.exists" xml:space="preserve">
+        ${wiki_to_html(context, "----\n== Recent Changes ==\n[[RecentChanges(%s/,5)]]\n----\n== Title Index ==\n[[TitleIndex(%s/,format=group)]]" % (page.name, page.name))}
+      </div>
     </div>
   </body>
 </html>

ここでは page 変数が要求されている Wiki ページであり、wiki_to_html 変数が TracWiki 文字列を HTML に変換するメソッドになっています。

これでページがない場合に RecentChanges, TitleIndex が表示されるようになります。さきほどの Log/2009 を参照すると以下のようになります。

TitleIndexを表示するようにした

Trac の template を変更して「うちではこんなことしてますよ」とかあれば、教えてください。