artdaq_mpich_plugin  v1_00_08
daqrate.py
1 #!/usr/bin/env python
2 
3 import sys
4 import os
5 
6 USAGE="\
7  Usage: %s [options] <num dect and src> <num sink> <qsize> <run#>\n\
8 Examples: %s 5 5\n\
9  %s 4 4 --nodes=grunt{1-5} --ddnodes=1 # 1 node sending to 4\n\
10  %s 4 4 --nodes=grunt{1-5} --ddnodes=4 # 4 nodes sending to 1\n\
11  %s 5 5 --nodes=grunt{1-5} --ddnodes=0 # \n\
12  %s 5 5 --nodes=grunt{1-5} # same as above\
13 "%((os.path.basename(sys.argv[0]),)*6)
14 
15 
16 
17 
18 ###############################################################################
19 
20 g_opt={'tlvlmsk':0}
21 if sys.version_info[0] == 2: exec( 'trc_one=1L' )
22 else: exec( 'trc_one=1' )
23 
24 
25 def TRACE( lvl, fmt_s, *args ):
26  import socket,time,os
27  global g_thisnode
28  # how is g_opt working w/o "global" declaration? - must default if read
29  if g_opt['tlvlmsk'] & (trc_one<<lvl):
30  if g_thisnode == None: g_thisnode=NodeInfo()
31  fo = open( "%s.%s.trc"%(g_thisnode.hostnames_l[0],os.getenv('RGANG_MACH_ID')), "a+" )
32  fd = fo.fileno()
33  os.write( fd,'%.2f:%s:%s:%d:%s\n'%(time.time(),socket.gethostname(),
34  g_thisnode.mach_idx,lvl,fmt_s%args))
35  fo.close()
36  # TRACE
37 
38 
39 ###############################################################################
40 # General Regular Expression class that allows for:
41 # xx = Re( re )
42 # ...
43 # if xx.search( line ):
44 # yy = xx.match_obj.group( x )
45 #
46 
47 class Re:
48  import re
49  ## Create an instance of the regular expression
50  def __init__( self, reg_ex=None,flags=0 ):
51  ## The compiled version of the regex
52  if reg_ex: self.compiled = self.re.compile(reg_ex,flags)
53  ## Match object representing all matches for the regex
54  self.match_obj=None
55  ## Find matches for the regular expression
56  def search(self,arg1,string=None):
57  if string: self.match_obj = self.re.search(arg1, string)
58  else: self.match_obj = self.compiled.search( arg1 )
59  return self.match_obj
60  # Re
61 
62 re_numeric = Re( r"([0-9a-f]+)-((0x{0,1}){0,1}[0-9a-f]+)" ) # the "r" prefix --> use Python's raw string notation
63 re_1alpha = Re( r"([a-zA-Z])-([a-zA-Z])" ) # the "r" prefix --> use Python's raw string notation
64 re_hex = Re( r"^[0-9a-f]+" )
65 
66 
67 
68 def findall_expands( ss ):
69  result = []; result_idx = 0; brace_lvl = 0
70  for cc in ss:
71  if cc == '{':
72  brace_lvl = brace_lvl + 1
73  if brace_lvl == 1: result.append('')
74  if brace_lvl > 0: result[result_idx] = result[result_idx] + cc
75  if cc == '}':
76  brace_lvl = brace_lvl - 1
77  if brace_lvl == 0: result_idx = result_idx + 1
78  if brace_lvl != 0: result.pop()
79  return result
80  # findall_expands
81 
82 
83 def numeric_expand( ss_l ):
84  ret = []
85  for sss in ss_l:
86  # single alpha check 1st so {a-f} is not mistaken for
87  # integer (not hex) numeric expand
88  if re_1alpha.search( sss ):
89  start = re_1alpha.match_obj.group(1)
90  end = re_1alpha.match_obj.group(2)
91  end = chr(ord(end)+1)
92  while start != end:
93  ret.append( start )
94  start = chr(ord(start)+1)
95  elif re_numeric.search( sss ):
96  start = re_numeric.match_obj.group(1)
97  end = re_numeric.match_obj.group(2)
98  bb = re_numeric.match_obj.group(3)
99  if bb == None:
100  for num in range(int(start),eval(end)+1):
101  ret.append( '%0*d'%(len(start),num) )
102  elif bb == '0':
103  for num in range(eval('0%s'%(start,)),eval(end)+1):
104  ret.append( '%0*o'%(len(start),num) )
105  elif bb == '0x':
106  for num in range(eval('0x%s'%(start,)),eval(end)+1):
107  ret.append( '%0*x'%(len(start),num) )
108  else: ret.append( sss )
109  TRACE( 28, 'numeric_expand returning %s', ret )
110  return ret
111  # numeric_expand
112 
113 def expand( ss ):
114  import string
115  import re
116  TRACE( 29, 'expand(%s)', ss )
117  ssIn = ss
118  try:
119  placeholder_idx = 0
120  expands = findall_expands( ss )
121  if not expands: return ss.split(',')
122  exp_result = []
123  for exp in expands:
124  ss = ss.replace( exp, '<%d>'%(placeholder_idx,), 1 )
125  placeholder_idx = placeholder_idx + 1
126  placeholder_idx = 0
127  for sss in ss.split(','):
128  TRACE( 30, 'expand sss=%s of ss=%s', sss, ss )
129  place_holders = re.findall( '<[0-9]+>', sss )
130  for idx in range(len(place_holders)):
131  p_holder = '<%d>'%(placeholder_idx+idx,)
132  expanding = expand( expands[placeholder_idx+idx][1:-1] ) #Recursive call
133  expanding = numeric_expand( expanding )
134  result = []
135  for ssss in sss.split(','):
136  holder_idx = ssss.find(p_holder)
137  if holder_idx != -1:
138  pre = ssss[:holder_idx]
139  post= ssss[holder_idx+len(p_holder):]
140  for expanded in expanding:
141  result.append( pre+expanded+post )
142  sss = ','.join(result)
143  exp_result = exp_result + sss.split(',')
144  placeholder_idx = placeholder_idx + len(place_holders)
145  except: # any
146  TRACE( 31, 'except - expand' )
147  exc, value, tb = sys.exc_info()
148  sys.stderr.write('Error expanding node list "%s": %s: %s\n'%(ssIn,exc,value) )
149  sys.stderr.write('Prehaps an invalid decimal/octal/hex digit\n' )
150  sys.stderr.write('remember: in the \'{seq1-seq2}\' syntax, seq2\n' )
151  sys.stderr.write('can begin with \'0x\' to force hex or \'0\' to\n' )
152  sys.stderr.write('force octal\n' )
153  if g_opt['tlvlmsk']:
154  for ln in traceback.format_exception( exc, value, tb ):
155  sys.stderr.write(ln)
156  sys.exit(1)
157 
158  return exp_result
159  # expand, numeric_expand, findall_expands
160 
161 
162 def build_quoted_str( args ):
163  import string # join
164  quoted_args=[]
165  for arg in args:
166  if repr(arg)[0] == "'": quoted_args.append( "'%s'"%(arg,) )
167  else: quoted_args.append( '"%s"'%(arg,) )
168  return ' '.join( quoted_args )
169  # build_quoted_str
170 
171 
172 
173 def main():
174  import getopt
175  art_args=''
176  if sys.argv.count('--'):
177  art_args = build_quoted_str( sys.argv[sys.argv.index('--' ) + 1:] )
178  pass
179  long_opt_spec=["help","ddnodes=","nodes="]
180  try:
181  opts, args = getopt.gnu_getopt(sys.argv[1:], "h", long_opt_spec)
182  except getopt.GetoptError, err:
183  # print help information and exit:
184  print str(err) # will print something like "option -a not recognized"
185  print(USAGE)
186  sys.exit(2)
187  ddnodes=0
188  nodes=[]
189  for o, a in opts:
190  if o in ("-h", "--help"):
191  usage()
192  sys.exit()
193  elif o in ("--ddnodes",):
194  ddnodes = int(a,0)
195  elif o in ("--nodes",):
196  nodes = expand(a)
197  else:
198  assert False, "unhandled option"
199 
200 
201  if len(args) < 4: print(USAGE); sys.exit()
202 
203  num_det = int( args[0],0 )
204  num_sink = int( args[1],0 )
205 
206  builder=os.popen("which builder 2>/dev/null").readline()
207  if not builder:
208  print("Error: builder executable not found.")
209  sys.exit(3)
210  pass
211 
212  print("opts=%s args=%s nodes=%s"%(opts,args,nodes))
213  rc = 0
214  if nodes:
215  if ddnodes >= len(nodes):
216  print("invalid configuration. ddnodes must be < nodes")
217  sys.exit(4)
218  pass
219  # create a nodes file... The number of lines should be == num_det+num_src+num_sink
220 
221  nodes_file="/tmp/nodes%s.txt"%(os.getpid(),)
222  fo=open(nodes_file,'w')
223 
224  # 1st set of ranks is for "detector" nodes
225  node_idx=0
226  for xx in range(num_det):
227  fo.write( "%s\n"%(nodes[node_idx],) ); node_idx += 1
228  if node_idx == len(nodes) or node_idx == ddnodes: node_idx=0
229  pass
230  if ddnodes: nodes=nodes[ddnodes:]
231 
232  node_idx=0 # dect and src get paired up
233 
234  # last set of ranks is for "sink" nodes
235  for xx in range(num_sink):
236  fo.write( "%s\n"%(nodes[node_idx],) ); node_idx += 1
237  if node_idx == len(nodes): node_idx=0
238  pass
239 
240  fo.close()
241 
242  os.system("cat %s"%(nodes_file,))
243  #os.remove( nodes_file )
244 
245  cmd ="mpirun_rsh -rsh -hostfile %s "%(nodes_file,)
246  cmd+="-n %d "%(num_det+num_sink,)
247  cmd+=" FHICL_FILE_PATH=\"$FHICL_FILE_PATH\" "
248  cmd+=builder[:-1]
249  if art_args: cmd+=" %s"%(art_args,)
250  print( "executing cmd: %s"%(cmd,) )
251  os.system(cmd)
252  else:
253  cmd ="mpirun -n %d "%(num_det+num_sink,)
254  cmd+=builder[:-1]
255  if art_args: cmd+=" %s"%(art_args,)
256  print( "executing cmd: %s"%(cmd,) )
257  rc = (os.system( cmd ) >> 8)
258  print "return status of %s is: %d\n" %(cmd, rc)
259 
260  print "return status is (really!) : %d\n" %(rc,)
261  sys.exit(rc)
262 
263 
264 if __name__ == "__main__":
265  main()
def search
Find matches for the regular expression.
Definition: daqrate.py:56
match_obj
Match object representing all matches for the regex.
Definition: daqrate.py:54
def __init__
Create an instance of the regular expression.
Definition: daqrate.py:50
compiled
The compiled version of the regex.
Definition: daqrate.py:52
General Regular Expression class that allows for: xx = Re( re ) ...
Definition: daqrate.py:47