メニュー

関連ページリンク

トップ > Googleカレンダー > Googleカレンダー - 人気ブログ(Blog)検索結果詳細 (2008年12月2日 7時)

symfony propelでシーケンス名が省略されてしまう

yukiです。

今回は「symfonyでよくあるトラブル」を掲載してからちょうど1年を経過したので、また今年も取り上げてみたいと思います。

前回はsymfony+MySQLを使っての場合でしたが、今回はsymfony+PostgreSQLでお送りします。
とはいえ以前よりもだいぶsymfonyを取り巻く状況も変化し、バグらしいバグもほとんど既知のものだったり、枯れて(?)きたのかな、とも思います。
そんななか、小一時間ほどハマってしまった不具合があったので、今回はそのご紹介のみになります。

symfony propel-build-modelで作成したSQLのシーケンス名が食い違う

どうもテーブル名やカラム名がある程度長いと、途中で省略されてしまったりして、誤認識してしまう。
PostgreSQLの場合英数字63文字(63byte)までは問題ないはずが、どうもそれより短い文字数でも途中で切れてしまう問題。
どうもPropelのバグらしいので、自作パッチを当てるなり、UPDATEで修正されることを期待するしかなさそうです。

$ cat symfony/lib/vendor/propel-generator/classes/propel/engine/platform/PgsqlPlatform.php
中略
    /** 
     * @see        Platform#getMaxColumnNameLength()
     */
    public function getMaxColumnNameLength()
    {   
        return 32; 
    }   

中略

今回もアッサリしたエントリになってしまいましたが、お役に立てれば幸いです。

作者: unoh

更新日:2008年12月1日 7時41分

このブログのホーム

NetBeansでConsolasフォントを使う

yamaokaです。

NetBeansの6.5がリリースされましたね。もともとNetBeansはJava用のIDEですが、今ではPHPやRuby、C/C++の開発にも使えるようになっています。PHPをバンドルしたものを試しているのですが、入力補完など基本的な動作はもちろん、Subversionなどバージョン管理ツールとの連携も便利で個人的な開発にはすっかり手放せないものとなってしまいました。

さて、新しいIDEやエディタを導入したとき、皆さんは初めに何をするでしょうか。私の場合はフォントの設定を行う場合が多いです。Consolasフォントがお気に入りなのですが、Windows環境に導入したNetBeansでエディタのフォントにConsolasを指定すると 日本語が正しく表示されません(豆腐文字になってしまいます)。Windowsのフォントリンクの機能なども試してみましたが、うまく表示されないようです。

NetBeans
NetBeans posted by (C)フォト蔵

NetBeansはSwingで動作しているので、Java側で設定されている論理フォント「Monospaced」の設定を書き換え、「Monospaced」を使うようにすれば表示することができるようになります。ということで、Java側の設定を変更してしまいます。ちなみに、今回NetBeansはJava SDK 1.6.0_10に付属のJREで動作しています。

Javaの設定はプロパティファイルで変更することができます。JDKをインストールしたフォルダに「jre」というフォルダがあるので、その中にある「fontconfig.properties.src」をコピーして同じ場所に「fontconfig.properties」というファイルを作り、エディタで編集します。

まず、Consolasフォントが使えるように末尾に次の内容を追記します。

filename.Consolas=CONSOLA.TTF
filename.Consolas_Bold=CONSOLAB.TTF
filename.Consolas_Italic=CONSOLAI.TTF
filename.Consolas_Bold_Italic=CONSOLAZ.TTF
また、なぜかWindows環境で「Monospaced」が指定された場合に英字フォントより日本語のフォントを優先して使うようになっているので、「sequence.monospaced.windows-31j」の値を「alphabetic」と「japanese」を逆にして次のように変更します。
sequence.monospaced.windows-31j=alphabetic,japanese,dingbats,symbol
最後に、「Monospaced」の英字フォント設定を変更します。デフォルトでは「Courier New」になっているので、「Consolas」に変更していきます。変更箇所は4ヶ所です。
monospaced.plain.alphabetic=Consolas
monospaced.bold.alphabetic=Consolas Bold
monospaced.italic.alphabetic=Consolas Italic
monospaced.bolditalic.alphabetic=Consolas Bold Italic
変更が終わったら「fontconfig.properties」を保存してNetBeansを起動しましょう。エディタのフォントはMonospacedに設定します。

NetBeansでConsolasフォント
NetBeansでConsolasフォント posted by (C)フォト蔵

英字部分はConsolasで、日本語部分はMSゴシックで表示されるようになるかと思います。日本語の表示を他のフォントに変更する場合は、同じように「fontconfig.properties」の値を書き換えることで変更できます。

フォントの変更方法について書いてきましたが、NetBeansはかなり便利です。何より、体感的にEclipseより動作が軽い気がします。XDebugを使ったリモートデバッグもできるようなので、そのうち試してみたいところです。

作者: unoh

更新日:2008年11月26日 5時52分

このブログのホーム

PHPライブラリ Net_TokyoTyrantの紹介

皆さんopenpearしてますか!
最近、インフルエンザの予防接種を受けたKeitaです。

ずいぶん前にですが、PHPからTokyoTyrantをネイティブに操作するライブラリをopenpearにてリリースしたので、簡単に紹介したいと思います。

Net_TokyoTyrantとは?

PurePHPで書かれた、TokyoTyrantのネイティブなインターフェースを叩くライブラリです。
memcache互換のインターフェースなどとは違い、TokyoTyrantのLUA拡張などTokyoTyrant本来の機能をほぼすべて使えるというのが特徴です。

インストール

PEARライブラリとして公開されているので非常に簡単にインストール可能です。
openpearのチャンネルを追加します。
pear channel-discover openpear.org

PEARコマンドでインストールを行います。
pear install openpear/Net_TokyoTyrant

サンプルコード

概ねですが下記のような感じで利用できると思います。
関数などは、TokyoTyrantの本家ページにあるものすべてをサポートしています。
require_once 'Net/TokyoTyrant.php';

$tt = new Net_TokyoTyrant();
$tt->connect('localhost', 1978); //接続


$tt->put('oyomesan', 'nounai');
var_dump($tt->get('oyomesan'));
$tt->put('kanozyo', 'pc no naka');
$tt->put('kareshi', 'otoko ha chotto');
var_dump($tt->mget(array('oyomesan', 'kanozyo')));
var_dump($tt->fwmkeys('ka', 100)); //kanozyo, kareshiが返ってくる

$tt->close() //切断

作成した経緯

当初、memcachedのインターフェースからTokyoTyrantを操作していたのですが、PHPのmemcache拡張は、複数の値を一括して取得するmgetや情報取得用の機能がないため、ついカッとなって一晩で作りました。

※今では、gree labsさんで公開されているlibmemcached用のインターフェースなどに備わっているので、memcachedをPHPから使うという場合限っては他の言語と同様に、PHPはまったく機能が不足しているといことはありません。

テストコードを書いたので休日のストレス解消に時々リファクタをしていますがほとんどインターフェースは変わってません。

今後について

以下をやってみたいなーとおもってます。
  • コメントをまったく書いてないのでコメントを書く
  • 例外周りの実装が美しくないので直す
  • TokyoTyrantが64bit整数を返してくるものがあるがそこらへんの扱いをPHPでどうするか考えてないので考える
  • 実践投入してみる

もしくはopenpearの設定で登録してあれば修正できるようになっているので誰かが修正してくれたらなーともおもっています。
また、ベンチマークコードも、oepanpearにて公開しているのでそこらへんの調査もきっちりできればなーというか誰かしてくれないかなぁなどと思っております。

最後に

Net_TokyoTyrantは、id:riafさんとid:sotarokさんが作られている、openpearにて公開されています。

実際に利用してみるとわかりますが、初めてでも1時間程度で、pearとして自分のライブラリを公開することができます。 なおかつsvnなどの面倒も見てくれるので個人でものを作るには非常に便利な環境です。

このサイト自体が、PHPフレームワーク(正確にはPHP libraries & Setup Framework)rhacoで書かれておりここらへんの話だけでも興味深いサイトといえると思います。

誰かのライブラリが公開されたら実際に使ってみて本ブログや個人のブログでご紹介というか他人のふんどしで相撲とらせていただこうかと思います。

長々と書きましたが要するにopenpearの宣伝をして皆さんのライブラリが公開されればいいな!というエントリでございました。ご参考になれば幸いです。

作者: unoh

更新日:2008年11月15日 8時33分

このブログのホーム

diff with C++

ミートソーススパゲティを作るときは、ミートソースから作るのが信条のbokkoです。それはさておき、今日はdiffのお話です。

diff

diffは指定した2つのファイルの差分を求めるコマンド、もしくはその差分そのものを指します。普段から何気なく使用しているコマンドですが、その中で使われているアルゴリズムは結構難しいです。

差分を計算するということ

差分を計算するというのは以下の3つを求めることに帰結します。 ・Levenshtein Distance(Edit Distance) ・LCS(Longest Common Subsequence) ・SES(Shortest Edit Script) 上から順に1つずつ説明していきます。

Levenshtein Distance

Levenshtein Distanceは2つのシーケンスの違いを数値化したもので編集距離とも言います。これは後述するSESにおける要素の「追加」と「削除」の合計数になります。

LCS

LCSはLongest Common Subsequenceの略で、最長共通部分列とも言います。シーケンスの組合せによってはLCSは複数存在する可能性があります。

SES

