2014-11-26

ssh を通じてパイプから読む tar にはなぜ -B が必要か

説明を書くことがあったので、なくさないように保存。間違いがあったら教えてください。

ファイルというものは、種類によって特性がいろいろあります。
特性とは、いいかえると、できることと、できないことです。

ディスクファイルは一番制約の少ないものです。
  • メディア容量いっぱいまで無制限に伸ばせる有限のバイト列が、1つのプロセスにつながっている
  • lseek(2) によって任意バイト目のに位置づけすることができて(後退も可能)、
  • その現在位置から任意個バイトを read(2) することができ、
  • ファイル終端で read するとゼロが返ることで、「読めるわけではないがエラーでもない状態」が通知され、
  • あるいは現在位置から任意個バイトを write(2) することもできてその後は破壊されず、
  • 要すれば現在位置から後の全データを truncate(2) によって破棄することもできる。
パイプはちょっと制約があります:
  • バイトストリーム(遡れない流れのイメージ)の両側がプロセスにつながっており、
    write する側と read する側が決まっている
  • write したバイト数だけパイプに入って、それ以下の数だけ read したときはその内容が得られる
    パイプに入っているバイト数を超えた数を read すると、入っているバイト数だけしか読めない
  • パイプに入るバイト数が決まっている(512バイトとか、Linuxだと4096バイトとか、そんなにデカくない)。
    満杯のパイプに書き込むと write がブロック(吸い出してもらえるまで止まる)し、
    空のパイプから読み出すと read がブロック(書き込んでもらえるまで停止)する
  • lseek(2) は常にエラーになり、つまり後退はできない
  • 書き込み側プロセスが先にパイプを閉じたとき、ファイルの終端と同じ状態になり、読み側 read() に 0 が返される
    逆に、読み込み側プロセスが先にパイプを閉じたとき、書き込み側が write(2) すると、シグナル SIGPIPE を受ける (ふつう13番だから exit code 141 に見える)
TCPソケットもパイプに似た特徴を持ちますが、書き込み側プロセスが書いたバイト列が一気にすぐ読み出し側プロセスに届くわけでなく(なにせ別ホストですからね)、read で何バイト取れるかはもっと予想がつきません。

テープは全然ちがいます:
  • ファイルはバイトではなくブロックの列
  • ブロックは「1回 write したバイト列」、昔は固定長だったみたいだが、いまどきは可変長、つまり書き込み側が指定できる(512バイトの倍数限定かも)
  • ブロックはテープに書かれていて、read はブロック単位でしか行えない。
    ブロック長以下の read はブロック先頭だけが読み出され、ブロック長を超える read はブロック長だけしか読み出せない
  • ファイル内の read 以外での前後移動はできないとおもったほうがよい。
  • テープ上のファイルの終わりは書き込みプロセスが close したら勝手にできる
    テープに書き込む際は、メディア上の後続のファイルは必ず破壊されるので、ftruncate にあたる別操作はない(必ず行われる)
  • テープ上のファイルの終わりでは read(2) が 0 を返すことはディスクファイルと同じ
  • 巻き戻しをしないテープデバイスでは、ファイルの終わりを読み出して close した直後に、次のファイルに移動している

このような特性は Linux なら st(7) や pipe(7) で説明されている、はずなのですが、あの文章では一見さんお断りですわね。
ともあれそれをふまえると、-B やら SIGPIPE の問題もよくわかると思います。

  • tar は、固定のブロック長で read/write を行う、つまり、1ブロックが1回で読めることを前提にしている
  • ブロック長は 512 バイトかける -b オプションの数
  • tar アーカイブに入れるファイル長がブロック長の倍数でないときは、末尾にゼロが埋められる(パディング)
  • テープから tar が読む場合、書き込んだときのブロック長が読み出されるので、自動的にブロック長を判定できる
  • パイプから tar が読む場合(特にネットワーク越しならなおさら)は、書き込んだときのブロック長はわからないし、1ブロックが1回で read できるとも限らない。
    1ブロック(と思い込んでいるバイト数)が1回で読めない場合、続きの読み出しをリトライさせるのが -B オプション。
  • また、パイプから読む tar はブロック長がわからないので、必要なファイルを解読したら終了してしまうようになっていると(gtar はそうではないと思う)、
    書き込み側はパディングを続けている間に読み出し側が終了して、SIGPIPE を受けて爆死、ということになるのでしょう。

2014-11-21

ソフトウェアデザイン12月号にコンテナ型仮想化環境 Docker の記事がある

正直これまでどんなもんだかまったく分からなかったのだが、ハイパーバイザと
比べると、 chroot(2) の進化の系列にあるという説明は腑に落ちた。
セマンティクスが普段と違って使い方が覚えられないものは普及しない、という
のは、まあ他にもあるかもしれないが SELinux のことをいっているのだろう。
http://gihyo.jp/magazine/SD/archive/2014/201412

平成26年度 数値予報研修テキスト

平成26年度 数値予報研修テキスト が気象業務支援センター http://www.jmbsc.or.jp/ から発売になったそうです。

