雑記帳

ちょっとした文章とかメモ書きとか。

カテゴリーアーカイブ: プログラミング

haroonga-httpdを書いた話

前にGroongaのHaskellバインディングのHaroongaを書いたので、どうせならHTTP越しにGroongaを使ってみたいと思っていたらつい書いてしまったというお話。

Github – haroonga-httpd

内部でHaroongaに依存しており、Groongaをライブラリとして呼んで使っています。

WebアプリケーションのフレームワークにはScotty(HaskellのSinatraクローン)を使っています。ScottyはSinatraのAPIに似せて作られていますが、内部で使っているWAIがConcurrentなため、ScottyもちゃっかりConcurrentになっています。

GroongaのHTTPのインターフェースほどしっかりパラメータをパースすると言うことはしていないです。。。

http://localhost:3000/d/<Groonga command>

のようなURLでアクセスするとGroongaのcommandがharoonga-httpdの動いているマシンで実行され、結果がGroonga互換のjsonで返ってくるようになっています。

起動のさせ方はGithubのREADMEなどを見ていただけると。

HaskellでもちゃんとGroongaがライブラリとして使えていますね!!

すごいcronとしてのJenkins

毎日ビルドなり、決まった時間にnightlyのバイナリをcurlでアクセスして取ってきたいなんて思った事はありませんか?

ありますよね。

そうなると*nix系の人ならcronを使う事になるのでしょうが、cronには親切なUIというものが付いてないですし、そもそもWindowsじゃ動きません。

そうなるとJenkinsの出番です。

Jenkinsとは一言で言うと親切なUIがくっ付いたスゴいcronです。
これを使わない手は有りませんね。

という事で、いくつか使ってみています。

使用例

一つ目:Mroongaのnightlyのバイナリを1ヶ月間分保存した上で決まった時間にアクセスして取りにいきたい。

そのジョブに使っているスクリプトはこちらです:https://github.com/cosmo0920/curl-daily-job-for-mroonga

その他、Jenkinsの定時に実行する設定が必要です。

二つ目:OSXまたはLinuxで”cabal install yesod yesod-bin”を実行して正常終了するか見たい。

そのジョブに使っているスクリプトはこちらです:https://github.com/cosmo0920/haskell-install-check-CI

こちらはOSXでは直接

cabal sandbox init

した後に、

cabal install yesod yesod-bin

しています。
が、Jenkinsを立てた時期とマシン事情によって、Linux向けの”cabal install yesod yesod-bin”のジョブにはDockerを使っています。

CIが失敗したときのDockerコンテナの残骸はどうやって処理しているんでしょうかね。気づいた時に手動で

docker rm `docker ps -a -q`
docker images | grep "<none>" | awk '{print $3}' | xargs docker rmi

な感じで削除しています。

三つ目:Jenkinsのslaveを立ててmasterとは異なるOSでのCIを行いたい

それに使っているスクリプトはこちらです:https://github.com/cosmo0920/PowerShell-for-Mroonga-building

WindowsのJenkins slaveを立てるにはJenkins slave agentをJNLP経由で接続すると楽です!

また、WindowsでのCIを行う際にはpowershell pluginを使うとpowershellでJenkinsのCIが行えるようになるのでCIが楽しくなります。

色々なJenkinsの使い方を試してみるとCIが楽しくなるかもしれません。

hsenvで複数の切り替え可能なghc環境を整える

RubyでいうrbenvのようなツールはもちろんHaskellにもあります。hsenvですね。

これは$HSENV_ROOT/bin/activateスクリプトにより独立したghc環境を作るものです。

rbenvの時とは少し作法が違うので注意してください。

hsenvの場合は、hsenvを実行したディレクトリに.hsenvが掘られ、そこにghc環境が新たに作成されます。使い方によってはcabal sandboxと被ってしまいますが、今回は異なるghc環境の切り替え用途で使ってみます。hsenvは$PATHで指定されているディレクトリに既に有るものとします。

$ mkdir ~/.haskell
$ cd ~/.haskell
$ hsenv --ghc=<ghc tarball>.tar.gz

とする事により、新たなhsenvによるghc環境が~/.haskell/.hsenv以下に作成されます。

例えば、ghc-7.8.2をhsenvを使った切り替え可能なghc環境としてインストールするとしたら次のようになります。

$ wget https://www.haskell.org/ghc/dist/7.8.2/ghc-7.8.2-<architecture & OS type>.tar.gz

としてghc-7.8.2のtarballをダウンロードしておき、

$ mkdir -p ~/.haskell/hsenv/ghc-7.8.2
$ cd ~/.haskell/hsenv/ghc-7.8.2
$ hsenv --ghc=<path to ghc-7.8.2 tarball>