SESはShortest Edit Scriptの略で、その名のとおり、片方のシーケンスをもう片方のシーケンスに変換するための最小手順を表します。例えば、abc → abdのSESは、
SES # C 共通, D 削除, A 追加
C a
C b
D c
A d
となります。また上記の場合、LCSは「ab」、編集距離は1+1=2(「追加」と「削除」の合計数)になります。

効率的な差分アルゴリズム

差分を計算する方法は古くから研究されており、多くのアルゴリズムが考案されています。差分を計算する典型的な手法としてはDP(動的計画法)がありますが、ここではより効率的なアルゴリズムであるO(ND)、O(NP)、Gestalt Approachの3つについて軽く紹介します。詳細については参考文献やURLを参照してください。

O(ND)

O(ND)という名前ですが、これはそのままO記法による計算量を表しています。Nは比較する二つのシーケンスの長さの合計数、Dは編集距離になります。つまり、2つのシーケンスが似ていればいるほど速くなります。DPの計算量がO(MN)になることを考えると、これはかなり大きな改善と言えるでしょう(M, Nはそれぞれのシーケンスの長さ)。実際にどうやって差分を求めるかですが、O(ND)やO(NP)は差分の問題を最短経路の問題に還元し、片方のシーケンスからもう片方のシーケンスに変換する最短経路を求めます(つまりこれがSESです)。 GNU diffutilsやGit(で使用されているLibXDiff)はこのO(ND)に近似アルゴリズムの改良を加えたものになっています。

O(NP)

O(NP)はSubversionやMonotone(C++で書かれたバージョン管理システム)で使用されているアルゴリズムで、究極的にはO(ND)の2倍高速に動作します。O(ND)と同じく、名前が計算量を表しています。O(ND)と同じく、Nは比較する二つのシーケンスの長さの合計数、またPはSESにおける削除の合計数を表しています。なので、O(ND)と同じく2つのシーケンスが似ていればいるほど速くなります。

Gestalt Approach

Pythonに標準で搭載されているdifflibパッケージで使われているアルゴリズムです。このアルゴリズムはまず最初に2つのシーケンス間の最長一致項を検出した後、その一致項を起点に、文字列を左側と右側に分割し、両側に対してまた最初に戻るということを繰り返すことによってLCSを求めます。このアルゴリズムは実際に実装したことがないので、憶測ですが、2つの文字列間の最長一致項を求めるというのは結構重い処理のはずなので、このアルゴリズムを使った実装ではおそらく、ある程度の長さの一致項を見つけたらそこでさっさと分割してしまって、速度を向上させるといった処置がなされているのではないかと思います。このようにO(ND)やO(NP)とは少し違ったアプローチによって差分を求めているのが特徴です。こちらに解説とアセンブリコードが載っています。また、余談ですが、素晴らしいことにPythonのdifflibにはUnified Formatで差分を出力するためのunified_diffという関数が含まれています。ソースコードを眺めたところ、Mercurialもこのライブラリを使用しているようです(ただし、バイナリdiffに関してはCで書かれています)。

各アルゴリズムの比較

各アルゴリズムのパフォーマンスについては少し前に僕が自分のブログに書いたこちらが参考になるかもしれません。ただ、アルゴリズムの比較というよりは各バージョン管理システムの比較であり、差分計算以外のボトルネックについては全く考慮していませんので、あくまで参考程度に捉えてください。また、差分の計算というのは非常に重い処理であり、現実的な応答時間で計算を終えるためには速度と精度を天秤にかける必要がどうしても生じます(LCS問題はNP-hard)。なので、遅いからといって「これはひどい」とは一概には言えません。逆に計算された差分自体は、非常に精度が高いものである可能性があります。しかし、現実問題として完全なLCSやSESが必要になるということはあまりないため、近似アルゴリズムやヒューリスティクスを用いて完全とはいかなくともそれなりに正しいLCSやSESを得るというアプローチを取る実装が存在します。これが上記でも述べたGNU diffutilsやLibXDiffです。Git内のdiffがSubversionやMonotoneに比べて高速なのはそのためです。

Unified Format

Unified Formatはバージョン管理システムを普段から使用している人なら非常になじみのあるフォーマットです。というのもSubversionやMercurial、Gitなどの比較的新しいバージョン管理システムは、デフォルトではdiffコマンドの出力がUnified Formatになっています(CVSは-uを付ける必要があります)。通常のdiffコマンドだとuオプションを指定するとUnified Formatで表示されます。diffの出力形式としてはほかにContext Formatなどがあります。そういえば今年の春頃、btoさんがdiffで-uを付けない人は勉強が足りてないとぼやいていました。(正直に告白すると、このぼやきを真後ろで聞いていた当時、僕は-uはおろかUnified Formatという言葉すら知りませんでした。それの反省もあって(?)dtlには差分をUnified formatで出力するサンプルプロプログラムが含まれています。) と、昔話はこれくらいにして、話の続きです。Unified Formatの詳細についてはRFCなどの明確な仕様はありませんが、Wikipediaのdiffの項目やPythonの開発者で有名なグイド・ヴァンロッサム氏の解説が参考になるでしょう。

C++で書かれたdiffライブラリ dtl

dtlはDiff Template Libraryの略で拙作のdiffライブラリです。C++のテンプレートにちなんで名付けています。アルゴリズムにはO(NP)を使用しており、ライセンスは修正BSDライセンスです。動作確認している環境は以下の通りです。
  • Mac OS X 10.5.5
    • GCC4.3.2
  • Ubuntu 7.10 (Paralles Desktop上)
    • GCC4.2.1

使い方

dtlは単一のヘッダファイル(dtl.hpp)から成っており、このファイルをインクルードするだけで使うことが出来ます。以下はdtlに含まれているサンプルプログラムであるstrdiff.cppです。
#include "../dtl.hpp"
#include "common.hpp"
#include <iostream>
#include <vector>
#include <cstdlib>
int main(int argc, char *argv[]){
  if (isFewArgs(argc)) {
    perror("few argument.");
    return(EXIT_FAILURE);
  }
  std::string A(argv[1]);
  std::string B(argv[2]);
  typedef char elem;
  dtl::Diff<elem, std::string> d(A, B);
  d.compose();
  // editDistance
  std::cout << "editDistance:" << d.getEditDistance() << std::endl;
  // Longest Common Subsequence
  dtl::Lcs<elem> lcs = d.getLcs();
  std::vector<elem> lcs_v = lcs.getSequence();
  std::vector<elem>::iterator vit;
  std::string lcs_s(lcs_v.begin(), lcs_v.end());
  std::cout << "LCS:" << lcs_s << std::endl;
  // Shortest Edit Script
  std::cout << "SES" << std::endl;
  dtl::Ses<elem> ses = d.getSes();
  std::vector< std::pair<elem, dtl::elemInfo> > ses_v = ses.getSequence();
  std::vector< std::pair<elem, dtl::elemInfo> >::iterator it;
  it = ses_v.begin();
  for (it=ses_v.begin();it!=ses_v.end();++it) {
    switch (it->second.type) {
    case dtl::SES_ADD :
      std::cout << "A " << it->first << std::endl;
      break;
    case dtl::SES_DELETE :
      std::cout << "D " << it->first << std::endl;
      break;
    case dtl::SES_COMMON :
      std::cout << "C " << it->first << std::endl;
      break;
    default :
      break;
    }
  }
  return 0;
}
上記のプログラムを実行すると2つの文字列をコマンドラインから入力として受け取って、編集距離とLCS、あとSESを表示します。
narazuya@bokkko% make strdiff
narazuya@bokkko% ./strdiff acbdeacbed acebdabbabed
editDistance:6
LCS:acbdabed
SES
C a
C c
A e
C b
C d
D e
C a
D c
C b
A b
A a
A b
C e
C d
narazuya@bokkko%
また、int型のvector同士の差分を取るサンプルもあります。(ソースはintdiff.cppを参照)
narazuya@bokkko% ./intdiff
1 2 3 4 5 6 7 8 9 10 
3 5 1 4 5 1 7 9 6 10 
editDistance:8
LCS: 3 4 5 7 9 10 
SES
D 1
D 2
C 3
A 5
A 1
C 4
C 5
D 6
A 1
C 7
D 8
C 9
A 6
C 10
narazuya@bokkko%
サンプルプログラムは他に、2つのファイルの差分をUnified Formatで出力するunidiffや、差分を適用して片方の文字列からもう片方の文字列に変換できるか試すpatchとそのファイル版であるfpatchがあります。

dtlのパフォーマンス

