Adding server modules
This commit is contained in:
@ -47,9 +47,12 @@ class AdaptiveOrbit:
|
|||||||
print("Initializing EPICS Channels")
|
print("Initializing EPICS Channels")
|
||||||
pvs = []
|
pvs = []
|
||||||
for x in chx:
|
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',':X-REF-FB')))
|
||||||
pvs.append(PV(x.replace(':X1',':Y-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:
|
else:
|
||||||
pvs.append(PV(x))
|
pvs.append(PV(x))
|
||||||
con = [pv.wait_for_connection(timeout=0.2) for pv in pvs]
|
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