2012年12月22日土曜日

ZFSの書き込み低速化?

ワンセグ野郎サーバがストールしていました。
リモートからログイン出来ず、ディスプレイ、キーボードも接続してなかったので電源断して再起動で対応。syslogにはこれといったメッセージは記録されていなかったが、3日ほどストールしていたようでした。

で、ワンセグ野郎の起動スクリプトを実行して復旧となったはずでしたが、数日後TSファイルが正常に記録されていないことに気がつきました。
番組表は更新されていたので気がつきませんでした…見たい番組がある時に限って。

ログを見るとdvbstreamが再起動を繰り返していて、ts.plのタイムアウト処理にかかっているのが直接原因のようです。
そこでdvbstramを単体で動かしてみましたが、シグナルレベルなどは問題ないようです。
しばらく調べていると出力をリダイレクトしたファイルサイズの増え方が遅いことに気がつきました。

まだ150GB位空きがあったので気にしていませんでしたが、どうもZFSは空き容量が少なくなると性能が低下するようです。取り合えず、200GBの空きを確保して試すと正常動作するようになりました。

時間と環境が出来たら、このあたり調べておきたいなぁ。

2012年9月15日土曜日

recpt1コンパイル

CentOS 6.3(x86_64)でPT3を使用するためドライバをインストールしましたが、今回は録画用のrecpt1をインストールします。

recpt1のソースは、Mercurialで管理されているのでパッケージをインストールしておきます。
# yum install mercurial
スマートカード関連のパッケージもインストールしておきます。
# yum install ccid pcsc-lite*

まず、libarib25をインストールします。
最新版には登録されていないので、リビジョンを指定してcloneします。
$ hg clone http://hg.honeyplanet.jp/pt1/ pt1_r73 -r 73
$ cd pt1_r73/arib25
$ make
# make install
/usr/local/libにインストールされるのでリンカの検索対象に登録しておきます。
次の例では、local.confを新規作成しています。
# echo "/usr/local/lib" > /etc/ld.so.conf.d/local.conf
# ldconfig
次は、recpt1の最新版をcloneしてコンパイルします。
$ hg clone http://hg.honeyplanet.jp/pt1/ pt1
$ cd pt1/recpt1
$ ./autogen.sh
$ ./configure --enable-b25
$ make
# make install
問題なくコンパイルできたので、PT3用にデバイス名を修正しました。
--device /dev/pt3video2のようにオプション指定すれば、ソース修正をしなくても使用できますが、PT3しか持っていないため修正してしまいました。
--- pt1_dev.h.original  2012-09-15 12:48:52.196329963 +0900
+++ pt1_dev.h   2012-09-15 13:14:59.360566755 +0900
@@ -3,24 +3,24 @@
 #define _PT1_DEV_H_

 char *bsdev[NUM_BSDEV] = {
-    "/dev/pt1video1",
-    "/dev/pt1video0",
-    "/dev/pt1video5",
-    "/dev/pt1video4",
-    "/dev/pt1video9",
-    "/dev/pt1video8",
-    "/dev/pt1video13",
-    "/dev/pt1video12"
+    "/dev/pt3video1",
+    "/dev/pt3video0",
+    "/dev/pt3video5",
+    "/dev/pt3video4",
+    "/dev/pt3video9",
+    "/dev/pt3video8",
+    "/dev/pt3video13",
+    "/dev/pt3video12"
 };
 char *isdb_t_dev[NUM_ISDB_T_DEV] = {
-    "/dev/pt1video2",
-    "/dev/pt1video3",
-    "/dev/pt1video6",
-    "/dev/pt1video7",
-    "/dev/pt1video10",
-    "/dev/pt1video11",
-    "/dev/pt1video14",
-    "/dev/pt1video15"
+    "/dev/pt3video2",
+    "/dev/pt3video3",
+    "/dev/pt3video6",
+    "/dev/pt3video7",
+    "/dev/pt3video10",
+    "/dev/pt3video11",
+    "/dev/pt3video14",
+    "/dev/pt3video15"
 };

 // 変換テーブル(ISDB-T用)
分波器を準備していないので、地デジしか試していませんが無事TSも出力されるようです。

2012年9月1日土曜日

PT3ドライバ

Express5800/GT110dのCentOS 6.3(x86_64)でPT3を使用するためドライバをインストールします。
カーネルのバージョンは、次になります。
$ uname -mrv
2.6.32-279.5.2.el6.x86_64 #1 SMP Fri Aug 24 01:07:11 UTC 2012 x86_64

まずは、ソースの展開から。
PT3のドライバは、GitHubで公開されているので、次のようにしてソースを展開します。
$ git clone https://github.com/m-tsubo/pt3.git
コンパイルとインストールは、次のように行います。
$ cd pt3
$ make
# make install
# modprobe pt3_drv
コンパイル時にwarningが出ますが、問題なさそうな内容ですので無視します。
$ ls /dev/pt3*
/dev/pt3video0  /dev/pt3video2  /dev/pt3video4  /dev/pt3video6
/dev/pt3video1  /dev/pt3video3  /dev/pt3video5  /dev/pt3video7
2枚挿しなので8つデバイスが出来ていますが、1枚の場合はpt3video0~pt3video3の4つ出来ていれば成功です。

PT3の発売から2ヶ月強で完成度の高いドライバが出来てるなんて、凄いなぁと思います。

recfsusb2nコンパイル

オリジナルのhttp://tri.dw.land.to/fsusb2n/での配布は終了してしまったようですが、ググるとまだ入手できるようです。よかった。

recfsusb2n-0.9.2.tar.gzを入手することが出来ました。
コンパイルは、Boostを使用しているためboost-develをインストールしておく必要がある位で、特に問題なく完了。 TSも無事出力されるようで、ハード改造も成功していたようです。
2つの同時利用も問題ないようです。

あと、Express5800/GT110dのCPUがCeleron G530なので、最適化オプションとして、-O -mfpmath=sse -msse4.2を指定してみました。
録画時に気持ち程度CPU使用率が下がったような気がします。

2012年8月26日日曜日

dvbstream: Overflow error, trying again...

ワンセグ野郎で使用しているdvbstreamが次のようなメッセージを出力するようになりました。
データを出力しないのでts.plによって、再起動を繰り返しています。
Caught signal 15 - closing cleanly.
dvbstream v0.5 - (C) Dave Chapman 2001-2004
Released under the GPL.
Latest version available from http://www.linuxstb.org/
Using DVB card "Siano Mobile Digital MDTV Receiver"
tuning DVB-T (in United Kingdom) to 533143000 Hz
polling....
Getting frontend event
Overflow error, trying again (status = -1, errno = 75)FE_STATUS:
polling....
Getting frontend event
FE_STATUS:
polling....
FE_STATUS:
polling....
FE_STATUS:
polling....
Getting frontend event
FE_STATUS: FE_HAS_SIGNAL FE_HAS_LOCK FE_HAS_CARRIER FE_HAS_VITERBI FE_HAS_SYNC
Event:  Frequency: 10600000
        SymbolRate: 0
        FEC_inner:  0

Bit error rate: 258
Signal strength: 15
SNR: 27
FE_STATUS: FE_HAS_SIGNAL FE_HAS_LOCK FE_HAS_CARRIER FE_HAS_VITERBI FE_HAS_SYNC
Setting filter for PID 8192
Output to stdout
Streaming 1 stream
該当するデバイスのUSBポートの電源On/Offでは復活せず、デバイスを抜き差ししても復活しません。
問題が発生しているのは1つだけなので、USBポートを変えてみましたがダメでした。

dvbstreamのソースを確認するとioctl()でエラーになっているようなので、デバイスが壊れた?と考え、スペアのデバイスと交換してもダメという状況に途方に暮れていると、あるものが目に留まりました。

ロッドアンテナにアンテナケーブルが接触している!

室内のアンテナコネクタに室内用ワンセグアンテナをつなぎ、周りにワンセグチューナのロッドアンテナを8本置いていたのですが、そのうちの1本がアンテナケーブルと接触していました。
で、接触しないように置き直したら、あっさり解決してしまいました…半日無駄にしました。

どうも、掃除したときに動いてしまったようです。以後、気をつけよう。

2012年8月25日土曜日

PT3とKTV-FSPCIE購入

KEIAN KTV-FSPCIEとアースソフトPT3を買ってきました。

早速、KTV-FSPCIEは、抵抗を外してファームウェアを入れ替え(先達の方々に感謝)、PT3はFPGA回路更新をあてて準備完了、のはずです。
PT3のLinuxドライバ開発も進んでいるようで、開発者の方には頭が下がります。すばらしい。

Express5800/GT110dもLinuxで使うつもりなので、Windows環境を作るのが一番大変でしたが、評価版がダウンロードできるタイミングだったのがラッキーでした。

今までPCでテレビ録画って全く興味が無かったのですが、ワンセグ野郎を使うようになって面白そうと思うようになりました。しばらく楽しめそうです。

2012年8月18日土曜日

NEC Express5800/GT110d購入

NEC Express5800/GT110dを購入しました。

以前、安さに惹かれHP ProLiant ML110 G7を買ったのですが、FANがうるさ過ぎて、狭い部屋で使うのは無理でした。
Express5800/GT110dは、動作音も静かでいい感じです。
フルセグ録画でも試してみようかな、と考えてます。

2012年7月21日土曜日

ZFS mirror(2台)からraidz(4台)に移行

HDD4台でZFSを使うときに使用しそうなパターンで、4KセクタHDD向けの設定比較をして来ました。
結果を見ると設定した方が良いのかなという感じです。

さて、一通り試したいことは出来たので、2台のmirrorから4台のraidzに移行しようと思います。
環境は、こんな感じです。
  • HP ProLiant MicroServer
  • Seagete ST3000DM001 x4台
  • CentOS 6.2
  • ZFS on Linux (0.6.0 RC8)
