Firefoxからアルクを検索する

WEB上で英語を読む時は前からアルクを使っているのですが、どうにかしてFirefoxの右クリックから検索できないものかと思っていました。

と、思ったらすでにいくつか方法があるみたいです。

ということで、今回は違う方法を。

popin

Firefoxプラグインpopinというのがあります。
何をやってくれるかと言うと、検索したいワードをドラッグで選択された状態にすると、右下に検索エンジンの選択が出てくるのでそこから検索できます。↓な感じで。(英語版WikipediaにてGoogleを検索)

popinの何がいいかと言うと、

  1. iframeを使っているので、アルクのホームページに飛ぶこと無く、その場で単語の確認ができる
  2. アルク以外にも検索窓があるサイトを検索したい検索エンジンに追加できる

何といっても、やはり一つ目のiframeでの検索がいいですね。
単語の意味を検索したいだけなので、わざわざ別タブを開くのは閉じるのがメンドイので。

アルクを追加する

詳しくは公式HPの動画を見ていただければと思います。
ちょうど、検索エンジンの追加例として、アルクが載っています。

ポイントはまあ、iframeで表示させる部分を選択する手順があるので、そこでいい感じに選択することですかね。↓

個人的にアルクを検索する時はこの方法が一番いいんじゃないかと思うこの頃です。

コードリーディング

引き続き今更WEB+DB Press Vol.35を読んで。

予備知識

  • 見るべきところ
    • モジュールの構成と役割
    • アルゴリズムとその意図
    • データ構造の意味
  • 解析の種類
    • 静的解析
    • 動的解析
      • 実際に動かす
  • 心得
    • 「メモ」をとりつづけること
      • わかったことをどんどんメモって残す、不要になったメモはどんどん捨てる
  • 全体構造の把握構造
    • README
    • ディレクトリ構造
      • viewというファイルがあればMVCモデルを使っているだろうとか
    • ビルドファイル(build.xml)
      • 依存関係の確認
    • 実際にビルド、またはサンプルプログラムを動かす
    • どのファイルが重要か、どのファイルから手をつけるかを確認

実践

  • ひらメソッド
    • 処理内容の把握は後回し
    • エントリポイントから呼び出している関数を洗い出し、コールグラフをまず書く
    • 末端の関数まで降りてきたら、そこで始めてコードを読む
    • 各メソッドごとにWikiでメモを残す
  • ソースディレクトリ全体の検索
    • $ find . -print | xargs grep -n キーワード
    • リフレクションやプロパティファイルの使用箇所を見つける
  • 意図を汲む
    • クラスや関数の名前に注目する
    • 単体テスト用のコードを見る
      • 単体のテストコードに実装コードの使い方、意図が書いてある

Javaの場合

  • インターフェースの多用
  • DIの使用
    • 呼び出し元がない場合はDIを疑う

Eclipseの便利技

  • F3
    • 宣言ジャンプ
  • F4
    • 型階層を開く(実装コードを開く)
  • Ctrl + Alt + h
    • 呼び出し階層を開く

感想

  • 知らないうちにやっている技?が多いので、それを意識してできるようになりたい
  • コールグラフは全体像を把握するのに良さげ
  • ひらメソッドがかなり良さそう
    • これでSeasar2のコード読みたい
    • 誰か先にやって、どっかのWikiで公開してないかなあ

Javascriptの高速化

こちらも今更ですが、WEB + DB Press Vol.35 を読んだメモ。
今日、jQueryとかのライブラリの躍進が目覚ましいので、それほどイベントハンドラをごちゃごちゃ書く機会もなくなっているのかなーとも思いますので、使いそうなところのみ。
(というか自分の能力がしょぼいから書く必要性を感じていないということかも...orz)

DOMへのアクセスを少なくする

DOMへのアクセスをできるだけ少なくする = できるだけ.(ドット)を使わないようにする

.(ドット)へのアクセス回数を減らす
var nameList = document.getElementById('name');
nameList.style.height = '100px';
nameList.style.weight = '100px';
nameList.style.top = '100px';

↓↓↓

var nameList = document.getElementById('name');
var style = nameList.style;
style.height = '100px';
style.weight = '100px';
style.top = '100px';
上に同じく。forでlengthを使うとき
var nameList = document.getElementById('name');
for (var i = 0; i < nameList.length; i++) {
    // 繰り返し処理
}

↓↓↓

