自作のwikiマクロの引数で、wikiリンクと同じ記法でリポジトリ上のリソースを指定させている。
{{macro(source:path/to/file)}}
redmine 1.3.0からwikiリンクとマクロの展開順が変わり、先にwikiリンクが処理されるようになったみたい。
冒頭のマクロ引数に対してHTMLリンクに展開済の文字列(HTML)が渡ってくるようになった。

  Redmine::WikiFormatting::Macros.register do
    desc '略'
    macro :some_macro do |wiki_content_obj, args|
    end
end
1.2.xの場合、args[0]に「source:path/to/file」
1.3.0の場合、args[0]に「<a href="/projects/sample/repository/entry/path/to/file" class="source">source:path/to/file</a>」
という文字列が渡ってくる。

「!」をつけると展開抑止になるので当面これで回避。
{{macro(!source:path/to/file)}}

あるいは引数の受け取り方を変えて
{{macro(param=source:path/to/file)}}
とすればHTMLリンクに展開されず引数を受け取れる。


jenkinsの DRY pluginで CPD 

|
jenkinsを使って継続的インテグレーションを行なっている。
数年前はCruiseControl .NETを使っていたのだけど、hudsonを試したときユーザフレンドリーさに打たれて乗り換えた)

以前からmakeなどで1手順ビルドできる仕組みを作ることにはこだわりがあった。
たけど、単にビルドの1手順化だけでなく、
  •  複数の環境でビルドしたものを統合(CIサーバに集約)
  •  リポジトリのコミットとビルドを結びつけ(さらにITSのチケットに結びつく)
  •  複数の環境で自動テスト実行、その結果とビルドの結びつけ
  •  ビルドのログやテストのログなど記録をとる(確認したいときにすぐ辿れる)
継続的インテグレーション入門 開発プロセスを自動化する47の作法
ということを手間なく繰り返し可能とする仕組みには大きな意味があると思う。

SCM、自動テスト、ITSそれぞれ単独でも役立つけど、
ビルドとこれらを結びつけられるCIの存在は大きい。


で、そのビルドと結びついた記録を取りたいものの1つがコードメトリクス。
気にしている指標はいくつかあるけど、コードクローンについて。

コードクローンの検出にCPD(PMD)を使っている。
CPDのレポートxmlをjenkinsのDRY Pluginに食わせるだけ。ビルドごとの静的解析の結果をとりまとめてくれるプラグインでトレンドを見ることができる。
正直に言えばjenkinsのビュー内でコードクローン部分そのものを見るのはあまり意味が無いというかかえって見づらいと思っている。eclipseにPMDプラグインをインストールしてクローン部分にアクセスする方が便利。
あくまでjenkins上では時系列(ビルド)でコードクローンの増減を概観したい。


ここの環境ではjenkinsのmasterをlinux上で動かしている。
CPDの実行はWindowsスレーブ上で行なっている。
入力はSJIS(MS932)でエンコードされたjavaソース。
jenkinsのslave配下でjavaモジュールのビルドをantで行う。同様にantでCPDのレポートを作成している。

PMDのlib下jarをCLASSPATHに指定してantタスクを定義
    <path id="cp.cpd">
        <fileset dir="${pmd.lib}">
            <include name="*.jar"/>
        </fileset>
    </path>

    <taskdef name="cpd" classpathref="cp.cpd" classname="net.sourceforge.pmd.cpd.CPDTask" />

cpdタスクを実行
    
<cpd encoding="Windows-31J" minimumTokenCount="100" format="xml" language="java" outputFile="${reports.cpd}/cpd.xml"> <fileset dir="${src.dir}"> <include name="**/*.java"/> </fileset> </cpd>

で、後はjenkinsのワークスペースに出力されたxmlのpathをDry Pluginの入力に設定するだけ。


当初、cpdタスクの入力エンコーディングを"MS932"にしていた。出力XMLのxml宣言にあるencodingも"MS932"になるのだけどこのままDry Pluginに読み込ませようとするとエラーになってしまう。
Dry Pluginのソースをgithubからcloneして、自動テストの入力xmlのencodingをMS932に書き換えて実行したらスタックトレースに
「Invalid encoding name "MS932".」と出ていた。
org.apache.xerces.*が使われるから?


環境:

Windows 7 x64
 JDK6 u26 x86
 ant-1.8.2