HDD2台でmirrorで運用していたものを、HDD4台のraidzの運用に変更します。
まず、mirrorで使用していたHDD1台と、性能比較で使用したHDD3台(poolはdestroy済み)を接続します。
$ cd /dev/disk/by-id
$ ls scsi*ST3000*part1
scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1
scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1
scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1
scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1
次のようにしてmirrorプールをimportします。
dtpoolとして使用していたものをopoolでインポートしています。
# zpool import -d /dev/disk/by-id/ dtpool opool
  pool: opool
    id: 3916950419245301417
 state: DEGRADED
status: One or more devices contains corrupted data.
action: The pool can be imported despite missing or damaged devices.  The
        fault tolerance of the pool may be compromised if imported.
   see: http://zfsonlinux.org/msg/ZFS-8000-4J
config:

        opool                                      DEGRADED
          mirror-0                                 DEGRADED
            ata-ST3000DM001-9YN166_Z1F0AAAA-part1  ONLINE
            sdb1                                   FAULTED  corrupted data

なんか、sta-*でimportされました。
次に、移行先のraidzを作るためのダミーデバイスを作ります。
$ dd if=/dev/zefo of=/var/tmp/dummy bs=1024K count=1 seek=3000000
raidzのデバイスの1つに穴開きファイルを使って、データ移行後に入れ換える作戦です。
次のようにraidzのプールを作ります。
# zpool create -o ashift=12 -f dtpool raidz \
    /var/tmp/dummy \
    scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1 \
    scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1 \
    scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1
# zpool list
NAME     SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
dtpool  10.9T   912K  10.9T     0%  1.00x  ONLINE  -
opool   2.72T  2.32T   412G    85%  1.00x  DEGRADED  -
#
ashift=12で、4Kセクタ用の設定を指定しています。
ダミーデバイス(ファイル)は、オフラインにしないとデータ移行時に書き込まれてしまうのでオフラインにします。/varに3TBなんてありません。
情報をみるとこんな感じになります。
# zpool offline dtpool /var/tmp/dummy
# zpool list
NAME     SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
dtpool  10.9T   912K  10.9T     0%  1.00x  DEGRADED  -
opool   2.72T  2.32T   412G    85%  1.00x  DEGRADED  -
# zpool status
  pool: dtpool
 state: DEGRADED
status: One or more devices has been taken offline by the administrator.
        Sufficient replicas exist for the pool to continue functioning in a
        degraded state.
action: Online the device using 'zpool online' or replace the device with
        'zpool replace'.
 scan: none requested
config:

        NAME                                          STATE     READ WRITE CKSUM
        dtpool                                        DEGRADED     0     0     0
          raidz1-0                                    DEGRADED     0     0     0
            /var/tmp/dummy                            OFFLINE      0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1  ONLINE       0     0     0

errors: No known data errors

  pool: opool
 state: DEGRADED
status: One or more devices could not be used because the label is missing or
        invalid.  Sufficient replicas exist for the pool to continue
        functioning in a degraded state.
action: Replace the device using 'zpool replace'.
   see: http://zfsonlinux.org/msg/ZFS-8000-4J
 scan: resilvered 39K in 0h0m with 0 errors on Fri Jun 29 22:41:17 2012
config:

        NAME                                       STATE     READ WRITE CKSUM
        opool                                      DEGRADED     0     0     0
          mirror-0                                 DEGRADED     0     0     0
            ata-ST3000DM001-9YN166_Z1F0AAAA-part1  ONLINE       0     0     0
            9459549258261188968                    UNAVAIL      0     0     0  was /dev/sdb1

errors: No known data errors
次のようにして移行元のマウントを変更します。
# zfs set mountpoint=/old/ts opool/ts
# zfs set mountpoint=/old/backup opool/backup
# zfs mount -a
# df -h
Filesystem            Size  Used Avail Use% Mounted on
 :
/dev/sde3              20G  1.2G   18G   7% /var
dtpool                7.8T  256K  7.8T   1% /dtpool
opool                 369G  128K  369G   1% /opool
opool/ts              2.7T  2.4T  369G  87% /old/ts
opool/backup          372G  2.7G  369G   1% /old/backup
#
移行先の領域をつくります。
# zfs create dtpool/ts
# zfs create dtpool/backup
# zfs set mountpoint=/data/ts dtpool/ts
# zfs set mountpoint=/data/backup dtpool/backup
# zfs mount -a
# df -h
Filesystem            Size  Used Avail Use% Mounted on
 :
dtpool                7.8T  128K  7.8T   1% /dtpool
opool                 369G  128K  369G   1% /opool
opool/ts              2.7T  2.4T  369G  87% /old/ts
opool/backup          372G  2.7G  369G   1% /old/backup
dtpool/ts             7.8T  128K  7.8T   1% /data/ts
dtpool/backup         7.8T  128K  7.8T   1% /data/backup
#
領域が出来たのでデータ移行します。
zfsのsend,receiveでも良かったんですが、今回は進捗を見たかったのでrsyncを使いました。
TSデータ以外は、バックアップして整理したら意外と少なくなりました。

データ移行が完了したら、mirrorプールを削除して、raidzプールのダミーデバイスをリプレースします。
# zpool destroy opool
# zpool list
AME     SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
dtpool  10.9T  3.27T  7.61T    30%  1.00x  DEGRADED  -
# zpool status
  pool: dtpool
 state: DEGRADED
status: One or more devices has been taken offline by the administrator.
        Sufficient replicas exist for the pool to continue functioning in a
        degraded state.
action: Online the device using 'zpool online' or replace the device with
        'zpool replace'.
 scan: none requested
config:

        NAME                                          STATE     READ WRITE CKSUM
        dtpool                                        DEGRADED     0     0     0
          raidz1-0                                    DEGRADED     0     0     0
            /var/tmp/dummy                            OFFLINE      0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1  ONLINE       0     0     0

errors: No known data errors
# zpool replace dtpool /var/tmp/dummy scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1
リプレース中は、次のような状態になります。
リプレース開始から暫くすると転送レートが安定して、それなりの終了時間がわかるようになります。
# zpool status
  pool: dtpool
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
 scan: resilver in progress since Sun Jul  1 19:01:13 2012
    35.4G scanned out of 3.27T at 232M/s, 4h3m to go
    8.84G resilvered, 1.06% done
config:

        NAME                                            STATE     READ WRITE CKSUM
        dtpool                                          DEGRADED     0     0     0
          raidz1-0                                      DEGRADED     0     0     0
            replacing-0                                 OFFLINE      0     0     0
              /var/tmp/dummy                            OFFLINE      0     0     0
              scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1  ONLINE       0     0     0  (resilvering)
            scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1    ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1    ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1    ONLINE       0     0     0

errors: No known data errors
で、大体4時間後に完了しました。
# zpool status
  pool: dtpool
 state: ONLINE
 scan: resilvered 836G in 3h51m with 0 errors on Sun Jul  1 22:53:02 2012
config:

        NAME                                          STATE     READ WRITE CKSUM
        dtpool                                        ONLINE       0     0     0
          raidz1-0                                    ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1  ONLINE       0     0     0

errors: No known data errors
# zpool list
NAME     SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
dtpool  10.9T  3.28T  7.60T    30%  1.00x  ONLINE  -
時間はかかりましたが、特に問題なく移行完了できました。

2012年7月14日土曜日

ZFS ashift比較その4 - stripe(4台)

ZFSでの4KセクタHDD向け設定比較の最後はstripeです。

4台構成のstripeで、ashiftオプションの設定による違いを確認します。
次のようにしてpoolを作ります。
# zpool create tank \
  scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1
# zpool status
  pool: tank
 state: ONLINE
 scan: none requested
config:

        NAME                                        STATE     READ WRITE CKSUM
        tank                                        ONLINE       0     0     0
          scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1  ONLINE       0     0     0
          scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1  ONLINE       0     0     0
          scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1  ONLINE       0     0     0
          scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1  ONLINE       0     0     0

errors: No known data errors
# zdb |grep ashift
            ashift: 9
            ashift: 9
            ashift: 9
            ashift: 9
# zpool list
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
tank  10.9T  80.5K  10.9T     0%  1.00x  ONLINE  -
ashift=9の場合の結果は、次のようになります。
$ bonnie++
~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 44318  99 334959  92 139748  49 43830  95 279734  42 353.9   6
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 12951  99 +++++ +++ 13327  99 12333  99 +++++ +++ 14310  99
abcde.localdomain,15488M,44318,99,334959,92,139748,49,43830,95,279734,42,353.9,6,16,12951,99,+++++,+++,13327,99,12333,99,+++++,+++,14310,99
次はashift=12を指定してpoolを作ります。
# zpool destroy tank
# zpool create -o ashift=12 tank \
  scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1
# zdb |grep ashift
            ashift: 12
            ashift: 12
            ashift: 12
            ashift: 12
# zpool list
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
tank  10.9T   872K  10.9T     0%  1.00x  ONLINE  -
ashift=12の場合の結果は、次のようになります。
$ bonnie+++
~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 44671  99 347417  94 175133  62 44037  97 307946  47 374.0   6
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 12908  99 +++++ +++ 14430  99 11167  99 +++++ +++ 13170  98
abcde.localdomain,15488M,44671,99,347417,94,175133,62,44037,97,307946,47,374.0,6,16,12908,99,+++++,+++,14430,99,11167,99,+++++,+++,13170,98
並べるとこんな感じです。
Sequential Writeのrewriteが2割強UPして、Block Readは1割UPしています。
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
ashift=9     15488M 44318  99 334959  92 139748  49 43830  95 279734  42 353.9   6
ashift=12    15488M 44671  99 347417  94 175133  62 44037  97 307946  47 374.0   6
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
ashift=9         16 12951  99 +++++ +++ 13327  99 12333  99 +++++ +++ 14310  99
ashift=12        16 12908  99 +++++ +++ 14430  99 11167  99 +++++ +++ 13170  98
Sequential Block Write/Readは、2台構成のmirrorと比べ大体3倍になっています。

