<s> """<STR_LIT>""" <EOL> import os <EOL> import time <EOL> import errno <EOL> import select <EOL> import signal <EOL> from supervisor . medusa import asyncore_25 as asyncore <EOL> from supervisor . options import ServerOptions <EOL> from supervisor . options import signame <EOL> from supervisor import events <EOL> from supervisor . states import SupervisorStates <EOL> from supervisor . states import getProcessStateDescription <EOL> class Supervisor : <EOL> stopping = False <EOL> lastshutdownreport = <NUM_LIT:0> <EOL> process_groups = None <EOL> stop_groups = None <EOL> def __init__ ( self , options ) : <EOL> self . options = options <EOL> self . process_groups = { } <EOL> self . ticks = { } <EOL> def main ( self ) : <EOL> if not self . options . first : <EOL> self . options . cleanup_fds ( ) <EOL> info_messages = [ ] <EOL> critical_messages = [ ] <EOL> warn_messages = [ ] <EOL> setuid_msg = self . options . set_uid ( ) <EOL> if setuid_msg : <EOL> critical_messages . append ( setuid_msg ) <EOL> if self . options . first : <EOL> rlimit_messages = self . options . set_rlimits ( ) <EOL> info_messages . extend ( rlimit_messages ) <EOL> warn_messages . extend ( self . options . parse_warnings ) <EOL> self . options . make_logger ( critical_messages , warn_messages , <EOL> info_messages ) <EOL> if not self . options . nocleanup : <EOL> self . options . clear_autochildlogdir ( ) <EOL> self . run ( ) <EOL> def run ( self ) : <EOL> self . process_groups = { } <EOL> self . stop_groups = None <EOL> events . clear ( ) <EOL> try : <EOL> for config in self . options . process_group_configs : <EOL> self . add_process_group ( config ) <EOL> self . options . process_environment ( ) <EOL> self . options . openhttpservers ( self ) <EOL> self . options . setsignals ( ) <EOL> if ( not self . options . nodaemon ) and self . options . first : <EOL> self . options . daemonize ( ) <EOL> self . options . write_pidfile ( ) <EOL> self . runforever ( ) <EOL> finally : <EOL> self . options . cleanup ( ) <EOL> def diff_to_active ( self , new = None ) : <EOL> if not new : <EOL> new = self . options . process_group_configs <EOL> cur = [ group . config for group in self . process_groups . values ( ) ] <EOL> curdict = dict ( zip ( [ cfg . name for cfg in cur ] , cur ) ) <EOL> newdict = dict ( zip ( [ cfg . name for cfg in new ] , new ) ) <EOL> added = [ cand for cand in new if cand . name not in curdict ] <EOL> removed = [ cand for cand in cur if cand . name not in newdict ] <EOL> changed = [ cand for cand in new <EOL> if cand != curdict . get ( cand . name , cand ) ] <EOL> return added , changed , removed <EOL> def add_process_group ( self , config ) : <EOL> name = config . name <EOL> if name not in self . process_groups : <EOL> config . after_setuid ( ) <EOL> self . process_groups [ name ] = config . make_group ( ) <EOL> return True <EOL> return False <EOL> def remove_process_group ( self , name ) : <EOL> if self . process_groups [ name ] . get_unstopped_processes ( ) : <EOL> return False <EOL> del self . process_groups [ name ] <EOL> return True <EOL> def get_process_map ( self ) : <EOL> process_map = { } <EOL> pgroups = self . process_groups . values ( ) <EOL> for group in pgroups : <EOL> process_map . update ( group . get_dispatchers ( ) ) <EOL> return process_map <EOL> def shutdown_report ( self ) : <EOL> unstopped = [ ] <EOL> pgroups = self . process_groups . values ( ) <EOL> for group in pgroups : <EOL> unstopped . extend ( group . get_unstopped_processes ( ) ) <EOL> if unstopped : <EOL> now = time . time ( ) <EOL> if now > ( self . lastshutdownreport + <NUM_LIT:3> ) : <EOL> names = [ p . config . name for p in unstopped ] <EOL> namestr = '<STR_LIT:U+002CU+0020>' . join ( names ) <EOL> self . options . logger . info ( '<STR_LIT>' % namestr ) <EOL> self . lastshutdownreport = now <EOL> for proc in unstopped : <EOL> state = getProcessStateDescription ( proc . get_state ( ) ) <EOL> self . options . logger . blather ( <EOL> '<STR_LIT>' % ( proc . config . name , state ) ) <EOL> return unstopped <EOL> def ordered_stop_groups_phase_1 ( self ) : <EOL> if self . stop_groups : <EOL> self . stop_groups [ - <NUM_LIT:1> ] . stop_all ( ) <EOL> def ordered_stop_groups_phase_2 ( self ) : <EOL> if self . stop_groups : <EOL> group = self . stop_groups . pop ( ) <EOL> if group . get_unstopped_processes ( ) : <EOL> self . stop_groups . append ( group ) <EOL> def runforever ( self ) : <EOL> events . notify ( events . SupervisorRunningEvent ( ) ) <EOL> timeout = <NUM_LIT:1> <EOL> socket_map = self . options . get_socket_map ( ) <EOL> while <NUM_LIT:1> : <EOL> combined_map = { } <EOL> combined_map . update ( socket_map ) <EOL> combined_map . update ( self . get_process_map ( ) ) <EOL> pgroups = self . process_groups . values ( ) <EOL> pgroups . sort ( ) <EOL> if self . options . mood < SupervisorStates . RUNNING : <EOL> if not self . stopping : <EOL> self . stopping = True <EOL> self . stop_groups = pgroups [ : ] <EOL> events . notify ( events . SupervisorStoppingEvent ( ) ) <EOL> self . ordered_stop_groups_phase_1 ( ) <EOL> if not self . shutdown_report ( ) : <EOL> raise asyncore . ExitNow <EOL> r , w , x = [ ] , [ ] , [ ] <EOL> for fd , dispatcher in combined_map . items ( ) : <EOL> if dispatcher . readable ( ) : <EOL> r . append ( fd ) <EOL> if dispatcher . writable ( ) : <EOL> w . append ( fd ) <EOL> try : <EOL> r , w , x = self . options . select ( r , w , x , timeout ) <EOL> except select . error , err : <EOL> r = w = x = [ ] <EOL> if err [ <NUM_LIT:0> ] == errno . EINTR : <EOL> self . options . logger . blather ( '<STR_LIT>' ) <EOL> else : <EOL> raise <EOL> for fd in r : <EOL> if combined_map . has_key ( fd ) : <EOL> try : <EOL> dispatcher = combined_map [ fd ] <EOL> self . options . logger . blather ( <EOL> '<STR_LIT>' , <EOL> dispatcher = dispatcher ) <EOL> dispatcher . handle_read_event ( ) <EOL> except asyncore . ExitNow : <EOL> raise <EOL> except : <EOL> combined_map [ fd ] . handle_error ( ) <EOL> for fd in w : <EOL> if combined_map . has_key ( fd ) : <EOL> try : <EOL> dispatcher = combined_map [ fd ] <EOL> self . options . logger . blather ( <EOL> '<STR_LIT>' , <EOL> dispatcher = dispatcher ) <EOL> dispatcher . handle_write_event ( ) <EOL> except asyncore . ExitNow : <EOL> raise <EOL> except : <EOL> combined_map [ fd ] . handle_error ( ) <EOL> [ group . transition ( ) for group in pgroups ] <EOL> self . reap ( ) <EOL> self . handle_signal ( ) <EOL> self . tick ( ) <EOL> if self . options . mood < SupervisorStates . RUNNING : <EOL> self . ordered_stop_groups_phase_2 ( ) <EOL> if self . options . test : <EOL> break <EOL> def tick ( self , now = None ) : <EOL> """<STR_LIT>""" <EOL> if now is None : <EOL> now = time . time ( ) <EOL> for event in events . TICK_EVENTS : <EOL> period = event . period <EOL> last_tick = self . ticks . get ( period ) <EOL> if last_tick is None : <EOL> last_tick = self . ticks [ period ] = timeslice ( period , now ) <EOL> this_tick = timeslice ( period , now ) <EOL> if this_tick != last_tick : <EOL> self . ticks [ period ] = this_tick <EOL> events . notify ( event ( this_tick , self ) ) <EOL> def reap ( self , once = False ) : <EOL> pid , sts = self . options . waitpid ( ) <EOL> if pid : <EOL> process = self . options . pidhistory . get ( pid , None ) <EOL> if process is None : <EOL> self . options . logger . critical ( '<STR_LIT>' % pid ) <EOL> else : <EOL> process . finish ( pid , sts ) <EOL> del self . options . pidhistory [ pid ] <EOL> if not once : <EOL> self . reap ( ) <EOL> def handle_signal ( self ) : <EOL> if self . options . signal : <EOL> sig , self . options . signal = self . options . signal , None <EOL> if sig in ( signal . SIGTERM , signal . SIGINT , signal . SIGQUIT ) : <EOL> self . options . logger . warn ( <EOL> '<STR_LIT>' % signame ( sig ) ) <EOL> self . options . mood = SupervisorStates . SHUTDOWN <EOL> elif sig == signal . SIGHUP : <EOL> self . options . logger . warn ( <EOL> '<STR_LIT>' % signame ( sig ) ) <EOL> self . options . mood = SupervisorStates . RESTARTING <EOL> elif sig == signal . SIGCHLD : <EOL> self . options . logger . debug ( <EOL> '<STR_LIT>' % signame ( sig ) ) <EOL> elif sig == signal . SIGUSR2 : <EOL> self . options . logger . info ( <EOL> '<STR_LIT>' % signame ( sig ) ) <EOL> self . options . reopenlogs ( ) <EOL> for group in self . process_groups . values ( ) : <EOL> group . reopenlogs ( ) <EOL> else : <EOL> self . options . logger . blather ( <EOL> '<STR_LIT>' % signame ( sig ) ) <EOL> def get_state ( self ) : <EOL> return self . options . mood <EOL> def timeslice ( period , when ) : <EOL> return int ( when - ( when % period ) ) <EOL> def profile ( cmd , globals , locals , sort_order , callers ) : <EOL> import profile <EOL> import pstats <EOL> import tempfile <EOL> fd , fn = tempfile . mkstemp ( ) <EOL> try : <EOL> if hasattr ( profile , '<STR_LIT>' ) : <EOL> profile . runctx ( cmd , globals , locals , fn ) <EOL> else : <EOL> raise NotImplementedError ( '<STR_LIT>' ) <EOL> stats = pstats . Stats ( fn ) <EOL> stats . strip_dirs ( ) <EOL> stats . sort_stats ( * sort_order or ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:time>' ) ) <EOL> if callers : <EOL> stats . print_callers ( <NUM_LIT> ) <EOL> else : <EOL> stats . print_stats ( <NUM_LIT> ) <EOL> finally : <EOL> os . remove ( fn ) <EOL> def main ( args = None , test = False ) : <EOL> assert os . name == "<STR_LIT>" , "<STR_LIT>" <EOL> first = True <EOL> while <NUM_LIT:1> : <EOL> options = ServerOptions ( ) <EOL> options . realize ( args , doc = __doc__ ) <EOL> options . first = first <EOL> options . test = test <EOL> if options . profile_options : <EOL> sort_order , callers = options . profile_options <EOL> profile ( '<STR_LIT>' , globals ( ) , locals ( ) , sort_order , callers ) <EOL> else : <EOL> go ( options ) <EOL> if test or ( options . mood < SupervisorStates . RESTARTING ) : <EOL> break <EOL> options . close_httpservers ( ) <EOL> options . close_logger ( ) <EOL> first = False <EOL> def go ( options ) : <EOL> d = Supervisor ( options ) <EOL> try : <EOL> d . main ( ) <EOL> except asyncore . ExitNow : <EOL> pass <EOL> if __name__ == "<STR_LIT:__main__>" : <EOL> main ( ) </s>