CentOS 5.6 x64
 JDK u26 x64
 ant-1.8.1

MT5に移行した 

|
「GAEに移行した」で書いたようにここのサイトは、手元のサーバ上においてMTで編集/生成した静的HTMLを、GAEのアプリケーションにリソースとして組み込みServletで返しているだけなので、MT4でもMT5でも関係ないといえばない。

MT4のときはSQLiteを使っていたので、MySQLに移行せざるを得なかった。
  • [MT4]システムメニューからバックアップ
  • [MT4]MySQLにMT用のDBとユーザを作成
  • [MT4]mt-config.cgiを書き換えてMySQLを参照する設定に。
  • [MT4]この状態でmt.cgiにアクセスすると新規セットアップになるので、適当に。
  • [MT4]システムメニューからバックアップを復元
  • [MT5]MT5のファイルをおいてアップグレード→再構築
てな感じで移行自体はできたんだけど、よく見るとカテゴリのリンクがまったく張られていない。
なんでかと思ったら全ての記事からカテゴリの情報が消えてた!!

ちまちまちまちま全記事にカテゴリを設定しなおすはめに。
記事の一括編集でカテゴリ設定できることに途中まで気がつかず無駄にしんどかった。あーぁ。

結果的に過去のエントリを見返すことになったのだけど、今も使ってるアプリ/OSSが結構古いバージョンのときから使ってたので驚いた。

環境:
 CentOS 5.5 x86
  MovableType 5.04


Arduinoと ATtiny2313で SPI 

|
気がついたら前回工作してから半年もたってた。
SN3E0090.jpg
ArduinoからATtinyに指示を送ってモーターの制御をする、てなことをやるつもり。で、まずはSPIで指示を送り、これに従って何かする、ことをやってみたい。

 ※以下の内容は単にやってみたことの記録です。すべて無保証で、障害・損害・不利益・不都合に対し、筆者は一切の責任を負いません。

SPI自体についてはこのへんを参照。
なんでSPIを選んだかというと、
I2Cよりも、仕組みが単純、転送速度も速くできるみたいだから。

  • Arduinoをマスター、AVR ATtiny2313Vをスレーブとする。
  • ATtiny2313にはSSがないみたいなので、PB4をLOWにしたらスレーブ選択、という体(てい)で。
  • マスターから送ったデータ8ビットを、スレーブ側でLED点灯で表現(面倒だったのでLEDは4つ。下位4ビットだけ・・・)&前回データを反転したものをマスターに返すことで、通信がうまくいったことを確認する。Arduino側はスレーブから受け取ったデータをSerialに書きだす。
ATtiny2313は、外部クリスタル8Mhzを使用かつCKDIV8を無効にしているので、システムクロックは8Mhz。
電源はUSBからArduinoに給電。ATtinyはArduinoから出ている5Vを使う。spi_test.PNG

マスター:
最近公開されたarduino 0022ではSPIが標準ライブラリになっているので、マスター側はこれを利用した。

#include <SPI.h>
#include <util/delay.h>

void setup()
{
Serial.begin(9600);

SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV8);
SPI.setDataMode(SPI_MODE0);

pinMode(2, OUTPUT);
digitalWrite(2, HIGH);

uint8_t d = 0;
for (;;)
{
digitalWrite(2, LOW);
uint8_t a = SPI.transfer(d);
digitalWrite(2, HIGH);

Serial.print(d, HEX);
Serial.write(", ");
Serial.println(a, HEX);
d++;
_delay_ms(300);
}
}


void loop()
{
}


スレーブ:

試しながら学ぶAVR入門―マイコンの基礎と電子工作とWindowsアプリケーションの作り方 (SkiLL up mycomputerシリーズ)
スレーブ側は、ATtinyのデータシートに、アセンブリ言語で書かれた実装例があるので、ニーモニックの説明を見つつC言語に書き下してみた。
ニーモニックについてはデータシートに説明がある。

外部割り込みがどういう挙動か知りたかったこともあり、SS相当のPB4で割り込みがかかるようにした。
PB4がLOWになったら受信開始。8ビット受信する。受信にあたりマスターへの送信データは、前回受け取ったデータをビット反転したものとした。特に意味はない。
受け取った8ビットのうち下位4ビットのON/OFFをPB0~PB3につないだLEDに反映する。


#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>