ZFS ashift比較その3 - raidz(4台)

今回は、RAIDZ構成で比較します。

4台構成のraidzで、ashiftオプションの設定による違いを確認します。
まずは、ashit=9でpoolを作ります。
# zpool create tank raidz \
  scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1
# zpool status
  pool: tank
 state: ONLINE
 scan: none requested
config:

        NAME                                          STATE     READ WRITE CKSUM
        tank                                          ONLINE       0     0     0
          raidz1-0                                    ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1  ONLINE       0     0     0

errors: No known data errors
# zdb |grep ashift
            ashift: 9
# zpool list
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
tank  10.9T   148K  10.9T     0%  1.00x  ONLINE  -
ashift=9の場合の結果は、次のようになります。
$ bonnie++
~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 45119  98 198220  54 96029  35 41985  94 353884  55 233.7   5
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 13007  99 +++++ +++ 13452  98 12167  99 +++++ +++ 14491  99
abcde.localdomain,15488M,45119,98,198220,54,96029,35,41985,94,353884,55,233.7,5,16,13007,99,+++++,+++,13452,98,12167,99,+++++,+++,14491,99
次は、ashift=12でpoolを作ります。
# zpool destroy tank
# zpool create -o ashift=12 tank raidz \
  scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1
# zdb |grep ashift
            ashift: 12
# zpool list
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
tank  10.9T  1.08M  10.9T     0%  1.00x  ONLINE  -
ashift=12の場合の結果は、次のようになります。
$ bonnie++
~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 44184  98 217651  57 120804  43 43254  93 228627  36 227.7   5
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 12981  99 +++++ +++ 13074  98 12308  99 +++++ +++ 14327  99
abcde.localdomain,15488M,44184,98,217651,57,120804,43,43254,93,228627,36,227.7,5,16,12981,99,+++++,+++,13074,98,12308,99,+++++,+++,14327,99
並べるとこんな感じになります。
Sequential Writeのrewriteが2割強UPして、Block Readが3割強DOWNしています。
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
ashift=9     15488M 45119  98 198220  54 96029  35 41985  94 353884  55 233.7   5
ashift=12    15488M 44184  98 217651  57 120804 43 43254  93 228627  36 227.7   5
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
ashift=9         16 13007  99 +++++ +++ 13452  98 12167  99 +++++ +++ 14491  99
ashift=12        16 12981  99 +++++ +++ 13074  98 12308  99 +++++ +++ 14327  99
Sequential block readで、性能ダウンするのは少し予想と違う結果になりました。
2台のmirror構成から4台のraidz構成に移行を考えているので、ashiftの設定をどちらにするか悩ましいところです。

2012年7月8日日曜日

ZFS ashift比較その2 - raid10

今回は、RAID10構成で比較します。 4台でmirror+stripeの構成を作り、ashiftオプションの設定による違いを確認します。

まずは、ashift=9から。
# zpool create tank \
  mirror scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1 \
         scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1 \
  mirror scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1 \
         scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1
# zpool status
  pool: tank
 state: ONLINE
 scan: none requested
config:

        NAME                                          STATE     READ WRITE CKSUM
        tank                                          ONLINE       0     0     0
          mirror-0                                    ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1  ONLINE       0     0     0
          mirror-1                                    ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1  ONLINE       0     0     0

errors: No known data errors
# zdb |grep ashift
            ashift: 9
            ashift: 9
# zpool list
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
tank  5.44T   110K  5.44T     0%  1.00x  ONLINE  -
ashift=9のbonnie++の結果は、次のようになります。
# bonnie++
~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 45686  99 190095  60 99181  36 43745  93 192523  32 335.0   6
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 12889  97 +++++ +++ 14336  99 12505  99 +++++ +++ 14838  99
abcde.localdomain,15488M,45686,99,190095,60,99181,36,43745,93,192523,32,335.0,6,16,12889,97,+++++,+++,14336,99,12505,99,+++++,+++,14838,99

次は、ashift=12。
# zpool destroy tank
# zpool create -o ashift=12 tank \
  mirror scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1 \
         scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1 \
  mirror scsi-SATA_ST3000DM001-9YN_Z1F0CCCC-part1 \
         scsi-SATA_ST3000DM001-9YN_Z1F0DDDD-part1
# zdb |grep ashift
            ashift: 12
            ashift: 12
# zpool list
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
tank  5.44T   110K  5.44T     0%  1.00x  ONLINE  -
ashift=12の結果は、次のようになります。
# bonnie+++
~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 44152  99 240200  74 112329  42 44438  95 195719  32 342.1   6
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 12948  99 +++++ +++ 13296  98 12095  99 +++++ +++ 14483  99
abcde.localdomain,15488M,44152,99,240200,74,112329,42,44438,95,195719,32,342.1,6,16,12948,99,+++++,+++,13296,98,12095,99,+++++,+++,14483,99

並べるとこんな感じになります。
Sequential Writeが2割強UPしてるのが目立ちます。
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
ashift=9     15488M 45686  99 190095  60 99181  36 43745  93 192523  32 335.0   6
ashift=12    15488M 44152  99 240200  74 112329 42 44438  95 195719  32 342.1   6
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
ashift=9         16 12889  97 +++++ +++ 14336  99 12505  99 +++++ +++ 14838  99
ashift=12        16 12948  99 +++++ +++ 13296  98 12095  99 +++++ +++ 14483  99
前回の2台構成のmirrorと比べるとRAID1とRAID10の比較になるので予想通りですが、Sequential Read/Writeがほぼ2倍になっていることが分かります。

2012年7月7日土曜日

ZFS ashift比較その1 - mirror(2台)

4KBセクタのHDDを使用しているHP ProLiant MicroServer, CentOS 6.2, ZFS on Linuxという環境で、ashiftの設定による性能を比較します。
環境はこんな感じです。
$ uname -r
2.6.32-220.23.1.el6.x86_64
$ rpm -q zfs-* spl-*
zfs-0.6.0-rc8.x86_64
spl-0.6.0-rc8.x86_64

まずは、今まで使用していた2台構成のmirrorで、ashiftオプションの設定による違いを確認します。

ashiftには、512byteセクタの場合は9、4096byteの場合は12を指定することになります。

こんな感じでpoolを作ります。
Seagate ST3000DM001は、論理セクタサイズを512byteと返すので、デフォルトだとashiftは9が使用されるようです。
# zpool create tank mirror \
  scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1
# zdb |grep ashift
            ashift: 9
# zpool list
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
tank  2.72T   552K  2.72T     0%  1.00x  ONLINE  -
#
ashift=9の場合の結果は、次のようになりました。
# bonnie++
~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 45832  99 114327  36 47687  20 41445  90 93675  16 265.3   4
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 13073  99 +++++ +++ 14567  99  7688  99 +++++ +++  5378  99
abcde.localdomain,15488M,45832,99,114327,36,47687,20,41445,90,93675,16,265.3,4,16,13073,99,+++++,+++,14567,99,7688,99,+++++,+++,5378,99

次は、4096byte用の設定を試します。
pool作製時に、-o ashift=12を指定します。
# zpool destroy tank
# zpool create -o ashift=12 tank mirror \
  scsi-SATA_ST3000DM001-9YN_Z1F0AAAA-part1 \
  scsi-SATA_ST3000DM001-9YN_Z1F0BBBB-part1
# zdb |grep ashift
            ashift: 12
# zpool list
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
tank  2.72T   552K  2.72T     0%  1.00x  ONLINE  -
#
ashift=12の場合の結果は、次のようになりました。
# bonnie++
~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 43242  99 135921  41 58642  24 43621  93 105678  19 284.4   5
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 12874  99 +++++ +++ 14309  99 11690  99 +++++ +++ 13996  99
abcde.localdomain,15488M,43242,99,135921,41,58642,24,43621,93,105678,19,284.4,5,16,12874,99,+++++,+++,14309,99,11690,99,+++++,+++,13996,99
結果を並べるとこんな感じになります。
Sequrntial Block Write/Readが大体1,2割性能UPしています。
Per charは、まあそんな感じかという値ですが、Random Create/Delteは、面白い結果ですね。
                    ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
ashift=9     15488M 45832  99 114327  36 47687  20 41445  90 93675  16 265.3   4
ashift=12    15488M 43242  99 135921  41 58642  24 43621  93 105678 19 284.4   5
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
ashift=9         16 13073  99 +++++ +++ 14567  99  7688  99 +++++ +++  5378  99
ashift=12        16 12874  99 +++++ +++ 14309  99 11690  99 +++++ +++ 13996  99
それぞれの設定についてbonnie++で数回計測したところ、大体同じような結果になったので初回実行時の結果を載せています。

2012年6月30日土曜日

ProLiant MicroServerにHDDを追加する

現在、HP ProLiant MicroServerに2台のHDDを入れてZFSのmirrorで使用しています。
使用しているHDDは、Seagate ST3000DM001で、4Kセクタのドライブです。

セットアップ時に、partedの情報で論理セクタサイズが512バイトに見えている事は分かっていましたが、SmartAlign技術が搭載されていたはずだということで気にしていませんでした。
が、ZFSで4Kセクタ向けの設定をすれば、もう少し性能が出るのでは?と今更ながら思いつきました。

調べるまでも無く、ZFS on LinuxのFAQにAdvanced Formet Drivesについての記述がありましたよ。
そう言えば、セットアップのときは、Write Cacheの件で面倒くさくなって適当に切り上げたんだった…。

