diff -urN tiarra-20040214/ChangeLog tiarra-20040215/ChangeLog --- tiarra-20040214/ChangeLog 2004-02-15 09:19:45.000000000 +0900 +++ tiarra-20040215/ChangeLog 2004-02-15 09:21:35.000000000 +0900 @@ -1,3 +1,21 @@ +2004-02-15 Topia + + * module/Client/Cache.pm: + - message_io_hook を追加。サーバとの通信を監視して、 + MODE や WHO を発行(して返答をもらっている)途中かどうかを + 記憶しておくように。 + - message_io_hook で記憶した情報を使って、 + (ほかのクライアントなどによって)サーバに情報を問い合わせている + 途中の時も、メッセージを破棄するようにした。 + 2つ以上のクライアントが同時につながったときに効果が出るはず。 + テストには LimeChat を 3 つ同時に接続させたが、 + サーバへの問い合わせは各チャンネルにつき1回までに抑えられていた。 + - クライアントに伝達される必要のあるメッセージではないので、 + RunLoop->shared_loop->notify_warn() if ::debug_mode; から + ::debug_printmsg(); に変更。 + - WHO キャッシュにおいて、 + データ不足であきらめたときのメッセージ表示をやめた。 + 2004-02-14 Topia * 全般: @@ -1216,7 +1234,7 @@ * これ以前のログは書いていません。 -# Id: $Id: ChangeLog,v 1.128 2004/02/14 11:48:17 topia Exp $ +# Id: $Id: ChangeLog,v 1.129 2004/02/15 00:19:31 topia Exp $ # Author: $Author: topia $ -# Date: $Date: 2004/02/14 11:48:17 $ -# Revision: $Revision: 1.128 $ +# Date: $Date: 2004/02/15 00:19:31 $ +# Revision: $Revision: 1.129 $ diff -urN tiarra-20040214/NEWS tiarra-20040215/NEWS --- tiarra-20040214/NEWS 2004-02-15 09:19:45.000000000 +0900 +++ tiarra-20040215/NEWS 2004-02-15 09:21:35.000000000 +0900 @@ -1,3 +1,13 @@ +2004-02-15 Topia + + * Client::Cache + - 昨日の分だけでは Excess Flood/Max SendQ Exceeded 対策として + 不十分だったので、アップデートを推奨します。 + - 2つ以上のクライアントが同時に同じ動作をする場合に、 + 今回の変更で効果が出ます。 + 長すぎず短すぎずの絶妙な差で同じ動作をされた場合には + 効きませんが、滅多にそんなことはない(と思いたい)です。 + 2004-02-14 Topia * Log::Recent, System::Raw, Channel::Freeze, Channel::Rejoin diff -urN tiarra-20040214/module/Client/Cache.pm tiarra-20040215/module/Client/Cache.pm --- tiarra-20040214/module/Client/Cache.pm 2004-02-15 09:19:46.000000000 +0900 +++ tiarra-20040215/module/Client/Cache.pm 2004-02-15 09:21:36.000000000 +0900 @@ -1,5 +1,5 @@ # ----------------------------------------------------------------------------- -# $Id: Cache.pm,v 1.2 2004/02/14 12:16:46 topia Exp $ +# $Id: Cache.pm,v 1.3 2004/02/15 00:19:31 topia Exp $ # ----------------------------------------------------------------------------- package Client::Cache; use strict; @@ -20,6 +20,45 @@ return 0; } +sub message_io_hook { + my ($this,$msg,$io,$type) = @_; + + if ($io->isa('IrcIO::Server')) { + if ($type eq 'out' && + $msg->command eq 'MODE' && + Multicast::channel_p($msg->param(0)) && + !defined $msg->param(1)) { + my $ch = $io->channel($msg->param(0)); + if (defined $ch) { + $ch->remark('fetching-switches', 1); + } + } elsif ($type eq 'in' && + $msg->command eq RPL_CHANNELMODEIS && + Multicast::channel_p($msg->param(1))) { + my $ch = $io->channel($msg->param(1)); + if (defined $ch) { + $ch->remark('fetching-switches', undef, 'delete'); + } + } elsif ($type eq 'out' && + $msg->command eq 'WHO' && + Multicast::channel_p($msg->param(0))) { + my $ch = $io->channel($msg->param(0)); + if (defined $ch) { + $ch->remark('fetching-who', 1); + } + } elsif ($type eq 'in' && + $msg->command eq RPL_WHOREPLY && + Multicast::channel_p($msg->param(1))) { + # 処理の都合上、一つでも帰ってきた時点で取り消し。 + my $ch = $io->channel($msg->param(1)); + if (defined $ch) { + $ch->remark('fetching-who', undef, 'delete'); + } + } + } + return $msg; +} + sub message_arrived { my ($this,$msg,$sender) = @_; @@ -38,33 +77,41 @@ my ($chan_short, $network_name) = Multicast::detach($chan_long); my $network = RunLoop->shared_loop->network($network_name); unless (defined $network) { - RunLoop->shared_loop->notify_warn( + ::debug_printmsg( __PACKAGE__.': "'.$network_name. '" network is not found in tiarra.' - ) if ::debug_mode; + ); last; } my $ch = $network->channel($chan_short); - last unless (defined $ch && $ch->remark('switches-are-known')); - my $remark = $sender->remark('mode-cache-used') || {}; - if (!exists $remark->{$chan_long}) { - $sender->send_message( - IRCMessage->new( - Prefix => Configuration->shared_conf->general->sysmsg_prefix, - Command => RPL_CHANNELMODEIS, - Params => [ - RunLoop->shared_loop->current_nick, - $chan_long, - $ch->mode_string, - ], - Remarks => { - 'fill-prefix-when-sending-to-client' => 1, - }, - ) - ); - $remark->{$chan_long} = 1; - $sender->remark('mode-cache-used', $remark); - return undef; + last if !defined $ch; + if ($ch->remark('switches-are-known')) { + my $remark = $sender->remark('mode-cache-used') || {}; + if (!exists $remark->{$chan_long}) { + $sender->send_message( + IRCMessage->new( + Prefix => Configuration->shared_conf->general->sysmsg_prefix, + Command => RPL_CHANNELMODEIS, + Params => [ + RunLoop->shared_loop->current_nick, + $chan_long, + $ch->mode_string, + ], + Remarks => { + 'fill-prefix-when-sending-to-client' => 1, + }, + ) + ); + $remark->{$chan_long} = 1; + $sender->remark('mode-cache-used', $remark); + return undef; + } + } else { + if ($ch->remark('fetching-switches')) { + # 取得しているクライアントがいるなら、今回は消す。 + return undef; + } + # 取得しにいってもらう。 } } elsif ($msg->command eq 'WHO' && $this->_yesno($this->config->use_who_cache) && @@ -73,10 +120,10 @@ my ($chan_short, $network_name) = Multicast::detach($chan_long); my $network = RunLoop->shared_loop->network($network_name); unless (defined $network) { - RunLoop->shared_loop->notify_warn( + ::debug_printmsg( __PACKAGE__.': "'.$network_name. '" network is not found in tiarra.' - ) if ::debug_mode; + ); last; } my $ch = $network->channel($chan_short); @@ -108,9 +155,6 @@ if (!$p->username || !$p->userhost || !$p->realname || !$p->server) { # データ不足。あきらめる。 - RunLoop->shared_loop->notify_warn( - __PACKAGE__.': cache data not enough: '.$p->info. - ' on '.$p->server) if ::debug_mode; die 'cache data not enough'; } @@ -140,6 +184,12 @@ $remark->{$chan_long} = 1; $sender->remark('who-cache-used', $remark); return undef; + } else { + if ($ch->remark('fetching-who')) { + # 取得しているクライアントがいるなら、今回は消して便乗。 + return undef; + } + # 取得しにいってもらう。 } } }