goo blog サービス終了のお知らせ 

P2Pとかプログラミング全般とか

P2Pアプリ開発を目指していこうかと。
基本、週末更新なので遅々として進まず。

デバッグした

2008-07-08 22:14:40 | Overlay Weaver
owemu で起動できるようにしたり、デバッグしたり。
http://cid-7862a61060e90b1f.skydrive.live.com/browse.aspx/NicoCacheWithOverlayWeaver?view=details

ログを java.util.logging 経由で出すようにしたので、logging.properties

java -Djava.util.logging.config.file=./logging.properties
みたいに指定して起動すべし。
今つかっているプロパティは、
handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = ALL

#.level=WARNING
.level=ALL
dareka.level=WARNING
dareka.ow.level=ALL
# for OW.
dht.level=WARNING
routing.level=WARNING
directory.level=WARNING
id.level=WARNING
ipmulticast.level=WARNING
messaging.level=WARNING
statcollector.level=WARNING
util.level=WARNING
mcast.level=WARNING
mrouted.level=INFO

こんな感じ。Overlay Weaver の Logging が階層構造になってないせいで
個別にレベル指定しなきゃいけないのがうざい。getClass().toString()
で Logger.getLogger してくれれば ow.level=WARNING で抑止できる
ものを…。

Kademlia だと RecursiveRouting は使えないらしい

2008-06-22 21:54:12 | Overlay Weaver
メーリングリストで気になる話題が出てた。
[Overlayweaver-discuss] put/get in kademlia using recursive style messages fails
Kademlia では Recursive Routing が使用できないそうだ。
Iterative なら動くのでそちらをつかおう。

メッセージピープのために

2008-06-01 21:54:14 | Overlay Weaver
DHT に put する場合、実際に DHT のネットワークにちゃんと参加できているのか、
それともまだ安定していない、もしくは参加できていないのかが重要になる。
標準ではそのような情報が得られないようなので、別の方法を考えてみた。

他のノードから REQ_SUCCESSOR, REQ_PREDECESSOR がくるはずなので、それを
検知して判断することを考える。まずはそのメッセージをどう受信するかだ。
以前書いたとおり、これらの Tag の値で MessageHandler を登録してしまうと
メッセージに対して null を返すほか無くなる(実際には応答メッセージを
返さなければならない)ので、なんとかして実際の MessageHandler より前に
ハンドラを登録する必要がある。

ここで JavaDoc やらドキュメントやらを眺めてみると ow.stat がある。
これは統計用にメッセージをフックしつつも実際のハンドラに影響を与えていない、
つまりは実際のハンドラよりも前に処理用ハンドラを登録することに成功している。
ただし ow.stat そのものは使えない。MessagingReporter はリポート用に
外部に接続を作成してしまう。そこまでする必要はない。なのでどうやって
ハンドラを登録しているのか調べてみた。
調査をしてみると、要するに Tag の値によってハンドラを呼び分ける MessageHandler
を登録するよりも前にフック用ハンドラを登録することでこれを実現していることがわかった。
Tag 値呼び分けハンドラは ow.routing.impl.AbstractRoutingDriver のコンストラクタ
で登録される。このクラスは IterativeRoutingDriver, RecursiveRoutingDriver
の親クラスのため、ルーティング方法が決定するより前に MessageReceiver を
作成できれば OK ということになる。

ow.stat ではどうやっているかというと、StatFactory.getMessagingCollector
で MessagingCollector を作成し、メンバメソッドの getMessagingProvider,
getMessageReceiver で作成している。これらで作成した時点ではルーティング用の
ドライバが作成されないので、フック用の MessageHandler が登録し放題となる。

と、これで問題なければよかったのだがそうは上手くいかなかった。テスト用に
owemu で実行したところ、NullPointerException 発生。調査したところ、
MessageReceiver に登録されているハンドラがフック用のもの1個だけになってる。
どうなってる?Tag 値呼び分けハンドラが登録されるはずでは?

さらに調べると、エミュレータ実行時の MessagingProvider である EmuMessagingProvider
の substitute() メソッドが新しいインスタンスを返している!
MessagingProvider は MessagingFactory.getProvider で作成される。普通なら
同一 Provide が返されるのだが、実装の中で substitute() を呼び出し、
null でなければ既に作成されているインスタンスの代わりにこれを返す。
これは要するにエミュレータ実行時に、仮想ノード毎に異なる Provide インスタンス
を返すための機能なのだと思う。
MessageReceiver は Provider によって生成されるが、通常はひとつ作れば
何度取得しようが同一インスタンスを返す。異なる Provide インスタンスになれば
当然異なる MessageReceiver を返す。
ow.stat に似せてフック用ハンドラを登録したとしても、DHT インスタンス
作成時に MessagingFactory.getProvider を呼ばれてしまうと、異なる Provider が
返され、フックが登録されていない MessageReceiver が作成され、そちらに
Tag 値呼び分けハンドラが登録されるわけだ。
で、どちらの MessageReceiver にメッセージが届けられるかといえば、フック用
ハンドラを登録した最初のインスタンス。こちらが emu0 のアドレスを振られるから。
で、こちらには Tag 値呼び分けハンドラがない→正常な要求メッセージに
null 値を返すしかなくなる→NullPointerException となるわけだ。
これはエミュレータでしかおきない。なぜならエミュレータ以外の TCP, UDP 用の
MessagingProvider では substitute() が同一インスタンスを返すため。
同一 Provider だから、最初にフック用ハンドラを登録した MessageReceiver を、
Tag 値呼び分けハンドラ登録時にも Provider が返してくれる。
ということで、エミュレータ実行時は ow.stat は使えないわけだね。