#define USCK PB7
#define MOSI PB5
#define MISO PB6


volatile uint8_t triggered = 0;

ISR(PCINT_vect)
{
if (!bit_is_set(PINB, 4))
{
triggered = 1;
}
}

uint8_t spi_slave_receive(uint8_t send)
{
USIDR = send;
USISR = (1<<USIOIF);
while (!(USISR & (1<<USIOIF)));
uint8_t receive = USIDR;

return receive;
}

void spi_slave_init()
{
USICR = (1<<USIWM0)|(1<<USICS1);

// MISO(PB6)は出力に
DDRB |= _BV(MISO);
// MOSI(PB5)/USCKは入力に
DDRB &= ~(_BV(MOSI) | _BV(USCK));

// MOSI(PB5)/USCK(PB7)プルアップ
PORTB |= (_BV(MOSI) | _BV(USCK));
}

int main(void)
{
spi_slave_init();

// LED(PB0..PB3)は出力に
DDRB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3);

// LEDを消灯
PORTB &= ~(_BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3));

// PB4プルアップ
PORTB |= _BV(PB4);

// PB4の変化割込み
GIMSK |= _BV(PCIE);
PCMSK |= _BV(PB4);

sei();

uint8_t d = 0x00;
for (;;)
{
while (!triggered)
{
}

// PB4がLOWになった

// clear
triggered = 0;


// 1バイト受信+送信
d = spi_slave_receive(~d);


// display bits as LED
for (int i = 0, check = 1; i < 4; i++, check*=2)
{
if (d & check)
{
PORTB |= check;
}
else
{
PORTB &= ~(check);
}
}
}
}


おわり:
ようやくマイコン間で8ビット転送できるようになった。
普段やってることは、重層な抽象化レイヤの上に成り立っているので、8ビットどころかネットワークを超えて簡単に送り放題だし、RPCでもなんでもいくらでもやりようがある。たまにこうやってプリミティブなところから積み上げるのもいい訓練になるなと思った。

環境:
 Windows 7 x64 Ultimate
  arduino 0022
  AVR Studio 4.18 + SP3
  WinAVR 20100110
Arduino Duemilanove
AVR ATtiny 2313V




GAEに移行した 

|
すっきりわかるGoogle App Engine for Javaクラウドプログラミング


オープンソース徹底活用 Slim3 on Google App Engine for Java
今年の夏は暑かったせいか、このブログをホストしているサーバが時々ハングしていた。
ので、なんとなく思い立ってGoogle App Engineに移行した。

ほぼ静的htmlしか公開していないサイトなので、静的ファイルのみのアプリケーションをGAEでホストするというゴージャス仕様。

短時間でなんとかしたいなと考え、まずは以下のように。

  • MTはperlで書かれているけど、これをGAE上で動くようにするのは道のりが遠いので、コメント/トラックバックの機能は閉じることにする。
    • MTの管理画面で両者を無効にして、サイト全体を再構築。
  • GAEアプリケーションのwar/ディレクトリ配下に公開する静的ファイルを全部置く。
  • デプロイする。
GAEのアカウントとったりアプリケーション登録したりと、こまごまやることはあったけど、静的ファイルを公開するだけならこれでおしまい。

・・・なのだけどハマったことがいくつか。

  • 静的ファイル数の制限が3000個。
    • cgiやライブラリを除くMTのファイル(画像やテーマなど)もまとめてデプロイしようとしたのだけど、ファイル数制限を超えてデプロイできなかった。使ってないファイルを調べてちまちま削除した。
  • ファイル数が多かったのでデプロイに妙に時間がかかった。
    • ftpやscpでアップロードするのとは状況が違い、単純にファイルとして格納されるわけではないそうで。自分ところではデプロイ開始から50分かかってしまった。

毎回デプロイに一時間近くかかってはこまるよなぁ、と。
ということで現在は以下のように変更。

  • 対象となる静的ファイルを、pathのハッシュを基準にいくつかのzipアーカイブに分割して保存。(現在は16分割している)
  • すべてのURLを受け付けるサーブレットを作成。
  • リクエストされたパスからハッシュ値をとって格納zipアーカイブを決定。
  • zipアーカイブから指定されたパスのリソースを取り出して応答。
  • 静的コンテンツ1つ1つを、毎アクセスごとにzipから読み込んではさすがに無駄があるので、キャッシュAPIを使う。
