2006-03-03 15:52:54 +00:00
# Copyright (C) 2004, 2006 Alex Schroeder <alex@emacswiki.org>
2004-07-16 00:40:42 +00:00
# 2004 Sebastian Blatt <sblatt@havens.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
2016-08-16 14:59:13 +02:00
# the Free Software Foundation; either version 3 of the License, or
2004-07-16 00:40:42 +00:00
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
2016-08-16 14:59:13 +02:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2004-07-16 00:40:42 +00:00
# Limits the number of parallel Oddmuse instances to
# $InstanceThrottleLimit by keeping track of the process ids in
# $InstanceThrottleDir
2015-03-27 03:01:01 +02:00
use strict ;
2015-08-18 10:48:03 +02:00
use v5 .10 ;
2015-03-27 03:01:01 +02:00
2014-08-21 22:23:23 +02:00
AddModuleDescription ( 'throttle.pl' , 'Limit Number Of Instances Running' ) ;
2004-07-16 00:40:42 +00:00
2012-07-21 00:36:33 +02:00
use File::Glob ':glob' ;
2015-04-10 13:31:28 +03:00
our ( $ q , $ DataDir ) ;
our ( $ InstanceThrottleDir , $ InstanceThrottleLimit ) ;
2004-07-16 00:40:42 +00:00
$ InstanceThrottleDir = $ DataDir . "/pids" ; # directory for pid files
$ InstanceThrottleLimit = 2 ; # maximum number of parallel processes
2015-04-11 23:41:33 +03:00
* OldDoSurgeProtection = \ & DoSurgeProtection ;
* DoSurgeProtection = \ & NewDoSurgeProtection ;
2004-07-16 00:40:42 +00:00
2015-04-11 23:41:33 +03:00
* OldDoBrowseRequest = \ & DoBrowseRequest ;
* DoBrowseRequest = \ & NewDoBrowseRequest ;
2004-07-16 00:40:42 +00:00
sub NewDoSurgeProtection {
DoInstanceThrottle ( ) ;
CreatePidFile ( ) ;
OldDoSurgeProtection ( ) ;
}
sub NewDoBrowseRequest {
OldDoBrowseRequest ( ) ;
RemovePidFile ( ) ;
}
# limit the script to a maximum of $InstanceThrottleLimit instances
sub DoInstanceThrottle {
2016-06-19 11:55:58 +02:00
my @ pids = Glob ( $ InstanceThrottleDir . "/*" ) ;
2004-07-16 00:40:42 +00:00
# Go over all pids: validate each pid by sending signal 0, unlink
# pidfile if pid does not exist and return 0. Count the number of
# zeros (= removed files = zombies) with grep.
my $ zombies = grep /^0$/ ,
2016-06-15 23:21:07 +02:00
( map { /(\d+)$/ and kill 0 , $ 1 or Unlink ( $ _ ) and 0 } @ pids ) ;
2004-07-16 00:40:42 +00:00
if ( scalar ( @ pids ) - $ zombies >= $ InstanceThrottleLimit ) {
2006-09-07 17:44:02 +00:00
ReportError ( Ts ( 'Too many instances. Only %s allowed.' ,
$ InstanceThrottleLimit ) ,
'503 Service Unavailable' ,
undef ,
$ q - > p ( T ( 'Please try again later. Perhaps somebody is running maintenance or doing a long search. Unfortunately the site has limited resources, and so we must ask you for a bit of patience.' ) ) ) ;
2004-07-16 00:40:42 +00:00
}
}
sub CreatePidFile {
CreateDir ( $ InstanceThrottleDir ) ;
2006-03-03 15:51:48 +00:00
my $ data = $ q - > request_method . ' ' . $ q - > url ( - path_info = > 1 ) . "\n" ;
foreach my $ param ( $ q - > param ) {
next if $ param eq 'pwd' ;
$ data . = "Param " . $ param . "=" . $ q - > param ( $ param ) . "\n" ;
}
WriteStringToFile ( "$InstanceThrottleDir/$$" , $ data ) ;
2004-07-16 00:40:42 +00:00
}
sub RemovePidFile {
my $ file = "$InstanceThrottleDir/$$" ;
2006-10-21 18:51:40 +00:00
# not fatal
2016-06-15 23:21:07 +02:00
Unlink ( $ file ) ;
2004-07-16 00:40:42 +00:00
}