とすると~/.haskell/hsenv/ghc-7.8.2の下にghc-7.8.2環境が作られます。

$ source ~/.haskell/hsenv/ghc-7.8.2/.hsenv/bin/activate

とすればこの作成した環境に切り替えられます。

これを、例えば~/.bash_aliases~/.zshenvなどに

alias hsenva='source ~/.haskell/hsenv/ghc-7.8.2/.hsenv/bin/activate'

みたいにしておけば環境の切り替えも楽に行えます。hsenvaはhsenv activateの略のつもりです
今回はghcを一つだけhsenvでインストールしたのですが、例えば

$ ~/.haskell/hsenv/ghc-<version>

のようなバージョニングルールを決めておけば、
複数のhsenvでインストールしたghc環境がどれがどれだったか分からなくなる事がなくなると思います。

hsenvにより新しいghc環境を作成した後、cabal sandbox init後に依存ライブラリを入れるようにすればより快適なHaskell開発環境が手に入ると思います。お試しあれ。

Ansibleでketerのデプロイ環境を整える

Ansibleを触って、keterでのデプロイが出来るまでのAnsible playbookを作成してみました。

目標:AnsibleでサーバーへHaskell開発環境を入れずにketerの環境を作成する。

Yesodのデプロイツールのketerサーバーで実行する段階ではネイティブのバイナリの実行ファイル(ELF)です。

Yesodのデプロイ環境をketerで作成するとプロダクションサーバーに一切開発環境やインタプリタやコンパイラを入れること無くアプリケーションを動かせる、ということになっています。

とってもセキュア!

そうして出来上がったのがこちらのplaybook: ansible-playbook-for-keter-deploy

このplaybookを動かすにはhostへの対象サーバーの記述と、binaryディレクトリへketerのELFバイナリを置く必要があります。

ついでにserverspecでserverの状態を確認するテスト書きました。

  • gcc, clang, ghc等の開発ツールを誤ってインストールしていないか
  • keterがサービスとして動いているか
  • avahi(bonjour) daemonが動いてホスト名の名前解決が行えるか

等のserverspecを書いてあります。(が、テストをどうやってCIするか悩んでいるのでCIはまだしてないです)

Yesodのデプロイ作業はいくらscpで<<Yesod App Name>>.keterをプロダクションサーバーに投げつけるだけとは言え、そこまでの環境を用意するのがめんどくさかったのですが、Ansibleのplaybook化してしまえばYesodのアプリケーションをデプロイするまでの作業がかなりラクになりそうですね。

新宿Scala座2014年3月号に参加してきた

新宿Scala座に参加してきました。

普段自分の時間を使って書く時はHaskellやらRuby(のC FFI)やらを書いている訳ですが、何を思ったかScalaに手を出してしまいました。

Scala始めて間もないのでScalaを書く時にはまったこと、というタイトルでスライドを作りました。

Scalaを書いていて結構OOPだなーと思っていると実はScalazがあるよ!みたいなことだったり、かなりBattery includedな感じだったりと、どうしても重厚なものになってしまうのは仕方ないのかなぁとか。

あと、最近はdispatchの新しいものが出たこともあり、dispatch-classicと新しいdispatchの情報が混在していてやめてくれーって感じでした。

Scala、もっと使っていきたいですね。

GroongaのHaskellバインディングを書いた。

Groongaのドキュメントの作業のお手伝いをしていく中で、自分の好きな言語の一つであるHaskellから使えたらなんて面白いんだろう、と思ったのでHaskellバインディングを書きました。

ツイートにある通り、Haskell + GroongaHaroonga(はろんが)です。
https://github.com/cosmo0920/haroonga

Groonga(ぐるんが)のようなどっしり(?)した響きではなく、Haroonga(はろんが)だと「Haskellの世界にはろー」みたいな軽いイメージが連想されますね。(「はろー」というよりも「はろろん」みたいなもっと砕けたイメージかなと思いますがまぁ置いておきましょうか。)

HaskellでFFIを使ったバインディングを書くにあたって何種類か方法があるわけですが、その中で使った方法がc2hschsc2hsを使う方法です。この方法を取ると、c2hscがC言語のヘッダーを静的に解析し、<c言語のヘッダー名>.hscという中間形式を吐きます。こうすることにより、FFIを行うにあたって8割以上の作業は終了します。

FFIを使用する理由は何でしょうか。そうですね、FFIを使ってその言語に無いライブラリを使いたいのです。その目的を達成するのには、APIがこなれないのかも知れないけれどもツールに頼るのが良いでしょう。
幸運な事に(Glasgow) Haskellではそのやり方を推奨しているように見えます。c2hscは使い方が単純ですし、hsc2hsはwell documentedなのです。