var nameList = document.getElementById('name');
for (var i = 0, var len = nameList.length; i < len; i++) {
    // 繰り返し処理
}
innerHTMLはコストが高いので、できるだけ参照しない
var nameList = document.getElementById('name');
name.innerHTML += '<div>\n';
name.innerHTML += 'div要素が追加されます.\n';
name.innerHTML += '</div>\n'

↓↓↓

var nameList = document.getElementById('name');
var html = nameList.innerHTML;
html += '<div>\n';
html += 'div要素が追加されます.\n';
html += '</div>\n'
nameList.innerHTML = html;

Postgresのレプリケーション

WEB+DB Press vol.35を今更読んで、前から気になっていたPostgresのレプリケーションについてメモ。
ただし、文章中にPostgres8.1.4とか出てくるので情報が古い、アンド、全然調べていないので未確認情報もあると思うので、本当にメモ程度ですね...

pg-pool II

  • コネクションプーリング
  • レプリケーション
    • 同期型
  • 負荷分散
  • パラレルクエリ
    • カラム i の値が10以下の時はノードAから、11以上の場合はノードBよりSELECTして、検索結果をマージ
    • 論理的には、ノードを増やせば増やすほど検索性能が上がる
    • ただしJOINを伴うような複雑な問い合わせは、あまり性能が出ない
  • レプリケーションモードかパラレルクエリモードのどちらかしか選べない
  • pg-pool adminによるGUIでの管理
  • pg-poolが落ちると、元も子もない
    • 以前ポスグレのカンファレンスで、pg-pool自体のレプリケーション検討って言ってたけど、もう実装されてるんかな??

PostgresForest

  • レプリケーション
    • 同期型
    • SELECTはノードのどれかに問い合わせ
    • オンラインリカバリが可能
  • 縮退運転から正常運転までに2つのフェーズがある
    • フェーズ1
      • ノードの差分を更新
    • フェーズ2
      • ノードの差分を更新している間の差分を更新
      • フェーズ2処理時はマスタの更新も止まる
      • アプリケーションからは処理を継続しているように見える
  • pg-poolみたいにデーモンとかいないのかな??
    • 仮想化モジュールで対応してる??(未確認)
  • そういえば、前は8.3に対応してなったけど、今は対応してるみたい

PGCluster

  • レプリケーション
  • PGCluster II
    • Oracle RACのようにディスクをシェアするシェアードエブリシング方式
      • ちなみにpg-poolは、ディスクをシェアしないシェアードナッシング方式
    • 高可用性
  • 三谷さん
    • 聞く限り三谷さんほぼ一人で開発されてる??
    • ちょっとそれは怖いかも...笑
    • でもサポートとかは、かなり誠意を以って対応してもらえるとも
    • いつ寝てるんだという噂も...笑

Slony-I

  • シングルマスタ/マルチスレーブ構成
    • マスタとスレーブは非同期で同期
    • 非同期なので、復旧手順を詰める必要がありそう
  • 各ノードにSlonデーモンというのが動いている
    • これが落ちたらどうするんやろう??

一度色々試してみたいですねー。

(function() {})()とかnew function() {}とか

一昔前に (function(){})() とか new function() {} とか function() {}() とかは何やねんという記事が流行った??時期がありました。

あの時は、いくつか記事を読んでも正直もう何が何だかわからなかったのですが、久しぶりに紐解いてみるとちょっとはわかったような気がしたのでメモ。

まず、(function() {})()とかnew function() {}の違い

これに関しては、ココが非常に単純明解です。
こちらも参照。

つまり、

  • (function(){})()
    • 無名関数を今すぐ実行
    • 最後の () が今すぐ実行するということ
    • ロード後1度だけ実行
// 無名関数をすぐに実行
(function(){
    // 初期化処理などを行う
    alert('test1');
})();
  • new function() {}
    • 無名オブジェクトを作成して、その場で new することでインスタンス生成(=無名コンストラクタ実行)
    • ロード後1度だけ実行
new function() {
    // 初期化処理などを行う
    alert('test2');
}

function(){} () は何者か??

例えば、よくみかける

var test3 = function() {
    return 'test3';
};

というのは、

var test3 = function() {
    return 'test3';
};
alert(test3)

だと、

function() {
    return 'test3';
};

というように、関数の文字列自体がalertされます。
なので、

var test3 = function() {
    return 'test3';
};
alert(test3()) // test3 じゃなくて test3()とする

とtest3が関数として見做され、「test3」 という文字列がalertされます。
つまり、変数test3は、関数自身を参照している?ことになる・・・のかな??

