Trac Lightning同梱のJenkinsをJenkins 2.xにバージョンアップする

Jenkins 2.0がリリースされたので試しにバージョンアップしてみる。公式サイトからwarファイルをダウンロードします。
既存のjenkins.warファイルをリネームして、差し替えするだけ。

後はアクセスするだけ。……が、動かない。

warファイルと同じ場所(デフォルトはC:\TracLight\jenkins)にjenkins.err.logという一目で何か書いてありそうだと分かるファイルがありました。
開いてみるとエラーメッセージがありました。

8 20, 2016 12:23:16 午前 winstone.Logger logInternal
SEVERE: Container startup failed
java.io.IOException: Failed to start a listener: winstone.Ajp13ConnectorFactory
at winstone.Launcher.spawnListener(Launcher.java:207)
at winstone.Launcher.(Launcher.java:148)
at winstone.Launcher.main(Launcher.java:352)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at Main._main(Main.java:246)
at Main.main(Main.java:91)
Caused by: java.lang.UnsupportedOperationException: AJP support is removed in Winstone 3.0 due to Jetty 9 not supporting AJP.
For reverse proxying, please use HTTP instead of AJP.
at winstone.Ajp13ConnectorFactory.start(Ajp13ConnectorFactory.java:31)
at winstone.Launcher.spawnListener(Launcher.java:205)
... 8 more

エラーメッセージで検索してみると、いくつか情報が見つかりました。どうもAJPのポートを書き換える必要があるようです。
jenkins 1から2へのアップグレード - Qiita

やはり同じフォルダにある jenkins.xml を修正します。

以下のように42行目 --ajp13Port=8009 から --ajp13Port=-1 に修正します。

サービスを再起動したら、Jenkinsが起動してきました!

TracのHyper Estraierプラグインで検索の絞り込みをしたい1

と思って調べてみました。WordやExcelやPDFなどファイルの種類で絞ったり、日時で絞り込みできたら便利だと思うのですが、とてもそこまでのスキルはありません。いろいろと試行錯誤してたぶんできました。。。Tracの日本語情報も最近はあまり出ないので、こんなレベルですが公開してみます(苦笑)。

WordやExcelで絞り込んでみるには一番簡単そうなのが、全文検索する文書データの結果を分けてしまうパターンです。美しくないですが。

makeindex.batでWordやExcelは別にしてみます。estcmd gatherで拡張子ごとに別のフォルダに出しています。

set EXPORT_FOLDER=c:\TracLight\search\repos\SampleProject\rep

set INDEX_FOLDER=c:\TracLight\search\repos\SampleProject\casket
set INDEX_FOLDER_WORD=c:\TracLight\search\repos\SampleProject\casket_word
set INDEX_FOLDER_EXCEL=c:\TracLight\search\repos\SampleProject\casket_excel

set REPOS_URI=file:///C:/TracLight/projects/svn/SampleProject/
rmdir /S /Q %EXPORT_FOLDER%

rmdir /S /Q %INDEX_FOLDER%
rmdir /S /Q %INDEX_FOLDER_WORD%
rmdir /S /Q %INDEX_FOLDER_EXCEL%

svn export %REPOS_URI% %EXPORT_FOLDER%

REM MS-Wordのインデックス
estcmd gather -cl -fx .doc,.docx T@estxfilt -ic CP932 -pc CP932 -cm -sd %INDEX_FOLDER_WORD% %EXPORT_FOLDER%

REM MS-Excelのインデックス
estcmd gather -cl -fx .xls,.xlsx T@estxfilt -ic CP932 -pc CP932 -cm -sd %INDEX_FOLDER_EXCEL% %EXPORT_FOLDER%

estcmd gather -cl -fx .pdf,.rtf,.ppt T@estxfilt -ic CP932 -pc CP932 -cm -sd %INDEX_FOLDER% %EXPORT_FOLDER%

で、Hyper Estraierプラグインはソースを修正しないといけないので、subversionshibuya.tracからチェックアウトします。
searchhyperestraier.pyを修正します。元のSearchHyperEstraierModule(Component)の部分をコピペして、SearchMSWordHyperEstraierModule(Component)とします。修正するのは数か所です。Excelも同様に実施します。

