"""Pyro RQL server:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr"""__docformat__="restructuredtext en"importosimportsysimportselectimportwarningsfromtimeimportlocaltime,mktimefromcubicweb.cwconfigimportCubicWebConfigurationfromcubicweb.server.repositoryimportRepositoryclassFinished(Exception):"""raise to remove an event from the event loop"""classTimeEvent:"""base event"""# timefunc = staticmethod(localtime)timefunc=localtimedef__init__(self,absolute=None,period=None):# local time tupleifabsoluteisNone:absolute=self.timefunc()self.absolute=absolute# optional period in secondsself.period=perioddefis_ready(self):"""return true if the event is ready to be fired"""now=self.timefunc()ifself.absolute<now:returnTruereturnFalsedeffire(self,server):"""fire the event must be overridden by concrete events """raiseNotImplementedError()defupdate(self):"""update the absolute date for the event or raise a finished exception """ifself.periodisNone:raiseFinishedself.absolute=localtime(mktime(self.absolute)+self.period)classQuitEvent(TimeEvent):"""stop the server"""deffire(self,server):server.repo.shutdown()server.quiting=TrueclassRepositoryServer(object):def__init__(self,config,debug=False):"""make the repository available as a PyRO object"""self.config=configself.repo=Repository(config,debug=debug)self.ns=Noneself.quiting=None# event queueself.events=[]# start repository looping tasksdefadd_event(self,event):"""add an event to the loop"""self.info('adding event %s',event)self.events.append(event)deftrigger_events(self):"""trigger ready events"""foreventinself.events[:]:ifevent.is_ready():self.info('starting event %s',event)event.fire(self)try:event.update()exceptFinished:self.events.remove(event)defrun(self,req_timeout=5.0):"""enter the service loop"""whileself.quitingisNone:try:self.daemon.handleRequests(req_timeout)exceptselect.error:continueself.trigger_events()defquit(self):"""stop the server"""self.add_event(QuitEvent())defconnect(self,host='',port=0):"""the connect method on the repository only register to pyro if necessary """self.daemon=self.repo.pyro_register(host)# server utilitities ######################################################definstall_sig_handlers(self):"""install signal handlers"""importsignalself.info('installing signal handlers')signal.signal(signal.SIGINT,lambdax,y,s=self:s.quit())signal.signal(signal.SIGTERM,lambdax,y,s=self:s.quit())defdaemonize(self,pid_file=None):"""daemonize the process"""# fork so the parent can existif(os.fork()):return-1# deconnect from tty and create a new sessionos.setsid()# fork again so the parent, (the session group leader), can exit.# as a non-session group leader, we can never regain a controlling# terminal.if(os.fork()):return-1# move to the root to avoit mount pbos.chdir('/')# set paranoid umaskos.umask(077)ifpid_fileisnotNone:# write pid in a filef=open(pid_file,'w')f.write(str(os.getpid()))f.close()# filter warningswarnings.filterwarnings('ignore')# close standard descriptorssys.stdin.close()sys.stdout.close()sys.stderr.close()fromloggingimportgetLoggerfromcubicwebimportset_log_methodsLOGGER=getLogger('cubicweb.reposerver')set_log_methods(CubicWebConfiguration,LOGGER)