そのうち、気象庁ホームページ http://www.jma.go.jp/jma/kishou/books/nwptext/nwptext.html にも掲載されるはずですが、このボリュームだと印刷物をみたいという方もあると思いますので、上記ご参考まで。

2014-11-13

他人からもらった JSON を eval してはいけない。かわりに JSON.parse() しよう

ということみたいだ。ポータビリティもありそう。

参照:

http://en.wikipedia.org/wiki/JSON#Security_issues

http://www.websec-room.com/2013/07/28/876

配信資料に関する技術情報 第406号 地方海上分布予報の提供開始について

11月12日づけで発出された、標記資料が気象庁ホームページに掲載されました。
http://www.data.jma.go.jp/add/suishin/jyouhou/pdf/406.pdf

画像(PNG)形式とGRIB2形式の両方で提供があります。GRIB2マニア的には、
PDT4.0なのは普通ですが、ビットマップが使われてい るのが特徴的でしょうか。

「東京」の気象観測地点の移転について(お知らせ出ました)

お問い合わせは、このお知らせに書かれている東京管区気象台の窓口にお願いいたします。

http://www.jma-net.go.jp/tokyo/sub_index/tokyo/kitanomaru/kitanomaru.html

2014-11-11

世界の自然災害の犠牲者数は20世紀前半とそれ以後でみれば大きく減っているらしい

ちょっと興味があってぐぐってみたらこんなページがみつかった。
http://www.ourworldindata.org/data/environmental-change/natural-catastrophes/

このデータの信憑性についてはよくわからないが、20世紀前半までは10万人ちか
い犠牲者を伴うような疫病・水害・旱魃があって、それはここ数十年はみられな いというこ
とはそれなりに説得力はある。

どうやって人類はそれを乗り越えたかというと衛生、治水、灌漑、いろいろあろうが、それをひとま
とめで呼ぶなら文明と言ってもいいんじゃないかと思う。一定の文明があたり まえに
なった後だけを論じれば、気候変動で文明が脆弱になってきているという論はできるのかも
しれないが、それなら文明開化以前まで視野に入れないと、ものをよく見 た気がしない。

2014-11-10

気象庁平年値(1981~2010)第4版

支援センター http://www.jmbsc.or.jp/ 曰く、
「気象庁平年値(1981~2010)第4版」が10月30日に発売になったそうです。

観測値はいろいろの理由であとから訂正されます。何年も経ってからも訂正は多数あるんだそうで、それをとりまとめて平年値が更新されます。

2014-11-05

配信資料に関する技術情報(気象編)第404号「黄砂予測モデルの改良について」出てます

平成26年10月29日付 配信資料に関する技術情報(気象編)第404号「黄砂予測モ
デルの改良について」が気象庁ホームページに掲載されました。
http://www.data.jma.go.jp/add/suishin/jyouhou/pdf/404.pdf

モデル開発としては、陸面モデルが置き換わったのが傍目からみても画期的なこ
とです。「そんなによいなら他のモデルにもなぜすぐ採用しない」と聞 かれそ
うですが、黄砂モデルは目的がシャープに絞られていますから、短期予報である
にもかかわらずユーラシアの春先積雪有無の予測がクリティカル という特別な
力点があります。他になんの影響もなく積雪だけが当たるようになるならば、何
も考えないでいいのですが、そう甘くはありません。融雪 速度は日射のうちど
の割合を大気との熱交換に使うかですから、さまざまなところが変わってきま
す。他モデルに使うには、それぞれの観点で評価して 現行以上の精度を確認し
なければならないわけです。

積雲対流モデルについては、よく知らないと申し上げておくのが正直でしょう。

2014-11-04

libecbufr を読んでみる(反復・次元に関するデータ構造はどうやって作られているか)

TEMP BUFR を bufr_decoder -dump していると

007007 {R=1}{5002=52.419998,6002=-4,4025=30} 1685

みたいな出力にでくわすことがある。
この中括弧はなんだろう。

0.8.5 のソースコード、 API/Sources/bufr_meta.c の
bufr_print_rtmd_data(char *outstr, BufrRTMD *rtmd) あたりでやっているよ
うだ。

まず、 rtmd == NULL ならば、この中括弧群は一切生成しないで関数を抜ける。

{R=1} というのが反復記述子による反復数であることはだいたい察しがつくけれ
ど、それは bufr_print_rtmd_repl() でやっている。
rtmd->nesting が真の場合に "R=" が表示され、 rtmd->nb_nesting が2以上の
場合は R=1.1.1 のようにピリオド区切りで数が表示される。
被表示数は rtmd->nesting[i] である。

(つまり rtmd->nesting が偽の場合は "{}" が表示されるロジックなんだが、
それでいいの? おそらくそれは起こらない想定だろうけど)

第2の括弧ブロックは、 rtmd->nb_tlc が真である場合に表示され、
rtmd->nb_tlc 個だけコンマ区切りの記述子・値ペアが表示される。
記述子は rtmd->tlc[i].descriptor, 値は rtmd->tlc[i].value である。