class SearchMSWordHyperEstraierModule(Component):
implements(ISearchSource)

# ISearchProvider methods
def get_search_filters(self, req):
if req.perm.has_permission('BROWSER_VIEW'):
yield ('wordhyperest', u'リポジトリ(Wordのみ)', 1)

def get_search_results(self, req, terms, filters):
if not 'wordhyperest' in filters:
return
#estcmd.exeのパス
estcmd_path = self.env.config.get('searchhyperestraier', 'estcmd_path','estcmd')
#estcmd.exeの引数
estcmd_arg = self.env.config.get('searchhyperestraier', 'estcmd_arg','search -vx -sf -ic Shift_JIS')
estcmd_encode = self.env.config.get('searchhyperestraier', 'estcmd_encode','mbcs')
#Tracのブラウザへのリンクを作るか否か。
#enabled:Tracのブラウザへのリンクを作る
#上記以外:replace_left,url_leftで指定したURLへのリンクを作る
browse_trac = self.env.config.get('searchhyperestraier', 'browse_trac','enabled')

#for multi repos
for option in self.config['searchhyperestraier']:
#リポジトリのパス
if not option.endswith('word.index_path'):
continue
mrepstr = option[:-len('word.index_path')] #'.index_path'の前の文字列がreponame
if RepositoryManager(self.env).get_repository(mrepstr) is None: #mrepstrのrepositoryがない
continue
#インデックスのパス
index_path = self.env.config.get('searchhyperestraier', mrepstr+'word.index_path','')
if index_path == '':#mrepstr+'.index_path'がない
continue
#検索結果のパスの頭で削る文字列
replace_left = self.env.config.get('searchhyperestraier', mrepstr+'word.replace_left','')
if replace_left == '': #mrepstr+'.replace_left'がない
continue
#URLを生成する際に頭につける文字列
#browse_trac=enabledの場合は/がリポジトリのルートになるように
url_left = self.env.config.get('searchhyperestraier', mrepstr+'word.url_left','')
if url_left == '': #mrepstr+'.url_left'がない
continue
if mrepstr != '': #defaultでない
url_left = '/' + mrepstr + url_left

#cmdline = "%s %s %s %s" % (estcmd_path,estcmd_arg,index_path,unicode(query,'utf-8').encode('CP932'))
qline = ' '.join(terms)
cmdline = "%s %s %s %s" % (estcmd_path,estcmd_arg,index_path,qline)
self.log.debug('SearchHyperEstraier:%s' % cmdline)
cmdline = unicode(cmdline).encode(estcmd_encode)
np = NaivePopen(cmdline)
#self.log.debug('Result:%s' % unicode(np.out,'utf-8').encode('mbcs'))
#self.log.debug('Result:%s' % np.out)
if np.errorlevel or np.err:
err = 'Running (%s) failed: %s, %s.' % (cmdline, np.errorlevel,
np.err)
raise Exception, err
if np.out=='': #何も入ってない
continue
dom = parseString(np.out)
root = dom.documentElement
#estresult_node = root.getElementsByTagName("document")[0]
element_array = root.getElementsByTagName("document")
for element in element_array:
#self.log.debug('Result:%s' % 'hoge')
url = ""
title = ""
date = 0
detail = ""
author = "不明"

#detailを生成
elem_array = element.getElementsByTagName("snippet")
detail = self._get_innerText("",elem_array)

#その他の属性を生成
attrelem_array = element.getElementsByTagName("attribute")
for attrelem in attrelem_array:
attr_name = attrelem.getAttribute("name")
attr_value = unicode(attrelem.getAttribute("value"))
#URLとタイトルを生成
#if attr_name == "_lreal": #"_lreal"ではファイル名に' 'などが入っている場合対応できない
# attr_value=attr_value[len(replace_left):].replace("\\","/")
# if browse_trac == "enabled":
# url = self.env.href.browser(url_left + attr_value)
# title = "source:"+ url_left + attr_value
# else:
# url = url_left + attr_value
# title = url_left + attr_value
if attr_name == "_lpath": #s-jisをquoteしたもの("file:///C|/TracLight/…"の形式)
attr_value = urllib.unquote(attr_value).encode('raw_unicode_escape').decode('CP932')
attr_value = attr_value[(len('file:///')+len(replace_left)):]
if browse_trac == "enabled":
url = self.env.href.browser(url_left + attr_value)
title = "source:"+ urllib.unquote(url).encode('raw_unicode_escape').decode('utf-8')
else:
url = url_left + attr_value
title = urllib.unquote(url).encode('raw_unicode_escape').decode('utf-8')
#更新日時を生成
elif attr_name =="@mdate":
date = time.strptime(attr_value,"%Y-%m-%dT%H:%M:%SZ")
self.log.debug('date:%s' % attr_value)
date = to_datetime(datetime.datetime(date[0],date[1],date[2],date[3],date[4],date[5],0,utc)) # for Trac0.11
yield(url,title,date,to_unicode(author,'utf-8'),to_unicode(detail,'utf-8'))
return