ほかのdiffと同じく、全然違うファイルの差分を計算しようとするとパフォーマンスが劣化します。 dtlの初期の頃の実装だと1万行単位のファイル同士で片方がC言語のソースコードでもう片方が全て空行のファイルを比較した際に数十秒かかっていたり、ひどいときはメモリを喰い過ぎてプログラムが落ちてしまったりしていました。今だとパフォーマンスはこんな感じです(unidiffにtimeつけて実行。最適化オプション-O2を付加)。環境は先述のMac OS Xのものに準じます。編集距離はGNU diffutilsのdiffの出力を元に事前に算出したものです。(なので、dtlのunidiffが出力する差分とは微妙に異なります)
ファイルAファイルB編集距離計算時間(sec)
9107行10452行23650.186
6351行6463行27560.290
6351行9107行146740.697
6351行35109行414540.870
O(ND)やO(NP)などのアルゴリズムは比較する2つのシーケンスが似通っている場合に特に効率よく動作します。逆に言うとシーケンス同士の差異が大きいほど最悪の計算量に近づいていきます。なので、真面目に差分の経路を記録しようとすると全然違うシーケンスを比較した際にかなりのメモリ領域が必要になります。当初は記録した経路のうちのあとでホントに必要になる経路だけを抽出して節約しようと試みたのですが、どうにもうまくいかなくて、単純に、経路記録のためのvectorが一定のサイズを越えたら、そこまでの経路の記録を使って、差分を計算してvectorを廃棄した後、また途中から経路を記録していくという実装になっています。(バージョン0.04から) これにより、差分が非常に大きい場合でも、メモリを大量に消費することはありません。最初はサイズ越えたら残りのシーケンスを「削除」と「追加」だけで構成するようになっていました。これは(途中までしか計算しないんで)めっちゃ速いんですが、精度の点であまりにダメダメだろうということで0.04からは今の実装になっています(でも、やっぱり個人的にはまだ「う~ん」という感じが否めないです)。ちなみに最後の一番行数の多いファイルはすべて空行のファイルで、残りはCのソースコードです。 余談ですが、GCCのバージョンの違いだけで最大0.2~0.3秒ぐらいパフォーマンスが変わりました。

dtlの今後の課題と展望

・効率改善 ・mergeの実装 ・unidiffの出力で、「-」→「+」の順ではなく、「+」→「-」の順で表示されることがある 現状の実装にはあまり満足していなくて、近似アルゴリズムを使ったら効率化できないかなあと思いつつ、そのへんは今のところ、さっぱりなので今必死こいて勉強してるところです。あと、作ったdiffを元にmergeも作ろうと考えてるところです。最後のは割と細かいことですが、undiffの出力が「削除」→「追加」ではなく、「追加」→「削除」の順に表示されてしまうことがある点です。ほかのdiffみたいに前者の形で表示された方が見やすいと思うので、これは暇を見て修正する予定です。

参考文献・URL

・E.W.MYERS, "An O(ND) Difference Algorithm and Its Variations" ・S.W.Maner, G.Myers, W.Miller, "An O(NP) Sequence Comparison Algorithm" ・文書比較アルゴリズムdiff(1), diff(2), diff(3)

作者: unoh

更新日:2008年11月13日 7時4分

このブログのホーム

BTSに関する四方山話

こんにちは! やまもと@テスト番長です。 最近gihyo.jpで連載させていただいている関係で、BTSについて考える機会が多くなっています。 思えば今までのエンジニア人生で色々なBTSを使ってきました。 今まで経験したことから、幾つか記事には出ないような四方山話をしてみたいと思います。

Bugzillaの蟻?画像が辛い

Bugzillaを使ってシステムテストをしていたとき、ふとTOPページの蟻?画像の話になりました。 使ったことのある方はご存知かと思いますが、昆虫の頭部の顕微鏡写真のようなあいつです。 忙しいだけでも辛いのに、アレを見るとゲンナリする!ということになり 急遽ほのぼの画像に差し替えたところ、相当印象が変わって見えました。 プロジェクトの雰囲気も若干良くなったように思います。

チケットがよく壊れるBTSもある

rubyで出来た某軽量BTS的なものを使っていたとき、チケットが1000件を越える頃から 段々ページが重くなり、頻繁にチケットが壊れるようになりました。 バグを取り扱うシステムに不都合が出るのはなんとも切ないものです。BTSの耐久性や安定性は大事ですね。 オープンソースで歴史のあるBTSはその点信頼性が高いものが多いようです。

ローカルルール色々

バグの取り扱いについての情報はあまり表に出ないように思います。 上手く行ってないけれど台所事情は人に相談しづらいというのが本音でしょう。 正式なお作法はどうなのかという話もそれほどなく、皆さんケースバイケースということのようです。 個人的な経験の中でも特に処理フローはまちまちでした。開発チームの体制に影響されるのが大きいです。
  • スキルの低いテスターが参加する場合は、チケットが有効か判定するフローを作る
  • リリース段階(ステージ→本番、など)に合わせて、確認段階を細かく作る
  • 場合によりクローズの確認を管理者のみ出来るようにする
などはすぐ思いつくところですね。

インストールが嫌

BTSのインストールは面倒なので出来ればやりたくありません。 全般に日本語の情報が少なく、バージョンが変わると以前の情報が役に立たなかったりして、なんだかんだで一日潰れたりします。 ここは皆さん苦労しているはずなので、もっと情報共有すべきなのかもしれません。

私製BTSでの運営は結構多い

既製品のカスタマイズの不便さや不具合を恐れて内製のBTSを使ってらっしゃるところも結構多く、2割くらいあるようです。 色々なものがあるようなので、表に出てきて比較できたら面白いのに。。とつい思ってしまいます。

BTSはコミュニケーションツールかもしれない

バグを管理してくれるBTSですが、結局人間が関わるものですので 「バグを抱えた人々のためのコミュニケーションツール」なのかもしれないと思うことが多々あります。 受託開発で顧客とBTS越しにやりとりする時などは特にそうですね。 バグを記録することだけに注目していると上手く回らないように思います。
xxx
取り留めのない話になりましたが、皆さんのご苦労話もあればお聞かせください。 連載記事のほうもお時間のあるときにでもお読みいただき、ご意見をいただけますと幸いです。 ソフトウェア開発の必須アイテム,BTSを使ってみよう

 

作者: unoh

更新日:2008年11月11日 8時52分

このブログのホーム

「はじめてのPHPプログラミング 基本編 5.3対応」を執筆しました

こんにちは。中村です。

この度は、執筆書籍のご紹介(宣伝)です。Do You PHP?の中の人である株式会社セランの下岡さんと共著でPHPの入門書籍を執筆させていただきました。

入門書籍ではありますが、HTMLにPHPを埋め込んだWebページとしてのサンプルはあまり網羅せずに、できるだけプログラミング言語としての動作や、その周辺知識に触れるようにしています。そのため、第7章に入るまではHTMLはなく、コマンドプロンプトで実行する環境で説明をしています。

また、後半になるに従ってPHPによるWebサイト構築に説明がシフトしてゆくようになっています。

はじめてのPHPプログラミング 基本編―5.3対応 (TECHNICAL MASTER 54)
下岡 秀幸 中村 悟
秀和システム
売り上げランキング: 83690

実際に書籍をご覧いただく際には、Do You PHP?内に書籍の正誤表がありますので、ご迷惑をおかけして恐縮ではありますが、そちらも参照いただけますと幸いです。

最後に目次です。

01 PHPの世界へようこそ
01-01 PHPの世界へようこそ [PHPって?]
PHPの世界へようこそ
PHPの特徴
PHPの生い立ち
プログラムって何だろう
プログラムを作るには、どんな知識が必要?
本書でやること

01-02 PHPが動作する環境を準備しよう [PHPのインストールと設定]
本書で対象とする環境
PHP5のインストール

01-03 PHPの動作確認 [PHPの動作確認]
PHP5の動作確認
サンプルプログラムとPHPマニュアルを展開する
そもそもどうやってプログラムを作って動かすの?
本書を読み進めるにあたって

02 プログラミングを始めよう
02-01 PHPプログラムのお約束ごと(1) []
プログラムの開始と終了
プログラムの行末

