2012-01-24

HBase shell で java.lang.Float.NaN を値として持つ行をフィルタリングする

不具合の調査で java.lang.Float.NaN が入っている行をフィルタリングしたいことがあったので調べました。文字列でフィルタリングするときは以下のような感じです。
import org.apache.hadoop.hbase.filter.ValueFilter
import org.apache.hadoop.hbase.filter.BinaryComparator
filter = ValueFilter.new(ValueFilter::CompareOp::EQUAL, BinaryComparator.new("some_value".to_java_bytes))
scan 'table_name', {"FILTER" => filter}
java.lang.Float の場合はそのままでは呼び出せないので以下のようにする必要があります。
import org.apache.hadoop.hbase.filter.ValueFilter
import org.apache.hadoop.hbase.filter.BinaryComparator
filter = ValueFilter.new(ValueFilter::CompareOp::EQUAL, BinaryComparator.new("\x7F\xC0\x00\x00".to_s.to_java_bytes))
scan 'table_name', {"FILTER" => filter}
本来はこれでいけるはずなのですが、なぜか問題のテーブルには \x7F\xC0\x00\x00 ではなく \xFF\xC0\x00\x00 が入っているっぽい。JDK の API ドキュメントでは 0x7fc00000NaN と書いてあるのですが。ということで Scala の REPL で軽く確認してみました。
scala> java.lang.Float.intBitsToFloat(0x7fc00000)
res0: Float = NaN

scala> java.lang.Float.intBitsToFloat(0xffc00000)
res1: Float = NaN
うーん java.lang.Float.NaN はバイナリ的に 2種類ある……のか?