Adding server modules

This commit is contained in:
2024-01-09 10:47:51 +01:00
parent 4ed4630b8d
commit a0b5ce4c58
5 changed files with 196 additions and 1 deletions

View File

@ -0,0 +1,2 @@
from .serverbase import ServerBase
from .zmqbase import ZMQBase

91
util/serverbase.py Normal file
View 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
View 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