で、ここであきらめてはプライドが許さない。これでもプログラマの端くれ。矜持は
あるつもり。
要は DHT 作成時に MessagingFactory.getProvider を呼ばず、こちらが用意した
Provider を受け入れてくれればいいはず。しかしどこをさがしても MessagingProvider
を受けてくれない。で、StandardDHTImpl をゴニョゴニョ探したところ、
コンストラクタが2つあることに気づく。DHTConfiguration を必要とするものと、
RoutingService を必要とするもの。比較してみると、前者は要するに RoutingService
を作成することが最終目的になっているようだ。後者のコンストラクタを
使用すれば、MessagingFactory.getProvider を呼ばずに DHT が構築できる。
つまりエミュレータ環境でも受信メッセージフックができる。

で、なんとか RoutingService を作成して DHT を作ってみると…。やっぱり NullPointerException。
なんでじゃと思ってさらに調べると、RoutingAlgorithm が null になってた。
StandardDHTImpl のコンストラクタを良く調べてみると、RoutingAlgorithmProvider
の initializeAlgorithmInstance を呼ばないと AbstractRoutingDriver に
アルゴリズムが登録されないらしい(AbstractRoutingAlgorithm のコンストラクタと、
AbstractRoutingDriver.setRoutingAlgorithm を調べてみるべし。特に後者を
使用しているところを Eclipse で検索すれば、他で登録していないことがわかる)。
で、最終的にはちゃんとフックできましたとさ。お疲れ様。

もうこういう面倒な調査しないでもフック(というか peep?)できるように
して欲しいよ、ホント…。


// メッセージフック設定。
RoutingService routingSvc = null;
if (cmd.hasOption("sam")) {
    StatConfiguration statConf = StatFactory.getDefaultConfiguration();
    DHTConfiguration dhtConf = DHTFactory.getDefaultConfiguration();
    statConf.setMessagingTransport(null != transport ? transport
            : dhtConf.getMessagingTransport());
    if (null != selfAddressAndPort) {
        MessagingUtility.HostAndPort hostAndPort = MessagingUtility
                .parseHostnameAndPort(selfAddressAndPort, dhtConf.getSelfPort());
        statConf.setSelfAddress(hostAndPort.getHostName());
        statConf.setSelfPort(hostAndPort.getPort());
    }
    statConf.setDoUPnPNATTraversal(false);
    try {
        MessagingCollector messagingCollector = StatFactory
                .getMessagingCollector(statConf);
        messagingCollector.getMessageReceiver().addHandler(
            new MessageHandler() {
                public Message process(Message msg)
                        throws Exception {
                    showReceivedMessage(msg);
                    return null;
                }
            });
        // RoutingService 作成。
        RoutingServiceProvider svcProvider = RoutingServiceFactory.getProvider(
                null != routingStyle ? routingStyle : DHTConfiguration.DEFAULT_ROUTING_STYLE);
        RoutingAlgorithmProvider algoProvider = RoutingAlgorithmFactory.getProvider(
                null != algorithm ? algorithm : DHTConfiguration.DEFAULT_ROUTING_ALGORITHM);
        routingSvc = svcProvider.getService(svcProvider.getDefaultConfiguration(),
                messagingCollector.getMessagingProvider(),
                messagingCollector.getMessageReceiver(),
                algoProvider, algoProvider.getDefaultConfiguration(), selfID);
        // アルゴリズム作成。
        RoutingAlgorithmConfiguration algoConfig = algoProvider.getDefaultConfiguration();
        algoProvider.initializeAlgorithmInstance(algoConfig, routingSvc);
    } catch (Exception e1) {
        e1.printStackTrace();
    }
}

0.8.6出てる

2008-05-21 08:58:01 | Overlay Weaver
最新バージョン0.8.6が出てる。
0.8.3 からの比較で言うと、メモリ消費量の削減が大きな変更みたい。
0.8.5 で通信メッセージのサイズ削減が行われた。具体的にはシリアライズ時に gzip で圧縮するようになった。
Message.encode(Message msg) で、Message.GZIP_MESSAGE が true の場合、
    if (GZIP_MESSAGE) {
        os = new GZIPOutputStream(os);
    }

