CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Mpslibclass.py
Go to the documentation of this file.
1 # This Jobdatabas-Class interacts with the mps.db file.
2 # It's member-variables are often called in the mps_... scripts.
3 #
4 # Meaning of the database variables: (still need to work on these)
5 #
6 # (1) Header
7 # header - version information
8 # batchScript - base script for serial job
9 # cfgTemplate - template for cfg file
10 # infiList - list of input files to be serialized
11 # classInf - batch class information (might contain two ':'-separated)
12 # addFiles - job name for submission
13 # driver - specifies whether merge job is foreseen
14 # nJobs - number of serial jobs (not including merge job)
15 # mergeScript - base script for merge job
16 # mssDir - directory for mass storage (e.g. Castor)
17 # updateTime - time of last update (seconds since 1970)
18 # updateTimeHuman - time of last update (human readable)
19 # elapsedTime - seconds since last update
20 # mssDirPool - pool for $mssDir (e.g. cmscaf/cmscafuser)
21 # pedeMem - Memory allocated for pede
22 # spare1
23 # spare2
24 # spare3
25 
26 # (2) Job-level variables/lists
27 # JOBNUMBER - ADDED, selfexplanatory
28 # JOBDIR - name of job directory (not full path)
29 # JOBSTATUS - status of job
30 # JOBRUNTIME - present CPU time of job
31 # JOBNEVT - number of events processed by job
32 # JOBHOST - presently used to store remark
33 # JOBINCR - CPU increment since last check
34 # JOBREMARK - comment
35 # JOBSP1 - spare
36 # JOBSP2 - possible weight for pede
37 # JOBSP3 - possible name as given to mps_setup.pl -N <name> ...
38 # JOBID - what is this?
39 
40 import datetime
41 import time
42 import os
43 import sys
44 
45 #-------------------------------------------------------------------------------
47 
48  JOBNUMBER, JOBDIR, JOBID, JOBSTATUS, JOBNTRY, JOBRUNTIME, JOBNEVT, JOBHOST, JOBINCR, \
49  JOBREMARK, JOBSP1, JOBSP2, JOBSP3 = ([] for i in range(13))
50 
51  header, batchScript, cfgTemplate, infiList, classInf, addFiles, driver, mergeScript, \
52  mssDir, updateTimeHuman, mssDirPool, spare1, spare2, spare3 = ('' for i in range(14))
53 
54  updateTime, elapsedTime, pedeMem , nJobs = -1, -1, -1, -1
55 
56  #-------------------------------------------------------------------------------
57  # parses the mps.db file into the member variables and arrays
58  def read_db(self):
59  try:
60  DBFILE = open('mps.db','r')
61  except IOError as e:
62  if e.args != (2, 'No such file or directory'):
63  raise
64  else:
65  msg = ("No 'mps.db' found. Make sure you are in a campaign "
66  "directory and that the campaign is set up.")
67  print msg
68  sys.exit(1)
69 
70  #read infolines at the top, used rstrip to delete the '\n'
71  self.header = DBFILE.readline().strip()
72  self.batchScript = DBFILE.readline().rstrip('\n')
73  self.cfgTemplate = DBFILE.readline().rstrip('\n')
74  self.infiList = DBFILE.readline().rstrip('\n')
75  self.classInf = DBFILE.readline().rstrip('\n') #formerly named 'class' ->conflict
76  self.addFiles = DBFILE.readline().rstrip('\n')
77  self.driver = DBFILE.readline().rstrip('\n')
78  self.mergeScript = DBFILE.readline().rstrip('\n')
79  self.mssDir = DBFILE.readline().rstrip('\n')
80  self.updateTime = int(DBFILE.readline())
81  self.updateTimeHuman = DBFILE.readline().rstrip('\n')
82  self.elapsedTime = int(DBFILE.readline())
83  self.mssDirPool = DBFILE.readline().rstrip('\n')
84  self.pedeMem = int(DBFILE.readline())
85  self.spare1 = DBFILE.readline().rstrip('\n')
86  self.spare2 = DBFILE.readline().rstrip('\n')
87  self.spare3 = DBFILE.readline().rstrip('\n')
88 
89  #read actual jobinfo into arrays
90  self.nJobs = 0
91  milleJobs = 0
92 
93 
94  for line in DBFILE:
95  line = line.rstrip('\n') #removes the pesky \n from line
96  parts = line.split(":") #read each line and split into parts list
97  self.JOBNUMBER.append(int(parts[0]))
98  self.JOBDIR.append(parts[1])
99  self.JOBID.append(int(parts[2]))
100  self.JOBSTATUS.append(parts[3])
101  self.JOBNTRY.append(int(parts[4]))
102  self.JOBRUNTIME.append(int(parts[5])) #int float?
103  self.JOBNEVT.append(int(parts[6]))
104  self.JOBHOST.append(parts[7])
105  self.JOBINCR.append(int(parts[8]))
106  self.JOBREMARK.append(parts[9])
107  self.JOBSP1.append(parts[10])
108  self.JOBSP2.append(parts[11])
109  self.JOBSP3.append(parts[12])
110 
111  #count number of jobs
112  if not self.JOBDIR[self.nJobs].startswith("jobm"):
113  milleJobs += 1
114  self.nJobs += 1
115  self.nJobs = milleJobs
116 
117  DBFILE.close()
118 
119 
120 
121  #-------------------------------------------------------------------------------
122  # prints the member varaiables and arrays to the terminal
123  def print_memdb(self):
124  #print metainfo
125  print "\n=== mps database printout ===\n"
126  print self.header
127  print 'Script:\t\t', self.batchScript
128  print 'cfg:\t\t', self.cfgTemplate
129  print 'files:\t\t', self.infiList
130  print 'class:\t\t', self.classInf
131  print 'name:\t\t', self.addFiles
132  print 'driver:\t\t', self.driver
133  print 'mergeScript:\t', self.mergeScript
134  print 'mssDir:\t\t', self.mssDir
135  print 'updateTime:\t', self.updateTimeHuman
136  print 'elapsed:\t', self.elapsedTime
137  print 'mssDirPool:\t', self.mssDirPool
138  print 'pedeMem:\t', self.pedeMem, '\n'
139 
140  #print interesting Job-level lists ---- to add: t/evt, fix remarks
141  print '### dir jobid stat try rtime nevt remark weight name'
142  print "------------------------------------------------------------------------------"
143  for i in xrange(self.nJobs):
144  print '%03d %6s %9d %6s %3d %5d %8d %8s %5s %s' % (
145  self.JOBNUMBER[i],
146  self.JOBDIR[i],
147  self.JOBID[i],
148  self.JOBSTATUS[i],
149  self.JOBNTRY[i],
150  self.JOBRUNTIME[i],
151  self.JOBNEVT[i],
152  self.JOBHOST[i],
153  self.JOBSP2[i],
154  self.JOBSP3[i])
155 
156  #print merge Jobs if merge mode
157  if self.driver == 'merge':
158  for i in xrange(self.nJobs,len(self.JOBDIR)):
159  print '%s %6s %9d %6s %3d %5d %8d %8s %5s %s' % (
160  'MMM',
161  self.JOBDIR[i],
162  self.JOBID[i],
163  self.JOBSTATUS[i],
164  self.JOBNTRY[i],
165  self.JOBRUNTIME[i],
166  self.JOBNEVT[i],
167  self.JOBHOST[i],
168  self.JOBSP2[i],
169  self.JOBSP3[i])
170 
171  #print summed info
172  totalEvents = sum(self.JOBNEVT[:self.nJobs])
173  totalCpu = sum(self.JOBRUNTIME[:self.nJobs])
174  meanCpuPerEvent = 0.
175  if totalEvents > 0:
176  meanCpuPerEvent = float(totalCpu)/totalEvents
177  print "------------------------------------------------------------------------------"
178  print "\t\t\t\t\tEvent total:\t", totalEvents
179  print "\t\t\t\t\tCPU total:\t", totalCpu, 's'
180  print "\t\t\t\t\tMean CPU/event:\t",meanCpuPerEvent,'s'
181 
182 
183 
184 
185 
186  #-------------------------------------------------------------------------------
187  # writes a new mps.db file from the members. Replaces the old mps.db
188  def write_db(self):
189  self.header = "mps database schema 3.2"
190  self.currentTime = int(time.time())
191  self.elapsedTime = 0;
192  if self.updateTime != 0:
193  self.elapsedTime = self.currentTime - self.updateTime
194  self.updateTime = self.currentTime
195  self.updateTimeHuman = str(datetime.datetime.today()) #no timezone :(
196  self.spare1 = "-- unused --"
197  self.spare2 = "-- unused --"
198  self.spare3 = "-- unused --"
199 
200  #if mps.db already exists, backup as mps.db~ (in case of interupt during write)
201  os.system('[[ -a mps.db ]] && cp -p mps.db mps.db~')
202 
203  #write mps.db header
204  DBFILE = open ("mps.db", "w")
205  headData = [ self.header, self.batchScript, self.cfgTemplate, self.infiList,
206  self.classInf, self.addFiles, self.driver, self.mergeScript,
207  self.mssDir, self.updateTime, self.updateTimeHuman,
208  self.elapsedTime, self.mssDirPool, self.pedeMem,
209  self.spare1, self.spare2, self.spare3 ]
210  for item in headData:
211  DBFILE.write("%s\n" % item)
212 
213  #write mps.db jobinfo
214  for i in xrange(len(self.JOBID)):
215  DBFILE.write('%03d:%s:%05d:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n' %
216  (i+1,
217  self.JOBDIR[i],
218  self.JOBID[i],
219  self.JOBSTATUS[i],
220  self.JOBNTRY[i],
221  self.JOBRUNTIME[i],
222  self.JOBNEVT[i],
223  self.JOBHOST[i],
224  self.JOBINCR[i],
225  self.JOBREMARK[i],
226  self.JOBSP1[i],
227  self.JOBSP2[i],
228  self.JOBSP3[i]))
229  DBFILE.close()
230 
231  #-------------------------------------------------------------------------------
232  # returns job class as stored in db
233  # one and only argument may be "mille" or "pede" for mille or pede jobs
234  def get_class(self, argument=''):
235  CLASSES = self.classInf.split(':')
236  if len(CLASSES)<1 or len(CLASSES)>2:
237  print '\nget_class():\n class must be of the form \'class\' or \'classMille:classPede\', but is \'%s\'!\n\n', classInf
238  sys.exit(1)
239  elif argument == 'mille':
240  return CLASSES[0]
241  elif argument == 'pede':
242  if len(CLASSES) == 1:
243  return CLASSES[0]
244  elif len(CLASSES) == 2:
245  return CLASSES[1]
246  else:
247  print '\nget_class():\n Know class only for \'mille\' or \'pede\', not %s!\n\n' %argument
248  sys.exit(1)