ただ、c2hscにも弱点はあります。複雑に定義されているC言語の構造体をごく稀にパーズできないことがあります。ただこれは本当にごく稀で、そのような構造体をHaskellの世界に持っていく事に迫られるケースは多くありません。Haroongaを作る際にもgrn_obj構造体の扱いに悩みましたが、これはあくまでもHaskell側からは型のみを取り出して中身はブラックボックス(Haskell側ではアクセスする手段を提供しないが、Haskellの世界にgrn_obj構造体に当たる型が存在する)、とする事に落ち着きました。

それにより嘘みたいに簡単に作成することができました。

こんな具合です。

Haroongaのモジュールの中でBindings.Groonga.RawはGroonga 3.1.1のgroonga.hからc2hscを使って生成した後、すこし手直しをしています。また、Bindings.Groonga.CommandAPIはgroongaコマンドで出来るレイヤーのAPIを提供します。当初このモジュール名はSimpleAPIでした。CommandAPIの方がどのように使え、何が出来るのか、が分かるのではないかというGroongaのメーリングリストの指摘によりこのモジュール名を選択しました。
指摘して下さった須藤さんありがとうございます!

現時点ではまだHackageにリリースされていませんが、もう少しAPIを練ってみて自分なりに納得したらリリース…できるといいなぁと。

Hackageのアップロード権限の申請が通ったので、Hackageにリリースしました!

cabal install haroonga

でGroongaが導入済みで、Haskell Platformがインストールされている環境ならばインストールすることができます。

近況報告

Ruby-GNOME2プロジェクトメンバーになりました。

Ruby-GNOME2のリポジトリへPull Requestを何回か送っていたらkouさんにRuby-GNOME2プロジェクトメンバーにならないかと提案されたので快諾しました。

現時点では「Ruby-GNOME2プロジェクトをもっとも知らないRuby-GNOME2 teamメンバー」です。よろしくおねがいします!!

追記:GithubへのPull Requestやissueの報告、返答はすべて英語で行いました。
というのも、GithubのRuby-GNOME2チームは日本語を第一言語としていないメンバーもいたためです。
日本語を読めない人々が議論に参加できるようにするならそのほうが良く、またプロジェクトの第一言語が英語であるならそれに従ったほうが良い、との判断から英語を用いてやり取りすることにしました。

MathJax.jsのSVGレンダリングでより綺麗に出力

MathJax

MathJax.jsはWebページに綺麗な数式を表示させるJavascriptです。

最新版は現在v2.2です(13/7/3現在)

MathJaxのCDNがあるのでそこから引っ張ってくるのが手軽な使い方です。

よく以下のように使うと書かれています。

<script type="text/javascript"
  src="https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

しかし、MathJax.jsのv2.2はsvg画像でのレンダリングもサポートしているのでこちらを使ったほうが拡大により数式が荒くならず、また、表示も速くなります。

svgでのレンダリングは以下のようにします(参考:http://docs.mathjax.org/en/latest/configuration.html#using-a-configuration-file):

<script type="text/javascript"
  src="https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG">
</script>

こうすることで、表示がsvgでされるようになります。

また、以下のようにしておくと日本語環境での場合の数式入力がよりしやすくなるかもしれません。参考:http://docs.mathjax.org/en/latest/configuration.html#using-in-line-configuration-options

<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [['$','$'], ["\\(","\\)"]],
      displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
    }
  });
</script>

こうすることで、数式の開始、終了に$記号が使えるようになります。

svgでのレンダリングの例が見当たらなかったのでメモ。

Wandboardで遊ぼう

Wandboard http://www.wandboard.org/ を入手したので色々いじくってみました。

Wandboard dualであればLinuxを動かすのにもちょうどよい性能なのでLinuxを入れてみましょう。

基本的な入れ方は、http://www.eewiki.net/display/linuxonarm/Wandboard を参考にすれば大丈夫です。

Linuxとして使うには(特にXorgを上げる場合には)、linux-swapパーティションを作りましょう。gpartedにより、ブートするmicroSDの後方1GBをlinux-swapにし、他はWikiと同様の設定とします(下図)

Screenshot_from_2013-05-07 06:21:14

Wikiではswapを作っていないので/etc/fstabも書き換えます。

/dev/mmcblk0p2   /              auto  errors=remount-ro  0   1
/dev/mmcblk0p1   /boot/uboot    auto  defaults           0   2
/dev/mmcblk0p3   none           swap  sw                 0   0

こうすることで、swapパーティションが有効になります。

