Hatena::ブログ(Diary)

こども(てれび)

2009-01-19

スケジュールとか難しいことは言わないからちゃんと会社に来てくれ 18:18

XSS脆弱性があったのを修正しました。ブックマークで報告してくださった jtw さん inarin さんありがとうございます。link_to に渡した文字列ってエスケープされるんだと思ってた・・。


日記顔写真をのせたのにウェブカレとしてわたしのブログに貼っていいですか?っていうメールがなかなか来ない。


ユーザーアイコンを変えました。モチーフはひみつです。

2009-01-18

スケジュール管理ツールを公開します 21:10

Google Code Archive - Long-term storage for Google Code Project Hosting.

動作デモ

知り合いの会社にこういうのほしいなーと言われて作ったスケジュール管理システムを公開します。渡して終わりにするのもなんなので。カレンダーに書き込むだけのシンプル操作、という感じです。革新的な機能や技術的に面白い所は特にありません。

@@ 2009/01/20 12:06 解凍してみましたが使い方が分かりません。どのようにしたらいいのでしょうか。

@@ 2009/01/20 12:09 すみません、ruby on railsのインストール方法に従えばいいって書いてあったので分かりました。

wanparkwanpark 2009/01/20 20:24 わかりにくくてすいません。プロジェクトのトップページからインストール手順のテキストにリンクするようにしました。テキストの内容も不親切なのですが。

【one from zero】【one from zero】 2010/09/13 18:33 管理ツール!早速つかってみます。
ありがとうございます。

【one from zero】【one from zero】 2010/09/13 18:34 管理ツール!早速つかってみます。
ありがとうございます。

犬好き犬好き 2011/03/10 17:11 私も使ってみます!ありがとうございます。

湘南でBBQ湘南でBBQ 2011/04/06 19:19 参考になる情報をいつもありがとうございます。

2009-01-14

きょうのほのぼの日記 04:22

f:id:wanpark:20090114022802j:image

今日はおかあさんから届いた荷物の中身を紹介します。


f:id:wanpark:20090114023029j:image

志満秀の海老なかよし。おかあさんの姉夫婦の家に毎年届くのだけど食べる人がいないのでいつも僕のところまでまわってくる、とのことです。えびがまるごと入った、なかなか庶民には口にできなそうな高級感あふれるおせんべです。おいしい。

f:id:wanpark:20090114023120j:image

大量のいかめしごはんを炊くのも面倒だし外に食べに行く気力もない、というときに重宝します。パックのいかめし普通に買うと結構値が張るのですが、マルエツ従業員であるおかあさんの前では正規の価格など意味を成しません。

f:id:wanpark:20090114023302j:image

人形焼です。僕はカステラっぽいもの全般がすきなのです。一緒に入っていた普通カステラはもう食べました。

f:id:wanpark:20090114023345j:image

レンジでできるリゾット。あたらしもの好きなので面白がって食べるだろう、というもくろみだと思われます。お茶の間CM感がします。

f:id:wanpark:20090114023907j:image

駄目になっているから廃棄するように電話で言われました。荷物と入れ違いで年末実家に帰ってしまったのですよね。

f:id:wanpark:20090114023957j:image

千葉の名産落花生甘味と香ばしさがあってそこそこの豆な感じがします、が最近落花生は食べていないので鑑定舌に自信はありません。


あとは似たようなおかしやおかず多数。いつも荷物を送った後に確認の電話をくれるのだけど、携帯電話の充電器が壊れていたりマナーモードで気付かなかったりで1週間くらい返事をしないでいたら、なにかあったんじゃないかと心配した、おとうさんに僕の部屋まで様子を見に行くように頼もうかと考えていた、と言われた。そんな大げさな、息子さんもいい歳なのに、と口では言いつつも、ちょっと嬉しかったりする、と書けばきれいに良い話という感じだけど、嬉しいかどうかはよくわからない。嫌だってことはないけど。おかあさんが死んだらなにか思うだろうか。小学校2年生のときにおじいちゃんが死んで、まわりが泣いているときにぼさっとしていたらあきちゃんのおばさんに、だいくんは小さいから人が死ぬってことがわからないのね、と言われて、わかってないのかーそうかーと思ったのを覚えているんだけど、あれからあまり変わっていない気がする。こんな事書いてると怒られるかな。ちいさいころ人の生き死にの話をするとおかあさんにそんな話するなって厳しく言われてたからね。だから浜ちゃん死ね死ね言うダウンタウン番組なんてみてたら絶対に怒られると思って、ガキの使いのある日は姉と2人で寝たふりをして、番組が始まる頃こっそり起きて、薄暗い中スピーカーに耳をあててくすくす笑ってた。今ではジャンクSPORTS始まるから8に変えてよとおかあさんが言ってるんだけど。