#XMLのElementを再帰的に探してテキストを生成
def _get_innerText(self,text,node_array):
for node in node_array:
if node.nodeType == node.TEXT_NODE:
text = text + unicode(node.data).encode('utf-8')
else:
text = self._get_innerText(text,node.childNodes)
return text

trac.iniにも以下のように追記します。word.url_leftは環境に合うように修正が必要です。

word.index_path = C:\TracLight\search\repos\SampleProject\casket_word
word.replace_left = C:\TracLight\search\SampleProject\rep
word.url_left = /

で、プラグインpython setup.py bdist_egg でビルドして、Tracの管理画面からHyper Estraierプラグインをインポートしたら完了です。これで検索画面でWordやExcelチェックボックスがっ表示されるはずです。

Hyper Estraierでは、属性を絞り込んだ検索というのもできるようなので、これもやってみます。

Trac 0.12系でダウンロードアイコンを追加してみる

Trac Lightning 4.0の開発が進んでおります。非常にありがたい!!

Trac Lightning 3.2(Trac 0.12系)でもリポジトリブラウザでダウンロードアイコンのリンクを表示できるか検証。テストしてみたところ、Trac本体のチェンジセット 9976で追加されているファイルを差し替えれば実現できたみたい。

フォルダからのZIPダウンロードは出来ていないのと他に問題が起きないかは未確認です。


で、以下のファイルを差し替えました。不要なものもあるかもしれませんが。場所的に全てのプロジェクトに影響が出ると思います。要検証です。

C:\TracLight\python\Lib\site-packages\Trac-0.12.4.ja1-py2.6.egg\trac\versioncontrol\templates\dir_entries.html

C:\TracLight\python\Lib\site-packages\Trac-0.12.4.ja1-py2.6.egg\trac\htdocs\css\browser.css

C:\TracLight\python\Lib\site-packages\Trac-0.12.4.ja1-py2.6.egg\trac\htdocs\css\trac.css

C:\TracLight\python\Lib\site-packages\Trac-0.12.4.ja1-py2.6.egg\trac\htdocs\js\expand_dir.js

C:\TracLight\python\Lib\site-packages\Trac-0.12.4.ja1-py2.6.egg\trac\versioncontrol\web_ui\browser.py

追記

これをするとリポジトリのコミットログが正しく表示されなくなりました。最後のログがすべてに表示されてしまいました。私ではこれを修正する方法がわからないので、素直にTrac 1.0系に移行したほうがよさそうです。

TracLightning-3.2.0 alpha2 + Windows 2012 Serverのベンチマーク

TracLightning-3.2.0 alpha2が公開されていたのでWindows 2012 Serverにインストールしてテスト。といっても動作は詳しく検証していないです。とりあえず、インストールして、AB(Apache Bench)で速度を測っただけです。

今回は同一セグメントから計測しました。結論から言うと困った……Hyper-V上でCPUを2つ割り当てると遅くなりました。なんでだろうなぁ、といった感じ。前回のGILの反省をいかして、CPUは1ソケットだけどXeonの3GHz以上 + RAM 10GB以上とそこそこのスペックのサーバーを用意したんですが。

ホストOSはWindows 2012 Serverです。サンプルプロジェクトにチケットを1つ作って、ab -n 100 -c 10 をしました。