また、Ubuntu11.10の元々のカーネルとWikiにある方法で作成するカーネルでは以下の違いが特に後々重大な影響※を及ぼします。

※重大な影響とは、一般ユーザーでtcp/udpが叩けなかったり、Xorgを上げても無反応になってなってしまうことを指します。

@@ -49,21 +63,9 @@ kernel/drivers/i2c/i2c-core.ko
kernel/drivers/i2c/i2c-dev.ko
kernel/drivers/i2c/busses/i2c-imx.ko
kernel/drivers/input/input-core.ko
-kernel/drivers/input/mousedev.ko
-kernel/drivers/input/evdev.ko
kernel/drivers/input/serio/serio.ko

あ…れ…evdev.koとmousedev.koがカーネルにbuiltinされてない…これでハマりました…orz evdevってXorgの入力に関わるところなんですね…知らなかった
(参考:http://www.yamasita.jp/linkstation/2012/03/120326_evdev.html)

CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_EVDEV=y

としましょう。

また、これ:

CONFIG_ANDROID_PARANOID_NETWORK=y

も後々困った事になるのでnにしておきましょう。このコンフィグが有効だとLinuxでは[sudo] rootでしかeth0をつかめなくなります。

このように。

# CONFIG_ANDROID_PARANOID_NETWORK is not set

また、後に回すとめんどくさいので起動直後に日本語ロケールを有効にします。

$ sudo locale-gen ja_JP.UTF-8
$ sudo update-locale LANG=ja_JP.UTF-8 LC_MESSAGES=POSIX

あとは、

$ sudo apt-get install lightdm
$ sudo apt-get install xubuntu-desktop

するだけでGUI環境ができます、Ubuntu便利ダナー…

あとは、gccを入れるなり、Monoを突っ込むなり、ghcを入れるなりしましょう。どれもapt-getで入ります。

% cat /proc/cpuinfo
Processor    : ARMv7 Processor rev 10 (v7l)
processor    : 0
BogoMIPS    : 790.52

processor    : 1
BogoMIPS    : 790.52

Features    : swp half thumb fastmult vfp edsp thumbee neon vfpv3
CPU implementer    : 0x41
CPU architecture: 7
CPU variant    : 0x2
CPU part    : 0xc09
CPU revision    : 10

Hardware    : Wandboard
Revision    : 61011
Serial        : 0000000000000000

WandboardのARM CPUはarmhfでdual coreなようですね。

% uname -a
Linux arm 3.0.35-wand3 #1 SMP PREEMPT Sat May 4 06:16:05 JST 2013 armv7l armv7l armv7l GNU/Linux

また、カーネルが古いので3.8から入ったf2fsはWikiの方法を踏襲すると使えません…残念!

追記:githubにevdevを有効にしたWandboard向けカーネルコンフィグをpushしました。
https://github.com/cosmo0920/LinuxKernelconfig/blob/master/3.0.35-wand3.config

更に追記:Wandboardの公式イメージのUbuntu11.10がグラフィックアクセラレーションが効くようになったのに加え、vivante_drv.so(WandboardのGPUのXorgのドライバ)がUbuntu12.10でうまくmakeできない&Ubuntu13.04でXorgが立ち上がらないので公式イメージを使うようにしました…orz

Kernel 3.9でv4l2loopbackを使う

Kernel 3.9ではV4L2に変更があります。

「3.8までのV4L2」は以下のV4L2 int deviceが該当します。
deprecated表示になっているのでV4L2を使う際は使うのは推奨されなくなりました。
v4l2loopbackデバイスを使う際はカーネルコンフィグで有効にしましょう。

Screenshot_from_2013-04-30 23:31:06

その上のV4L2 sub-device userspace APIだけにチェックを入れた場合にv4l2loopback/webcamstudioのカーネルモジュールをinsmodしようとすると次のエラーが出ます。

$ sudo insmod webcamstudio.ko
insmod: error inserting 'webcamstudio.ko': -1 Unknown symbol in module
$ dmesg
[  ... ] webcamstudio: Unknown symbol video_ioctl2 (err 0)
[  ... ] webcamstudio: Unknown symbol video_devdata (err 0)
[  ... ] webcamstudio: Unknown symbol video_unregister_device (err 0)
[  ... ] webcamstudio: Unknown symbol video_device_alloc (err 0)
[  ... ] webcamstudio: Unknown symbol __video_register_device (err 0)
[  ... ] webcamstudio: Unknown symbol video_device_release (err 0)

また、webcamstudioは0.57系にとどまっているのではなく、より新しいものに更新しましょう。
Ubuntu12.04+で起動できない問題は既に修正済みです:
http://code.google.com/p/webcamstudio/issues/detail?id=75#c38