/[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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.9  
changed lines
  Added in v.25

  ViewVC Help
Powered by ViewVC 1.1.26