サーバ機にSSDを使うのは時期尚早

という話を聞いた

  • ファイルシステムSSDに対応していない、現在のファイルシステムはDiscで使うことを想定している。回転ディスクの場合、円盤の内側の方が速度が速いため、ファイルシステムは円盤のなるべく内側を使おうとする傾向がある。しかし、SSDの場合セル毎に寿命があるため、同じセルに読み書きされ、寿命が急速に縮まる可能性がある。早いと3ヵ月とかでダメになるらしい。
  • 書き込みが半分以上を超えると、書き込み速度がHDDを下回る。これはどのセルにどのデータが書き込みされているかなどを計算する部分がボトルネックとなっていると思われる。今後ドライバの更新などで改善されるかもしれない。

ただし、読み込みは確かに早いので、読み込み専用のシステムや書き込みの少ないシステムには有効

携帯のSSL証明書

今までは ベリサインのを使うのが普通だっただが、RapidSSL(reseller?)のRoot証明書が2009/05/29付でEquifax Secure Certificate Authorityに変更になったため、ほとんどの端末で利用可能になりそうだ。ベリサインの証明書を使うと年間8万とかかかるけど RapidSSLだと4000円くらいで済むし、ワイルドカードも発行できるため、低コストで運用したい場合にはいいかもしれない。

参考
http://www.rapid-ssl.jp/rapidssl-support/faq/index.php?action=artikel&cat=4&id=1&artlang=ja
http://www.geotrust.co.jp/resources/compatibility_listing/index.html

携帯キャリアがサイトを何にカテゴライズしてるか分かるスクリプト

require "rubygems"
require "net/http"
require "uri"
require "nkf"
require "nokogiri"
uri = URI.parse("http://category.netstar-inc.com/check/res.php")
Net::HTTP.start(uri.host, uri.port) do |http|
   request = Net::HTTP::Post.new(uri.path)
   request["user-agent"] = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"
   request.set_form_data({:url => ARGV[0]})
   html = Nokogiri(NKF::nkf("-w -m0", http.request(request).body))
   html.search(".result_text").each do |result|
     print result.inner_html
   end
end

入力

ruby categorize.rb http://gree.jp

出力

■確認したURLhttp://gree.jp■分類結果大カテゴリ コミュニケーション<br>小カテゴリ 掲示板<br>

NTTの支払い明細を紛失してしまった場合の対処方法

NTTの支払い明細を紛失してしまって、そのこと自体も忘れていて、ついにネットが停止してしまった。この場合の支払い方法の手順のメモ

  • ミニストップサークルK、サンクス、スリーエフ、ローソン、ファミリーマートなどに無料で置かれているスマートピットカードをゲットする。
  • NTT料金問い合わせセンターに電話し、スマートピットカードでの支払いをしたい趣を伝え、スマートピットカードの番号を通知する
  • NTT料金問い合わせセンターがカード番号と支払情報の紐づけを行ってくれる
  • コンビニに行って、ミニストップサークルK、サンクス、スリーエフならばカードを直接レジで提示して、ローソン、ファミリーマートは店内にある端末でレシートを発行して、料金の支払いを行う
  • 1時間後くらいに復旧

便利な世の中だー。ちなみにサービス元締めはNTT COMWAREらしい

Railsプラグイン ez_where がクソ便利

Railsの検索画面などを作るときに、入力パラメータに合わせて conditionsを変更したい場合等が多数あると思うけどそういう場合は ez_whereがめちゃ便利

インストール

./script/plugin install http://opensvn.csie.org/ezra/rails/plugins/dev/ez_where/

Userテーブルのemailかnameかcategoryのどれかが入力されていて、入力されている値でconditionsを生成したいという場合は以下の通り

  options = {:limit => 300}
  @users = User.ez_find(:all, options) do |where|
    where.email == params[:email] unless params[:email].blank?
    where.name  =~ "%#{params[:name]}%" unless params[:name].blank?
    where.category == params[:category] unless params[:category].blank?
  end

演算子によって where句がうまく生成される。ちなみに演算子とwhereの対応は