もう少しHDDの値段が下がるのを待てばよかったんですが、結局、ST3000DM001を追加で買ってしまったので、軽く性能を比べてからmirrorからraidzに移行しようと思います。

2012年6月2日土曜日

ワンセグ野郎 with ProLiant MicroServer

少し間が空きましたが実験の続きです。

ZFS on Linuxでmirror設定のプールにDeduplicationを有効にして、ワンセグ野郎を動作させ8ch分のTSデータの記録を始めました。
約一日動かして様子をみるとワンセグ野郎だけ動作させた状態だと、いつものサイズ(188,70x,xxx ±188byte数個分)で安定してTSファイルを書き込むことができるようです。

しかし、ファイルサーバとしても使う予定なので、ワンセグ野郎が安定動作するだけでは足りません。
次は、ワンセグ野郎を動かしつつ、旧PCに溜まった約900MBのTSファイルをrsyncして負荷をかけます。

…しばらく動かしていると、dvbstreamが終了してしまいました。ts.plによって起動し直されるので、定期的に再起動を繰り返します。
どうも字幕データの取り込み処理が動くタイミングでdvbstreamが終了してしまうようですが、当該処理をcronから外しても、タイミングがずれるだけでdvbstreamはやはり終了してしまうため、直接原因というわけではなさそうです。

結局、dvbstreamにstraceかけ、ざっとソースを見てもあたりが付かず、ライブデバックするまでのモチベーションも無かったので原因特定は諦めました。(タイミングの問題っぽくて、面倒くさそうだったのもあります)

で、Deduplicationを無効にして再開すると、問題なくrsyncが完了したのでこの設定で運用することにしました。

zdbの情報によると、TSデータでは、Deduplicationの効果はあまりでないようです。
# zdb -S dtpool
Simulated DDT histogram:

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     1    7.48M    950G    950G    950G    7.48M    950G    950G    950G
     2    1.27K   84.9M   84.9M   84.9M    2.89K    175M    175M    175M
     4      283   1.26M   1.26M   1.26M    1.32K   6.77M   6.77M   6.77M
     8      110    882K    882K    882K    1.09K   8.42M   8.42M   8.42M
    16        8    132K    132K    132K      182   3.09M   3.09M   3.09M
    32        1     512     512     512       42     21K     21K     21K
    64        1     512     512     512       78     39K     39K     39K
 Total    7.48M    950G    950G    950G    7.49M    950G    950G    950G

dedup = 1.00, compress = 1.00, copies = 1.00, dedup * compress / copies = 1.00

2012年5月19日土曜日

ZFSの機能を試す

HP ProLiant MicroServerにZFS on Linuxをセットアップしたので、本格的に移行する前に機能を試してみました。
BIOSでSATAのDrive Write Cacheを有効にしないとWriteが遅すぎて駄目でしたので、この設定を有効にして試すことにします。

ワンセグ野郎とファイルサーバとして使う予定なので、容量の有効利用としてDeduplication、Compressionが使えればいいなと思っています。あとは、Shapshots、ディスク管理の柔軟性も魅力です。

ベンチマークには、bonnie++を使用することにしたので、最新版の1.03eをインストールします。
SPECファイルがついてるのでRPMでインストールできますが、書式が古いようなので修正する必要があります。
$ gzip -d bonnie++-1.03e.tgz
$ ls
bonnie++-1.03e.tar
$ rpmbuild -ta bonnie++-1.03e.tar
error: line 5: Unknown tag: Copyright: GPL
となるので、SPECファイルの5行目にあるCopyrightタグをLicenseに編集すればOKです。

次の環境でベンチマークを取ります。
$ cat /etc/redhat-release
CentOS release 6.2 (Final)
$ uname -mrsv
Linux 2.6.32-220.13.1.el6.x86_64 #1 SMP Tue Apr 17 23:56:34 BST 2012 x86_64
# zpool list
NAME     SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
dtpool  2.72T   136K  2.72T     0%  1.00x  ONLINE  -
# zpool status
  pool: dtpool
 state: ONLINE
 scan: resilvered 85.5K in 0h0m with 0 errors on Sat May 12 00:11:40 2012
config:

        NAME                                          STATE     READ WRITE CKSUM
        dtpool                                        ONLINE       0     0     0
          mirror-0                                    ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_ABCD1234-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_EFGH5678-part1  ONLINE       0     0     0

errors: No known data errors
まずは、Deduplicationなしで測定します。
# zfs set dedup=off dtpool

$ bonnie++
 ~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 45557  99 100987  32 68528  24 43526  93 219130  39 251.7   3
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 13168  96 +++++ +++ 14296  99 12609  99 +++++ +++ 14937  99
abcde.localdomain,15488M,45557,99,100987,32,68528,24,43526,93,219130,39,251.7,3,16,13168,96,+++++,+++,14296,99,12609,99,+++++,+++,14937,99
$
次に、Deduplicationありで測定します。
# zfs set dedup=on dtpool

$ bonnie++
 ~ 略 ~
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
abcde.locald 15488M 42486  97 31812  20 24758  31 43788  95 101344  13 213.5   3
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16 14201  99 +++++ +++ 13835  98 12326  97 +++++ +++ 12738  98
abcde.localdomain,15488M,42486,97,31812,20,24758,31,43788,95,101344,13,213.5,3,16,14201,99,+++++,+++,13835,98,12326,97,+++++,+++,12738,98
$
Deduplicationを有効にすると、Writeが1/3、Readも1/2になるようです。
うーん、予想以上の劣化具合です。CPUが非力な性でしょうか、Compressionは諦めることにしました。

取り合えず、Deduplicationを有効にしてワンセグ野郎を動かすことにしました。負荷をかけて様子を見てみます。

ZFS on CentOS

HP ProLiant MicroServerにCentOS6をセットアップし、ZFS on Linuxをインストールしました。
ZFSのLinux実装には、FUSE版もありますが、今使用するならやっぱりカーネルモジュール版でしょう。

ということで、ZFS on Linuxから最新版のspl-0.6.0-rc8とzfs-0.6.0.rc8を使用しました。
インストールは、SPLZFSに書かれているとおりで問題なしです。
インストール後は、こんな感じになります。
$ grep zfs /proc/filesystems
nodev   zfs
$ lsmod |grep -E '(zfs|spl)'
zfs                  1075574  3
zcommon                42648  1 zfs
znvpair                47487  2 zfs,zcommon
zavl                    6925  1 zfs
zunicode              323120  1 zfs
spl                   256427  5 zfs,zcommon,znvpair,zavl,zunicode
zlib_deflate           21629  1 spl
準備ができたので、HDDを設定していきます。
パーティション情報を確認すると、こんな感じになります。
# parted -l
Error: /dev/sda: unrecognised disk label

Error: /dev/sdb: unrecognised disk label

Model: ATA VB0250EAVER (scsi)
Disk /dev/sdc: 250GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
~ 略 ~
ODDポートに接続したHDDにOSをインストールしてあり/dev/sdcと認識されています。
/dev/sdaと/dev/sdbをZFSで使用するため、次のようにGNU partedでディスクラベルとパーティションを設定します。
# parted /dev/sda
GNU Parted 2.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) mklabel gpt
(pqrted) print
Model: ATA ST3000DM001-9YN1 (scsi)
Disk /dev/sda: 3001GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt

Number  Start  End  Size  File system  Name  Flags

(parted) mkpart primary 1M 3000GB
(parted) print
Model: ATA ST3000DM001-9YN1 (scsi)
Disk /dev/sda: 3001GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt

Number  Start   End     Size    File system  Name     Flags
 1      1049kB  3000GB  3000GB               primary

(parted) quit
Information: You may need to update /etc/fstab.

#
同様に/dev/sdbも設定しておきます。

さて、いよいよZFSの設定です。まずは、ストレージプールを作成します。
まずは、/dev/disk/by-id配下を参照して、/dev/sda1にリンクされている名前を調べます。
$ cd /dev/disk/by-id
$ ls -l scsi*part1
~ scsi-SATA_ST3000DM001-9YN_ABCD1234-part1 -> ../../sda1
~ scsi-SATA_ST3000DM001-9YN_EFGH5678-part1 -> ../../sdb1
~ scsi-SATA_VB0250EAVER_IJKL9012-part1 -> ../../sdc1
この情報を利用して、次のようにストレージプールを作成します。
# zpool create dtpool scsi-SATA_ST3000DM001-9YN_ABCD1234-part1
# zpool list
NAME     SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
dtpool  2.72T    79K  2.72T     0%  1.00x  ONLINE  -
# zpool status
  pool: dtpool
 state: ONLINE
 scan: none requested
config:

        NAME                                        STATE     READ WRITE CKSUM
        dtpool                                      ONLINE       0     0     0
          scsi-SATA_ST3000DM001-9YN_ABCD1234-part1  ONLINE       0     0     0

errors: No known data errors
dtpoolという名前で、ストレージプールが作成されたことが確認できます。
ストレージプールには、tankという名前がよく使われるようです。
次に、mirrorで使用するため、次のように/dev/sdb1をストレージプールのsda1にアタッチします。
# zpool attach dtpool scsi-SATA_ST3000DM001-9YN_ABCD1234-part1 scsi-SATA_ST3000DM001-9YN_EFGH5678-part1
# zpool list
NAME     SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
dtpool  2.72T   136K  2.72T     0%  1.00x  ONLINE  -
# zpool status
  pool: dtpool
 state: ONLINE
 scan: resilvered 85.5K in 0h0m with 0 errors on Sat May 12 00:11:40 2012
config:

        NAME                                          STATE     READ WRITE CKSUM
        dtpool                                        ONLINE       0     0     0
          mirror-0                                    ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_ABCD1234-part1  ONLINE       0     0     0
            scsi-SATA_ST3000DM001-9YN_EFGH5678-part1  ONLINE       0     0     0