1.Windows Server 2012 (Hyper-V上)
・CPUを1つでOSをインストール後にTracをインストール
1回目 3.64[#/sec]
2目目 4.34[#/sec]
3目目 5.43[#/sec]
4目目 5.72[#/sec]

・CPUを2つに変更
1回目 1.03[#/sec]
2回目 1.17[#/sec]
3回目 1.16[#/sec]

2.Windows Server 2008 R2(Hyper-V上)
・CPUを1つでOSをインストール後にTracをインストール
1回目 4.86[#/sec]
2回目 5.37[#/sec]
3回目 4.89[#/sec]

・CPUを2つに変更
1回目 1.17[#/sec]
2回目 1.17[#/sec]
3回目 1.19[#/sec]

3.Windows Server 2008 R2 ServerCore(Hyper-V上)
・CPUを1つでOSをインストール後にTracをインストール

1回目 4.34[#/sec]
2回目 4.43[#/sec]
3回目 4.46[#/sec]

・CPUを2つに変更
1回目 0.97[#/sec]
2回目 1.19[#/sec]
3回目 1.20[#/sec]
※ServerCoreだとjenkinsの起動時にエラーが出力されました。

何故CPUを増やすとここまで下がるんでしょうか。ちなみに、物理HWのWindows 2012 Serverにインストールしても1くらいしか出なかったです。何でだろう……2008 Serverの時でもここまで悪くないのに。やり方が悪いのかなぁ。

ひとまず、5がでる構成で運用するしかないかな。

CentOS 5.8(x86_64)にKanonをインストール

CentOS 5.8(x86_64)にKanonをインストールするのに少し苦労したのでメモ。
試行錯誤の結果なので、ちょっと間違いや勘違いがあるかもです。


数ヶ月前にこちらのサイト様を参考にインストールしてうまくいったので、その手順で実施。……したら、EPELリポジトリのURLとか変わってまして上手くインストール出来ず。

Linux に一撃で Trac をインストールする

WEBの情報を検索すると、下記のサイト様を発見。EPELリポジトリのリンク切れ……あ、これだ。
感謝をしつつ、同じ現象がでる問題2と問題3の手順を参考にして再度インストールを試みます。

kanon のインストールメモ - 桜、抹茶、白、日記

インストールはうまくいってる様子……が、apacheの起動に失敗。

httpd を起動中: Syntax error on line 3 of /etc/httpd/conf.d/vcs.conf:
Unknown DAV provider: svn

これは……おそらく、mod_dav_svnが入っていなくて出たんだと思う。
yumでさくっとインストールします。
※でもこれは間違ってたため、このバージョンは下記にもありますが削除しました


apacheが起動するようになる。よし!完了と思って、TracのSampleProjectにアクセスするとリポジトリが参照できず以下のメッセージが表示されました。

警告: リポジトリ "(default)" との同期ができません (サポートされていないバージョン管理システム "svn": "No module named svn")。
詳細は Trac のログを参照してください

おそらく、該当部分のログ。

Trac Trac[svn_fs] INFO: Failed to load Subversion bindings Traceback(most recent call last):
File "build/bdist.linux-x86_64/egg/trac/versioncontrol/svn_fs.py", line 266, in __init__ _import_svn()
File "build/bdist.linux-x86_64/egg/trac/versioncontrol/svn_fs.py", line 68, in _import_svn from svn import fs, repos, core, delta
ImportError: No module named svn

エラーメッセージを元に色々と検索したのですが、良くわからなかった為、上記サイト様の手順5を試しにやってみました。

yumCentOSのupdatesリポジトリからインストールしたsubversion.x86_64 1.6.11-10.el5_8 と mod_dav_svn.x86_64 1.6.11-10.el5_8 をアンインストール。

kanonリポジトリにあるi386版とx86_64版のsubversionとmod_dav_svnパッケージの 1.6.15-1.el5 をwgetでダウンロード後にインストールしました。
※下記にありますが、私の環境ではi386版はインストールするとうまく動作しない

早速、Tracアクセスしてみると上記エラーが解消して、リポジトリが正しく表示されるようになりました!


で、作業完了のはずだったのですが、既存のプロジェクトをコピーしてきて、trac-adminコマンドからリポジトリのリシンクを実施するとエラーが発生。

# /opt/kanon/bin/trac-admin /var/opt/kanon/trac/プロジェクト名 repository resync "(default)"
TracError: サポートされていないバージョン管理システム "svn": "/usr/lib/python2.6/site-packages/libsvn/_fs.so: wrong ELF class: ELFCLASS32"

またも情報を検索するとうまく見えてないので、パスを設定して下さい、といった情報が。


ん〜、でも半年前はこんな事してないしなぁと悩む。よくよく考えると先ほど、i386版のsubversionとmod_dav_svnをインストールしているので、もしかしてこれが原因?と思い、i386版だけアンインストール。

rpm -e subversion-1.6.15-1.el5.i386.rpm mod_dav_svn-1.6.15-1.el5.i386.rpm

すると、リポジトリのリシンクも問題なく動作するようになりました!
いや、はまりました。力不足が大きな要因なんですけどね。


EPELのリンク切れを報告しようと思ったら、Bitbucketでは修正されていました。
確認不足で報告するところだった……。

TracLightningのチューニング……その後

以前にTrac Lightningの速度改善のアドバイスをいただいたとき、Kanonをオススメされたので、インストールして調査中。

Trac Lightningからの移行は問題なさそうで、バックアップしたデータをそのままLinuxに持って行って利用できました。速度もKanonの方がめちゃくちゃ早いです。AB(Apache Bench)で、Trac LightningだとRequests per secondが3くらいでしたが、Kanonだと2008年頃のPCにインストールしたものでも15まであがりました。これはGILの制限らしく、仕組み上仕方ないようです。

あ、あと、Windows 2003でPOOL_SIZEを1000まであげたら、Requests per secondが5まであがりました。

まとめると……

・標準の状態(Windows 2003 R2)
Requests per second: 2.57〜2.72 [#/sec]

TRAC_DB_POOL_SIZE=500(Windows 2003 R2)
Requests per second: 2.83〜2.86 [#/sec]

・POOL_SIZE=500 + eggファイルを展開(Windows 2003 R2)
Requests per second: 3.11〜3.14 [#/sec]

・POOL_SIZE=1000 + eggファイルを展開(Win 2003 R2のみ効果を確認、Win 2008では3でした)
Requests per second: 約5 [#/sec]

Kanon 標準の状態(CentOS 5.x)
Requests per second: 約15 [#/sec]

という結果でした。たしかに、速度が必要な場合はKanonの方が良さそうですね。

ちなみにPOOL_SIZEを1000まであげて良いのかというのは分かりませんので、自己責任でお願いします。 3000まであげましたが、ABの結果は5以上にはなりませんでした。

それでも、Trac Lightningの方が色々と敷居は低いような気がします。Web上で公開されている事例数も多いしね。

追記
Twitterを眺めていたら、GanttCalendarプラグインがバージョンアップしたそうで、テスト中のKanonに入れてみました。特に問題なさそう……お、週間カレンダーが追加されたのかって思ったら、少し前に追加されていた……。

今回は下記のチケットの対応のようです。

チケット #26739: PATCH improving Code Readability - Shibuya.trac - SourceForge.JP

変更点はを見て確認するのか。……出来るかな(苦笑)。

iTunesで買った曲の音がiPhoneで聞くと音が小さい……なんでやねん

1〜2曲のためにCDを買うのもなぁ……でも商品を買って応援したいなって思って気持ちもあって落としどころとして音楽配信サービスだ!と思って検索。

するとmora(モーラ)っていうサイトを発見。買いたい曲があったので買おうと思ったら、専用プレーヤーがいるらしく100MB以上ダウンロードする途中で萎える。

そこでiTunesは使いにくい感じもあって使ってなかったけど、検索してみると買いたい曲も買えそう。iPhoneで聞くわけだし、むしろこっちで良かったのかな。で、早速、ダウンロードして、iPhoneに転送して就寝。

朝、電車で早速聞こうとすると他の曲と比べて音が極端に小さい。……萎えるw ってことで調べると、以下のサイトに対応手順がありました。

iTunesでipodを接続し再生しましたが音量が小さいです。iTunesで.. - 人力検索はてな

で、それでもちょっと既存の曲と違うので、既存の曲(mp3)をMP3Gainというツールを使用してちょっと小さくして保存し直し。それをiPhoneにもう一回転送し直し。結構、時間がかかった……というか、mp3を転送したりするのにiTunesって使いづらくないですか?