02-02 PHPプログラムのお約束ごと(2) [/**/ // エラー ]
コメント
プログラムのエラー
バグとデバッグ

02-03 変数 [変数]
変数と定数
変数を定義する
変数に値を代入する

02-04 定数 [定数]
定数

02-05 型 [型]
型
型を変更する

02-06 配列 array [配列を使う(1)]
配列

02-07 計算式を使う [計算 比較]
計算をしてみよう
値を比較する

02-08 論理演算 文字列演算 [計算式を使う(2)]
論理演算をする
文字列に使う演算子

03 プログラムの流れを変えよう
03-01 条件分岐 [if]
はじめに
もっとも単純なif文

03-02 複雑なif文 [if else]
「もし~ならば~、そうでなければ~」
「{」や「}」を使わない書き方

03-03 いろいろの条件分岐 [三項演算子とswitch文]
三項演算子
switch文

03-04 繰り返す(1) [while do-while]
はじめに
while文
繰り返しを止めるbreak文
do-while文

03-05 繰り返す(2) [for foreach]
for文
foreach文

04 いろいろな関数を使ってみよう
04-01 関数とは [関数]
関数とは

04-02 文字列操作 [文字列 print echo]
はじめに
文字列を出力する

04-03 文字列操作(2) [strlen explode substr str_replace]
文字列の長さを調べる
文字列を分割する
文字列の一部を取り出す
文字列を置換する

04-04 日本語文字列操作 [mb_strlen mb_substr mb_convert_kana]
日本語文字列の長さを調べる
日本語文字列の一部を取り出す
かなを変換する

04-05 パターンマッチング [ereg ereg_replace]
はじめに
正規表現
一連の文字列に一致するパターン
正規表現関数

04-06 日付と時刻 [date mktime]
はじめに
日付や時刻を特定の形式で取得する
特定の日時を表す
DateTimeクラス

04-07 ファイル操作 [fopen fclose]
はじめに
ファイルを操作する手順
ファイルを開く
ファイルを閉じる

04-08 ファイルの読み書き [fread fgets feof]
ファイルの読み込みと書き込み
ファイル関数

04-09 独自の関数 [function]
はじめに
独自の関数を定義する
簡単な関数の例
関数の引数
値渡しと参照渡し

05 クラスを使ってみよう
05-01 クラスとオブジェクト [クラス オブジェクト]
オブジェクト指向
クラスとオブジェクト

05-02 クラスを使う [class new extends]
クラスを定義する
クラスからオブジェクトを作る
親クラスと子クラス

05-03 インターフェースと例外 [interface try catch throw]
インターフェース
例外

05-04 SimpleXML [SimpleXML]
SimpleXMLとは

06 効率よく開発するために
06-01 他のプログラムファイルを使う [PEAR ]
プログラムの再利用
他のプログラムファイルを使う

06-02 PEARライブラリ [PEARライブラリ]
PEARライブラリ
PEARライブラリを使う

07 PHPとWebアプリケーション
07-01 PHPとWebアプリケーション [PHPとApache]
Webプログラミングを始めよう
Apacheのインストール
PHPをApacheに組み込む
ブラウザからプログラムファイルを実行する
HTTP

07-02 HTMLとPHPスクリプト [HTMLとPHP]
はじめに
HTMLとPHPスクリプト
HTMLフォームからのデータを受け取る
ラジオボタンとチェックボックス
コンボボックス
ファイルのアップロード

07-03 クッキー [Cookie]
HTTPは非常に物忘れが激しい
クッキーとは
クッキーをやりとりする
クッキーを削除する

07-04 PHPによるアクセス認証 [認証]
いろいろな認証
BASIC認証
PHPプログラムでBASIC認証をおこなう

07-05 PHPでのセッション管理 [セッション]
セッションとは
セッションとクッキー
PHPでセッションを使う
セッションに保存した値を削除する
セッションの有効期限を設定する
セッションを破棄する

07-06 PHPとJSON [JSON]
AjaxとJSON
PHPとJSON
JSONから配列やオブジェクに変換する
配列やオブジェクトからJSONに変換する

07-07 Webアプリケーションのセキュリティ [セキュリティ]
はじめに
クロスサイトスクリプティング脆弱性
なぜクロスサイトスクリプティング脆弱性は起こる?
クロスサイトスクリプティング脆弱性の対策法は?
まとめ

08 データベース
08-01 データベース「SQLite」 [SQLite]
データベースとは
テーブル・カラム・レコード
主キー - Primary Key
カラムの制約
Windowsで使えるオープンソースのデータベース
SQLiteとは
PHP5とSQLite
SQLiteManager
SQLiteManagerをインストールする
データベースを作成する
テーブルを作成する

08-02 SQL(Structured Query Language) [SQL文]
はじめに
データの基本操作
INSERT文
SELECT文
UPDATE
DELETE文
条件検索
あいまい検索
並べ替え
グルーピング
重複の取り除き
取得する件数の制限
範囲検索
トランザクション

08-03 PHPからのデータベース操作 [sqlite_open]
PHPプログラムからSQLiteを操作する
SQLiteを操作してデータを取り出す
SQLiteを操作してデータを登録・更新・削除する

08-04 データベースのセキュリティ [SQLインジェクション]
はじめに
SQLインジェクション
SQLインジェクションの対策法は?
まとめ

09 アプリケーションを作ってみよう
09-01 ミニミニブログを作る [ミニミニブログ ]
はじめに
ミニブログとは
Webアプリケーションとして見たミニブログ

09-02 ミニミニブログの機能概要 [機能概要]
ミニミニブログの機能を考える
ミニミニブログで使う技術について考える

09-03 ミニミニブログを作ってみよう [ディレクトリ]
ミニミニブログ用のディレクトリを用意する

09-04 メインページのHTMLを作成する [メインページHTML]
HTMLで画面サンプルを作る
ミニミニブログ画面のHTMLとCSSを確認する

09-05 データベース・テーブルの作成とテストデータの登録 [データベース]
ミニミニブログ用のデータベースを用意する
ミニミニブログ用のテーブルを作成し、テストデータを登録する

09-06 ミニミニブログ用テーブルについて [データテーブル]
ミニミニブログで使うテーブルの構成

09-07 友達一覧を作る [友達一覧]
友達一覧を実現する処理を考える
友達一覧で使うSQLを考える
HTMLにプログラムを埋め込む

09-08 投稿一覧を作る [投稿一覧]
投稿一覧を実現する処理を考える
投稿一覧で使うSQLを考える
投稿一覧を実現するプログラムを追加する

09-09 投稿機能の実装 [投稿機能]
投稿機能を実現する処理を考える
データ登録後のリダイレクト処理
投稿機能で使うSQLを考える
投稿機能を実現するプログラムを追加する

09-10 ページめくり機能を追加する [ページめくり機能]
ページめくり機能の処理を考える
2ページ目に表示するのは何件目から何件目?
前のページや次のページがあるかどうかの判断
ページめくり機能のプログラムをHTMLに追加する

09-11 ユーザー認証機能の追加 [ユーザー認証]
ユーザー認証機能の処理を考える
ユーザー認証をおこなうプログラムを追加する

09-12 友達登録機能を追加する [友達登録機能]
友達追加機能の処理を考える
「友達登録する」リンクを表示する処理を考える
データベースに友達情報を登録する処理を考える
友達追加機能のプログラムを追加する

09-13 セキュリティ対策 [セキュリティ]
何か忘れていませんか?
セキュリティ対策用の関数を用意する
セキュリティ対策用の関数をindex.phpから利用する
データのセキュリティ対策
データベースファイルのセキュリティ対策

09-14 リファクタリングする [リファクタリング]
リファクタリング
リファクタリングの方針を考える
データベースアクセスに関するプログラム
用語単位に分けたプログラム
ミニミニブログの機能単位に分けたプログラム
リファクタリング後のindex.php
まとめ

作者: unoh

更新日:2008年10月29日 6時52分

このブログのホーム

5分くらいで知るScala

はじめまして。今月入社した内田です。 以前は業務系のSI会社に勤めていたので、Web系という畑の違う環境に少々戸惑うこともありますが、最近少しずつ慣れてきました。 今回は先日、社内勉強会でやった「Scala」について5分くらいで紹介したいと思います。

Scalaとは

関数型言語とオブジェクト指向言語の特徴を統合したマルチパラダイム言語です。 主にJavaVM上で動作し、他にも.NET Framework、Google Android等でも動作が確認されています。そしてJavaや.NET等の既存の豊富なライブラリを使用することが可能です。 このあたりはwikipediaに詳しく書かれています。

Wikipedia:Scala

約1年程前には日本でのScala人口は1桁とも言われていましたが、最近では各地で勉強会が開催される等盛り上がりをみせ、「次の言語」として注目されています。個人的にScalaの魅力は前述した豊富なライブラリを使用できることと、スクリプト言語としての簡単な構文、そしてマルチコアに対応したアプリを簡単に記述できるActorの存在が大きいと思います。 すでに1分近くたってる様な気がするのでサクサクとコードを紹介します。

Hello World!

まずはプログラミングの基本「Hello World!」
object HelloWorld {
    def main(arg:Array[String]) = {
        println("Hello World!")
    }
}
上記の様にobjectキーワードを使うことでアプリケーションを実行することができます。 このコードを「HelloWorld.scala」として保存し
$ scalac HelloWorld.scala
$ scala HelloWorld
で実行されます! またscalaを引数無しで起動すると対話的に実行することができます。以下は全て対話的に行っています。

文法

Scalaは文法的にかなり曖昧な書き方もできてしまうので、全てを紹介することはできませんが、基本的な部分をサラッと紹介します。

変数

関数型的な「val」と手続き指向的な「var」
val i = 1
var i = 1
val i:String = "hello"
var i:String = "hello"

制御構文

if文(javaなんかと一緒)
if (a == b) {
    println("一緒")
} else {
    println("違うよ")
}
ループ。foreachのようなもの。
val l = List(1, 2, 3, 4, 5)
for (n <- l) {
    println(n)
}
10回ループしたかったら
for (n <- 1 to 10) yield println(n)
パターンマッチ switch caseの拡張版 _はその他
val name = "tarou"
name match {
    case "tarou" => println("nice to meet you")
    case _ => println("how are you")
}

関数

関数の基本的な書き方
def 関数名(引数:引数型):戻値型 = { 処理 }
def hello(name:String):String = {
    "hello, " + name
}
hello("tarou")

クラスとメソッド

クラス定義

ほとんどJavaと同じですね。 thisはコンストラクタのオーバーロード。 private宣言しない変数は全てpublicになります。
class Car {
    var name:String = ""
    def this(name:String) = {
        this()
        this.name = name
    }
}
var c = new Car("hello")
c.name
class宣言とコンストラクタを纏めることができます
class Car(var name:String)
var c = new Car("hello")
c.name

メソッド

Unitはvoidと一緒
class Car(var name:String) {
    def move():Unit = {
        println(name + " is moving")
    }
}
一行で書いてもOK
class Car(var name:String) {
    def move = println(name + " is moving")
}
3分くらいたちました。残りの時間で無名関数、カリー化、高階関数といった関数型言語的な内容を紹介します

無名関数、クロージャ

(引数:引数型) => { 処理 }
val l = List(1, 2, 3)
l.map((x:Int) => {
    x * 2
})
無名関数だけではないのですが、引数の型は型推論されるため、省略できる場合が多いです
l.map((x) => { x * 2 })
単一の式の場合{}はいりません
l.map((x) => x * 2)
()もいりません
l.map(x => x * 2)
引数が一つの場合_に代入され、こんな省略もできます
l.map(_ * 2)
クロージャなのでローカル変数を保持します
def add(x:Int) = {
    (y:Int) => x + y
}
val add2 = add(2)
add2(3)

カリー化

複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること(wikipediaより)。 関数型言語では基本的な考え方で、Scalaでも構文的にサポートしています。 前述のクロージャと同じ処理を実現していますが、直感的に分かりやすい実装になっています。 複数の引数(x,y)をとる関数を、引数が「x」で戻り値が「引数に「y」を使い結果を返す関数」であるような関数
def add(x:Int)(y:Int) = {
    x + y
}
add(3)(2)
val l = List(1, 2, 3)
l.map(add(3))
余談なのですが、意味が通る範囲内ではメソッドの括弧と.は省略できます
l map add(3)

高階関数

関数を引数にとる関数。 関数を戻り値とする関数。
def calc(x:Int, y:Int, f:(Int, Int) => Int) = { f(x, y) }
def add(x:Int, y:Int) = { x + y }
calc(1, 2, add)
もちろん無名関数も引数にできます
calc(1, 2, (x:Int, y:Int) => { x + y })
カリー化も関数を戻り値とするので高階関数の一種ですね。 _を使うことで関数として代入できます。
def add(x:Int)(y:Int) = x + y
val add2 = add(2)_
add2(3)

まとめ

5分をオーバーしたかもしれませんが基本的な部分を紹介することができました。 Scalaにはまだまだ特徴的な構文が存在し、面白い言語です。今回をきっかけにScalaを一緒に学んでいきましょう! 次回は紹介できなかった残りの文法とライブラリを中心に見ていきたいと思います。 *本文の間違った内容や面白い情報がありましたら教えてください!

作者: unoh

更新日:2008年10月27日 7時6分

このブログのホーム

シェルの仕組み(前編)

尾藤正人(a.k.a BTO)です 社内勉強会でシェルの仕組みというのをやってみましたので、資料を公開します。 シェルはUNIXを使う上で、必ず使用される非常に身近なツールです。 毎日使用しているツールにも関わらず、具体的にどのような動作をしているのか知らない方も多いのではないのでしょうか。 シェルの使い方に関する情報はたくさんありますが、シェルの実装についての情報はほとんどないなと思ってシェルを題材に取り上げました。 シェルにはUNIXプログラミングのエッセンスがぎっしりつまっています。 シェルの内部の仕組みが分かるようになると、UNIXプログラミングが分かるようになると言っても過言ではないのかもしれません。

シェルの仕組み(前編) - Upload a Document to Scribd
社内勉強会中にustreamで動画を流していたのですが、動画を保存するのを忘れてしまいました。 本当は動画も公開できればよかったのですが... すみません。

作者: unoh

更新日:2008年10月23日 8時20分

このブログのホーム

PL/SQLを浅く紹介

こんにちは。中村です。

先日、社内勉強会でPL/SQLがどういうものかを浅く紹介しましたので、そのときのスライドを公開します。

ウノウの入る前のことですが、受託開発をやっていたときの経験では、Oracleの現場が8割、SQL Serverの現場が1割、その他の現場が1割という印象でしたが、ウノウも含めてWebサービスではMySQLやPostgreSQLなどのOSSを使うことの方が圧倒的に多いようです。

そういう訳で、Webサービスの構築ではOracleで動作するPL/SQLを触る機会がめっきり少ないかもしれませんが、どういうものかを知っておくのは良いかもしれません。私自身もかなり忘れてしまっていたので、復習もかねて取り上げてみました。

plsql - Upload a Document to Scribd

参考情報: アプリケーション開発者用のPL/SQL

作者: unoh

更新日:2008年10月17日 13時6分

このブログのホーム

Tips for HyperEstraier

先月、VX Revolution VX-Rを購入して、その使い心地の良さに素直に感動しているbokkoです。

HyperEstraier

HyperEstraierは平林幹雄さんが開発されている全文検索エンジンです。全文検索エンジンとして使えるのはもちろん、全文検索のためのライブラリとして使うこともできます。ウノウではHyperEstraier(以下HE)をフォト蔵の写真検索に利用しています。 今回はHEの活用や運用に関するTipsについて紹介します。

インデックスの作成

HEのインデックスを作成する方法はいくつかありますが、単にデータが空のインデックスを作るのであれば以下で十分です。
$ estcmd create idx
実際には想定されるインデックスのサイズなどに応じてオプションを追加するといったことが必要になるでしょう。ファイルやディレクトリ(内のファイル)をインデックスに追加するにはgatherコマンドを使います。
$ estcmd gather idx data # dataはファイルもしくはディレクトリ
gatherはデフォルトではサポート外の拡張子のファイルは無視するので、サポートされていない拡張子のファイルをインデックスに追加する場合は、-feオプションを付けましょう。

インデックスの最適化

HEのインデックスに追加されたデータは削除することが可能ですが、データがインデックスから削除されても削除された領域分、データが小さくなるわけではありません。つまり、インデックスからデータが削除されても、削除された領域はゴミとして残ります。これはインデックス内のデータへのアクセス速度に後々影響を与えるので、optimizeコマンドを使って、削除された領域を整理し、インデックスのサイズを縮小するとよいでしょう。
$ estcmd optimize idx
なお、インデックスの最適化はインデックスのサイズが大きいと時間がかかる上にCPUリソースをかなり消費するので、注意しましょう。また、インデックスの無駄な整理するのはpurgeコマンドに-clオプションを付けて実行することでも可能です。
$ estcmd purge -cl idx

インデックスの分割とマージ

HEのインデックスは件数が増えてくると段々(特に更新の)パフォーマンスが劣化し始めます。そのため、導入時などに件数の多いデータのインデックスを作成する際は、まず小さいインデックスをたくさん作り、後で各インデックスをマージしてまとめる方が効率がよいです。
$ estcmd merge idx1 idx2 # idx2をidx1にマージ

属性検索と属性インデックス

属性検索は非常に遅いので、使う場合はできるだけ属性インデックスを作成しましょう。ただ、それでも通常の検索に比べると遅い上にCPUリソースを結構喰うので、どうしても使いたい時だけ使いましょう。特にesmasterに対して検索リクエストを送って属性検索を行うとインデックスのサイズが大きい場合、時間がかかるだけでなく、最悪の場合、estmasterが落ちてしまう可能性があります(estmasterについては後述)。また、属性にインデックスを貼るとインデックスの更新が遅くなります。
$ estcmd create -attr @str_data str idx # 属性str_dataに文字列インデックスを貼る

estmasterの運用

HEのP2P機能やノードAPIを使ってアプリケーションを作成する場合、サーバプログラムであるestmasterを使用する必要があります。estmasterは検索やインデックスの更新、削除などのリクエストをHTTP経由で受け取り、実行します。estmasterを使うにはまず、専用のサーバルートディレクトリを以下のコマンドで作成します。
 $ estmaster init casket
間違っても既にあるサーバルートディレクトリを再度初期化しないようにしましょう。_node以下のインデックスが丸ごと消えます。(導入作業が佳境に差し掛かった頃に一度消して泣きそうになりました)estmasterを起動するには以下のコマンドを実行します。デフォルトではポート番号1978が使用されますが、この設定はサーバルート以下の_confファイルを編集することで変更できます。
 $ estmaster start casket
バックグラウンドで走らせるには-bgオプションを指定します。ただ、estmasterから検索を行う場合、estmasterが落ちてしまうと何もできなくなってしまうので、対策が必要になります。前回のdaemontoolsの解説でも述べましたが、フォト蔵ではestmasterの管理にdaemontoolsを活用しています。起動スクリプトは単純ですが、estmasterを扱う場合、例えば↓のような記述が必要になります。
SERVER_ROOT=/var/casket
PID_FILE=${SERVER_ROOT}/_pid
if [ -e $PID_FILE ]
then
    rm $PID_FILE
else
    :
fi
estmasterは起動すると、サーバールート以下に_pidというプロセスIDが書かれたファイルが作成され、終了するとこのファイルは削除されます。しかし、異常終了した場合はこのファイルが残ってしまい、estmasterを再起動しようとすると、estmaster自身は既に起動していると思い込んでしまい、起動することができなくなります。このため、runスクリプトで_pidの存在の有無を確認し、存在する場合は削除するようにします。

リクエストが受信できているか確認する

estmasterが正常に検索やそのほかのリクエストを受信できているか確認するには、サーバールート以下にある_logファイルの内容を確認します。実際には以下のようにtailコマンドを使うのがよいでしょう。
 $ tail -f _log

管理画面からの操作

HEにはestmasterやestmasterが使用しているインデックスを管理するためのWebインタフェースが用意されています。このestmasterの管理画面ではインデックスの作成やリンクの設定などいろんな操作ができますが、オプションを指定することができないので、実際のインデックスはestcmdコマンドで作成した方がいいでしょう。また、ノード間リンクの設定など、管理画面上から設定してもestmasterが終了すると設定が失われるものがあります。実際の設定変更を行う際は管理画面からではなく、estcallコマンドやAPI経由で行うのがよいでしょう。ただし、コマンドラインからestcallを使ってestmasterに命令を発行する際、ユーザ名とパスワードを直打ちしなければならないので、履歴にパスワードが残ってしまう可能性があります。なので、究極的にはAPIを使う方が良いでしょう。

検索用と更新用にインデックスを分ける

HEではインデックスを更新している間、そのインデックスに対して検索をかけることができません。このため、フォト蔵では検索用のインデックスと更新用のインデックスを明確に分けています。estmasterにHTTP経由で検索クエリを投げる処理はフォト蔵自体がPHPで書かれていることもあって、PHPで書いていますが、インデックスの更新スクリプトはPerlでHTTPを介さず、コアAPIを経由する形で書いています。

1文字検索

HEはN.M-gram方式(N=2、M=2)と転置インデックスにより、データが保存されているので、1文字で検索した場合、検索漏れが生じる可能性があります。1文字の場合はワイルドカード検索になり、一定回数だけ、データをインデックスから検索します。

アルファベットや数字から成る文字列の検索

HEはN.M-gram方式ではありますが、アルファベットや数字から成る文字列に対しては、N文字単位(N=2、後に続くM文字(M=2) )で転置インデックスを作成するようなことはせず、まとめて転置インデックスを作成します。このため、アルファベットや数字から成る文字列に対しては、検索キーワードが完全に一致しなければ検索に引っかからないという現象が発生します。例えば、インデックス内に「photozou」という文字列が格納されている文書がある場合、「photozou」で検索すれば、引っかかりますが、「photo」では引っかかりません。これはSennaやMySQLの全文検索インデックスでも似たような動作をします。理由としては全文検索において、上記のような文字列を含む文書に対して完全なN-gram(N=2)で転置インデックスを作成しても、インデックスが肥大化する割にはさほど効果がないことが挙げられます。HEでこの問題に対処するには、検索条件式を「通常書式」か「簡便書式」にして、キーワードの前方一致や後方一致を有効にします。検索条件式はoptionパラメータによって制御されているので、このパラメータに適切な値をセットすることによって、検索条件式を変更することができます。各検索条件式の値はestraier.hを見ると以下のように定義されています。
enum {                                   /* enumeration for options */
  ESTCONDSURE = 1 << 0,                  /* check every N-gram key */
  ESTCONDUSUAL = 1 << 1,                 /* check N-gram keys skipping by one */
  ESTCONDFAST = 1 << 2,                  /* check N-gram keys skipping by two */
  ESTCONDAGITO = 1 << 3,                 /* check N-gram keys skipping by three */
  ESTCONDNOIDF = 1 << 4,                 /* without TF-IDF tuning */
  ESTCONDSIMPLE = 1 << 10,               /* with the simplified phrase */
  ESTCONDROUGH = 1 << 11,                /* with the rough phrase */
  ESTCONDUNION = 1 << 15,                /* with the union phrase */
  ESTCONDISECT = 1 << 16,                /* with the intersection phrase */
  ESTCONDSCFB = 1 << 30                  /* feed back scores (for debug) */
};
通常書式の場合、前方一致を有効にするには検索キーワードを「[BW] photo」、後方一致を有効にするには検索キーワードを「[EW] photo」という具合に指定します。簡便書式の場合、前方一致を有効にするには検索キーワードを「photo*」、後方一致を有効にするには検索キーワードを「*photo」という具合に指定します。 ただし、1文字検索と同様、これはワイルドカード検索となり、一定回数だけしかデータをインデックスから検索しないので、検索漏れが生じる可能性があり、CPUの負荷も増大します。

estmasterが管理しているインデックスのバックアップ

estmasterは/master?action=backupがリクエストされると、サーバルート以下の_confファイル内のbackupcmdで指定されたバックアップコマンドを実行します。このリクエストを受け取るとestmasterはインデックスをディスクと同期させるので、比較的安全にバックアップを行うことができます。estmasterの起動中に、estmasterが管理しているインデックスをディスクと同期させずにコピーしたり移動したりすると、インデックスが壊れることがあるので、estmasterを起動させたまま、バックアップを取るときは必ずbackupcmdで指定したスクリプトで行いましょう。

パラメータの調整

サーバディレクトリ以下にある_confファイルを編集することによって、estmasterの動作を調整することができます。要はApacheのhttpd.confのようなものです。以下にいくつかのパラメータについて解説します。ほかのパラメータについては公式サイトを参照してください。

maxconn

ApacheでいうMaxClientsです。

searchtimeout

検索のtimeout値です。通常の検索に比べて遅い属性検索を使用する場合は少し高めに設定するのがよいでしょう。

backupcmd

/master?action=backupがリクエストされた際に起動するバックアップコマンドを指定します。

whildmax

先述の通り、HyperEstraierはN.M-gram方式(N=2,M=2)なため、1文字では検索漏れが生じる可能性があります。1文字の場合はワイルドカード検索になり、一定回数しかデータを検索しません。この回数を指定するのがwhildmaxパラメータであり、デフォルト値は256となっています。

参考文献・URL

全文検索システム Hyper EstraierN.M-gram: ハッシュ値付きN-gram 法による転置インデックスの実現 また、余談ですが、検索に関する基礎的な知識やアルゴリズムについて理解したいのであれば、以下の書籍が参考になると思います。
情報検索アルゴリズム
北 研二 津田 和彦 獅々堀 正幹
共立出版
売り上げランキング: 145553
おすすめ度の平均: 3.5
3 基本知識の足しになれば
4 わかりやすくてよい

作者: unoh

更新日:2008年10月10日 10時42分

このブログのホーム

携帯とCookieドメイン

こんばんわ五十川です。

しばらく前になりますが、ソーシャルスクラップブックclippのモバイル版をリリースしました。cippモバイルではドコモ以外は、セッション管理にCookie(のみ)を利用することにしたのですが、そのときCookieドメインではまりました、というお話。

PC向けclippのドメイン名は、トップページなどのユーザ共通ページは「clipp.in」、ユーザ個別のページは「{username}.clipp.in」(例えばclipp-info.clipp.in)となっています。ケータイサイトをマルチなサブドメインにする例はあまり多くないと思いますが、clippモバイルでは、ルーティング直すのめんどくさいという怠け者な理由で、PC版のドメイン名がそのまま使えればいいなと思って取り掛かりました。しかし、その目論見はあっさりと破綻することになるのでした。

  • 以下の内容は手元の数多くない端末で確認しただけのもので、各キャリアのサイトに掲載されているドキュメントにはこのあたりの話題は見当たらないようです(あったらごめんなさい)。なので間違ってたりヌけてたりする可能性はたぶんにあります。もしこのあたりの話題をご存知のかたがいらっしゃいましたら、ご教示いただければ幸いです。
  • 以下はCookieに関する話題のうちドメインについてのみです。ケータイサイトでのCookieについては、この他にもいろいろな制約がありますが、ググればいろいろ出てきますので、そのへんはそちらをご参照ください。

まずはau/EZweb

EZwebのCookieドメインには以下のようなルールがあるようです。

  • ドメイン名の評価は後方一致
  • ホスト名を省略した指定では先頭にドットが必要

後者のルールに従えば「{username}.clipp.in」に合致するCookieドメインは「.clipp.in」でなければなりませんが、「.clipp.in」は「clipp.in」には後方一致しません。

そこで、モバイル版のユーザ共通ページのドメインは「m.clipp.in」に変更しようと考えました。

続いてソフトバンクモバイル

さてしかし、これではソフトバンクモバイルでうまくいきません。「clipp.in」というドメイン名は「クリッピン(グ)」から採ったものですが、ソフトバンクモバイルのCookieドメインには以下のようなルールがあるようで、「clipp.in」のトップレベルドメイン「.IN」がこの制約を受けます。

  • gTLD、及び他のいくつかのトップレベルドメイン(.JPのみ?)では2ヶ以上、その他は3ヶ以上のドットが必要

これはNetscapeのCookie仕様でお馴染みのハナシで、実際のところ属性ドメインを含む(かもしれない)ccTLDなどの扱いはウェブブラウザの実装によって差異がありますが、ソフトバンクモバイルでは、「.IN」は3ヶ以上のドットが必要なドメインとなるようです。つまりドメインに「.clipp.in」を指定したCookieは無効で、有効なCookieであるためにはドメインを「.{なんとか}.clipp.in」という形式にしなければならないようなのです。

しかし、Cookieドメインを例えば「.m.clipp.in」に変更すると、当然「{username}.clipp.in」には合致しません。そこで、ユーザ個別ページのドメイン名も「{username}.m.clipp.in」に変更しようと考えました。

再びau/EZweb

しかし、Cookieドメインを「.m.clipp.in」とすると、ユーザ共通ページのドメイン名「m.clipp.in」が、前述のEZwebの後方一致ルールでNGなので、EZwebではCookieドメインを「.clipp.in」、ソフトバンクでは「.m.clipp.in」と分ければいいかと考えました。

さてしかし、これでもやっぱりうまくいきません。EZwebは「{username}.m.clipp.in」に対して、ドメインに「.clipp.in」を指定したCookieを返してくれません。これはどうやら:

  • ホスト名を省略した指定では、ホスト名部分にドットが含まれてはいけない

というルールのようです。RFC 2109の4.3.2にあるA Set-Cookie from request-host y.x.foo.com for Domain=.foo.com would be rejected, because H is y.x and contains a dotですね。ちなみにソフトバンクモバイルは、このパターンはOKのようです。

ということで結局

以上のような試行錯誤を繰り返した挙句にclippモバイルはリリースされました。結局どうしたか、ご興味のあるかたは実際にclippモバイルにアクセスしてお確かめください(笑)。

本日のまとめ

  • ケータイサイトでマルチサブドメインは止めとくが吉
  • もしやらなければならないのならgTLDまたは.JPなドメイン名で

ではでは。

作者: unoh

更新日:2008年10月8日 15時4分

このブログのホーム

四角いリンク

yamaokaです。 最近タブをメタファーにしたナビゲーションをよく見るようになりました。タブには大抵、内容を示すキャプションが付けられています。さて、どこからどこまでがリンクでしょうか。どの部分をクリックすればそのタブを選択できるでしょうか。 タブ型ナビゲーション 例えば、キャプションの文字だけにリンクが貼られている場合。利用者はタブの中のさらに狭い範囲、文字の部分を狙ってクリックしなくてはなりません。 タブ型ナビゲーション(文字だけリンク) 実はマウスの操作というのは難しいのです。狭い範囲を狙って指定することにはあまり向いていません。目的到達のために狭い範囲のクリックを強制するのはどう考えてもよいインターフェースではありません。 そこで大抵のタブ型インターフェースではタブの枠の中全体をリンクとして扱えるようになっています。 タブ型ナビゲーション(ブロックリンク) アンカー要素のdisplay属性をblockにして、必要な高さと幅を与えることでリンクの範囲を四角形に広げることができますね。大きさを固定値で指定してもかまいませんが、そうするとキャプションの文字の大きさによってははみ出てしまうかもしれません。padding属性を使えば大丈夫です。

.nav a {
  display: block;
  padding: 5px 10px;
}
マウスのポインタがタブの上に乗ったときにタブの色に変化をつけてあげると、よりリンクであることを強調することができるかもしれません。
.nav a:hover {
  background-color: #DEE;
}
ほとんどのサイトで同様のテクニックが使われていて、利用する側としては当たり前のように使っているインターフェースはいろいろとあります。 しかしそういうインターフォースでも、「なぜそうなっているのか?」と考えてみると面白いと思います。

作者: unoh

更新日:2008年10月1日 9時55分

このブログのホーム

TipsUI

開発に集中するための3つのWebアプリ徹底活用

季節の変わり目にものの見事に風邪をひかされたyukiです。今日は普通にライフハックネタをお送りします。すでにみなさん実践されていることも多いかと思いますが、自分なりにちょっとアレンジしてあったり、微妙に使い方を変えていたりするので、何かひとつでも参考になればと思います。

スケジュール管理はGoogleカレンダーで一元化

まずひとつめ、身も蓋もないですがGoogleカレンダー 使いましょう。モバイルにアラートメールくれたり、早朝に当日の予定をメールで送ってくれたり、とても便利です。
ウノウではサイボウズを使ってスケジュール管理しているので、「Cybozu Office 6のカレンダーをGoogle Calendarで表示する 」を使って自宅サーバーへ取り込み、それをURL追加して利用しています。
また、Googleカレンダーはモバイルでも見られますが1週間表示固定だったりと色々と使い勝手が悪いので、こちらは「 yamamo's Blog - Google Calendar Mobile Gateway」さんのWebアプリが秀逸ですので、こちらを使わせてもらっています。

ToDo管理はRemember The Milk

ふたつめ、こちらも有名ですがToDo管理は「Remember The Milk (RTM)」というWebアプリを利用しています。RTMを採用した一番の理由は、メールでToDo作成出来ることです。これだと、日常に起きる「気づき」をメールすれば自然とToDo管理できますので「そういえばティッシュがきれていた」とか、その名のとおり「牛乳を買う」とかもサッと携帯でメールするだけでOKなので、非常に重宝しています。他にも、キーボードショートカットが充実していたり、モバイルでも編集・確認できたり、iPhoneアプリと連携して同期させたり(有料)、「GoogleGears 」を利用してオフラインでも使えたりと非常に使い勝手がいいです。

Thunderbird(Lightning) / Sunbird

上記の2つが優れている点は、 Thunderbird を使っている方はLightning を、そうでない方はSunbird を使うと、いくつかのアドオンを入れるだけで、ブラウザを立ち上げずともスケジュール確認ができることです。

自宅サーバーにWikiを導入

みっつめ、自宅サーバーに認証をかけた上で、Wikiを利用して個人データベースにしてしまうというものです。私の場合はSSL+Basic認証で認証を行っています。パスワードや個人情報、使っているハードや周辺機器の型番などを記述しています。といっても全部完璧に揃えようと思うと膨大な時間がかかるので、思い出した時に追記する感じにしています。wikiのいいところは、出先でも携帯からサッと取り出せる所です。電話番号を自動リンクするプラグイン を導入すれば、「携帯でwikiから探す」→「見つかった問い合わせ先へ電話」とワンステップですぐに行動することが出来るので、携帯のメモリに入れるほどではないが、必要なときにいつでも取り出せる簡易電話帳として、とても便利に利用しています。

たいていのものは自宅サーバーへ置いておく

これは自分のジンクスみたいなものですが、なぜか私の使うHDDは高確率で故障します。それも、購入から数年(短いと1年程...)で確実に。なので、大事なデータは常に自宅サーバーへ置いておき、かつバックアップを毎日退避させることにしています。設定の導入までは大変ですが、やってしまえば非常に快適なので(当然会社のセキュリティポリシーに反しない範囲で)全ての情報を自宅サーバーで管理するようにしています。「必ず情報(データ)はそこにある」というのは非常に安心感もありますし、なにより探す手間を省いてくれるので、非常に楽です。極端な例ですが、私の場合家計簿はGnuCash を利用しているのですが、このデータも自宅サーバーに置いておき、クライアントから読み出して利用するようにしています。

いかがでしたでしょうか。割と有名なものや、既に実践している事も多いかと思いますが、やはり個人情報やスケジュール/ToDoも一元管理すると大幅に(心理的、または時間の)コストを下げることが出来たと思うので、まだ実践されていない方は、一度検討してみるのもいいかもしれません。

作者: unoh

更新日:2008年9月30日 10時56分

このブログのホーム

IDEでマルチプラットフォームなGUIアプリを開発する環境構築のメモ (C++ & wxWidgets)

gotandajinです。

なにかGUIアプリケーションを作ろうとした時、一番手軽に手を出せる開発環境はVisual Studioあたりかなぁと思われますが、Visual Studio は基本的にWindows専用です。Javaを使えばプラットフォーム間の差異を吸収して、同一ソースでWindows、Mac、Linux などの複数のOSで動くGUIアプリを作れますが、他の選択肢としては、開発言語をCやC++で、マルチプラットフォームなGUIフレームワークを利用しての開発、なんかが挙げられます。マルチプラットフォームなGUIフレームワークを使えば、Javaと同様に同一ソースで複数のプラットフォーム用のGUIプログラムが作成できます。こちらはJavaとは違い、オブジェクトコードとして生成できるのが特徴です。

代表的なマルチプラットフォームGUIフレームワークにはQT(キュート)やwxWidgetsが挙げられますが、昨今一番隆盛なのはたぶんQTの方です。こちらはSkype、Google Earth、Operaなど、稼動実績に有名どころが集まっているのですが、一番手軽に使えるオープンソース版でもGPLの制限がかかります。GPLより緩く使いたい場合は、ライセンス料を支払う必要があります。

一方、wxWidgetsは成果物のバイナリをほぼ自由に配布できるフレームワーク (http://www.wxwidgets.org/about/licence3.txt 参照) なので、手の出し易さではこちらの方が上と思われます。現在の最新版が2.8.9で更新日時が2008/09/22 、一つ前のバージョンの更新日時が 2008/6/28 なので、割と継続して更新もされています。 http://wxwidgets.info/

今回はwxWidgetsとEclipseなどのIDEを連携させたマルチプラットフォームなGUIアプリ開発環境の構築について書いてみようと思います。また、ここではプログラムをビルドする環境はWindows XP、開発言語はC++ です。

とりあえずまずはC++のコンパイラをインストールする

WindowsでC++のソースをコンパイルしようとした時、手段はVisual C++、Cygwin、Boraland C++ Builder など色々ありますが、ここではMinGWとMSYSを使うことにします。MinGWは、Windows用に移植されたGCCを使うための環境です。また、MSYSはUNIX風なCUI環境としてMinGWを補うツールです。

MinGWとMSYSのインストールについてはここでは割愛します。 http://www.knatech.info/Dev-mingw-install.html
ここの説明が分かりやすいのでご参照ください。

wxWidgets(wxMSW)をインストールする

http://www.wxwidgets.org/downloads/#latest_stable
このwxWidgetsのページからwxMSWのパッケージをダウンロードします。wxMSWはインストーラの形式で配布されています。wxMSWというのは、wxWidgetsのWindows環境用のパッケージです。LinuxのGTK環境用であればwxGTK、Mac環境用であればwxMacを使用します。

wxMSWのインストーラをダウンロードしたら実行し、上でインストールしたMSYSの、homeディレクトリの下層にファイルを展開します。(現在の最新版は2.8.9)

wxMSWinstall
wxMSWinstall posted by (C)フォト蔵 (筆者の場合)

ファイルの展開が終わったら、MSYSから、たった今展開したwxWidgets-2.8.9のディレクトリにcdで移動し、./configureで makefileを設定した後、makeでコンパイル、make install でwxWidgetsをインストールします。

$ pwd
/home/gotanda  (筆者の場合)
$ ls
wxWidgets-2.8.9
$ cd wxWidgets-2.8.9/
$ ./configure --disable-shared --disable-threads --enable-monolithic --enable-unicode
$ make
$ make install

これでインストールできるはずです。

./configure 以下はけっこう時間がかかります。特にmakeではスタティックリンクライブラリを大量に生成するのでなかなか終わらないです。スペックの低いPCだと数十分かかるかもしれません。

./configure 時のオプションの詳細についてはここでは割愛します。
以下参考にさせて頂いたサイトです。
http://0xcc.net/pub/uu-2004-08/
http://www.nslabs.jp/wxwidgets-install.rhtml

サンプルプログラムをコンパイルしてみる。

インストールが終わったらちゃんとGUIアプリを作成できるか試してみます。

test.zipにサンプルプログラムを用意しました(簡単なテキストエディタプログラムです)。解凍したら表示されるtestディレクトリをmsysのhomeの下層ディレクトリに置いてください。

MSYSから

$ pwd
/home/gotanda (筆者の場合)
$ ls
test
$ cd test
で、testディレクトリに移動し、
g++ -c TestApp.cpp TestFrame.cpp `wx-config --cppflags`
g++ -o test.exe TestApp.o TestFrame.o `wx-config --libs`
でコンパイル&リンクします。これでtest.exeが生成され、正常に実行できればwxWidgetsのインストールに成功しています。

test.exeの起動 test_editor
test_editor posted by (C)フォト蔵

wx-config --cppflags というのはコンパイル時のオプションを吐くコマンドで、wx-config --libsはリンク時のオプションを吐くコマンドです。バッククオートで囲ってg++のオプションとして渡しています。

なお、GUIをデザインするためのRADツールにはwxGladewxFormBuilder などがあります。 ここではwxFormBuilderを使ってみました。

IDEからwxWidgetsを使う

やっとwxWidgetsを利用できるようになりましたが、毎回MSYSからコンパイルするのは面倒なのでwxWidgetsのプロジェクトをIDEからビルドできるように設定してみます。wxWidgetsのインストールについての資料はウェブ上でたくさん見つかるのですが、IDEから使う場合についての記述は意外となかったので、これからやろうとしている方々のお役に立てれば幸いです。

IDE(統合開発環境)はプログラミングに必要なツール(ソースエディタやコンパイラなど)を一つのインターフェースからまとめて使えるようにしたり、makefileを自動生成してくれたりと色々便利ですが、種類も色々あります。ここではEclipse CDT、NetBeans の場合について載せておきます。

Eclipse CDT の場合

EclipseはJava用の統合開発環境ですが、プラグインを入れることでC++やPHPの開発にも使えます。 ここではC++の開発ができればよいので、 http://www.eclipse.org/downloads/ から、Eclipse IDE for C/C++ Developers をダウンロードして使ってみました。versionは3.4.0でした。

まずはプロジェクトを作ります。 プロジェクトというのは、1つのプログラムを生成するために使うソースや設定などをひとまとめにしたものです。メニューのFileからNew→C++ Project と進み Project Name に適当な名前を入力したらFinishを押します。

次にwxWidgetsを利用できるようにプロジェクトを設定します。 MSYSからコンパイルする時は、`wx-config --cppflags`のようなコマンド置換によるオプションの生成ができたのですが、どうもEclipse CDT からビルドする際バッククオート(`)がちゃんと評価されないようでうまくいかなかったので、wx-config --xxxで吐かれるオプションをプロジェクトの設定に直書きしてしまい、なんとかビルドできるようにしました。

最初に、コンパイル時の設定をします。 wx-config --cppflags で吐かれるオプション

-I/usr/local/lib/wx/include/msw-unicode-release-static-2.8
-I/usr/local/include/wx-2.8 -D__WXMSW__
を、C:ドライブからのフルパス表記に変えて、それぞれ設定します。

メニューのProjectからProperties→C/C++ Build→Settings→Tool Settings → GCC C++ Compiler と進み、 PreprocessorのDefined Symbolに

__WXMSW__
を、 DirectoriesのInclude Paths(-I)に

C:/msys/1.0/local/lib/wx/include/msw-unicode-release-static-2.8
C:/msys/1.0/local/include/wx-2.8

を追加します。

cdt_setting1
cdt_setting1 posted by (C)フォト蔵

そして、リンク時の設定です。wx-config --libs で吐かれるオプション

-L/usr/local/lib   -Wl,--subsystem,windows -mwindows /usr/local/lib/libwx_mswu-2.8.a -lwxregexu-2.8 -lwxexpat-2.8 -lwxtiff-2.8 -lwxjpeg-2.8 -lwxpng-2.8 -lwxzlib-2.8 -lrpcrt4 -loleaut32 -lole32 -luuid -lwinspool -lwinmm -lshell32 -lcomctl32 -lcomdlg32 -lctl3d32 -ladvapi32 -lwsock32 -lgdi32
を、コンパイル時の設定と同様、C:ドライブからのフルパス表記に変えてそれぞれ設定します。

メニューのProjectからProperties→C/C++ Build→Settings→Tool Settings → MinGW Linker と進み、 Libraries の Libraries (-l) に

wx_mswu-2.8 wxregexu-2.8 wxexpat-2.8 wxtiff-2.8 wxjpeg-2.8 wxpng-2.8 wxzlib-2.8 rpcrt4 oleaut32 ole32 uuid winspool winmm shell32 comctl32 comdlg32 ctl3d32 advapi32 wsock32 gdi32
を1つずつ追加、 cdt_setting2
cdt_setting2 posted by (C)フォト蔵 Librariy search path (-L) に
C:/msys/1.0/local/lib
を追加、 Miscellaneous の Linker Flags に
-Wl,--subsystem,windows -mwindows
を追加します。 これで設定は完了です。

最後にビルド、GUIアプリの生成です。 メニューのFiles→New→Source Folder で左側の Project Explorer にソースフォルダが新しく生成されるので、そこに先ほどのtestプログラム(簡易テキストエディタ)のソースファイル4つをpasteします。 eclipse build
eclipse build posted by (C)フォト蔵 そして、メニューのProject→Build Project でビルドに成功するはずです。

NetBeans の場合

NetBeansもEclipse と同じような統合開発環境です。NetBeansでもwxWidgetsを利用できるようにしてみましたが、Eclipse CDT の場合とほとんど同じなので画像だけ載せておくことにします。

netbeans_setting1
netbeans_setting1 posted by (C)フォト蔵 netbeans_setting2
netbeans_setting2 posted by (C)フォト蔵

・・と、こんな感じで、IDEとwxWidgetsを組み合わせて、C++でマルチプラットフォームなGUIアプリを開発できるようになりました。

作者: unoh

更新日:2008年11月26日 11時59分

このブログのホーム

Macでのスクリーンショットの撮り方まとめ

yamaokaです。

Mac(Mac OS X)でスクリーンショットを撮る方法についてまとめてみます。いつも忘れてしまうので個人的な備忘録だったりしますが、同じことで悩んでしまう方にとって少しでも参考になれば幸いです。

「Command + Shift + 3」を押下

単純に画面全体のキャプチャ画像が必要な場合に使います。ショートカットキーを押した瞬間、デスクトップに画面全体のキャプチャ画像が保存されます(PNG形式)。

「Command + Shift + 4」を押下

マウスカーソルが十字(ヘアライン)に変わり、画面上の範囲を選択できるようになります。ドラッグして範囲選択した上でマウスのボタンを離すと、選択範囲のキャプチャ画像がデスクトップに保存されます(PNG形式)。

「Command + Shift + 4」を押下、さらに「Space」を押下

マウスカーソルがカメラの形に変わり、その時点で開いているウィンドウが選択できるようになります。いずれかのウィンドウを選択してマウスをクリックすると、そのウィンドウのキャプチャ画像がデスクトップに保存されます(PNG形式)。

クリップボードに保存したい場合

画像をファイルとして保存するのではなくクリップボードに保存したい場合は、今までのショートカットキーに「Control」を加えて押下するようにします。例えば、画面全体のキャプチャは「Command + Shift + Conrol + 3」です。

「グラブ」を使う

「アプリケーション」→「ユーティリティ」とフォルダをたどっていくと、「グラブ」というアプリケーションが目に入ります。実はこのアプリケーション、スクリーンショットを撮るためのものです。ダブルクリックして起動してみましょう。

「グラブ」の特徴は2つあって、「マウスポインタを含めたキャプチャ画像が作れること」、「タイマー撮影が行えること」です。

グラブの環境設定画面

環境設定を見るとデフォルトではマウスポインタを含めない設定になっていますが、含めるように設定すればマウスポインタを含めたスクリーンショットを撮ることができます。また、「取り込み」メニューからタイマー撮影をすることができるのもわかります(10秒後のスクリーンショットを撮ることができます)。

スクリーンショットの撮影後は保存するためのウィンドウが表示されるので、必要な場所にファイルとして保存しましょう(TIFF形式)。

(番外編)screencaptureコマンドを使う

ターミナルを立ち上げて、おもむろに「screencapture test.png」と入力してreturnキーを押下すると画面全体のキャプチャ画像が「test.png」として保存されることになります(PNG形式)。専用のコマンドが用意されているのですね。

man screencapture

screencaptureコマンドにはきちんとmanも用意されているので、見てオプションを確認しておくといいかもしれません。sleepコマンドと組み合わせればタイマー撮影ができるようになりますね。

まとめ

上で挙げた方法はいずれもMacの初期状態で行うことのできるものばかりです。スクリーンショットを撮るには標準の機能だけで十分備わっていると言えます。ただ、頻繁にスクリーンショットを撮るという目的には適わない場合があるかもしれません。そういう場合は、InstantShot!などのソフトウェアを使うとより便利になると思います。

作者: unoh

更新日:2008年9月24日 18時10分

このブログのホーム