このようにしてシリアライズを圧縮してる。正直、どの程度縮むのか多少疑問だけど
テキストベースでキロバイト単位のメッセージならかなり効果的だとは思うので
うれしい修正だ。
Message.GZIP_MESSAGE が static final なのでメッセージ毎に圧縮非圧縮を選ぶ
ことはできない。さらに gzip 圧縮かどうかのフラグをメッセージのバイト列に
持たないので、ノード同士は Message.GZIP_MESSAGE が同じ値のものでしか
通信できない。このへんはちょっとだけ気をつけるべきかも。

あっというまに0.8.3

2008-05-05 14:27:17 | Overlay Weaver
Overlay Weaver 0.8.3 が出てる。
前回、Collective Routing が複数 ID に複数の値を put, get, remove する機能だと書いたが間違いだった。すまん。
正確な説明はメーリングリストを見ると判る。要するに同一の宛先データを別パケットにしないで一個にまとめる
機能のことらしい。
同一 ID への要求は同じノードをたどって到着することが多いという考えなのだろうか。

そのほかの修正は以下。

(1)DHT.put メソッドから TTL 指定が抜けた。
 結構大きな変更。Overlay Weaver を使ってプログラムを書いている人は自分の
ソースを再度チェックが必要。

(2)DHT.put, DHT.remove にオーバーロードメソッドが追加。1 つの ID に対して複数の値を受け付ける。
 正直、どういう時に 1 つの ID に複数の値が出てくるのかわからん。たとえば
とあるメンバーの名前と年齢をひとつのクラスに収めないで、String と Long で
別々に登録するとか?

(3)DHT.put, DHT.remove で同一 ID への複数メッセージを1つにたばねるようになった。
 これは Collective Routing に関係する修正と見た。受け取ったノードに任せない
で、送出元でまとめられるときはまとめちゃうほうが効率いいしね。


ところで Collective だと集めるとか集合って意味で、メッセージをまとめる感が
薄い感じ。代わりに Bundle Forward とかどうだろう。

0.8.2が出てる

2008-04-29 21:16:53 | Overlay Weaver
Overlay Weaver 0.8.2 が出てる。

注目は2つ。
・recursive ルーティングのバグをいくつか修正した。
 Iterative があんまり好きになれない私にとってはうれしい修正。
・collective routing を実装した。
 第3のルーティングが登場、かと思ったんですが違うみたいです。たぶん。
 ow.dht.DHT インターフェイスの get, put, remove に複数 ID 用のメソッドが
 追加されました。たぶんこれが collective routing かと思われます。
 ソースを全文検索する限り、collective が出てくるのはここだけなので。
 CollectiveRoutingDriver なんてクラスが追加されたのかと思ってワクワク
 したんですけどね…。

P4Pについての論文の日本語紹介があった

2008-04-29 13:47:39 | P2P
Geekなぺーじ : P4P : P2Pの進化系?

P2P ソフトウェア側からでは調べきれない情報をプロバイダが提供することで、
プロバイダへの負荷を下げ、利用効率をもっと上げることを目的とする P2P が
P4P ってことになるのかな。なんで 2 の次が 3 じゃないのかと思ったが、
よくよく考えてみれば P3P ってもう単語として存在するよね。

「P4Pのモチベーション」の欄を見てもらうのが一番わかり易いんだけど、要するに
P4P をやるとこんな良い事が!だからお互い手を取り合って頑張っちゃおうよ!
ってのが書かれてる。
「情報共有(P2P)研究会」感想の (3) で亀井さんが発表していた懸念に
一緒に対処していこうよ、ってのが P4P なんだろうなと思った。

ただ「やろうよ!」って言ってるだけじゃなく、実際にやってみて、計測して、論文
で出しているのが良い。証拠がちゃんとあるよ、検証できるよ、って姿勢を示す
ことでプロバイダ側のモチベーション、やる気を引き出そうとしている。
日本でもこういう運動を進めていくべきなんだろうな。文句を言うだけじゃ変わらない。
アプリ開発者の端くれとして、微力だけど動いていかなければ。

今週末も仕事+風邪

2008-04-20 10:25:25 | Weblog
体調めっちゃ悪いですが、週末も仕事です。
プログラミングしたいです。休み欲しいです。
それではまた来週。

療養中

2008-04-13 18:40:06 | Weblog
本当は週末の仕事があったんだけど、土曜日に帰ってきたら体調が悪くなって
今日は寝込んでしまった。
というわけでまた来週。最近、本当に時間がなくて進まないなぁ…。

ver0.8.1が出てますね

2008-04-07 07:48:51 | Overlay Weaver
http://sourceforge.net/project/showfiles.php?group_id=156419&package_id=174533
新しいバージョンが出てます。
メーリングリストには何も投稿されなかったので見逃してしまった。