以上ほのぼの日記でした。

2009-01-12

きょうの日記 02:48

今日祝日だと先週末に教えてもらった。いつも祝日と知らずに出社して、ふにゃーっとなっているので。今後のためにRainlendarというデスクトップカレンダーを入れてiCalの祝日データインポートした。祝日イベント扱いなので土日と表示色が違ってちょっときになる。スキンをいじろうとしたらバイナリファイルだったのでまあいいやということにした。

だらだらとゲームでもしてようと思って近所のツタヤno titleを買ったら、これが失敗した。思えばレジ初回特典ドラマCDを渡されたところでもう嫌な予感がしたのだ。お正月実家世界樹の迷宮をやって楽しかったので似たようなゲームがやりたくて選んだのだけど、FFっぽいというのだろうか、紙芝居の間にキャラクターを動かすRPGという感じで、まあそれはそれでいいんだけど、「やってみなきゃわかんねぇだろ!」が口癖の主人公少年と仲間たちの語らいがつらい。

主人公「で、その話にオチはあるの?」

幼馴染「なにいってんのよ!」

一同「はははは」

僕「勘弁してくれ」

という具合で。もぎたてチンクルにすればよかった。

そういうわけで、なにしよう。ブックマークエントリーに全コメントしよう。http://b.hatena.ne.jp/entrylist?url=http://d.hatena.ne.jp/&threshold=3 から。

classList、relList - 素人がプログラミングを勉強するブログ
複数クラス名をjavascriptから扱うのは気が引ける、というのはありますよね。そこらへんはブラウザが面倒を見てくれるようになる、ようです。
いましろたかしが好きなやつはセンスがない - ハックルベリーに会いに行く
増田に書け。いや書かないで。冗談です。このエントリ自体がいましろたかしの作風をもとにひねったネタだったりするのでしょうか。
グエボスの少女のはなし - 続・Cinema, the Jury 映画が掟だ! はてな死闘編
ファ文関連。挑戦せねばなるまい。んー。女の子が降ってくるのはばれているから、それを逆手にとってですね、なにかの破片がぽたぽた空から降ってきて、読者がああこの破片が合体して少女になる前に弾を打ち込んで撃破するとボーナス点だなと思ったところを、なにかこう。んー。
戦艦大和は沖縄を本気で守るために出撃した、と宣伝する小学校教師 - 土曜の夜、牛と吼える。青瓢箪。
わんわん
フェルクリンゲン、高いところは足下すかすか - 鳥よ!
にゃーにゃー

あきらめた。おふろはいる。

matsukazutomatsukazuto 2009/01/12 05:32 世界樹の迷宮面白かったです.
こんど焼き鳥食べにいきましょう.

wanparkwanpark 2009/01/14 02:23 また近所にきたら連絡してね

2008-11-13

HBase InputFormat/OutputFormat for Hadoop Streaming 14:50

What is this?

InputFormat/OutputFormat to use HBase tables as input/output of MapReduce in Hadoop Streaming.

Repository

http://github.com/wanpark/hadoop-hbase-streaming/tree/master

Usage

debian:~% hadoop dfs -mkdir dammy_input
debian:~% hadoop jar hadoop-streaming.jar \
              -input dammy_input \
              -output output \
              -mapper /bin/cat \
              -inputformat org.childtv.hadoop.hbase.mapred.JSONTableInputFormat \
              -jobconf map.input.table=scores \
              -jobconf map.input.columns=course:
debian:~% hadoop dfs -cat output/*
Dan     {"course:math":"87","course:art":"97"}
Dana    {"course:math":"100","course:art":"80"}

Setting

  1. Set up Hadoop 1.7.2, HBase 0.2.1
  2. Download hadoop-hbase-streaming.jar from repository
  3. Edit $HADOOP_HOME/conf/hadoop-env.sh and add downladed jar to HADOOP_CLASSPATH
  4. Run Hadoop Streaming with selected format and jobconf options.

Supported Options

-jobconf map.input.table=<value>
Input table name for the Map step
-jobconf map.input.columns=<value>
Column name to scan. Separate by whitespace for multi columns
-jobconf map.input.binary=<true|false>
Optional. Input column names and cell values are Base64 encoded if true
-jobconf map.input.timestamp=<true|false>
Optional. Timestamps are added to input if true
-jobconf reduce.output.table=<value>
Output table name
-jobconf reduce.output.binary=<true|false>
Set true when column names and cell values are Base64 encoded

InputFormats

org.childtv.hadoop.hbase.mapred.JSONTableInputFormat
Dan     {"course:math":"87","course:art":"97"}

-inputformat=json -jobconf map.input.timestamp=true

Dan     {"course:math":{"value":"87","timestamp":"1226501804191"},"course:art":{"value":"97","timestamp":"1226501810087"}}
org.childtv.hadoop.hbase.mapred.XMLTableInputFormat

Same format as REST API GET /[table_name]/row/[row_key]/

Dan     <?xml version="1.0" encoding="UTF-8"?><row><column><name>course:art</name><value>97</value></column><column><name>course:math</name><value>87</value></column></row>

Values are also same when add option -jobconf map.input.binary=true

Dan     <?xml version="1.0" encoding="UTF-8"?><row><column><name>Y291cnNlOmFydA==</name><value>OTc=</value></column><column><name>Y291cnNlOm1hdGg=</name><value>ODc=</value></column></row>
org.childtv.hadoop.hbase.mapred.ListTableInputFormat

Only values of cell separated by whitespace.

Dan     97 87

You can change separator.

-inputformat=list -jobconf map.input.value.separator=,

Dan     97,87
custom format

Implement a subclass of org.childtv.hadoop.hbase.mapred.TextTableInputFormat

OutputFormats

Read comments on sources.

hadoop-hbase-streaming を更新しました 12:23

前のエントリーマニュアルっぽく更新

http://d.hatena.ne.jp/wanpark/20081112/1226504022

変更点

今後の予定

  • output でテーブルに書き出す

その他

Thrift っていうのを使えば普通に他の言語から扱えるの?よく知らない

追記

InputFormat だけあればいいんじゃないですか、確かにそうですね、ということで InputFormat だけにした。

追記

OutputFormat も書いた。飽きてきたのでソース読めってことにしとく。

2008-11-12

Hadoop Streaming で HBase を使う 00:33

HBase のテーブルを Hadoop Streaming の入出力にするための InputFormat/OutputFormat を書きました。

GitHub - wanpark/hadoop-hbase-streaming: HBase InputFormat/OutputFormat for Hadoop Streaming

debian:~% hadoop dfs -mkdir dammy_input
debian:~% hadoop jar hadoop-streaming.jar \
              -input dammy_input \
              -output output \
              -mapper /bin/cat \
              -inputformat org.childtv.hadoop.hbase.mapred.JSONTableInputFormat \
              -jobconf map.input.table=scores \
              -jobconf map.input.columns=course:
debian:~% hadoop dfs -cat output/*
Dan     {"course:math":"87","course:art":"97"}
Dana    {"course:math":"100","course:art":"80"}

使い方

  1. Hadoop 1.7.2, HBase 0.2.1 を準備します。
  2. リポジトリから hadoop-hbase-streaming.jar をとってきます。
  3. とってきた jar を $HADOOP_HOME/conf/hadoop-env.sh の HADOOP_CLASSPATH に加えます。
  4. 選んだフォーマットと、jobconf に適切な値を指定して Hadoop Straming を実行します

コマンドオプション

-jobconf map.input.table=<value>
入力元のテーブル名を指定します。必須です。
-jobconf map.input.columns=<value>
走査するカラム名を指定します。複数カラムはスペースで区切ります。必須です。
-jobconf map.input.binary=<true|false>
true にすると、カラム名と cell の値を Base64エンコードして map に渡します。デフォルトは false
-jobconf map.input.timestamp=<true|false>
true にすると各 cellタイムスタンプを加えます。デフォルトは false

input format の説明

org.childtv.hadoop.hbase.mapred.JSONTableInputFormat
Dan     {"course:math":"87","course:art":"97"}

-jobconf map.input.timestamp=true だと構造が変わります。

Dan     {"course:math":{"value":"87","timestamp":"1226501804191"},"course:art":{"value":"97","timestamp":"1226501810087"}}
org.childtv.hadoop.hbase.mapred.XMLTableInputFormat

REST API の GET /[table_name]/row/[row_key]/ と同形式の XML を出力します。

Dan     <?xml version="1.0" encoding="UTF-8"?><row><column><name>course:art</name><value>97</value></column><column><name>course:math</name><value>87</value></column></row>

-jobconf map.input.binary=true にすると、中身の値も REST API と同じになります。

Dan     <?xml version="1.0" encoding="UTF-8"?><row><column><name>Y291cnNlOmFydA==</name><value>OTc=</value></column><column><name>Y291cnNlOm1hdGg=</name><value>ODc=</value></column></row>
org.childtv.hadoop.hbase.mapred.ListTableInputFormat

cell の値のみを空白で区切って出力します。

Dan     97 87

-jobconf map.input.value.separator=<sep> で区切り文字を指定できます。

-jobconf map.input.value.separator=,

Dan     97,87
独自のフォーマット

org.childtv.hadoop.hbase.mapred.TextTableInputFormat のサブクラスを実装します。簡単です。


output format の説明

ソースコメントを読んでください

HBase 入門 (2) 06:31

HadoopMapReduce で HBase を使ってみましょう。

0. 参考ページ

http://wiki.apache.org/hadoop/Hbase/MapReduce

1. セットアップ

$HADOOP_HOME/conf/hadoop-env.sh の HADOOP_CLASSPATH に HBase のパスを加えます。

export HADOOP_CLASSPATH=$HBASE_HOME/hbase-0.2.1.jar:$HBASE_HOME/conf

前回のプログラムで動作確認。

debian:~/tmp/hbase% jar cf hbase-basic.jar HBaseBasic.class
debian:~/tmp/hbase% $HADOOP_HOME/bin/hadoop jar hbase-basic.jar HBaseBasic

前回通りに動けばOKです。

2. MapReduce を理解する

404 Not Found を読むのがよいと思います。また検索すれば多くの情報がみつかります。Example: WordCount v1.0 が理解できればまあいいでしょう。

3. 簡単な例

前回同様 Error 404 Not Found を参考にします。大体同じようなコードですが、バージョンに合わせて修正したりしています。

scores テーブル

grade:course:mathcourse:art
Dan18797
Dana210080

この成績表から、各科目の平均点を計算します。

courses テーブル

stats:average
math93.5
art88.5
hbase(main):001:0> create 'scores', 'grade', 'course'
0 row(s) in 6.3180 seconds
hbase(main):002:0> create 'courses', 'stats'
0 row(s) in 7.8030 seconds
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.util.Map;
import java.util.Iterator;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.hbase.io.BatchUpdate;
import org.apache.hadoop.hbase.io.RowResult;
import org.apache.hadoop.hbase.io.Cell;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapred.TableMap;
import org.apache.hadoop.hbase.mapred.TableReduce;
import org.apache.hadoop.hbase.util.Writables;

public class StatsScore  extends Configured implements Tool {

    // Sara {math:62, art:45} -> {math, 62}, {art, 45},
    public static class StatsMap extends TableMap<Text, IntWritable> {
        public void map(ImmutableBytesWritable key, RowResult value,
                        OutputCollector<Text, IntWritable> output,
                        Reporter reporter) throws IOException {
            for (Map.Entry<byte[], Cell> entry : value.entrySet()) {
                Text course = new Text(new String(entry.getKey()).split(":", 2)[1]);
                IntWritable score = new IntWritable();
                Writables.copyWritable(entry.getValue().getValue(), score);
                output.collect(course, score);
            }
        }
    }


    // {math, {62, 45, 87}} -> {math, 65.6}
    public static class StatsReduce extends TableReduce<Text, IntWritable> {
        public void reduce(Text key, Iterator<IntWritable> values,
                           OutputCollector<ImmutableBytesWritable, BatchUpdate> output,
                           Reporter reporter) throws IOException {
            int size = 0;
            int sum = 0;
            while (values.hasNext()) {
                size++;
                sum += values.next().get();
            }
            float average = (float)sum / (float)size;

            BatchUpdate bu = new BatchUpdate(key.getBytes());
            bu.put("stats:average", Writables.getBytes(new FloatWritable(average)));
            output.collect(new ImmutableBytesWritable(key.getBytes()), bu);
        }
    }


    public int run(String[] args) throws Exception {
        JobConf conf = new JobConf(getConf(), this.getClass());
        conf.setJobName("compute average scores");
        TableMap.initJob("scores", "course:", StatsMap.class, Text.class, IntWritable.class, conf);
        TableReduce.initJob("courses", StatsReduce.class, conf);
        JobClient.runJob(conf);
        return 0;
    }

    public static void main(String [] args) throws Exception {
        ToolRunner.run(new Configuration(), new StatsScore(), args);
    }
}

実行。

debian:~/tmp/hbase% javac -d classes StatsScore.java
debian:~/tmp/hbase% jar cf stats-score.jar classes
debian:~/tmp/hbase% $HADOOP_HOME/bin/hadoop jar stats-score.jar StatsScore

結果はてきとうに確認してください。

データの処理の流れは次のようになっています。

scores テーブル

↓

Dan { course:math => 87, course:art => 97 }

↓ map()

(math, 87), (art, 97)

↓

(math, [87, 100])

↓ reduce()

(math, 93.5)

↓

couses テーブル

重要なのは map 関数と reduce 関数です。それぞれ TableMap, TableReduce のサブクラス定義されています。

TableMap を使うと、テーブル内の全ての row を走査して map に渡すことができます。HTable から map するときは大抵使うことになるでしょう。動作の設定は TableMap.initJob で行います。第2引数では取得したいカラム名をスペース区切りの文字列で渡していて、この場合は scores テーブルの course: カラムファミリーを含む RowResult が map に渡されます。

map の値を reduce で集計、という部分は普通MapReduce と変わりません。

TableReduce は、output に BatchUpdate を渡すと、TableReduce.initJob で指定したテーブルにコミットしてくれるようになります。テーブルのインスタンスを管理しなくていい、程度のありがたみです。

両 initJob で各種設定を済ませてくれるので、conf.setInputFormat() などを手動で設定する必要はありません。


次回はもうすこし規模の大きい実践的なプログラムをみて、理解を深めます。

HBase 入門 (1) 00:21

Hadoop と HBase で分散処理が書けるのはわかったけど、いざ使ってみるとなるとドキュメントが少なくて……、というあなたの為の HBase 入門、今回はセットアップから JavaAPI で HBase を触るまでを勉強します。

使用するバージョンHadoop 0.17.2.1、HBase 0.2.1 です。

0. 参考ページ

404 Not Found

FrontPage - Hadoop Wiki

404 Not Found

Hbase - Hadoop Wiki

404 Not Found

1. Hadoop のセットアップ

404 Not Found を参考にインストールします。Java 1.5.x とありますが、1.6 でもたぶん動きます。今回は学習用にスタンドアローンで動かすので、$HADOOP_HOME/conf/hadoop-env.sh の JAVA_HOME を書くだけでよいでしょう。サンプルで動作を確認しましょう。

2. HBase のセットアップ

ダウンロードページ からとってきて展開します。Hadoop と同じく、$HBASE_HOME/conf/hadoop-env.sh の JAVA_HOME だけ設定します。

3. HBase の起動

$HBASE_HOME/bin/start-hbase.sh を実行して HBase を起動します。

debian:~/lib/hbase-0.2.1% bin/start-hbase.sh
starting master, logging to /home/wanpark/lib/hbase-0.2.1/bin/../logs/hbase-wanpark-master-debian.out
localhost: starting regionserver, logging to /home/wanpark/lib/hbase-0.2.1/bin/../logs/hbase-wanpark-regionserver-debian.out

Hadoop の起動は不要です。

4. shell で HBase に慣れよう

$HBASE_HOME/bin/hbase shell でシェルが起動します。実体は irb です。いくつかコマンドを打って慣れましょう。

debian:~/lib/hbase-0.2.1% bin/hbase shell
HBase Shell; enter 'help<RETURN>' for list of supported commands.
Version: 0.2.1, r693938, Wed Sep 10 13:13:09 PDT 2008
hbase(main):001:0> help
HBASE SHELL COMMANDS:
 alter     Alter column family schema;  pass table name and a dictionary
 ...

次のような成績表を作りましょう(Error 404 Not Found を参考にしました)。

grade:course:mathcourse:art
Dan18797
Dana210080

縦を column、横を row、データの1マス1マスを cell と呼びます。

hbase(main):002:0> create 'scores', 'grade', 'course'
0 row(s) in 4.1610 seconds
hbase(main):003:0> list
scores
1 row(s) in 0.0210 seconds
hbase(main):004:0> describe 'scores'
{NAME => 'scores', IS_ROOT => 'false', IS_META => 'false', FAMILIES => [{NAME => 'course', BLOOMFILTER => 'fal
se', IN_MEMORY => 'false', LENGTH => '2147483647', BLOCKCACHE => 'false', VERSIONS => '3', TTL => '-1', COMPRE
SSION => 'NONE'}, {NAME => 'grade', BLOOMFILTER => 'false', IN_MEMORY => 'false', LENGTH => '2147483647', BLOC
KCACHE => 'false', VERSIONS => '3', TTL => '-1', COMPRESSION => 'NONE'}]}
1 row(s) in 0.0130 seconds
hbase(main):005:0> put 'scores', 'Dan', 'grade:', '1'
0 row(s) in 0.0070 seconds
hbase(main):006:0> put 'scores', 'Dan', 'course:math', '87'
0 row(s) in 0.0040 seconds
hbase(main):007:0> put 'scores', 'Dan', 'course:art', '97'
0 row(s) in 0.0030 seconds
hbase(main):008:0> put 'scores', 'Dana', 'grade:', '2'
0 row(s) in 0.0040 seconds
hbase(main):009:0> put 'scores', 'Dana', 'course:math', '100'
0 row(s) in 0.0030 seconds
hbase(main):010:0> put 'scores', 'Dana', 'course:art', '80'
0 row(s) in 0.0050 seconds
hbase(main):011:0> get 'scores', 'Dan'
COLUMN                       CELL
 course:art                  timestamp=1224726394286, value=97
 course:math                 timestamp=1224726377027, value=87
 grade:                      timestamp=1224726360727, value=1
3 row(s) in 0.0070 seconds
hbase(main):012:0> scan 'scores'
ROW                          COLUMN+CELL
 Dan                         column=course:art, timestamp=1224726394286, value=97
 Dan                         column=course:math, timestamp=1224726377027, value=87
 Dan                         column=grade:, timestamp=1224726360727, value=1
 Dana                        column=course:art, timestamp=1224726424967, value=80
 Dana                        column=course:math, timestamp=1224726416145, value=100
 Dana                        column=grade:, timestamp=1224726404965, value=2
6 row(s) in 0.0410 seconds
hbase(main):013:0> scan 'scores', ['course:']
ROW                          COLUMN+CELL
 Dan                         column=course:art, timestamp=1224726394286, value=97
 Dan                         column=course:math, timestamp=1224726377027, value=87
 Dana                        column=course:art, timestamp=1224726424967, value=80
 Dana                        column=course:math, timestamp=1224726416145, value=100
4 row(s) in 0.0200 seconds

MySQL などの一般的な RDB では row 単位データを扱いますが、HBase では cellデータ単位です。<row, column, value> のタプルが寄せ集まっていると思えばいいでしょう。

カラム名は (ファミリー名):(サブカラム名) となっていて、テーブルの定義ではファミリー名のみを指定します。サブカラム名はデータを挿入する際に自由に付けることができます。上の scan の例のように、同一ファミリーカラムはまとめて指定できます。

cell にはエポックミリ秒の timestamp がついています。同一の row, column でもtimestamp が異なれば複数の cell が保存できます。ですが基本的に最新の timestamp を持つ cell使用のみが想定されているようなので、同一 column 名での保存は上書きに近いです。

5. Java から HBase を使おう

Hadoop/HBase の jar と conf、それと必要なライブラリに classpath を通しておきます。ant などを使う場合は $HADOOP_HOME/lib 以下の jar ファイルクラスパスに加えるといいでしょう。

debian:~/tmp/hbase% export HADOOP_HOME=~/lib/hadoop-0.17.2.1
debian:~/tmp/hbase% export HBASE_HOME=~/lib/hbase-0.2.1
debian:~/tmp/hbase% export CLASSPATH=.:$HADOOP_HOME/hadoop-0.17.2.1-core.jar:$HADOOP_HOME/conf:$HBASE_HOME/hbase-0.2.1.jar:$HBASE_HOME/conf:$HADOOP_HOME/lib/commons-logging-1.0.4.jar:$HADOOP_HOME/lib/log4j-1.2.13.jar

前項と同じ成績表を作ります。

import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.util.Map;

import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.io.BatchUpdate;
import org.apache.hadoop.hbase.io.RowResult;
import org.apache.hadoop.hbase.io.Cell;
import org.apache.hadoop.hbase.util.Writables;

public class HBaseBasic {

    public static void main(String[] args) throws Exception {
        HBaseConfiguration config = new HBaseConfiguration();
        HBaseAdmin admin = new HBaseAdmin(config);

        if (admin.tableExists("scores")) {
            System.out.println("drop table");
            admin.disableTable("scores");
            admin.deleteTable("scores");
        }

        System.out.println("create table");
        HTableDescriptor tableDescripter = new HTableDescriptor("scores".getBytes());
        tableDescripter.addFamily(new HColumnDescriptor("grade:"));
        tableDescripter.addFamily(new HColumnDescriptor("course:"));
        admin.createTable(tableDescripter);

        HTable table = new HTable(config, "scores");

        System.out.println("add Dan's data");
        BatchUpdate danUpdate = new BatchUpdate("Dan");
        danUpdate.put("grade:", Writables.getBytes(new IntWritable(1)));
        danUpdate.put("course:math", Writables.getBytes(new IntWritable(87)));
        danUpdate.put("course:art", Writables.getBytes(new IntWritable(97)));
        table.commit(danUpdate);

        System.out.println("add Dana's data");
        BatchUpdate danaUpdate = new BatchUpdate("Dana");
        danaUpdate.put("grade:", Writables.getBytes(new IntWritable(2)));
        danaUpdate.put("course:math", Writables.getBytes(new IntWritable(100)));
        danaUpdate.put("course:art", Writables.getBytes(new IntWritable(80)));
        table.commit(danaUpdate);

        for (RowResult row : table.getScanner(new String[] { "course:" })) {
            System.out.format("ROW\t%s\n", new String(row.getRow()));
            for (Map.Entry<byte[], Cell> entry : row.entrySet()) {
                String column = new String(entry.getKey());
                Cell cell = entry.getValue();
                IntWritable value = new IntWritable();
                Writables.copyWritable(cell.getValue(), value);
                System.out.format("  COLUMN\t%s\t%d\n", column, value.get());
            }
        }
    }

}

HBase には byte 列でアクセスするのでややまどろっこしい事になっていますが、やっていることは shell の時と同じです。これを実行します。

debian:~/tmp/hbase% javac HBaseBasic.java
debian:~/tmp/hbase% java HBaseBasic
drop table
08/10/23 12:51:59 INFO client.HBaseAdmin: Disabled scores
08/10/23 12:51:59 INFO client.HBaseAdmin: Deleted scores
create table
add Dan's data
add Dana's data
ROW     Dan
  COLUMN        course:art      97
  COLUMN        course:math     87
ROW     Dana
  COLUMN        course:art      80
  COLUMN        course:math     100

お疲れ様でした。次回は「HadoopMapReduce で HBase を使おう」をお送りします。

2008-01-27

今日日記 19:35

かまってほしくてanondに機能つけたよーと書いたらちょっとうざがられた。no titleを見て、合成したDNA酵母の中で繋げて今までより1オーダー長いのが作れましたってこと?ともかくDNAプログラマーなんて楽しそうだねーと思った。えーと後は、水曜に雪が降ったのでざくっざくざくと歌いながら散歩をしていたら迷子になってしまって携帯電話も持ってないし困ったなーと途方に暮れていたらたまたま下校中の知り合いの小学生に会って道案内をしてもらって助かった。ひどい話だな。

べんきべんき 2008/02/14 20:41 京都に戻るんですね

wanparkwanpark 2008/02/15 12:32 僕はまだどうするか決めてません

ああああ(勇者)ああああ(勇者) 2008/03/29 00:43 戻らなかったんですね。

06725970672597 2008/08/15 21:36 お知らせ
10月より教育テレビ 毎週木曜日午後7時〜(アニメ どんまい)を放送開始する予定です。(8/25)

http://www3.nhk.or.jp/anime/

ヒロイン里見優を演じるのは
中原麻衣

キャスト発表

里見優 中原麻衣
松平公平/リリー 関智一
ヒロミ 豊口めぐみ
並川真太郎 茶風林
岩井俊夫 屋良有作
坂本道子 鈴木れい子
大村晴男 中村大樹

2007-09-20

[]Gears of War 23:01

ついに収容所を抜けた。そのままCasualをクリアジンルイダ。ドカーンフィードインポート元を見誤ってtumblrのきれい写真をやたらみてしまった。写真となるととたんに感傷的になるヤツラメ、クルシメー。

智さん智さん 2007/10/31 22:22 教育テレビ土曜18:30枠のアニメ 12月から
「どんまい!」

人気コミック[どんまい!]をアニメ化。新米介護ヘルパー、里見優。行く家々で騒動を巻き起こし、苦情の嵐を受けながら[どんまい!]と、小さな希望の種をまいていく、パワフルな介護アニメです。

キャスト
里見優…下屋則子
松平公平…関智一
並川真太郎…滝口順平
ヒロミ…豊口めぐみ
岩井俊夫…八木光生
坂本道子…京田尚子
大村晴男…中村大樹

12月8日放送開始に先立ち、11月1日より
http://www3.nhk.or.jp/pr/keiei/shiryou/2007/11/001.pdf にて掲載されます

http://www3.nhk.or.jp/anime/donmai←NHKアニメワールドにて11月公開

智さん智さん 2007/11/11 13:29 11月12日放送予定の[豆丸、テングになる]で梅田陽子が挑戦!

梅田陽子さんが11月12日放送の[ぜんまいざむらい]
にて豆丸の天狗女房という役で登場します。お楽しみに。

智さん智さん 2008/03/04 20:22 4月5日からの教育テレビ 土曜17時台
17時〜17時25分[アニメ 雪の女王]
17時25分〜17時40分[テクテクキッズ コミー&ハーディー]
17時40分〜17時45分[ミニアニメ]
17時45分〜18時[モリゾーとキッコロ 森へ行こうよ]

2007-09-15

きょうの日記 プログラムを書くために理解が必要なレイヤーに限りはあるの? 16:08

論理的な面は一階述語論理を抑えておけばいいんだろう。ハードウェアがわからない。きっと技術進歩したら素粒子はまたなんとか子からできていることがわかって、でそういう無限後退は折り畳みなんとか理論でどうこうなって、って感じかなーと思っていたんだけど、Physical Chemistry: A Molecular Approachを読んでいたらそうでもない気がしてきた。というのもさ、原子スケールの世界が単純すぎると思うんだよね。シュレーディンガー方程式を解くのもニュートン運動方程式も、せいぜい自由度整数と実数くらいの差がある程度でそんなに変わらなそうなのに。整数が相互作用してべき乗で実数でそのくらいか。いやよくわからない。ともかくおかしい。もっと素粒子がごちゃごちゃしてわけわからなくなってるものじゃないの?わかってないってだけかな。自分と違うものは画一的に見えるものだからね。先週妹の高校文化祭に行って高校生達を見てたら、彼らは世界を漫画ストーリーとして認識してるんじゃないかと思ったからね。学校に行く前に妹の本棚漫画を読んだからなんだけど。イキガミっていう中高生向け人間交差点みたいな話で、嫌なものを見たなと思った。また勉強したら更新します。しなそう。

2007-08-19

きょうの日記 02:38

夜9時から夕方6時まで寝てしまった。大戸屋チキンかあさん煮定食を食べる。寝起きで食べるには味が濃い。その後最近は興味が一周して生物学ブームなのでDevelopmental Biologyを読み進める。学部の発生の授業くらいはやっているので英語の感覚をとりもどそうというチョイスで。適当な総説を読むほうが楽しそうなんだけど手頃な入手手段がない。大学のそばに住みたいな。最終的な目的生物様のシステムを作ろうで、発生様式をかたっぱしから知りたいなーと思っていたんだけど、脊椎動物昆虫以外は細胞系譜固定でと書いてあるのでそんなに面白くない気もする。いや脊椎動物がどうこうっていつの時代のヨーロッパだという話だ。ホヤ脊椎動物でこうも違うなんて不思議だねーなんだけど明確な差があるわけじゃないんだろう、というのは本に書いてあったことだけど。そういうところの変化によりその後の形態進化の質が変わったのだ、なんて話だと楽しいね。魚の形を考えるという本を読む。ETVでも頻出の左ヒラメに右カレイ教育的正当性をぶつぶつとグループで言う、にしても教育のことは知らないからいいやということになった。それから仕事を始めて、気が乗らないのですぐやめる。時計の短針と長針を見違えてブックファーストに行きそびれた。アナログ時計UIがうんたら、というのは今web日記用に考えたことで特に思ってはない。そういえばkusigahamaがなんか言ってたなと思ってTest Drive Unlimitedを買う。いまここ

kusigahamakusigahama 2007/08/19 22:38 わんぱーくは意外と気に入るかも。
ダメだったら買い取るよー。

wanparkwanpark 2007/08/20 13:00 Xboxごと差し上げるので今後一切ともみちゃんに近づかないでください。

rikoriko 2007/08/20 14:22 みんななかよく!><

06725970672597 2008/10/12 10:41 (アニメターサン) キャスト

第1話
ターサン 進藤尚美 ハゲタカパパ 平井啓二
オウム 田の中勇 馬 龍田直樹 王妃 山崎和佳奈
カール11世 田中秀幸 ボルト 郷里大輔
ダニエル 田中一成 パン屋の主人A 田中大文
パン屋の主人B 竹本英史 八百屋の主人 岡本寛志
女性A 斉藤貴美子 女性B 豊嶋真千子
仕立て屋さん 中山さら

智さん智さん 2008/10/21 20:47 ターサン 進藤尚美 ハゲタカパパ 平井啓二
馬 龍田直樹 王妃 山崎和佳奈 ダニエル 田中一成
アラン 神谷浩史 アランの母 久川綾
ポール 日比愛子 ジャン 白石涼子
キャリー 神田朱未 郵便屋 沼田祐介
町の男A 森岳志 町の男B 宮坂俊蔵

智さん智さん 2008/10/26 20:31 ターサン 進藤尚美 ハゲタカパパ 平井啓二
馬 龍田直樹 カール11世 田中秀幸
ダニエル 田中一成 フィリップ 草尾毅
アラン 神谷浩史 ナナ 今野宏美
サイモン 矢田耕司 ボーリー伯爵 野田圭一
ビリー 三浦祥朗 マリー 鹿野優以 兵士A 岡本寛志
兵士B 田中大文 兵士C 宮坂俊蔵 兵士D 福原耕平

06725970672597 2008/11/02 19:25 ターサン 進藤尚美 ハゲタカパパ 平井啓二
馬 龍田直樹 フィリップ 草尾毅
ダニエル 田中一成 ナナ 今野宏美
アラン 神谷浩史 おじさん 八奈見乗児
ダニー 浦和めぐみ トニー 田中真弓
客A 福原耕平 客B 高塚正也