errors: No known data errors
これで、2台構成のmirrorでストレージプールが作成されました。
ストレージプールがマウントされていることを確認できます。
# df -h
 :
dtpool                2.7T     0  2.7T   0% /dtpool
ストレージプールにZFSファイルシステムを作成します。
今回は、ワンセグ野郎のTSデータ格納用の領域を作成することにします。
# zfs create dtpool/ts
次のように、マウントポイントを/data/tsに変更してマウントし直します。
# mkdir /data
# zfs set mountpoint=/data/ts dtpool/ts
# df -h
 :
dtpool                2.7T  128K  2.7T   1% /dtpool
#
# zfs mount -a
# df -h
 :
dtpool                2.7T  128K  2.7T   1% /dtpool
dtpool/ts             2.7T  128K  2.7T   1% /data/ts
以上で/data/tsを使い始めることができます。
zpool、zfsコマンドは長くても数十秒でプロンプトが返ってくるし、mkfsする必要もないので楽々です。

初めて使うファイルシステムなので、少し実験してからデータ移行しようと思います。

2012年5月14日月曜日

HP ProLiant MicroServer購入

ワンセグ野郎を使い始めて3ヶ月、ファイルサーバとしても使っているPCなので、毎日ガリガリ書き込みをしているHDDの故障が心配になってきました。
という分けで、壊れる前にHP ProLiant MicroServerを購入して、移行することにしました。

構成は、次のような感じです。
  • HP ProLiant MicroServer (AMD Turion II NEON40L, HDD 250GB, メモリ2GB)
  • Seagate ST3000DM001 ×2個(3TB×2)
  • SanMax SMD-8G68EHP-13H-D ×1個(4GB×2)
HDD価格がまだ高いですが3TBのHDDを2台、ECCメモリ8GBで組むことにしました。
SATAカードと外付けHDDケースで増設も考えたのですが、結局新しくPCを買ったほうが安く上がるという。
CentOS+ZFSでセットアップする予定です。

2012年5月3日木曜日

ISDB-T Digital TV Receiver 再び

DealExtremeから購入していた予備用のISDB-T Digital TV Receiverの動作確認をしました。
しばらく使用しているとデータが取れなくなる問題の件で、故障を疑って追加購入したものの、物が届くまでの間に対処法を見つけたので開梱だけして放っておいた物です。

追加購入した全てがSianoチップでしたが、Nova BとNiceが混在してました。
lsusbの結果は、次のとおり。
Bus 002 Device 003: ID 187f:0201 Siano Mobile Silicon Nova B
Bus 002 Device 004: ID 187f:0202 Siano Mobile Silicon Nice
初回購入時は、たまたま全てNiceだったんでしょうかね。
何れにせよ、使えるチップだったのでよかった。

2012年4月30日月曜日

字幕検索 その3

検索機能は、検索対象を番組情報と字幕情報の2つから選んで検索できるようにして利用しています。
番組情報の検索は、単純にLIKE演算子を使用して、字幕情報の検索ではブール全文検索を使用しています。

次のようにして字幕検索結果のリスト表示をしています。
my $query = 'バイク -自転車';
search_caption($query);

sub search_caption()
{
        my $query = shift @_;
        my $sql = <<END;
select
        c.dc_name,
        c.dc_ch,
        e.dv_start_time,
        date_format(addtime(e.dv_start_time, e.dv_duration), '%H%i%s'),
        e.dv_duration,
        e.dv_name,
        e.dv_favorite,
        timediff(a.dp_start_time, e.dv_start_time),
        time_to_sec(timediff(a.dp_start_time, e.dv_start_time)),
        a.dp_text
from
        da_caption as a
        inner join
                (da_event as e
                        inner join
                                da_channel as c
                        on
                                c.dc_network_id = e.dv_original_network_id
                        and
                                c.dc_service_id = e.dv_service_id
                )
        on
                a.dv_id = e.dv_id
where
        match(a.dp_text) against(? in boolean mode)
order by e.dv_start_time desc
END

        my $dsn = 'DBI:mysql:database=oneseg24;host=localhost';
        my $dbh = DBI->connect($dsn, 'user', 'password', {RaiseError => 1, AutoCommit => 0, mysql_enable_utf8 => 1});

        my $sth = $dbh->prepare($sql);
        my $rv = $sth->execute("${query}");

        my %program = ();
        my @order = ();

        while (my $ref = $sth->fetch()) {
                my @tmp = @$ref;

                my $key = "$tmp[1]-$tmp[2]";
                if ($#{$program{$key}} < 0) {
                        push(@order, $key);
                }

                push(@{$program{$key}}, [@tmp]);
        }

        $dbh->disconnect();

        print "
    = 29); print ">\n"; printf "

    %d件の一致、キーワード: %s

    < br />\n", $#order+1, $query; foreach my $k (@order) { my $i = 0; foreach my $a (sort {$a->[8] <=> $b->[8]} @{$program{$k}}) { my ($dc_name, $dc_ch, $dv_start_time, $end_time, $dv_duration, $dv_name, $dv_favorite, $dp_offset, $dp_offset_sec, $dp_text) = @$a; my $t = Time::Piece->strptime($dv_start_time, "%F %T"); my $start_time = $t->strftime("%y%m%d-%H%M%S"); my $link = join("-", ($start_time, $end_time, $dc_ch)); if ($i++ == 0) { print "<li"; print " data-icon='star'" if ($dv_favorite); print ">"; print "

    $dv_name

    "; print "

    $dc_name $dv_start_time ($dv_duration)

    \n"; } print "

    $dp_offset\t$dp_text

    \n"; } print "
    \n"; } print "
\n"; }
特に変わった処理はしていませんが、お気に入りフラグ(dv_duration)が立っている番組は、アイコンを☆マークに変えています。(以前に書いたかもしれませんが、jQuery Mobileを利用しています。)
また、お気に入りフラグが立っている番組は、ディスクの空き容量確保のためのデータ自動削除処理で、削除対象から除外されるようにしています。

<pre>タグ内で、<br />がうまく記述できないので、表記が少しおかしくなっています。

2012/5/1追記)
Internet Explorerで表示が崩れていたので修正しました。
<pre>~</pre>内でも、HTMLタグを解析するような動作をしているようなので、一部<を&lt;としました。

2012年4月21日土曜日

字幕検索 その2

字幕検索のつづき、データの入れ込み部分についてです。

字幕データの取り出しは、ぱぱネット(仮)さんのdumpeit最新版20110718を使わせてもらうことにしました。 TSの切り出しやEPGの取出しができたりと高機能なのでreq.plやepg.plを置き換えるのがスマートな気がしますが、既にts.plやepg.plを弄っちゃってるので、字幕データの取り出し機能だけ利用することにしました。

次のようなオプションでdumpeitを実行すると、拡張子が.subの字幕ファイルが生成されるので、その内容をDBに取り込むことにします。
dumpeit -f TSファイル
字幕ファイルからDBへのデータ取り込みは、次のように処理しています。
my $sql = make_sql('/path/to/xxxx.sub');
if (defined $sql) {
        store_data($sql);
}

sub make_sql()
{
        my ($file) = shift @_;

        if (!-e $file or -z $file) {
                return undef;
        }

        if ($file !~ /(\d{8})_Ch(\d+)\.sub$/) {
                return undef;
        }
        my $dt = $1;
        my $ch = $2;

        my $t = Time::Piece->strptime($dt, "%y%m%d%H");
        my $date = $t->ymd;


        my @sql = ();
        open my $fh, "<", $file or do {
                return undef;
        };

        my ($t1, $t2, $dv_id) = (undef, undef, undef);
        while (my $line = <$fh>) {
                chomp($line);
                my ($tmp, $msg) = split(/\s/, $line, 2);
                my ($tm, $pid_s) = split(/\./, $tmp);

                my $t = Time::Piece->strptime("$date $tm", "%F %T");

                if (!defined $dv_id or !($t1 <= $t and $t <= $t2)) {
                        my ($id, $stime, $etime) = find_event($ch, "$date $tm");
                        if (defined $id) {
                                $t1 = Time::Piece->strptime($stime, "%F %T");
                                $t2 = Time::Piece->strptime($etime, "%F %T");
                        }
                        $dv_id = $id;
                }

                push @sql, sprintf "($ch, '$date $tm', $pid_s, '$msg', %s)", $dv_id ? $dv_id : "NULL";
        }
        close($fh);

        if ($#sql < 0) {
                return undef;
        }

        my $sql_header = 'INSERT INTO da_caption ';
        $sql_header .= '(dc_ch, dp_start_time, dp_pid, dp_text, dv_id) VALUES ';

        return $sql_header . join(',', @sql);
}
データをそのまま入れているだけですが、検索結果を表示するときに番組情報を調べやすくするために、次の処理で番組データとの関連を追加しています。
sub find_event
{
        my ($ch, $date) = @_;

my $sql = <<END;
select
        e.dv_id,
        e.dv_start_time,
        addtime(e.dv_start_time, e.dv_duration)
from
        da_event as e
        inner join
                da_channel as c
        on
                e.dv_service_id = c.dc_service_id
where
        e.dv_start_time <= ?
and
        ? < addtime(e.dv_start_time, e.dv_duration)
and
        c.dc_ch = ?
order by
        e.dv_start_time
limit
        1
END

        my $dbh = dbiConnect();

        my ($sth, $rv) = ();
        eval {
                $sth = $dbh->prepare($sql);
                $rv = $sth->execute($date, $date, $ch);
        };

        return undef if ($@);
        my @events = ();
        while (my $ref = $sth->fetch()) {
                my ($dv_id, $start_time, $end_time) = @$ref;
                push(@events, [$dv_id, $start_time, $end_time]);
        }

        dbiDisconnect($dbh);

        if ($#events < 0) {
                return undef;
        }

        return @{$events[0]};
}
コミット処理は、次のようにしています。
字幕データ用のテーブルは、MyISAMなので意味が無い気がしますが、その他のテーブルはInnoDBで利用しているので処理を共通化しています。 
sub store_data
{
        my ($sql) = shift @_;

        my $dbh = dbiConnect();

        my $retry=3;
        while ($retry--) {
                eval {
                        my $ddh = $dbh->prepare($sql);
                        my $rv = $ddh->execute();

                        $dbh->commit();
                };
                last if (!$@);
                my $rnd = int(rand(10)) +1;
                my $st = 100000 * $rnd;
                printf STDERR "sleep %.1fs, retry(%d)", $st/1000000, $retry;
                usleep($st);
        }
        if ($retry < 0) {
                print STDERR "store-caption was give up.";
        }

        dbiDisconnect($dbh);

        return !$@;
}
あまり考えないでコーディングを始めてしまうので、テーブル構成がイマイチとか後から思ったりしたのですが…遊びなので結局そのままです。

