001
002
003
004 import os,sys,commands,tempfile
005 from CoolConvUtilities.AtlCoolLib import pathResolver as pathResolver
006
007 class FileError:
008 "Class to store details of errors in one file"
009 def __init__(self,code,guid,count,lfn,pfn,folders):
010 self.code=int(code)
011 self.guid=str(guid)
012 self.count=int(count)
013 self.lfn=str(lfn)
014 self.pfn=str(pfn)
015 self.folders=folders
016
017 class checkFile:
018 "Wrapper for AtlCoolCopy command which does POOL file checking"
019 def __init__(self,dbname,taglist,runsince,rununtil,filename="",verbose=False,oracle=False,openfile=False,nocat=False,poolcats=[],magic=[],parfiles=[],passOpt=""):
020 self.dbname=dbname
021 self.taglist=taglist
022 self.runsince=runsince
023 self.rununtil=rununtil
024 self.filename=filename
025 self.verbose=verbose
026 self.oracle=oracle
027 self.openfile=openfile
028 self.nocat=nocat
029 self.poolcats=poolcats
030 self.magictags=magic
031 self.passOpt=passOpt
032 self.parfiles=parfiles
033 self.poollist=[]
034 self.guidlist=[]
035
036 self.tfilename=tempfile.mktemp()
037 print "Analyse database %s runs from %i to %i" % (self.dbname,self.runsince,self.rununtil)
038 for tag in self.taglist: print "Top-level tag %s" % tag
039 if (self.openfile):
040 print "Files will be physically opened to check GUID consistency"
041
042 self.dblist=[]
043 if (self.dbname.find('/')<0):
044
045 schemas=[]
046 if (self.oracle):
047
048
049
050 if self.dbname.find('OFLP')>=0:
051 schemas=['COOLONL_INDET','COOLONL_TRT','COOLONL_LAR',
052 'COOLONL_CALO','COOLONL_GLOBAL','COOLOFL_GLOBAL']
053 elif self.dbname.find('CMCP')>=0:
054 schemas=['COOLONL_INDET','COOLONL_TRT','COOLONL_LAR',
055 'COOLONL_CALO','COOLONL_GLOBAL']
056 elif self.dbname.find('COMP')>=0:
057 schemas=['COOLONL_INDET','COOLONL_TRT','COOLONL_LAR',
058 'COOLONL_CALO','COOLONL_GLOBAL','COOLOFL_GLOBAL']
059 elif self.dbname.find('TMCP')>=0:
060 schemas=['COOLONL_LAR','COOLONL_CALO']
061 else:
062
063 schemas=['COOLONL_GLOBAL']
064 for s in schemas:
065 self.dblist+=['%s/%s' % (s,self.dbname)]
066 else:
067
068 self.dblist=[self.dbname]
069
070 def execute(self):
071 "Execute the checks, return non-zero code if some files are not OK"
072
073 poolopts=""
074 print "List of POOL file catalogues to be checked:"
075 if (len(self.poolcats)==0 and not self.nocat):
076
077 cats=[]
078 if self.dbname.find('OFLP')>=0:
079 cats=['oflcond']
080 elif self.dbname.find('CMCP')>=0:
081 cats=['cmccond']
082 elif self.dbname.find('COMP')>=0:
083 cats=['comcond','oflcond']
084 elif self.dbname.find('TBDP')>=0:
085 cats=['tbcond']
086 elif self.dbname.find('TMCP')>=0:
087 cats=['tbcond','oflcond']
088 for cat in cats:
089 fname=pathResolver('poolcond/PoolCat_%s.xml' % cat,
090 retFile=False)
091 if (fname is not None):
092 poolopts+=' -poolcat %s' % fname
093 print fname
094 else:
095 print "Warning: Cannot find catalogue file for %s" % cat
096 else:
097 for i in self.poolcats:
098 poolopts+=' -poolcat %s' % i
099 print i
100
101 sumret=0
102 nerr=0
103 for dbname in self.dblist:
104 comm='AtlCoolCopy.exe %s X -nocopy -excludehead -checkrefs -listpfn -hitag -rs %i -ru %i -checkoutput %s%s' % (dbname,self.runsince,self.rununtil,self.tfilename,poolopts)
105 for tag in self.taglist: comm+=' -tag %s' % tag
106 if (self.oracle): comm+=' -readoracle'
107 if (self.openfile):
108 comm+=' -checkfiles'
109 else:
110 comm+=' -checkrefs'
111 if (self.passOpt!=""): comm+=" %s" % self.passOpt
112 for mtag in self.magictags:
113 comm+=" -magic %s" % mtag
114 print "Adding magic tag %s" % mtag
115 for i in self.parfiles:
116 comm+=" -parfile %s" % i
117 print "Opening database",dbname
118 (s,o)=commands.getstatusoutput(comm)
119 if (self.verbose): print o
120 if (s==111*256):
121 print "Problems detected for files referenced by %s" % dbname
122 elif (s!=0):
123 print "Problems with DB access, AtlCoolCopy error %i (try --debug to see more)" % (s/256)
124 sumret+=s
125
126 try:
127 infile=open(self.tfilename,"r")
128 for line in infile.readlines():
129 tokens=line.split()
130 if int(tokens[0])>0: nerr+=1
131 guid=tokens[1]
132 if (guid not in self.guidlist):
133 self.poollist+=[FileError(int(tokens[0]),tokens[1],
134 int(tokens[2]),tokens[3],
135 tokens[4],tokens[5:])]
136 self.guidlist+=[guid]
137 infile.close()
138 except IOError:
139
140 pass
141
142 if (self.filename!=""):
143 opfile=open(self.filename,"w")
144 else:
145 opfile=None
146 print "Total of %i POOL files with problems" % nerr
147 if (len(self.poollist)>0):
148 print "ErrCode GUID Count LFN PFN Folders"
149 for ifile in self.poollist:
150 print '%2i %36s %4i %s %s' % (ifile.code,ifile.guid,ifile.count,ifile.lfn,ifile.pfn) ,
151 for j in ifile.folders:
152 print j,' ',
153 print
154 if (opfile):
155 opfile.write('%2i %36s %4i %s %s ' % (ifile.code,ifile.guid,ifile.count,ifile.lfn,ifile.pfn))
156 for j in ifile.folders:
157 opfile.write(j+' ')
158 opfile.write('\n')
159 else:
160 print "All files resolved successfully"
161 if (opfile): opfile.close()
162
163 try:
164 os.remove(self.tfilename)
165 except OSError:
166 pass
167 return sumret
168
169 def makeCD(self,filename,ignoremissing=False):
170 "Make conditions release with the set of files which were found"
171
172 nbad=0
173 prestagelist=[]
174 for ifile in self.poollist:
175 if (ifile.code!=0 or ifile.pfn=='' or ifile.pfn=='noPFN'):
176 nbad+=1
177 idx=ifile.pfn.find('/castor/')
178 if (idx>=0):
179 prestagelist+=[' -M %s' % ifile.pfn[idx:]]
180 if (nbad>0):
181 print "WARNING: %i files are bad/missing" % nbad
182 if (ignoremissing):
183 print "Continuing build with missing files"
184 else:
185 print "Cannot build conditions release - ABORT"
186 return 1
187
188 if len(prestagelist)>0:
189 print "Pre-staging %i files from castor" % len(prestagelist)
190
191 for i in range(0,len(prestagelist),10):
192 comm='LD_LIBRARY_PATH="";stager_get'
193 for j in range(i,min(i+10,len(prestagelist))):
194 comm+=prestagelist[j]
195 print "Staging files %i %s: " % (i,comm)
196 os.system(comm)
197
198 print "Building conditions release with %i files to output file %s" % (len(self.poollist),filename)
199
200 packdir=tempfile.mktemp()
201 os.mkdir(packdir)
202 reldir=packdir+'/CDRelease'
203 os.mkdir(reldir)
204 pooldir=reldir+'/poolcond'
205 os.mkdir(pooldir)
206 xmldir=reldir+'/XMLConfig'
207 os.mkdir(xmldir)
208
209 dummies=[]
210 if (self.dbname.find('OFLP')>=0):
211 cat='oflcond'
212 elif (self.dbname.find('COMP')>=0):
213 cat='comcond'
214 dummies+=['oflcond','comcond_castor']
215 elif (self.dbname.find('CMCP')>=0):
216 cat='cmccond'
217 else:
218 cat='nocond'
219 print "Unknown database instance %s - cannot derive catalogue name" % self.dbname
220
221 for dummy in dummies:
222 print "Making dummy catalogue for %s" % dummy
223 dcat=PoolCat('%s/PoolCat_%s.xml' % (pooldir,dummy))
224 dcat.close()
225 catname='%s/PoolCat_%s.xml' % (pooldir,cat)
226 print "POOL file catalogue will be generated at %s" % catname
227 catalog=PoolCat(catname)
228 print "Using temporary directory %s" % packdir
229
230 os.system('cp $CORAL_AUTH_PATH/authentication.xml %s' % xmldir)
231 os.system('cp $CORAL_DBLOOKUP_PATH/dblookup.xml %s' % xmldir)
232 nbad=0
233 for ifile in self.poollist:
234 if (ignoremissing and (ifile.pfn=='noPFN' or ifile.code!=0)):
235 continue
236 idx=ifile.pfn.rfind('/')
237 if (idx>0):
238 leafname=ifile.pfn[idx+1:]
239 else:
240 print "Cannot extract leafname from file %s" % ifile.pfn
241 leafname='BADFILE'
242 idx=ifile.pfn.find('/castor/')
243 if (idx>=0):
244
245 print "Copying from castor: %s" % ifile.pfn[idx:]
246 rc=os.system('rfcp %s %s/%s' % (ifile.pfn[idx:],pooldir,leafname))
247 else:
248 os.symlink(ifile.pfn,'%s/%s' % (pooldir,leafname))
249 rc=0
250 if (rc!=0):
251 print "Problems linking/copying %s" % ifile.pfn
252 nbad+=1
253 catalog.makeEntry(ifile.guid,ifile.lfn,leafname)
254 catalog.close()
255 if (nbad>0):
256 print "ERRORs detected in linking/copying %i files - ABORT" % nbad
257 return 2
258
259
260 setupfile=open('%s/setup.py' % reldir,'w')
261 setupfile.write("""
262 import os, fileinput
263
264 class Setup(object):
265 def __init__(self, dbdir = None):
266 if dbdir is None:
267 self.dbdir = os.getcwd()
268 else:
269 self.dbdir = dbdir
270 print "Setting up CDRelease:"
271 self.custom()
272 self.env()
273
274 def custom(self):
275 fns = ['PoolCat_oflcond.xml', 'PoolCat_tbcond.xml',
276 'PoolCat_cmccond.xml', 'PoolCat_comcond.xml']
277 fps=[]
278 for fn in fns:
279 f=os.path.join(self.dbdir,'poolcond',fn)
280 if os.path.exists(f):
281 fps+=[f]
282 print " Editing pool catalogs ... "
283 print fps
284 for line in fileinput.input(fps, inplace=1):
285 print line.replace('--GENERATED--',
286 os.path.join(self.dbdir, 'poolcond') + os.sep),
287
288 def env(self):
289 datapath = os.environ.get('DATAPATH')
290 if datapath:
291 datapath = datapath.split(os.pathsep)
292 else:
293 datapath = []
294 datapath = [d for d in datapath if 'DBRelease' not in d.split(os.sep)]
295 datapath.insert(0, self.dbdir)
296 coralpath=os.path.join(self.dbdir,'XMLConfig')
297
298 print " Setting up environment ..."
299 self.dbenv = { 'DATAPATH' : os.pathsep.join(datapath) ,
300 'CDRELEASE' : os.path.basename(self.dbdir),
301 'CORAL_DBLOOKUP_PATH' : os.path.join(self.dbdir, 'XMLConfig'),
302 'CORAL_AUTH_PATH' : os.path.join(self.dbdir,'XMLConfig')}
303 os.environ.update(self.dbenv)
304
305 def __str__(self):
306 return '\\n'.join(['%s=%s' % i for i in self.dbenv.iteritems()])
307
308 if __name__ != 'setup':
309 print Setup()
310
311 """)
312 setupfile.close()
313
314
315 print "Creating tar file"
316 rc=os.system('cd %s;tar cvf %s.tar CDRelease -h' % (packdir,filename))
317 if (rc==0):
318 rc=os.system('gzip %s.tar' % filename)
319 if (rc!=0):
320 print "Non-zero return code %i from gzipping" % rc
321 return 3
322 else:
323 print "Non-zero return code %i from tarfile creation" % rc
324 return 2
325
326 os.system('rm -rf %s' % packdir)
327 print "All done"
328 return 0
329
330 class PoolCat:
331 "Class to output POOL file catalogue"
332 def __init__(self,catname):
333 "Open the catalogue file and write headers"
334 self.catfile=open(catname,'w')
335 self.catfile.write("""<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
336 <!-- Edited By POOL -->
337 <!DOCTYPE POOLFILECATALOG SYSTEM "InMemory">
338 <POOLFILECATALOG>\n""")
339
340 def makeEntry(self,guid,lfn,pfnleaf):
341 "Make one entry in the file catalogue"
342 self.catfile.write("""
343 <File ID="%s">
344 <physical>
345 <pfn filetype="ROOT_All" name="--GENERATED--%s"/>
346 </physical>
347 <logical>
348 <lfn name="%s"/>
349 </logical>
350 </File>
351 """ % (guid,pfnleaf,lfn))
352
353 def close(self):
354 "Close the file, writing trailer"
355 self.catfile.write('</POOLFILECATALOG>\n')
356 self.catfile.close()
357
358
359
360 if __name__=='__main__':
361
362 import getopt
363 def usage():
364 print"usage: AtlCoolCheckFiles.py {<options>} dbname top-level-tag {top-level-tag}"
365 print " dbname is instance e.g. OFLP200 or full COOL connect-string"
366 print " top-level-tag(s) is global tag in the database instance"
367 print "Options are:"
368 print "--help : Display this help"
369 print "--debug : Dump full output from AtlCoolCopy command"
370 print "--rs=<run> First run to consider"
371 print "--ru=<run> Last run to consider (inclusive)"
372 print "--r=<run> Consider single run"
373 print "--geo=<geometry tag>: Only include magic tags for given geometry"
374 print "--readoracle: Read data from Oracle rather than DBrelease"
375 print "--open: Actually open POOL files to check GUID"
376 print "--output=<file>: Output POOL catalogue data on <file>"
377 print "--poolall: List all POOL files referenced, not only those with errors"
378 print "--poolcat=<cat>: Use specific catalogue rather than defaults"
379 print "--nocat : Do not attach any POOL file catalogues"
380 print "--makecd <file> : Make CDRelease POOL file tarball with given name"
381 print "--ignoremissing : Ignore missing files when making CDRelease"
382 print "--passopt=\"<options>\": Pass additional options to AtlCoolCopy"
383 print "--parfile <file> : Pass file as additional options to AtlCoolCopy"
384 try:
385 longopts=['r=','rs=','ru=','readoracle','open','nocat','output=',
386 'poolcat=','debug','passopt=','parfile=','makecd=','geo=',
387 'poolall','ignoremissing','help']
388 opts,args=getopt.getopt(sys.argv[1:],'',longopts)
389 except getopt.GetoptError,e:
390 print e
391 usage()
392 sys.exit(-1)
393 if (len(args)<2):
394 usage()
395 sys.exit(-1)
396 dbname=args[0]
397 tags=args[1:]
398
399 runsince=0
400 rununtil=(2 << 31)-1
401 filename=""
402 oracle=False
403 openfile=False
404 nocat=False
405 verbose=False
406 parfiles=[]
407 poolcats=[]
408 geo=[]
409 makecd=""
410 passopt=""
411 ignoremissing=False
412
413 for o,a in opts:
414 if (o=='--rs'):
415 runsince=int(a)
416 if (o=='--ru'):
417 rununtil=int(a)
418 if (o=='--r'):
419 runsince=int(a)
420 rununtil=runsince
421 if (o=='--open'):
422 openfile=True
423 if (o=='--nocat'):
424 nocat=True
425 if (o=='--output'):
426 filename=str(a)
427 if (o=='--readoracle'):
428 oracle=True
429 if (o=='--poolcat'):
430 poolcats+=[str(a)]
431 if (o=='--parfile'):
432 parfiles+=[str(a)]
433 if (o=='--debug'):
434 verbose=True
435 if (o=='--passopt'):
436 passopt+=str(a)+" "
437 if (o=='--poolall'):
438 passopt+='-poolall '
439 if (o=='--geo'):
440 geo+=[str(a)]
441 if (o=='--makecd'):
442 makecd=str(a)
443 passopt+='-poolall -listpfn '
444 if (o=='--ignoremissing'):
445 ignoremissing=True
446 if (o=='--help'):
447 usage()
448 sys.exit()
449
450 if len(geo)==0: geo=['ATLAS-']
451
452 myCheck=checkFile(dbname,tags,runsince,rununtil,filename,
453 verbose,oracle,openfile,nocat,poolcats,geo,parfiles,passopt)
454 rc=myCheck.execute()
455 if (makecd!=""): myCheck.makeCD(makecd,ignoremissing)
456
Due to the LXR bug, the updates fail sometimes to remove references to deleted files. The Saturday's full rebuilds fix these problems |
This page was automatically generated by the
LXR engine.
|
|