では、本題の下記はどうかと言うと

var test4 = function() {
    return 'test4';
}();
alert(test4);

は、「test4」という文字列が表示されます。
つまり変数test4は実行結果が代入されていることになります。
で、

var test4 = function() {
    return 'test4';
}();
alert(test4());

は、firebugだと、「test4 is not a function」とエラーになります。
つまり、上記の変数test4は、実行結果なので関数じゃないよ、って怒られているようです。
となると、単に関数宣言の後に () があると今すぐ実行になるよ、ってだけの話のようです。

という結論が、もっと詳しくココに書いてあります。

ちなみに

式と文の件はもうお腹一杯なので、ココとか、見るといいかもしれません。
あと、この記事は勉強になりました。
以上、今更ですがメモ程度に。

Javaにおけるファイルロックについて

いわゆるファイルロック

File lockFile = new File("pid.lock");
lockFile.deleteOnExit();

while (lockFile.createNewFile()) {
    try {
        // ロックを取得している場合の処理
        ...
    } finally {
        lockFile.delete();
    }
} else {
    throw new RuntimeException("ロックを取得できませんでした.");
}

上記はいわゆるファイルロックと言われるものです。
マルチスレッド環境の際に同じ処理が並列に実行されるとマズい場合、ファイルロックにより同じ処理が並列に実行され内容に制御します。
File#createNewFile() は、ファイルが存在しなければ新規にファイルを作成しTrueを返し、既にファイルが存在すればFalseを返します。
ただし、上記はうまく動かない場合があります。
詳しくはこちらを見ていただくといいかと思いますが、要はJavaVMが異常終了したときなどにロックファイルが残り続けてしまうのが問題となります。
ちなみに、

  • File#deleteOnExit()
    • JavaVMが「正常終了」した時にファイルを削除
    • 「正常終了」の定義は、Java言語仕様に書いてあるそうですが、プロセスをkillするとかディスクがぶっ飛ぶとかしない限りは正常終了に当たるっぽいです。(未確認)

FileLockオブジェクト

ということで紹介されている通り、FileLockオブジェクトを使用します。
ちなみにFile#createNewFile()のJavaDocにも、File#createNewFile()はファイルロックに使用すべきでなく、FileLockを使用するよう書いてあります。
FileLockを使用すると、下記のようになります。

try {
    File lockFile = new File("pid.lock");
    lockFile.deleteOnExit();

    fs = new FileInputStream(lockFile);
    FileChannel fc = fs.getChannel();

    FileLock lock = fc.tryLock();

    if (lock == null) {
        new RuntimeException("ロック中");
    }

    try {
        // ロックを獲得している場合の処理
        ...
    } finally {
        // ロックの開放
        lock.release();
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
    	fs.close();
    } catch (IOException e) {
    	e.printStackTrace();
    }
}

FileLockオブジェクトは、FileChannelを通して取得します。
FileLockは、ここに詳しい説明が書いてありますが、

基本となるオペレーティングシステムのネイティブのロック機能に直接マッピングされます。
このため、ファイルにアクセスできるあらゆるプログラムが、作成に使用された言語とは関係なく、このファイル上に保持されたロックを認識します。