こんな感じでスクリプト一つ作り、一時間毎にTSデータから字幕データをDBに取り込んで、約24日分の番組情報のデータ量は以下のようになっています。 
mysql> select count(*) from da_caption;
+----------+
| count(*) |
+----------+
|  1195794 |
+----------+
1 row in set (0.00 sec)

mysql> select count(*) from da_event;
+----------+
| count(*) |
+----------+
|     8436 |
+----------+
1 row in set (0.00 sec)

mysql>
この状態で字幕検索を行っても、今のところ一秒以内に結果が返ってくるので、CGIからの読み出しでもストレス無く使えています。

2012年4月14日土曜日

字幕検索 その1

EPGデータから番組名と番組情報の検索は出来るようにして使っていましたが、少し物足りなくなってきたので、字幕データも突っ込んで全文検索できるようにしてみました。
# MySQLで全文検索を試してみたかったんです。

CentOS 6を利用しているので、MySQLは下記のバージョンを使用しています。

% rpm -q "mysql-*"
mysql-5.1.61-1.el6_2.1.x86_64

MySQLで日本語の全文検索をするために、MySQL full-text parser plugin collectionmecab pluginを使ってみることにしました。
上記のソフトを付属のINSTALLファイルを参照して、インストールします。
ロケールにUTF8を使用しているので、mecab-0.993, mecab-ipadic-2.7.0-20070801のconfigureのオプションに --with-charset=utf8 を指定する必要がありました。(デフォルトはEUC)

取りあえず、こんな感じでテーブルを作ると、
create table da_caption (
        dp_id integer primary key NOT NULL AUTO_INCREMENT,
        dc_ch integer,
        dp_start_time timestamp,
        dp_pid integer,
        dv_id integer,
        dp_text text
        ) engine = myisam DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

create index da_caption_index on da_caption (dp_start_time, dc_ch);
create fulltext index da_caption_fulltext_index on da_caption (dp_text) with parser mecab;
次のような検索できるようになります。
mysql> select * from da_caption where match(dp_text) against('バイク -自転車' in boolean mode) limit 5;
+---------+-------+---------------------+--------+--------+--------------------------------------------------------------------------------------------+
| dp_id   | dc_ch | dp_start_time       | dp_pid | dv_id  | dp_text                                                                                    |
+---------+-------+---------------------+--------+--------+--------------------------------------------------------------------------------------------+
| 2337207 |    27 | 2012-03-31 16:19:30 |   1415 | 190710 | 同じ排気量のバイクに乗るため→                                                              |
| 2337241 |    27 | 2012-03-31 16:22:40 |   1415 | 190710 | でも ほとんど バイクのパーツ代に消えてしまうんだそうです。                               |
| 2399738 |    23 | 2012-04-01 19:54:08 |   4231 | 194390 | 知人らしきバイクの女性が颯爽と登場。                                                       |
| 2380118 |    21 | 2012-04-01 13:01:38 |    340 | 193580 | <ベトナムは バイク大国>                                                                 |
| 2380122 |    21 | 2012-04-01 13:02:03 |    340 | 193580 | <バイクの多い…>                                                                         |
+---------+-------+---------------------+--------+--------+--------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

2012年4月12日木曜日

USBポートの電源制御

ワンセグ野郎を始めて2ヶ月位経ちますが、3回ほどdvbstreamからデータを取れなくなって停止していることがありました。
dvbstream起動時に、次のようなメッセージを出力しているので、信号を受信できない状態になるようです。

Bit error rate: 0
Signal strength: 0
SNR: 0
FE_STATUS:
Setting filter for PID 8192
FILTER 8192: DMX SET PES FILTER: Connection timed out

こうなってしまうとUSBデバイスを抜き差ししないと回復しません。
USBデバイスへの電源On/Offでよさそうなのですが、リブートしてもUSBデバイスへの給電は切れないようなので、USBポートの電源制御をする必要があるようです。

USBコントローラーが電源制御をサポートしていれば、ソフト的に制御できることが分かったのですが、残念ながら使用しているマザーボードでは未サポートでした。

さらに調べるとポート毎に電源制御ができるUSB HUBがあり、Linux向けのソフト(節電USB・HUB(U2H-SW4)の制御ソフト)を公開している方を見つけました。
作者の方は、sianoチップ利用のワンセグ野郎ユーザーのようで、同じ症状改善のために書かれたようです。すばらしい。

早速、コンパイルして使用してみましたが、私の環境ではそのままでは上手く動きませんでした。
HUBの仕様変更を疑ってSnoopyProでデータを確認したり、あれこれ調べたところ、/dev/hidrawXとの送受信データの先頭に1byte付けてあげる(レポートID用?)と上手く動くことが分かりました。

で、ts.plに組み込みたかったので、perlで書いてみました。

set_status('/dev/hidraw0', 1, 0);  # hidraw0のポート1の電源OFF
usleep((1000000*0.3));
set_status('/dev/hidraw0', 1, 1);  # hidraw0のポート1の電源ON

sub set_status()
{
        my ($file, $port_num, $power) = @_;

        sysopen my $fh, $file, O_RDWR|O_NONBLOCK or do {
                print STDERR "cannot open $file: $!\n";
                return 0;
        };

        my @set_status = (0,0x03,0x5d,0,0,0,0,0,0);

        if ($port_num == 1) {
                $set_status[4] = 0x05;
        }
        elsif (1 < $port_num and $port_num < 5) {
                $set_status[4] = int($port_num);
        }
        else {
                return 0;
        }

        $set_status[5] = 0x01 if ($power);

        my $dat = pack("C9", @set_status);
        my $r = syswrite $fh, $dat, 9;

        if ($r != 9) {
                print STDERR "syswrite failed: f=$file, p=$port_num: $!\n";
                return 0;
        }
        close $fh;
}

U2H-SW4は、lsusbで確認するとUSB portを5つ持っていて、USB port1がHIDになっているようです。
USB port5が機器に印刷されている1番ポートに対応しています。

ポートの状態確認は、次のようにして取得できます。
4byte目の該当するビットが立っている場合は、電源Onを表しています。

my $port = get_status("/dev/hidraw0");
print "$file\n";
foreach my $i (0..3) {
        my $on = $port & (1<< $i);
        printf " port%d: %s\n", $i+1, $on ? "On" : "Off";
}

sub get_status()
{
        my ($file) = shift @_;

        sysopen my $fh, $file, O_RDWR|O_NONBLOCK or do {
                print STDERR "cannot open $file: $!\n";
                return undef;
        }

        my @get_status = (0,0x03,0x5d,0x02,0,0,0,0,0);

        my $dat = pack("C9", @get_status);
        my $r = syswrite $fh, $dat, 9;

        my ($rout, $info) = (undef, undef);
        my $rin = '';
        vec($rin, fileno($fh), 1) = 1;
        my ($nfound, $timeleft) = select($rout=$rin, undef, undef, 3);

        $r = read $fh, $info, 9;
        close $fh;

        return undef if ($r != 9);

        my @st = unpack("C9", $info);
        if (($st[3] & 0xc3) != 0x03 and $st[5] == 0x75) {
                printf STDERR "unknown data received: %s\n", unpack("H*", $info);
                return undef;
        }

        my ($port, $i) = (0, 0);
        foreach my $flg (0x20, 0x04, 0x08, 0x10) {
                $port |= (1 << $i) if ($st[3] & $flg);
                $i++;
        }
        return $port;
}
ts.plに組み込むにあたり、dvbstreamで使用しているDVBデバイスが接続しているU2H-SW4を見つける必要があります。
もっとスマートな方法があると思いますが、udevadmコマンドでdevpathを調べることで接続しているU2H-SW4とHUB portを特定できました。

U2H-SW4のHIDは、次のように/dev/hidraw*からベンダー/プロダクトコードが一致するものを調べ、udevadmコマンドでdevpathを取得しておきます。
説明用のコードでは、見やすさのためにエラー処理はdie()にしました。
sub find_u2hsw4()
{
        my $HIDIOCGRAWINFO = 0x80084803;

        opendir my $dh, '/dev' or die "cannot opendir /dev: $!";
        my @files = sort grep /^hidraw\d+$/, readdir($dh);
        closedir $dh;

        my @target = ();
        foreach my $f (@files) {
                my $file = "/dev/$f";
                my $info = undef;

                open my $fd, '+<', $file or die "cannot open $file: $!";
                ioctl($fd, $HIDIOCGRAWINFO, $info) or die "ioctl failed: $file: $!";
                close $fd;

                my ($busy, $vendor, $product) = unpack("Iss",$info);

                # find ActionStar USB HID
                if ($vendor == 0x2101 and ($product & 0xffff) == 0x8501) {
                        my $path = `/sbin/udevadm info --query=path --name=$file`;
                        chomp($path);
                        $path =~ s!/hidraw/${f}$!!;
                        push @target, [$file, $path];
                }
        }

        return @target;
}
上記で見つけたHIDのdevpathと、dvbstreamで使用している/dev/dvb/adapterX/frontendXのdevpathを調べることにより、接続しているHUBとHUB portを見つけることが出来ます。