てなことをしたら、デプロイも数十秒で収まるようになった。

アプリケーションが自分でOpenするファイルは、リソースファイルとしてデプロイしておく必要がある。

ここのサイト用アプリは次のようなディレクトリ構成になっていて、

gae-static-content/
  src/
    サーブレットなどのソース
  war/
    static-contents/
      passing-static-0.zip
      passing-static-1.zip
      passing-static-2.zip
      passing-static-4.zip以下 -f.zipの16分割。
    WEB-INF/
      classes/
      lib/
      appengine-web.xml
      logging.properties
      web.xml

war/static-contens/*.zipをリソースファイルとしてデプロイするために、appengine-web.xmlに以下のように指定している。デフォルトではstatic-fileとリソースファイルの両方としてデプロイされるそうなので、静的ファイルからは除外、とした。

	<static-files>
<exclude path="/static-contents/*" />
</static-files>

MTで記事編集→
再構築してhtml生成→
静的ファイルのpathに応じて分割アーカイブ→
アプリケーションとしてデプロイ

てな流れ。分割アーカイブはperlで書いたスクリプトで一括処理。

処理と作業の単純化のため、pathのハッシュ基準にzip分割しているのだけど、ファイルサイズを考慮していないのでそれぞれのアーカイブがGAEのファイルサイズ制限にひっかかってしまう可能性がある。が、今のところ最も大きいzipでも3MBなので、まあいいかと思っている。


環境:
 Windows 7
  JDK6u20
  Eclipse 3.6
 App Engine SDK 1.3.7


統合Windows認証用にktpass.exeを用いてサービス用のkeytabを作成。
Active Directoryと apacheで 統合Windows認証
kinitにこのkeytabを指定することで、パスワードを入力することなしでTGTを得ることができる。

W2k8がDCな環境(krb5.confにおいて当該REALMのkdcにこの2008を指定している状態)で、上記エントリで作成したkeytabをkinitしようとすると、以下のエラーになってしまった。

kinit(v5): Key table entry not found while getting initial credentials
下のリンクは、2000と2003環境の話だけど、要領は同じみたい。
IBM Tivoli | Microsoft Windows Server 2003環境でのWindows統合認証設定の考慮点 (Tivoli-08-030):

クライアント側が合わせる場合:
上記keytabはRC4で暗号化されたエントリが入っているので、krb5.conf側で暗号化にRC4を明示する。

[libdefaults]
default_tkt_enctypes = rc4-hmac
default_tgs_enctypes = rc4-hmac

keytab側をAESで暗号化する場合:
以下のようにして暗号化にAESを明示する。

ktpass -princ HTTP/somehost.example.com@EXAMPLE.COM -mapuser マップするユーザ名 -crypto AES256-SHA1 -ptype KRB5_NT_SRV_HST +rndPass -out 適当なファイル.keytab

複数の暗号化でエントリを作成してもいいかも。だけど、どうせなら暗号強度が強い方に倒した方がいいのかなーと。

$ kinit -kt keytabファイル HTTP/somehost.example.com
$ klist
Ticket cache: FILE:/tmp/krb5cc_9999
Default principal: HTTP/somehost.example.com@EXAMPLE.COM

Valid starting Expires Service principal
08/30/10 19:02:41 08/31/10 05:02:42 krbtgt/EXAMPLE.COM@EXAMPLE.COM
        renew until 08/31/10 19:02:41


Kerberos 4 ticket cache: /tmp/tkt9999
klist: You have no tickets cached

まずはこの状態で、SASL-GSSAPIによる認証を用い、ldapsearchでAD上のオブジェクトを検索できるとこまで確認した。つづきはそのうち。


環境:
Windows Server 2008 Standard x64
CentOS 5.5
 krb5-workstation-1.6.1-36.el5_5.5
 krb5-libs-1.6.1-36.el5_5.5



embed-astah.pngなんとなくアイデアを書いてからもう4カ月。書いたっきり手つかずで放置してたけど、突然やる気になってみた。

astah*で図を書いて redmineの wikiに埋め込むプラグインを考える その1

ソースはgithubに。例によって無保証です。
tckz's redmine_wiki_astah at master - GitHub

前のエントリに書いたように、astaファイルから図をエクスポートするのは非常に時間がかかる。だから、wikiマクロでは、エクスポート対象astaファイルをDBに記録するだけにした。そして別途cronなどを使ってエクスポート処理を動かす、という流れ。

主なfeature

  • wikiマクロ、{{astah_diagram}}を追加。
  • astaファイルは、public配下に置いたものまたは、リポジトリに入れたものを指定できる。
{{astah_diagram}}マクロ

    {{astah_diagram(public:foo.asta, namespace/diagram)}}
{{astah_diagram(source:/repo/path/foo.asta, namespace/diagram)}}
{{astah_diagram(option=value...,public:foo.asta, namespace/diagram)}}

  • astaファイル:
    • public:path/to/.asta
      • RAILS_ROOT/public/配下に置いた.astaを指定する。
      • RAILS_ROOT/public/sample.astaなら、指定する値はpublic:sample.asta
    • source:repo/path/to/.asta
      • リポジトリに格納したastaを指定する。プロジェクトにリポジトリがないと意味がない。
      • wikiのsourceリンク展開と同じように記述。
      • リポジトリの直下にあるsample.astaなら、source:sample.asta
  • 図のpath:
    • Asta*で図をエクスポートした際のpathに準ずる。
    • 図や名前空間に「/」が含まれると、エクスポートの際に「_」に変換される。ので、マクロに指定する値も「_」に変換した値とする。他にもあるかもしれないが不明。
オプション:
  • align=value
    • 埋め込まれた図のIMG要素に追加するalign属性
    • 例:right, left
  • width=value
    • 埋め込まれた図のIMG要素に追加するwidth属性
    • 例:100px, 100%
  • height=value
    • 埋め込まれた図のIMG要素に追加するheight属性
    • 例:100px, 100%
  • target={_blank|any}
    • 埋め込まれた図のIMG要素に追加するtarget属性
    • 別ウィンドウで開くなら_blank

インストール

事前に、astah(のGUI)を実行可能な状態に。↓のエントリで書いたように、図のエクスポートにはGUIが動くように、DISPLAYとライセンスを適切に設定する必要がある。
astah*で図を書いて redmineの wikiに埋め込むプラグインを考える その1

1. プラグインをRAILS_ROOT/vendor/plugins/配下に置く。

    #{RAILS_ROOT}/vendor/
      plugins/
        redmine_wiki_astah/
2. redmine_wiki_astah/run-astah.shを環境に合わせて編集する。
    ASTAH_HOME : Astah*を展開したディレクトリを設定。astah-pro.jarがあるディレクトリ。
    DISPLAY    : 当該環境のディスプレイをポイントする。自分ところでは前のエントリのとおり、vncserverを使っている。
3. プラグインが使うテーブルを準備。
  rake db:migrate:plugins RAILS_ENV=production
4. Redmineを再起動
5. 管理者でredmineにログインする。
6. プラグインの設定画面で'secret key'に適当な文字列を設定する。
7. 図のエクスポートを定期的に行うようセットアップする。

図をエクスポートする

wikiに埋め込まれたastaをエクスポートして実際の図イメージを作成する。
Astah.export_diagrams()を定期的に実行する必要がある。

こんな感じで。
#{RAILS_ROOT}/script/runner Astah.export_diagrams -e production

エクスポートしたイメージをredmineを実行しているユーザから参照できるよう、実行ユーザに注意。


おわり


astaにたくさん図が含まれるとエクスポートに何分もかかってしまう。
図のID(astaファイル中の内部的なID。APIで取得できる)があらかじめわかっていれば、特定の図だけをエクスポートすることで短縮もできるが・・・・。
先のエントリに書いたように、大き目の図が多いせいでwikiに埋め込むと小さい。widthを付けることで収まりはよくなるが、リンクをクリックして図だけを表示しないと読み取るのは難しいかも。

環境:
  CentOS 5.5 i386
    ruby-1.8.7-p299(from source)
      redmine-1.0.0
      sqlite3-ruby (1.3.1)
    sqlite-3.7.0-1
    astah* pro 6.2




Powered by Google App Engine

Photos

  • spi_test.PNG
  • SN3E0090.jpg
  • embed-astah.png
  • SN3E0079.JPG
  • SN3E0078.JPG
  • SN3E0076.JPG
  • SN3E0072.JPG
  • SN3E0073.JPG
  • SN3E0071.JPG
  • uc.png
Powered by Movable Type 5.04