だそうです。
FileLockオブジェクトは、たぶんJavaVMが正常終了・異常終了に関わらず、終了すれば消えてくれる??ので、File#createNewFile()みたいにロックが残りつづけることがないんでしょうかね。(未確認)
(File#createNewFile()は、ファイルの有無=ロックの有無なので。ということでFileLockオブジェクトを使用してもファイルは残る、でもロックは解除される??)

  • FileChannel
  • FileChannel#tryLock()
    • ロックを取得します。ただし、ロックを獲得できなかった場合は、すぐにメソッドを終了し、nullを返します。
    • 逆にFileChannel#lock()は、ロックを獲得するまでの間処理をブロックして待機します。
  • FileLock#release();
    • ロックを開放します。
    • FileChannelを先に閉じてしまうと、ClosedChannelExceptionが発生するので注意。
  • FileInputStream#close();
    • ファイル入力ストリームを閉じます。
    • ここにあるように、FileChannelは作成元となったストリームと密接に関係しているため、FileChannelも同時に閉じられます。

気になったこと

FileChannel#tryLock()の仕様

JavaDocによると、

オーバーラップしたロックが別のプログラムによって保持されていたためロックに失敗した場合、null が返されます。その他の原因でロックに失敗した場合は、適切な例外がスローされます。

とあります。
ですが、どうもnullが返されず、いつもOverlappingFileLockExceptionがスローされます。
nullっていつ返ってくるんでしょうかね。

ロックの種類

ここの余談にもありますが、Linuxはアドバイザリ・ロック、Windowsは強制ロックでJavaが実装されているようです。

  • アドバイザリ・ロック
    • あるプロセスのロックは異なるプロセスへ影響を与えない。
    • つまり異なるプロセス間のロックによる管理は行えない。
  • 強制ロック
    • あるプロセスのロックは異なるプロセスへも影響を与える。
    • つまり異なるプロセス間のロックも行える。

ということで、LinuxWindowsの挙動が違います。
Javaのプロセスの定義とスレッドの定義がイマイチまだよくわかっておらず、どうしたらマルチスレッドでどうしたらマルチプロセスなのか。
つまり、例えば java コマンドで複数実行すればマルチプロセスになるのかどうかとか。(←それくらいすぐ調べられるから調べろよ。。。)

FileLockの仕様

ここに下記のような文章があります。

ファイルロックは Java 仮想マシン全体のために保持されます。これらは、同一仮想マシン内の複数スレッドによるファイルへのアクセスを制御するには適していません。
ファイルロックオブジェクトは、複数の並行スレッドで安全に使用できます。

これがまた曲者で、読み手の読み方次第でいろんな解釈の仕方がありそうなんですが。。。
「複数スレッド」と「複数の並行スレッド」ってそんなに意味が変わらないような。
つまるところ、「ファイルアクセス制御」には使うな、でも「ロック」としては使えるってこと??

UbuntuJDK

Ubuntuを使用しているので、apt-getよりJDK1.6.10をインストールしています。
で、何が問題なのかと言うと、Ubuntuのコマンドには「fcntl(2)」コマンドがありません。。。
ここの余談では、LinuxJDKは「fcntl」で実装されているそうなんですが。
で、調べてみると「fcntl」はシステムコールだそうです。(システムコールとは)

システムコールの種類は unistd.h というファイルで一覧が確認できるみたいなので、調べてみました。
使ってるPCはcore2quad(アーキテクチャx86)なので、/usr/src/linux-headers-2.6.27-14-generic/include/asm-x86/unistd_32.h を見ると、

#define __NR_fcntl               55

って書いてあるので、システムコールとしては存在するみたいですね。
まあUbuntuLinuxという大きな枠組みの中の一つのカーネルですので、まああるとは思っていたのですがコマンドから使えないシステムコールもあるんですね。(まあそりゃそうか)
「55」っていう番号の意味はこことかがわかりやすいです。

Ubuntuのvimでfuzzyfinder3.1を使う

fuzzyfinderというvimスクリプトがあるのは前から知っていたのですが、3系がリリースされたのでこれを機に使うことにしました。
使い方は、ここからダウンロードして、docを見てください。(でも個人的には少しわかりにくかったので、時間があればまとめたいです)

作業ログ

$ mkdir ~/.vim/fuzzyfinder
$ unzip vim-fuzzyfinder.zip -d ~/.vim/fuzzyfinder
$ vi .vimrc
----------------------------------------------------
" fuzzyfinder
set runtimepath+=~/.vim/fuzzyfinder
----------------------------------------------------

doc/fuf.jaxのインストール方法はこれだけなんですが、なぜかこれだけでは:FufBufferとかのコマンドが出てきませんでした。
2系列のfuzzyfinderはうまく動いたので、2から3に変わるときに何か変更が入ったんかなーと思って見てみると、各vimファイルの下記がだめなようです。
たとえば、plugin/fuf.vimであれば、

if exists('g:loaded_fuf') || v:version < 702
   finish
endif
let g:loaded_fuf = 1

というように、全てのvimファイルに上記のようにv:version < 702と書いてあり、Ubuntuのパッケージの最新のgvimは701なのでスクリプトの読み込みがされていないようでした。
ということで動くかどうかわからんけど、やってみようということで少しif条件を変更してみました。

gvimを起動して、cdで~/.vim/fuzzyfinderに移動
で、コマンドラインモードより下記をタイプ

:vimgrep /v:version/ **/*.vim | cwin

んでもって、702の部分を全て701に変更しました。
まあ、sedとかでもいいんですが、せっかくなのでvimgrepを使用しての変更にしてみました。笑
今のところこれでも普通に使えてるので、問題ないのかなーという感じです。
うーん、こりゃ便利。今までなんで使ってなかったんやろうと後悔しますねー。