ts.plでdvbstreamにSIGTERMを送った後、dvbstreamのログから直近でSNR: 0を見つけた場合に、電源をOn/Offするようにして使ってます。

この記事からSyntaxHighlighter を設定してみました。

2012年3月31日土曜日

iPhone4S購入

メインにAu携帯、データ通信用にEMOBILE携帯を使っていましたが、iPhone4Sが安かったのでEMOBILEをMNPしました。

32GBモデルが実質ではなく一括価格で9,800円、Auポイントが溜まってたので1,400円で購入となりました。
本当は、3年使ったメイン携帯を機種変更したかったのですが、機種変更では安くならないとのこと。機種変更でも使用年数で割引率を変えてもいいんじゃないの?と思う。

テザリングはできなくなりましたが、iPodを持ち歩かなくてすむ分荷物が少なくなったので良しとするか。

2012年3月29日木曜日

マルチ編成のTS

iPadでTOKYO MXが再生できなくなった件ですが、iOS5.1のアップデートでMPEG-2 TSの処理が変わったのが原因のようです。
アップデート前は、多重化された番組を含むTS(多重化されたストリーム?)については、主番組を再生してくれていたようですが、アップデート後は再生しなくなったようです。

ワンセグでは、PMT(Program Map Table)が、0x1fc8を主番組とし、副番組は0x1fc9~0x1fcfになるようなので、試しにts.cgiで $ts->{pid} が0x1fc9のパケットを出力しないようにしてみると、以前のように再生できるようになりました。

取りあえず、目処は立ったのでもう少し調べてマルチ編成の番組を再生できるようにしてみようかと思います。

2012年3月26日月曜日

TOKYO MXが再生できなくなった

iPadで便利に使用していたのですが、TOKYO MXの番組が全て再生できなくなっていることに気が付きました。
最初は、TSファイルが壊れたのかと疑ったのですが、JW PlayerやアップデートしていないiPod touchでは再生できるので、TSファイルが壊れているわけではなさそうです。
どうやらiOS5.1にアップデートしたのが原因のようなのですが…困ったなぁ。

2012年3月3日土曜日

iPad対応

oneseg24 for LinuxのOneSeg24foriPhone.tar.gzを利用すれば、iPadでワンセグ野郎を使用できるようになります。
表示サイズの変更やシークの操作も、HTML5のvideoタグを使用すればできます。
Safari HTML5 Audio and Video Guideを参考に、次のようなHTMLを出力すればOKです。

<video width="427" height="240" src="m3u8.cgi?XXXXXX-XXXXXX-XXXXXX-XX" controls></video>

上記の<video>エレメントのheight, widthプロパティで縦横のサイズを、currentTimeプロパティで再生位置を変えることができます。
また、jQuery Mobileを使えば、タッチパネル操作もしやすいものになって便利です。

2012年2月18日土曜日

MySQL対応

取りあえず動くようにできました。
DATABASE_NAME, USER_NAME, PASSWORDは適当に読み替えてください。
MySQLのテーブル作成時に、da_channel, da_event, da_genreのプライマリキーにNOT NULL AUTO_INCREMENTを追加しました。

--- epg.pl.orig 2009-01-25 16:32:56.000000000 +0900
+++ epg.pl      2012-02-18 12:03:30.000000000 +0900
@@ -190,7 +190,7 @@
 and
        ? <= dv_start_time
 and
-       dv_start_time < datetime(?, ?)
+       dv_start_time < addtime(?, ?)
 END

        my $sth = $dbh->prepare($sql);
@@ -218,7 +218,7 @@
 update
        da_event
 set
-       dv_duration = time(julianday(?) - julianday(dv_start_time) - 0.5)
+       dv_duration = timediff(?, dv_start_time)
 where
        dv_service_id = ?
 and
@@ -226,7 +226,7 @@
 and
        dv_start_time < ?
 and
-       ? < datetime(dv_start_time, dv_duration)
+       ? < addtime(dv_start_time, dv_duration)
 END

        my $udh = $dbh->prepare($sql);
@@ -325,8 +325,8 @@
 }

 sub dbiConnect {
-       my $dsn = 'DBI:SQLite:dbname=epg.db';
-       my $dbh = DBI->connect($dsn, undef, undef, {RaiseError => 1, AutoCommit => 0});
+       my $dsn = 'DBI:mysql:database=DATABASE_NAME;host=localhost';
+       my $dbh = DBI->connect($dsn, 'USER_NAME', 'PASSWORD', {RaiseError => 1, AutoCommit => 0, mysql_enable_utf8 => 1});
        return $dbh;
 }

epg.cgiは、次のようになりました。
サブクエリが遅かったので、distinctをつけましたが影響あるのか分かりません。まあジャンルなので。

--- epg.cgi.orig        2009-01-25 15:38:34.000000000 +0900
+++ epg.cgi     2012-02-18 13:00:08.000000000 +0900
@@ -3,9 +3,11 @@
 use strict;
 use DBI;
 use CGI;
+use utf8;
+
+my $dsn = 'DBI:mysql:database=DATABASE_NAME;host=localhost';
+my $dbh = DBI->connect($dsn, 'USER_NAME', 'PASSWORD', {RaiseError => 1, AutoCommit => 0, mysql_enable_utf8 => 1});

-my $dsn = 'DBI:SQLite:dbname=../oneseg24/epg.db';
-my $dbh = DBI->connect($dsn, undef, undef, {RaiseError => 1, AutoCommit => 0});

 my @tm = localtime(time - 60*60*4); $tm[5] += 1900; $tm[4]++;
 my $q = new CGI;
@@ -33,6 +35,7 @@
        '#553333',
 );

+binmode(STDOUT,":utf8");
 print "Content-type: text/html\n\n";

 print <<END;
@@ -126,12 +129,12 @@
        p.dv_name,
        p.dv_text,

