/[meteor]/googlecode.com/svn/trunk/meteord
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /googlecode.com/svn/trunk/meteord

Parent Directory Parent Directory | Revision Log Revision Log


Revision 55 - (hide annotations)
Thu Feb 28 00:21:39 2008 UTC (11 years, 6 months ago) by andrew.betts
File size: 8876 byte(s)
Fixed: Made eof() work properly
Added nocache querystring param and modified Subscriber.pm to allow it
Rewrote stream.html to ensure we capture the last chunk of data before a reset
Incremented version

1 knops.gerd 11 #!/usr/bin/perl -w
2     ###############################################################################
3     # Meteor
4     # An HTTP server for the 2.0 web
5     # Copyright (c) 2006 contributing authors
6     #
7     # The Meteor daemon
8     #
9     # Main program should call Meteor::Config::setCommandLineParameters(@ARGV),.
10     # Afterwards anybody can access $::CONF{<parameterName>}, where
11     # <parameterName> is any valid parameter (except 'Help') listed in the
12     # @DEFAULTS array below.
13     #
14     ###############################################################################
15     #
16     # This program is free software; you can redistribute it and/or modify it
17     # under the terms of the GNU General Public License as published by the Free
18     # Software Foundation; either version 2 of the License, or (at your option)
19     # any later version.
20     #
21     # This program is distributed in the hope that it will be useful, but WITHOUT
22     # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23     # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
24     # more details.
25     #
26     # You should have received a copy of the GNU General Public License along
27     # with this program; if not, write to the Free Software Foundation, Inc.,
28     # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29     #
30     # For more information visit www.meteorserver.org
31     #
32     ###############################################################################
33    
34 knops.gerd 42 ###############################################################################
35     # meterod version
36     ################################################################################
37    
38 andrew.betts 55 $::VERSION='1.05.11';
39 knops.gerd 45 $::RELEASE_DATE='not yet released';
40 knops.gerd 11
41     ###############################################################################
42     # Configuration
43     ###############################################################################
44    
45     use strict;
46    
47 knops.gerd 48 use Socket;
48    
49 knops.gerd 11 use Meteor::Syslog;
50    
51     use Meteor::Socket;
52     use Meteor::Connection;
53     use Meteor::Controller;
54     use Meteor::Subscriber;
55     use Meteor::Channel;
56     use Meteor::Document;
57     use Meteor::Config;
58    
59     $::CRLF="\r\n"; # Line separator to be used throughout all modules
60    
61     our $CONTROL_QUEUE_SIZE=5;
62     our $SUBSCRIBER_QUEUE_SIZE=20;
63    
64     our $MAIN_LOOP_TIMEOUT=60;
65     our $AGE_CHECK_INTERVALL=60;
66    
67     our $MAX_EXIT_DELAY=120;
68 knops.gerd 48
69     our $UDP_MAX_MESSAGE_SIZE=8192;
70 knops.gerd 11
71     ###############################################################################
72     # Main
73     ###############################################################################
74    
75     #
76 knops.gerd 25 # Record startup time
77     #
78     $::STARTUP_TIME=time;
79     $::STARTUP_TIME+=0; # avoid warning
80    
81     #
82 knops.gerd 11 # Program name
83     #
84     $::PGM=$0;
85     $::PGM=~s/^.*\///;
86    
87     #
88     # Handle command line options and config file
89     #
90     Meteor::Config->setCommandLineParameters(@ARGV);
91    
92     #
93     # Do something about warn and die
94     #
95     unless($::CONF{'Debug'})
96     {
97     $SIG{'__WARN__'}=\&Meteor::Syslog::myWarn;
98     $SIG{'__DIE__'}=\&Meteor::Syslog::myDie;
99     }
100    
101     &::syslog('info',"$::PGM launched!");
102    
103     #
104     # Daemonize
105     #
106     {
107     $0="$::PGM daemon";
108    
109 knops.gerd 47 my $facility=$::CONF{'SyslogFacility'} || $Meteor::Syslog::DEFAULT_FACILITY;
110    
111     unless($::CONF{'Debug'} || $facility eq 'none')
112 knops.gerd 11 {
113     # close standard file descriptors
114     close(STDIN);
115     close(STDOUT);
116     close(STDERR);
117     chdir("/");
118     umask(0);
119     # fork and exit parent
120     exit if fork;
121     setpgrp(0, $$) if defined $SIG{TTOU};
122     $SIG{TTOU}='ignore' if defined $SIG{TTOU};
123    
124     # Avoid 'stdin reopened for output' warning with newer perls
125     open(NULL,'/dev/null');
126     <NULL> if(0);
127    
128     open(OUT,">/var/run/$::PGM.pid");
129     print OUT "$$\n";
130     close(OUT);
131     }
132     else
133     {
134 knops.gerd 47 &::syslog('info',"PID\t%s",$$);
135 knops.gerd 11 }
136     }
137    
138     #
139     # Signal handlers
140     #
141     $::HUP=$::TERM=$::USR1=$::USR2=0;
142     $SIG{'HUP'}=sub{$::HUP=1};
143     $SIG{'TERM'}=sub{$::TERM=1};
144     $SIG{'USR1'}=sub{$::USR1=1};
145     $SIG{'USR2'}=sub{$::USR2=1};
146    
147     #
148     # Run server
149     #
150     my $con_counter=0;
151     my $con;
152    
153     my $controlServer=Meteor::Socket->newServer(
154     $::CONF{'ControllerPort'},
155     $CONTROL_QUEUE_SIZE,
156     $::CONF{'ControllerIP'}
157     );
158     my $controlServerFN=$controlServer->fileno();
159    
160     my $subscriberServer=Meteor::Socket->newServer(
161     $::CONF{'SubscriberPort'},
162     $SUBSCRIBER_QUEUE_SIZE,
163     $::CONF{'SubscriberIP'}
164     );
165     my $subscriberServerFN=$subscriberServer->fileno();
166    
167 knops.gerd 48 my $udpServer=undef;
168     my $udpPort=$::CONF{'UDPPort'};
169     my $udpServerFN=undef;
170     if($udpPort && $udpPort>0)
171     {
172     $udpServer=Meteor::Socket->newUDPServer(
173     $udpPort,
174     $::CONF{'UDPIP'}
175     );
176     $udpServerFN=$udpServer->fileno();
177     }
178    
179 knops.gerd 11 my $serverVector='';
180     vec($serverVector,$controlServerFN,1)=1;
181     vec($serverVector,$subscriberServerFN,1)=1;
182 knops.gerd 48 vec($serverVector,$udpServerFN,1)=1 if(defined($udpServerFN));
183 knops.gerd 11
184     my $lastAgeCheck=time;
185    
186     my $nextPing=undef;
187     if(exists($::CONF{'PingInterval'}) && $::CONF{'PingInterval'}>2)
188     {
189     $nextPing=$::CONF{'PingInterval'}+$lastAgeCheck;
190     }
191    
192     while(!$::TERM)
193     {
194     eval
195     {
196     while(!$::TERM)
197     {
198     my $rVec=$serverVector;
199     my $wVec='';
200     my $eVec='';
201 knops.gerd 47
202 knops.gerd 11 my $rout;
203     my $wout;
204     my $eout;
205 knops.gerd 47
206 knops.gerd 11 Meteor::Connection->addAllHandleBits(\$rVec,\$wVec,\$eVec);
207    
208     my $timeout=$MAIN_LOOP_TIMEOUT;
209     if(defined($nextPing))
210     {
211     $timeout=$nextPing-time;
212     }
213    
214     my $result=0;
215     if($timeout>0)
216     {
217     $result=&Meteor::Socket::sselect($rout=$rVec,$wout=$wVec,$eout=$eVec,$timeout);
218     }
219    
220     if($result>0)
221     {
222     if(vec($rout,$controlServerFN,1))
223     {
224     Meteor::Controller->newFromServer($controlServer);
225     }
226     if(vec($rout,$subscriberServerFN,1))
227     {
228     Meteor::Subscriber->newFromServer($subscriberServer);
229     }
230 knops.gerd 48 if(defined($udpServerFN) && vec($rout,$udpServerFN,1))
231     {
232     &handleUPD($udpServer);
233     }
234 knops.gerd 11
235     Meteor::Connection->checkAllHandleBits($rout,$wout,$eout);
236     }
237     elsif($result<0)
238     {
239     &::syslog('crit',"Select failed: $!");
240     sleep(30);
241     }
242    
243     if($::HUP)
244     {
245     $::HUP=0;
246    
247     &::syslog('info',"Received SIGHUP, re-reading config and clearing document cache!");
248    
249     Meteor::Config->readConfig();
250     Meteor::Config->updateConfig();
251    
252     Meteor::Document->clearDocuments()
253     }
254    
255     if($::USR1)
256     {
257     $::USR1=0;
258    
259     &::syslog('info',"Received SIGUSR1, clearing channel buffers!");
260    
261     Meteor::Channel->clearAllBuffers();
262     }
263    
264     if($::USR2)
265     {
266     $::USR2=0;
267    
268     &::syslog('info',"Received SIGUSR2, clearing document cache!");
269    
270     Meteor::Document->clearDocuments()
271     }
272    
273     my $t=time;
274     if($t>$lastAgeCheck+$AGE_CHECK_INTERVALL)
275     {
276     my $minTimeStap=time-$::CONF{'MaxMessageAge'};
277     Meteor::Channel->trimMessageStoresByTimestamp($minTimeStap);
278     $lastAgeCheck=time;
279     $t=$lastAgeCheck;
280    
281     Meteor::Subscriber->checkPersistentConnectionsForMaxTime();
282     }
283    
284     if(defined($nextPing) && $nextPing<=$t)
285     {
286     $nextPing=undef;
287    
288     Meteor::Subscriber->pingPersistentConnections();
289    
290     if(exists($::CONF{'MaxMessageAge'}) && $::CONF{'MaxMessageAge'}>2)
291     {
292     $nextPing=$::CONF{'PingInterval'}+time;
293     }
294     }
295     }
296     };
297     unless($::TERM)
298     {
299     &::syslog('alert',"$::PGM loop died (will restart in 2 seconds): $@");
300     sleep(2);
301     }
302     }
303    
304     #
305     # Proper shutdown
306     #
307     if($::TERM)
308     {
309     &::syslog('info',"Received SIGTERM, begin shutdown!");
310    
311     $subscriberServer->close();
312     $controlServer->close();
313    
314     unlink("/var/run/$::PGM.pid") unless($::CONF{'Debug'});
315    
316     Meteor::Connection->closeAllConnections();
317    
318     my $timoutAt=time+$MAX_EXIT_DELAY;
319    
320     while(Meteor::Connection->connectionCount() && time<$timoutAt)
321     {
322     my $rVec='';
323     my $wVec='';
324     my $eVec='';
325    
326     my $rout;
327     my $wout;
328     my $eout;
329    
330     Meteor::Connection->addAllHandleBits(\$rVec,\$wVec,\$eVec);
331    
332     my $result=&Meteor::Socket::sselect($rout=$rVec,$wout=$wVec,$eout=$eVec,$timoutAt-time);
333    
334     if($result>0)
335     {
336     Meteor::Connection->checkAllHandleBits($rout,$wout,$eout);
337     }
338     }
339    
340     if(my $cnt=Meteor::Connection->connectionCount())
341     {
342     &::syslog('info',"$cnt client(s) unresponsive, will shutdown anyway");
343    
344     exit(1);
345     }
346    
347     &::syslog('info',"shutdown succeeded");
348    
349     exit(0);
350     }
351    
352     &::syslog('emerg',"$::PGM loop exited");
353    
354 knops.gerd 48 ###############################################################################
355     # Subroutines
356     ###############################################################################
357     sub handleUPD {
358     $udpServer=shift;
359    
360     my $line;
361     my $hispaddr=recv($udpServer->{'handle'},$line,$::UDP_MAX_MESSAGE_SIZE,0);
362    
363     &::syslog('debug',"udp message received: %s",$line);
364    
365     return unless($line=~s/^(\S+)\s//);
366    
367     my $cmd=$1;
368    
369     if($cmd eq 'ADDMESSAGE')
370     {
371     return unless($line=~s/^(\S+)\s//);
372    
373     my $channelName=$1;
374     my $channel=Meteor::Channel->channelWithName($channelName);
375     my $msg=$channel->addMessage($line);
376     my $msgID=$msg->id();
377     &::syslog('debug',"udp: new message added, ID %s",$msgID);
378     }
379     }
380    
381 knops.gerd 11 1;
382 andrew.betts 3 ############################################################################EOF

  ViewVC Help
Powered by ViewVC 1.1.26