まあ、どうせ、次元記述子の修飾関係を明示するというつもりなのはわかるのだ
が、出現条件が知りたい。

ここらでコールツリーの上方へ探索。

bufr_print_rtmd_data() を読んでいるのは API/Sources/bufr_dataset.c の
bufr_fdump_dataset(BUFR_Dataset *dts, FILE *fp) である。

それを呼んでいるのは同じソースの bufr_dump_dataset(BUFR_Dataset *dts,
const char *filename) である。

それを呼んでいるのは Utilities/bufr_decoder.c の run_decoder(void) <=
main() である。
まあ、なんというか、 main を見つけると安心するよね。

さて、 run_decoder から下方探索はしんどいので後回しにして、

BufrRTMD::nb_nesting を設定しているのは bufr_meta.c:
bufr_create_rtmd(int count) である。
これは単純に反復記述子を数えているようである。

BufrRTMD::nb_tlc を設定しているのは bufr_ddo.c:
bufr_assoc_location(BufrDescriptor *bc, BufrDDOp *ddo) である。
これは ddo->current_location の各要素から記述子と値をとっている。

これを呼んでいるのは bufr_sequence.c: bufr_apply_Tables(BufrDDOp *ddoi,
BUFR_Sequence *bsq, BUFR_Template *tmplt, ListNode *current, int
*errcode) である。
これは多数回呼ばれるので上方探索が難しい。

あきらめて dts に戻る。
bufr_print_rtmd_data に食わされる BufrRTMD は bufr_fdump_dataset() 内で
は bcv->meta と呼ばれている。
これは bcv = bufr_datasubset_get_descriptor(subset, j) といって抽出される。
subset は bufr_get_datasubset(dts, i) といって dts->datasubsets から抽出
される。

BUFR_Dataset::datasubsets は DataSubsetArray 型でありそれは ArrayPtr 型
のエイリアスである。
ArrayPtr 型は名目上は char * と定義されているけれど、それは実際には
Array 構造体をさしている。
管理ルーチン arr_create(), arr_add() など以外が内部を操作しないようにオ
ペーク化しているのである。

Array の構造は Array::grow の値によって大きく異なる。
Array::grow が零または負であれば固定長配列で、 Array::eles が指す配列は
Array そのものと一体的に malloc される。
Array::size が1要素の大きさ、Array::total = [arr_create() の引数 len] が
要素数である。
Array::grow が正であれば可変長配列で、 初期には Array そのものとは別に
Array::total 個の要素が確保され、
不足時には Array::grow 個増やして realloc(3) される。

さて run_decoder() 内で dts の構築は bufr_decode_message(BUFR_Message
*msg, BUFR_Tables *tables) がしている。

その中で dts->datasubsets は ...

今日はちょっとここらでおしまい。たぶん続きは書かれない。

2014-11-02

2014年11月3日、英国・オランダが文字形式の地上気象実況報(FM 12 SYNOP)の発信を停止します。今後はBUFRをお使いください

明日です。とうとうこの日がやって参りました。

世界気象機関(WMO)では全球気象監視計画(World Weather Watch Programme) の一環である Regional Basic Synoptic Network <URL:http://www.wmo.int/pages/prog/www/ois/rbsn-rbcn/rbsn-rbcn-home.htm> として加盟各国の地上・高層観測結果をリアルタイムに通報することとしています。

データを送るわけですから形式についても決まりがあり、WMO Manual on Codes <URL:https://www.wmo.int/pages/prog/www/WMOCodes.html> というものにまとめられています。そのうちこれまで実際に使われてきたものは、伝統的文字形式通報式(TAC: traditional alphanumeric codes)という、テキストというか電報を使うことを前提にして文字列でデータを表現するものでした。地上ならば地上気象実況報 FM 12 SYNOP です(具体は非公式ながら <URL:http://www.megakastro.gr/weather_agro/SYNOP_format%28FM-12%29.htm> がわかりやすいと思います)。

しかしTACにはいろいろ問題があり、WMOでは表参照型通報式(TDCF: table driven code form)というものへの移行を進めています。FM 94 BUFR (二進形式汎用気象通報式) と FM 95 CREX (文字形式) の2つがありますが、本則は BUFR であって CREX は通信システムの都合上テキストしか流せない場合ということになっています。

さてずいぶん昔に作られた移行計画というのがありまして、SYNOPを含む主要な通報については2014年11月をもってTAC-TDCFの平行配信を終了、ということになっています。つまり11月からは、各国の判断次第でTACの送信を止めることができる、というわけです。かわりに使ってほしいという BUFR については、気象庁から配信資料に関する技術情報第334号というのがでています(国立国会図書館蔵だからこのURLは変わらないよ)。


さて各国判断次第、というその先頭を切って11月3日に英国・オランダが、11月4日にはアイルランドがそれぞれ FM 12 SYNOP の配信停止を予告しています。

準備はできているはずなのですが、明日、どうなるか、 ちょっと緊張しています。