-       (select
+       (select distinct
                g1.mg_name
        from
-               da_genre g
+               da_genre as g
                        left outer join
-                               ma_genre1 g1
+                               ma_genre1 as g1
                        on
                                g1.mg_level1 = g.mg_level1
        where
@@ -145,21 +148,21 @@
        c.dc_id,
        c.dc_ch,

-       strftime('%s', p.dv_start_time),
-       strftime('%s', datetime(p.dv_start_time, p.dv_duration)),
-       strftime('%Y%m%d-%H%M%S', p.dv_start_time),
-       strftime('%H%M%S', datetime(p.dv_start_time, p.dv_duration)),
-       strftime('%H', p.dv_start_time),
-       strftime('%M', p.dv_start_time),
-
-       julianday(p.dv_start_time) - julianday(?),
-       p.dv_start_time <= datetime('now', 'localtime'),
-       datetime('now', 'localtime') < datetime(p.dv_start_time, p.dv_duration)
+       unix_timestamp(p.dv_start_time),
+       unix_timestamp(addtime(p.dv_start_time, p.dv_duration)),
+       date_format(p.dv_start_time, '%Y%m%d-%H%i%s'),
+       date_format(addtime(p.dv_start_time, p.dv_duration), '%H%i%s'),
+       date_format(p.dv_start_time, '%H'),
+       date_format(p.dv_start_time, '%i'),
+
+       datediff(p.dv_start_time, ?),
+       p.dv_start_time <= localtime(),
+       localtime() < addtime(p.dv_start_time, p.dv_duration)

 from
-       da_event p
+       da_event as p
                inner join
-                       da_channel c
+                       da_channel as c
                on
                        c.dc_network_id = p.dv_original_network_id
                and
@@ -167,9 +170,9 @@
 where
        c.dc_id = ?
 and
-       datetime(?, '4 hours') <= p.dv_start_time
+       date_add(?, INTERVAL 4 hour) <= p.dv_start_time
 and
-       p.dv_start_time < datetime(?, '29 hours')
+       p.dv_start_time < date_add(?, INTERVAL 29 hour)
 order by
        p.dv_start_time
 END
diffをそのまま書くと間延びしますのね。
スタイルシートとかでスクロールできるようにした方がいいのかも。

2012年2月17日金曜日

database is locked

epg.plがほぼ毎日、次のようなメッセージを出力しています。
DBD::SQLite::st execute failed: database is locked at /var/oneseg24/epg.pl line 209.
それぞれのチャンネルで動作しているepg.plのDB処理がかぶるタイミングが結構あるようです。
MySQLを使用するように改造してみようと思います。
DBIを使用しているので修正は簡単にできそうですが、SQLiteの手軽さが無くなってしまうのはちょっと微妙な感じもします。

2012年2月12日日曜日

ワンセグ野郎できた!

ワンセグ野郎のセットアップは、特に書くこともないくらい簡単でした。
無事に生TSが取れてたようで、番組も問題なく見ることができました。
これでワンセグ野郎の仲間入りです。

URLをメモしておきます。開発者に方々に感謝!

OneSeg24 for Linux
perlRTMP
DVB tools - dvbstream




Siano Niceが動いた!

PachworkにステータスがRFCですが、パッチがありました。firmwareの選択処理とモジュールの依存関係処理を追加しているようです。
私の環境では、ファームウェアは正しく読み込めているようなので、モジュールの依存関係のところだけコードを変更しました。

--- sms-cards.c.orig       2012-02-11 07:45:34.642588548 +0900
+++ sms-cards.c 2012-02-11 17:52:52.515595099 +0900
@@ -299,6 +299,7 @@
        case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
        case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
        case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+       case SMS1XXX_BOARD_SIANO_NICE:
                request_module("smsdvb");
                break;
        default:
修正前

$ lsmod |grep sms
smsusb                  9020  0
smsmdtv                32268  1 smsusb
rc_core                19720  7 smsmdtv,ir_lirc_codec,ir_sony_decoder,ir_jvc_decoder,ir_rc6_decoder,ir_rc5_decoder,ir_nec_decoder
修正後、smsdvbがロードされて/dev/dvbもできました。
$ rmmod smsusb smsmdtv
$ lsmod |grep sm
smsdvb                 13579  0
dvb_core              104074  1 smsdvb
smsusb                  9020  0
smsmdtv                32268  2 smsdvb,smsusb
rc_core                19720  7 smsmdtv,ir_lirc_codec,ir_sony_decoder,ir_jvc_decoder,ir_rc6_decoder,ir_rc5_decoder,ir_nec_decoder
$ ls /dev/dvb
adapter0

$ dmesg
usb 1-1.2: new high speed USB device using ehci_hcd and address 8
usb 1-1.2: New USB device found, idVendor=187f, idProduct=0202
usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1.2: Product: MDTV Receiver
usb 1-1.2: Manufacturer: MDTV Receiver
usb 1-1.2: configuration #1 chosen from 1 choice
usb 1-1.2: firmware: requesting isdbt_nova_12mhz_b0.inp
smscore_set_device_mode: firmware download success: isdbt_nova_12mhz_b0.inp
DVB: registering new adapter (Siano Nice Digital Receiver)
DVB: registering adapter 0 frontend 0 (Siano Mobile Digital MDTV Receiver)...
usbcore: registered new interface driver smsusb
DVB toolsで提供されているdvbstreamを使用して、TSが取れるか確認します。 試しにTBS(周波数527143)を指定してみると、データは取れているようです。

$ ./dvbstream -c 0 -f 527143 8192 -o > test.ts
dvbstream v0.5 - (C) Dave Chapman 2001-2004
Released under the GPL.
Latest version available from http://www.linuxstb.org/
Using DVB card "Siano Mobile Digital MDTV Receiver"
tuning DVB-T (in United Kingdom) to 527143000 Hz
polling....
Getting frontend event
FE_STATUS:
polling....
Getting frontend event
FE_STATUS: FE_HAS_SIGNAL FE_HAS_LOCK FE_HAS_CARRIER FE_HAS_VITERBI FE_HAS_SYNC
Event:  Frequency: 10600000
SymbolRate: 0
FEC_inner:  0

Bit error rate: 258
Signal strength: 30
SNR: 15
FE_STATUS: FE_HAS_SIGNAL FE_HAS_LOCK FE_HAS_CARRIER FE_HAS_VITERBI FE_HAS_SYNC
Setting filter for PID 8192
Output to stdout
Streaming 1 stream
^C
Caught signal 2 - closing cleanly.
取りあえず、東京で見られる8局は受信できるようなので、生TSが取れていることを期待してOneSeg24 for Linuxをセットアップします。

sianoモジュールコンパイル

Windowsマシンで付属CDからドライバをインストールすると、C:\windows\system32にisdbt_nova_12mhz_b0.inpがインストールされます。これは、LinuxTVのCVOC-E121で書かれているファームウェアと同じなので、まずはNova Bと同じ方法を試してみることにします。

CentOS6で使用するので、CentOSのwikiを参考に環境を準備します。

まず、カーネルソースをインストールしてパッチを当てます。

$ uname -r
2.6.32-220.4.1.el6.x86_64
$ rpm -iv kernel-2.6.32-220.4.1.el6.src.rpm
$ cd ~/rpmbuild/SPEC
$ rpmbuild -bp --target=`uname -m` kernel-2.6.spec


取りあえず、標準のモジュールをコンパイルしてみます。

$ cd ~/rpmbuild/BUILD/kernel-2.6.32-220.4.1.el6/linux-2.6.32-220.4.1.el6.x86_64
$ cp /lib/modules/`uname -r`/build/Module.symvers .
$ make prepare
$ make modules_prepare
$ make M=drivers/media/dvb/siano

特にエラーも出ないようなので、、LinuxTVのCVOC-E121にあるパッチを/tmp/siano.patchとして保存し、コンパイルします。
kernel 2.6.35.10用のパッチですが、そのままあたりました。

$ cd drivers/media/dvb/siano
$ patch -p1 < /tmp/siano.patch
patching file smscoreapi.c
Hunk #2 succeeded at 529 (offset -2 lines).
Hunk #3 succeeded at 576 (offset -2 lines).
Hunk #4 succeeded at 605 (offset -2 lines).
patching file smscoreapi.h
patching file smsdvb.c
$ cd -
$ make M=drivers/media/dvb/siano

オリジナルモジュールのバックアップを取って、入れ替えます。

$ tar cfz /tmp/siano-`uname -r`.tar.gz /lib/modules/`uname -r`/kernel/drivers/media/dvb/siano
$ su
# cp drivers/media/dvb/siano/*.ko /lib/modules/`uname -r`/kernel/drivers/media/dvb/siano

lsmodでsms*がロードされているか確認し、必要に応じrmmodします。
チューナーを再度挿してみると、次のような表示が出ました。いけそうな感じです。

$ dmesg
usb 1-1.2: new high speed USB device using ehci_hcd and address 4
usb 1-1.2: New USB device found, idVendor=187f, idProduct=0202
usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1.2: Product: MDTV Receiver
usb 1-1.2: Manufacturer: MDTV Receiver
usb 1-1.2: configuration #1 chosen from 1 choice
usb 1-1.2: firmware: requesting isdbt_nova_12mhz_b0.inp
smscore_set_device_mode: error -2 loading firmware: isdbt_nova_12mhz_b0.inp, trying again with default firmware
usb 1-1.2: firmware: requesting isdbt_nova_12mhz_b0.inp
smscore_set_device_mode: error -2 loading firmware: isdbt_nova_12mhz_b0.inp
smsusb_init_device: line: 382: smscore_start_device(...) failed
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
sms_ir_exit:
smsusb: probe of 1-1.2:1.0 failed with error -2

winodwsマシーンからisdbt_nova_12mhz_b0.inpをコピーして、/lib/firmwareに置いて再挑戦するとエラーにならなくなりましたが、/dev/dvb/*ができません。

$ dmesg
usb 1-1.2: new high speed USB device using ehci_hcd and address 6
usb 1-1.2: New USB device found, idVendor=187f, idProduct=0202
usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1.2: Product: MDTV Receiver
usb 1-1.2: Manufacturer: MDTV Receiver
usb 1-1.2: configuration #1 chosen from 1 choice
usb 1-1.2: firmware: requesting isdbt_nova_12mhz_b0.inp
smscore_set_device_mode: firmware download success: isdbt_nova_12mhz_b0.inp
$ ls -l /dev/dvb*
ls: cannot access /dev/dvb*: No such file or directory

もうちょい作業が必要なようです。

2012年2月11日土曜日

Siano Mobile Silicon Nice

購入したチューナーはSianoチップでしたが、実績のあるNova BではなくNiceのようです。

$ lsusb
Bus 001 Device 003: ID 187f:0202 Siano Mobile Silicon Nice

LinuxTVのSmart Plusを見ると、動作していないような記述があります。
dmesgは、次のようになりました。

usb 1-1.2: new high speed USB device using ehci_hcd and address 3
usb 1-1.2: New USB device found, idVendor=187f, idProduct=0202
usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1.2: Product: MDTV Receiver
usb 1-1.2: Manufacturer: MDTV Receiver
usb 1-1.2: configuration #1 chosen from 1 choice
IR NEC protocol handler initialized
usb 1-1.2: firmware: requesting dvb_nova_12mhz_b0.inp
smscore_set_device_mode: error -2 loading firmware: dvb_nova_12mhz_b0.inp, trying again with default firmware
usb 1-1.2: firmware: requesting dvb_nova_12mhz_b0.inp
smscore_set_device_mode: error -2 loading firmware: dvb_nova_12mhz_b0.inp
smsusb_init_device: line: 382: smscore_start_device(...) failed
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
IR RC5(x) protocol handler initialized
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
smsusb_onresponse: line: 117: error, urb status -2, 0 bytes
sms_ir_exit:
smsusb: probe of 1-1.2:1.0 failed with error -2
usbcore: registered new interface driver smsusb
IR RC6 protocol handler initialized
IR JVC protocol handler initialized
IR Sony protocol handler initialized
lirc_dev: IR Remote Control driver registered, major 249
IR LIRC bridge handler initialized


いろいろ試してみる必要がありそうです。

ISDB-T Digital TV Receiver

LinuxTVのISDB-T USB Devicesで実績のあるチップ、特にSiano Mobile Silicon Nova Bチップだと日本でも使用出来るようです。

ワンセグ野郎の夢敗れたり・・・で、蟹チップに変わってしまった商品が紹介されていたので参考にさせて頂き、dealextremeからISDB-T Digital TV Receiver USB Dongle with IR Remote Controllerを購入してみました。
使えなくても諦めのつく価格だったので、8個注文してしまいました。(ダメだったらもったいないけど)

届いたものは、USB ATSC Receiverと印刷されていて、違う商品のパッケージっぽいです。
画像


中身はこんな感じで、EzTV ISDB-Tとドングルにプリントされてました。
画像


注文してから届くまで20日も掛かったのに、ATSCのレシーバーだったらゴミになるところでした。

2012年2月9日木曜日

ワンセグ野郎

今更ながら24時間ワンセグ野郎を知りました。
調べてみると、Linuxで利用できるチューナーがまだ入手できるようなので、OneSeg24 for Linuxを構築してみることにしました。