]> jfr.im git - irc/SurrealServices/srsv.git/blob - tags/0.4.3.1-pre2/SrSv/IRCd/Queue.pm
cut of branches/0.4.3
[irc/SurrealServices/srsv.git] / tags / 0.4.3.1-pre2 / SrSv / IRCd / Queue.pm
1 # This file is part of SurrealServices.
2 #
3 # SurrealServices is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7 #
8 # SurrealServices is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with SurrealServices; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
17 package SrSv::IRCd::Queue;
18
19 # The purpose of this module is to make sure lines get processed in an
20 # order that makes sense, e.g., a JOIN should not be processed before
21 # the corresponding NICKCONN has been.
22
23 # FIXME: This may not be well optimized. It also can be fouled up by
24 # conflicting messages with the same WF value, such as the same nick
25 # disconnecting and connecting at once.
26
27 use strict;
28
29 use Exporter 'import';
30 BEGIN { our @EXPORT_OK = qw(ircd_enqueue queue_size) }
31
32 use SrSv::Debug;
33 use SrSv::Message qw(message);
34 use SrSv::Constants qw( WF_MAX );
35
36 our @queue = map [], 0..WF_MAX;
37
38 sub ircd_enqueue($) {
39 my ($message) = @_;
40 my ($ircline, $wf) = @$message{'IRCLINE', 'WF'};
41
42 if($wf == 0) {
43 message($message);
44 return;
45 }
46
47 push @{$queue[$wf]}, $message;
48
49 if(_is_runnable($message)) {
50 print "$message->{IRCLINE} is runnable immediately. (WF=$message->{WF})\n" if DEBUG;
51 message($message);
52 $message->{_Q_RUNNING} = 1;
53 }
54 }
55
56 sub queue_size(;$) {
57 my ($depth) = @_;
58 if(!$depth) {
59 $depth = WF_MAX;
60 }
61 my $r;
62 for(my $i = 0; $i < $depth; ++$i) {
63 $r += scalar @{$queue[$i]};
64 }
65 return $r;
66 }
67
68 sub finished {
69 my ($message) = @_;
70 my ($ircline, $wf) = @$message{'IRCLINE', 'WF'};
71
72 print "Called finished() for $ircline\n" if DEBUG();
73
74 for(my $i; $i < @{$queue[$wf]}; $i++) {
75 if($queue[$wf][$i]{IRCLINE} == $ircline) {
76 splice(@{$queue[$wf]}, $i, 1);
77 last;
78 }
79 }
80
81 if($message->{TYPE} eq 'SEOS') {
82 $message->{TYPE} = 'POSTSEOS';
83 message($message);
84 }
85
86 _dequeue();
87 }
88
89 sub _is_runnable($) {
90 my ($message) = @_;
91 my ($ircline, $wf) = @$message{'IRCLINE', 'WF'};
92
93 for(1..($wf-1)) {
94 if(defined($queue[$_][0]) and $queue[$_][0]{IRCLINE} < $ircline) {
95 print "Line $ircline must wait for $queue[$_][0]{IRCLINE}\n" if DEBUG;
96 return 0;
97 }
98 }
99
100 return 1;
101 }
102
103 sub _dequeue {
104 foreach my $q (@queue) {
105 INNER: foreach my $message (@$q) {
106 next INNER if $message->{_Q_RUNNING};
107
108 if(_is_runnable($message)) {
109 print "$message->{IRCLINE} is now runnable\n" if DEBUG;
110
111 message($message);
112 $message->{_Q_RUNNING} = 1;
113 }
114 else {
115 last INNER;
116 }
117 }
118 }
119 }
120
121 1;