#!/usr/bin/env python # # This script is for feeding data to the monitoring system while running CDAQ # instead of CODA. The data are read from files appearing on volatile. # # This takes no arguments but it does expect the following: # # RUN_PERIOD - from RUN_PERIOD environment variable # run number - from HD:coda:daq:run_number EPICS variable # # In addition, the ET_FILENAME and host are hard-coded here. In particular, if # the ET line in $DAQ_HOME/config/monitoring/nodes.conf changes, then it should # be changed here as well. # # This will continuously scan for files on all gluonraid partitions for whatever # the current run is (by way of the HD:coda:daq:run_number EPICS variable). # When a new one is found, it runs file2et to feed events from it into the # secondary ET system. If a newer file appears, the existing file2et process # is killed and a new one started for the new file. # import os import sys import glob import time import psutil import socket import datetime import subprocess from epics import caget RUNPERIOD = 'RunPeriod-2019-11' proc_file2et = None CURRENT_FILE = '' LAST_RUN_NUMBER = 0 SLEEP_TIME = 10 # seconds to sleep between iterations ET_FILENAME = '/tmp/et_sys_monitoring' # This is the default in start_monitoring ET_HOST = 'gluon102' # This is specified in $DAQ_HOME/config/monitoring/nodes.conf hostname = socket.gethostname() hostname_short = hostname.split('.jlab.org')[0].split('-daq')[0] #---------------------------- # StartFile2ET # # Find age of most recently modified file in seconds in given directory. #---------------------------- def StartFile2ET(fname): global proc_file2et, CURRENT_FILE, ET_FILENAME, ET_HOST logfile = '/gluex/log/file2et_%s.log' % hostname_short cmd = ['hdlog', '-c', '-o', logfile, 'file2et', '-f', ET_FILENAME, '-H', ET_HOST, fname] print('[%s] Running: %s' % (datetime.datetime.now(), ' '.join(cmd))) proc_file2et = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) CURRENT_FILE = fname #---------------------------- # StopFile2ET # # Find age of most recently modified file in seconds in given directory. #---------------------------- def StopFile2ET(): global proc_file2et, CURRENT_FILE if not proc_file2et: return # no process to stop! print('[%s] Stopping process feeding file: %s' %(datetime.datetime.now(), CURRENT_FILE)) # Send SIGTERM and wait up to 3 seconds for process to terminate. # If it doesn't, then send a SIGKILL. proc_file2et.terminate() gone,alive = psutil.wait_procs( [proc_file2et], timeout=3 ) if proc_file2et in alive: proc_file2et.kill() # Reset globals proc_file2et = None CURRENT_FILE = '' #=========================================================================== # Loop over command line arguments for arg in sys.argv[1:]: pass RUN_PERIOD = os.getenv('RUN_PERIOD') if not RUN_PERIOD: print('RUN_PERIOD environment variable not set!') os.exit(-1) # Loop forever, checking the run number and looking for new files while True: # Get run number from EPICS try: run_number = int(caget('HD:coda:daq:run_number')) if run_number != LAST_RUN_NUMBER: print('[%s] Run number changed from %d to %d' % (datetime.datetime.now(), LAST_RUN_NUMBER, run_number)) StopFile2ET() LAST_RUN_NUMBER = run_number except: print('[%s] ERROR getting run number from EPICS!' % (datetime.datetime.now())) print(sys.exc_info()) run_number = -1 # Search for most recent file on volatile from current run/runperiod filepat = '/gluonraid*/data*/rawdata/volatile/%s/rawdata/Run%06d/hd_rawdata_*.evio' %( RUN_PERIOD, run_number) files = glob.glob( filepat ) if files: latest_file = max( files, key=os.path.getctime) if latest_file != CURRENT_FILE: StopFile2ET() # This will silently do nothing if the run number changed and StopFile2ET() was already called above StartFile2ET(latest_file) else: if not proc_file2et: print('[%s] No new files to process for run %d' % (datetime.datetime.now(), run_number)) else: print('[%s] No files to process for run %d' % (datetime.datetime.now(), run_number)) # Check if existing process is stopped if proc_file2et: if proc_file2et.poll() is not None: print('[%s] Process ended for file: %s' % (datetime.datetime.now(), CURRENT_FILE)) proc_file2et = None # Note: do not reset CURRENT_FILE here since that would cause the above to re-run it. else: print('[%s] Continuing to feed %s' % (datetime.datetime.now(), CURRENT_FILE)) time.sleep( SLEEP_TIME )