Adding server modules
This commit is contained in:
@ -47,9 +47,12 @@ class AdaptiveOrbit:
|
||||
print("Initializing EPICS Channels")
|
||||
pvs = []
|
||||
for x in chx:
|
||||
if ':X1' in x or ':X2' in x:
|
||||
if ':X1' in x:
|
||||
pvs.append(PV(x.replace(':X1',':X-REF-FB')))
|
||||
pvs.append(PV(x.replace(':X1',':Y-REF-FB')))
|
||||
elif ':X2' in x:
|
||||
pvs.append(PV(x.replace(':X2',':X-REF-FB')))
|
||||
pvs.append(PV(x.replace(':X2',':Y-REF-FB')))
|
||||
else:
|
||||
pvs.append(PV(x))
|
||||
con = [pv.wait_for_connection(timeout=0.2) for pv in pvs]
|
||||
|
33
template/ServerTemplate.py
Normal file
33
template/ServerTemplate.py
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
import signal
|
||||
|
||||
import ServerBase
|
||||
|
||||
class ServerTemplate(ServerBase.ServerBase):
|
||||
def __init__(self, PVroot = 'MyServer', debug = False):
|
||||
self.version='1.0.0'
|
||||
self.program ='Server Template'
|
||||
super(ServerTemplate, self).__init__(PVroot,debug,'127.0.0.1', 5678) # last too numbers are the IP adress and port of watchdog
|
||||
|
||||
# connect to the individual handler, which must have the function terminate() implemented
|
||||
# each handler should be their own thread to not interfere with the main process-loop
|
||||
self.handler={}
|
||||
|
||||
def terminateSubThreads(self):
|
||||
for subserver in self.handler.keys():
|
||||
self.handler[subserver].terminate()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
debug = True
|
||||
server = ServerTemplate('SF-BC-SERVER', debug)
|
||||
signal.signal(signal.SIGTERM,server.terminate)
|
||||
try:
|
||||
server.run()
|
||||
except KeyboardInterrupt:
|
||||
server.terminate(None,None)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,2 @@
|
||||
from .serverbase import ServerBase
|
||||
from .zmqbase import ZMQBase
|
||||
|
91
util/serverbase.py
Normal file
91
util/serverbase.py
Normal file
@ -0,0 +1,91 @@
|
||||
import sys
|
||||
import signal
|
||||
import os
|
||||
import socket
|
||||
import logging
|
||||
import logging.handlers
|
||||
from logging.handlers import RotatingFileHandler
|
||||
from datetime import datetime
|
||||
import time
|
||||
|
||||
from epics import PV
|
||||
import ZMQBase
|
||||
|
||||
class ServerBase (ZMQBase):
|
||||
def __init__(self, root = 'MyServer', debug = False, WDServer = '127.0.0.1', WDPort = 5678):
|
||||
|
||||
super(ServerBase,self).__init__(WDServer,WDPort)
|
||||
|
||||
self.debug = debug
|
||||
self.root = root
|
||||
self.suffix=''
|
||||
if self.debug:
|
||||
self.suffix='-SIMU'
|
||||
self.host = socket.gethostname()
|
||||
self.pid = os.getpid() # process ID
|
||||
|
||||
# enabling logging
|
||||
self.logfilename="/sf/data/applications/BD-SERVER/%s.log" % self.root
|
||||
handler = RotatingFileHandler(filename=self.logfilename,
|
||||
mode='a',
|
||||
maxBytes=5 * 1024 * 1024,
|
||||
backupCount=1,
|
||||
delay=0)
|
||||
if self.debug:
|
||||
logging.basicConfig(level=logging.INFO,
|
||||
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
|
||||
datefmt='%m-%d %H:%M:%S')
|
||||
else:
|
||||
logging.basicConfig(level=logging.INFO,
|
||||
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
|
||||
datefmt='%m-%d %H:%M:%S',
|
||||
handlers=[handler,])
|
||||
self.logger=logging.getLogger(self.program)
|
||||
|
||||
# setting up ZMQ interface
|
||||
self.ZMQServerInfo(self.root,self.host,self.pid)
|
||||
|
||||
# individual channels of main thread
|
||||
self.PVstop = PV('%s:STOP%s' % (self.root,self.suffix))
|
||||
self.PVstop.value = 0
|
||||
self.PVstop.add_callback(self.stop)
|
||||
self.PVping = PV('%s:PING%s' % (self.root,self.suffix))
|
||||
self.PVlog = PV('%s:LOG%s' % (self.root,self.suffix))
|
||||
|
||||
def stop(self,pvname=None,value=None,**kws):
|
||||
self.logger.info('PV:STOP triggered at %s' % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||
if value > 0:
|
||||
self.running=False
|
||||
|
||||
def start(self):
|
||||
self.logger.info('Starting Server: %s at %s' % (self.root,datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
|
||||
self.logger.info('PV Root: %s' % self.root
|
||||
self.logger.info('Version: %s' % self.version)
|
||||
self.logger.info('Host: %s' % self.host)
|
||||
self.logger.info('PID: %d' % self.pid)
|
||||
if self.debug:
|
||||
self.logger.info('Debug Mode')
|
||||
|
||||
def run(self):
|
||||
self.start()
|
||||
self.running=True
|
||||
while self.running:
|
||||
time.sleep(1)
|
||||
if self.ZMQPoll():
|
||||
self.logger.info('Watchdog Server requested termination')
|
||||
self.running = False
|
||||
self.PVping.value = datetime.now().strftime('Last active at %Y-%m-%d %H:%M:%S')
|
||||
self.terminate(None,None)
|
||||
|
||||
def terminate(self,signum,frame):
|
||||
# stopping any sub thread with the server specific function terminateSubThreads
|
||||
self.terminateSubThreads()
|
||||
self.logger.info('Terminating Server at %s' % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||
self.ZMQPoll('quit') # informing the watchdog
|
||||
print('Bunch Compressor Server is quitting...')
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
|
||||
|
||||
|
66
util/zmqbase.py
Normal file
66
util/zmqbase.py
Normal file
@ -0,0 +1,66 @@
|
||||
import zmq
|
||||
import socket
|
||||
import sys
|
||||
|
||||
class ZMQBase:
|
||||
def __init__(self, host='127.0.0.1',port = 5678):
|
||||
|
||||
self.host=host
|
||||
self.port = port
|
||||
self.msg={'action':'','PV':'','host':'','pid':0}
|
||||
|
||||
self.REQUEST_TIMEOUT = 500
|
||||
self.REQUEST_RETRIES = 2
|
||||
self.SERVER_ENDPOINT = "tcp://%s:%d" % (host,port)
|
||||
self.serverIsOffline=False # assume that it is online
|
||||
|
||||
def ZMQServerInfo(self,PVroot,host,pid):
|
||||
self.msg['PV']=PVroot
|
||||
self.msg['host']=host
|
||||
self.msg['pid']=pid
|
||||
|
||||
|
||||
def ZMQPoll(self,tag='ping'):
|
||||
self.msg['action']=tag
|
||||
context = zmq.Context()
|
||||
client = context.socket(zmq.REQ)
|
||||
client.connect(self.SERVER_ENDPOINT)
|
||||
client.send_pyobj(self.msg)
|
||||
|
||||
retries_left = self.REQUEST_RETRIES
|
||||
while True:
|
||||
if (client.poll(self.REQUEST_TIMEOUT) & zmq.POLLIN) != 0:
|
||||
reply = client.recv_pyobj()
|
||||
check = self.ZMQIdentifyReply(reply)
|
||||
if self.serverIsOffline:
|
||||
self.logger.info("Watchdog server came online")
|
||||
self.serverIsOffline=False
|
||||
if check:
|
||||
return (reply['action'] == 'quit')
|
||||
else:
|
||||
self.logger.warning("Malformed reply from server")
|
||||
continue
|
||||
|
||||
retries_left -= 1
|
||||
# Socket is confused. Close and remove it.
|
||||
client.setsockopt(zmq.LINGER, 0)
|
||||
client.close()
|
||||
if retries_left == 0:
|
||||
if not self.serverIsOffline:
|
||||
self.logger.info("Watchdog server seems to be offline")
|
||||
self.serverIsOffline=True
|
||||
return False
|
||||
|
||||
# Create new connection
|
||||
client = context.socket(zmq.REQ)
|
||||
client.connect(self.SERVER_ENDPOINT)
|
||||
client.send_pyobj(self.msg)
|
||||
|
||||
|
||||
def ZMQIdentifyReply(self,reply):
|
||||
for field in ['PV','host','pid']:
|
||||
if not reply[field] == self.msg[field]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
Reference in New Issue
Block a user