foo == 'bar' ["foo = ?", 'bar']
foo =~ '%bar' ["foo LIKE ?", '%bar']
foo <=> (1..5) ["foo BETWEEN ? AND ?", 1, 5]
foo === [1, 2, 3, 5, 8] ["foo IN(?)", [1, 2, 3, 5, 8]]
foo > 1 ["foo > ?", 1]

という感じになる。またwill_paginateなどで使用したい場合は

  cond = Caboose::EZ::Condition.new
  cond << ["email = ?", params[:email]] unless params[:email].blank?
  cond << ["name like ?", "%#{params[:name]}%"] unless params[:name].blank?
  cond << ["category = ?", params[:category]] unless params[:category].blank?
  @users = User.paginate(:page => params[:page], :per_page => 30,
                         :conditions => cond.to_sql)

と conditionsに << で追加する形式も対応している。

Hadoopの 0.18.0には fuse-dfsが含まれている

というより、元々あったのだが、 0.18.0からは contrib に含まれるようになった。これを使うと、Hadoop分散ファイルシステムである dfs に普通に読み書きしたりできる。今までは基本的にJavaのbyteStreamで読み出さなければならなかった。基本的には hadoop/src/contrib/fuse-dfs/README を見ながらやる。

  • fuse が入っているか確かめて無かったら入れる
lsmod | grep fuse
fuse                   47124  0
  • antでHadoopをリビルドする
cd hadoop_root
# fuse-dfs の READMEの通りではできなかった
# make でエラーが出たら jni.h や fuse-devel にinclude pathを通す
ant compile-contrib -Dcompile.c++=1 -Dlibhdfs=1 -Dlibhdfs-fuse=1

hadoop/src/contrib/fuse-dfs/srcあたりにfuse_dfsができるので、一緒のディレクトリにある起動補助スクリプトを開いてJAVA_HOME,HADOOP_HOME, LD_LIBRARY_PATH, CLASSPATHあたりを修正しておく。また、あらかじめ Hadoopを起動してファイルシステムをフォーマットしておく。

mkdir /mnt/haddoop
./fuse_dfs_wrapper.sh dfs://localhost:54310 /mnt/haddoop
# 起動補助スクリプトを使用しない場合は
./fuse_dfs --server=localhost --port=54310 /mnt/hadoop -o-o allow_other,rw -d

で lsとかができれば成功、アンマウントは

fusermount -u /mnt/haddoop

これで安価でスケーラビリティや障害耐性のある、バックアップシステムとかは簡単に作れそうだ。

MeCabをJNIから利用する

MeCabの 各言語のバインディングは Swing経由で利用できるのだが、なぜか Java版がうまく動かなかったので、他のバインディングを探したところ

http://code.google.com/p/cmecab-java/

があった。ただ品詞IDが取れなかったので、それを取れるようにソースを修正した。

cmecab-java/jni/net_moraleboost_mecab_Node.h

+ JNIEXPORT jlong JNICALL Java_net_moraleboost_mecab_Node__1postid
+  (JNIEnv *, jclass, jlong);

cmecab-java/jni/mecab.cpp

JNIEXPORT jint JNICALL
Java_net_moraleboost_mecab_Node__1posid(
    JNIEnv* env,
    jclass clazz,
    jlong hdl
    )
{
    DECLARE_CLASS(oomError, env, CLASS_OUT_OF_MEMORY_ERROR, 0);
    DECLARE_CLASS(mecabException, env, CLASS_MECAB_EXCEPTION, 0);

    try {
        const MeCab::Node* node = hdl2node(hdl);
        return node->posid;
    } catch (...) {
        env->ThrowNew(mecabException, "Unknown error.");
    }

    return 0;
}

cmecab-java/src/net/moraleboost/mecab/Node.java

+  public int posid()
+  {
+      if (prevHandle == 0) {
+          return 0;
+      } else {
+          return _posid(prevHandle);
+      }
+  }
+  private static native int _posid(long hdl);

    while (node.hasNext()) {
        System.out.println(node.posid());
    }

な感じで使える。