ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/CRAB/python/cms_cmssw.py
(Generate patch)

Comparing COMP/CRAB/python/cms_cmssw.py (file contents):
Revision 1.17 by slacapra, Wed Jun 28 13:39:03 2006 UTC vs.
Revision 1.49 by slacapra, Thu Oct 5 15:32:20 2006 UTC

# Line 2 | Line 2 | from JobType import JobType
2   from crab_logger import Logger
3   from crab_exceptions import *
4   from crab_util import *
5 + import math
6   import common
7   import PsetManipulator  
8  
9 < import DBSInfo_EDM
10 < import DataDiscovery_EDM
11 < import DataLocation_EDM
9 > import DBSInfo
10 > import DataDiscovery
11 > import DataLocation
12   import Scram
13  
14 < import os, string, re
14 > import glob, os, string, re
15  
16   class Cmssw(JobType):
17 <    def __init__(self, cfg_params):
17 >    def __init__(self, cfg_params, ncjobs):
18          JobType.__init__(self, 'CMSSW')
19          common.logger.debug(3,'CMSSW::__init__')
20  
20        self.analisys_common_info = {}
21          # Marco.
22          self._params = {}
23          self.cfg_params = cfg_params
24 +
25 +        # number of jobs requested to be created, limit obj splitting
26 +        self.ncjobs = ncjobs
27 +
28          log = common.logger
29          
30          self.scram = Scram.Scram(cfg_params)
# Line 29 | Line 33 | class Cmssw(JobType):
33          self.scriptExe = ''
34          self.executable = ''
35          self.tgz_name = 'default.tgz'
36 <
36 >        self.pset = ''      #scrip use case Da  
37 >        self.datasetPath = '' #scrip use case Da
38  
39          self.version = self.scram.getSWVersion()
40          self.setParam_('application', self.version)
36        common.analisys_common_info['sw_version'] = self.version
37        ### FEDE
38        common.analisys_common_info['copy_input_data'] = 0
39        common.analisys_common_info['events_management'] = 1
41  
42          ### collect Data cards
43          try:
# Line 44 | Line 45 | class Cmssw(JobType):
45              log.debug(6, "CMSSW::CMSSW(): datasetPath = "+tmp)
46              if string.lower(tmp)=='none':
47                  self.datasetPath = None
48 +                self.selectNoInput = 1
49              else:
50                  self.datasetPath = tmp
51 +                self.selectNoInput = 0
52          except KeyError:
53              msg = "Error: datasetpath not defined "  
54              raise CrabException(msg)
# Line 82 | Line 85 | class Cmssw(JobType):
85          try:
86              self.pset = cfg_params['CMSSW.pset']
87              log.debug(6, "Cmssw::Cmssw(): PSet file = "+self.pset)
88 <            if (not os.path.exists(self.pset)):
89 <                raise CrabException("User defined PSet file "+self.pset+" does not exist")
88 >            if self.pset.lower() != 'none' :
89 >                if (not os.path.exists(self.pset)):
90 >                    raise CrabException("User defined PSet file "+self.pset+" does not exist")
91 >            else:
92 >                self.pset = None
93          except KeyError:
94              raise CrabException("PSet file missing. Cannot run cmsRun ")
95  
# Line 110 | Line 116 | class Cmssw(JobType):
116          # script_exe file as additional file in inputSandbox
117          try:
118              self.scriptExe = cfg_params['USER.script_exe']
113            self.additional_inbox_files.append(self.scriptExe)
119              if self.scriptExe != '':
120                 if not os.path.isfile(self.scriptExe):
121                    msg ="WARNING. file "+self.scriptExe+" not found"
122                    raise CrabException(msg)
123 +               self.additional_inbox_files.append(string.strip(self.scriptExe))
124          except KeyError:
125 <           pass
126 <                  
125 >            self.scriptExe = ''
126 >        #CarlosDaniele
127 >        if self.datasetPath == None and self.pset == None and self.scriptExe == '' :
128 >           msg ="WARNING. script_exe  not defined"
129 >           raise CrabException(msg)
130 >
131          ## additional input files
132          try:
133 <            tmpAddFiles = string.split(cfg_params['CMSSW.additional_input_files'],',')
133 >            tmpAddFiles = string.split(cfg_params['USER.additional_input_files'],',')
134              for tmp in tmpAddFiles:
135 <                if not os.path.exists(tmp):
136 <                    raise CrabException("Additional input file not found: "+tmp)
137 <                tmp=string.strip(tmp)
138 <                self.additional_inbox_files.append(tmp)
135 >                dirname = ''
136 >                if not tmp[0]=="/": dirname = "."
137 >                files = glob.glob(os.path.join(dirname, tmp))
138 >                for file in files:
139 >                    if not os.path.exists(file):
140 >                        raise CrabException("Additional input file not found: "+file)
141 >                    pass
142 >                    self.additional_inbox_files.append(string.strip(file))
143                  pass
144              pass
145 +            common.logger.debug(5,"Additional input files: "+str(self.additional_inbox_files))
146          except KeyError:
147              pass
148  
149          # files per job
150          try:
151 <            self.filesPerJob = int(cfg_params['CMSSW.files_per_jobs']) #Daniele
152 <            self.selectFilesPerJob = 1
151 >            if (cfg_params['CMSSW.files_per_jobs']):
152 >                raise CrabException("files_per_jobs no longer supported.  Quitting.")
153          except KeyError:
154 <            self.filesPerJob = 0
140 <            self.selectFilesPerJob = 0
154 >            pass
155  
156          ## Events per job
157          try:
# Line 147 | Line 161 | class Cmssw(JobType):
161              self.eventsPerJob = -1
162              self.selectEventsPerJob = 0
163      
164 <        # To be implemented
151 <        # ## number of jobs
152 <        # try:
153 <        #     self.numberOfJobs =int( cfg_params['CMSSW.number_of_job'])
154 <        #     self.selectNumberOfJobs = 1
155 <        # except KeyError:
156 <        #     self.selectNumberOfJobs = 0
157 <
158 <        if (self.selectFilesPerJob == self.selectEventsPerJob):
159 <            msg = 'Must define either files_per_jobs or events_per_job'
160 <            raise CrabException(msg)
161 <
162 <        if (self.selectEventsPerJob  and not self.datasetPath == None):
163 <            msg = 'Splitting according to events_per_job available only with None as datasetpath'
164 <            raise CrabException(msg)
165 <    
164 >        ## number of jobs
165          try:
166 <            self.total_number_of_events = int(cfg_params['CMSSW.total_number_of_events'])
166 >            self.theNumberOfJobs =int( cfg_params['CMSSW.number_of_jobs'])
167 >            self.selectNumberOfJobs = 1
168          except KeyError:
169 <            msg = 'Must define total_number_of_events'
170 <            raise CrabException(msg)
171 <        
172 <        CEBlackList = []
169 >            self.theNumberOfJobs = 0
170 >            self.selectNumberOfJobs = 0
171 >
172          try:
173 <            tmpBad = string.split(cfg_params['EDG.ce_black_list'],',')
174 <            for tmp in tmpBad:
176 <                tmp=string.strip(tmp)
177 <                CEBlackList.append(tmp)
173 >            self.total_number_of_events = int(cfg_params['CMSSW.total_number_of_events'])
174 >            self.selectTotalNumberEvents = 1
175          except KeyError:
176 <            pass
176 >            self.total_number_of_events = 0
177 >            self.selectTotalNumberEvents = 0
178  
179 <        self.reCEBlackList=[]
180 <        for bad in CEBlackList:
181 <            self.reCEBlackList.append(re.compile( bad ))
182 <
183 <        common.logger.debug(5,'CEBlackList: '+str(CEBlackList))
179 >        if self.pset != None: #CarlosDaniele
180 >             if ( (self.selectTotalNumberEvents + self.selectEventsPerJob + self.selectNumberOfJobs) != 2 ):
181 >                 msg = 'Must define exactly two of total_number_of_events, events_per_job, or number_of_jobs.'
182 >                 raise CrabException(msg)
183 >        else:
184 >             if (self.selectNumberOfJobs == 0):
185 >                 msg = 'Must specify  number_of_jobs.'
186 >                 raise CrabException(msg)
187  
188 <        CEWhiteList = []
188 >        ## source seed for pythia
189          try:
190 <            tmpGood = string.split(cfg_params['EDG.ce_white_list'],',')
190 <            for tmp in tmpGood:
191 <                tmp=string.strip(tmp)
192 <                CEWhiteList.append(tmp)
190 >            self.sourceSeed = int(cfg_params['CMSSW.pythia_seed'])
191          except KeyError:
192 <            pass
193 <
196 <        #print 'CEWhiteList: ',CEWhiteList
197 <        self.reCEWhiteList=[]
198 <        for Good in CEWhiteList:
199 <            self.reCEWhiteList.append(re.compile( Good ))
200 <
201 <        common.logger.debug(5,'CEWhiteList: '+str(CEWhiteList))
192 >            self.sourceSeed = None
193 >            common.logger.debug(5,"No seed given")
194  
195 <        self.PsetEdit = PsetManipulator.PsetManipulator(self.pset) #Daniele Pset
195 >        try:
196 >            self.sourceSeedVtx = int(cfg_params['CMSSW.vtx_seed'])
197 >        except KeyError:
198 >            self.sourceSeedVtx = None
199 >            common.logger.debug(5,"No vertex seed given")
200 >        if self.pset != None: #CarlosDaniele
201 >            self.PsetEdit = PsetManipulator.PsetManipulator(self.pset) #Daniele Pset
202  
203          #DBSDLS-start
204          ## Initialize the variables that are extracted from DBS/DLS and needed in other places of the code
205          self.maxEvents=0  # max events available   ( --> check the requested nb. of evts in Creator.py)
206          self.DBSPaths={}  # all dbs paths requested ( --> input to the site local discovery script)
207 +        self.jobDestination=[]  # Site destination(s) for each job (list of lists)
208          ## Perform the data location and discovery (based on DBS/DLS)
209          ## SL: Don't if NONE is specified as input (pythia use case)
210 <        common.analisys_common_info['sites']=None
210 >        blockSites = {}
211          if self.datasetPath:
212 <            self.DataDiscoveryAndLocation(cfg_params)
212 >            blockSites = self.DataDiscoveryAndLocation(cfg_params)
213          #DBSDLS-end          
214  
215          self.tgzNameWithPath = self.getTarBall(self.executable)
217
218        # modify Pset
219        if (self.datasetPath): # standard job
220            self.PsetEdit.maxEvent(self.eventsPerJob) #Daniele  
221            self.PsetEdit.inputModule("INPUT") #Daniele
222
223        else:  # pythia like job
224            self.PsetEdit.maxEvent(self.eventsPerJob) #Daniele  
225            self.PsetEdit.pythiaSeed("INPUT") #Daniele
226            try:
227                self.sourceSeed = int(cfg_params['CMSSW.pythia_seed'])
228            except KeyError:
229                self.sourceSeed = 123456
230                common.logger.message("No seed given, will use "+str(self.sourceSeed))
231        
232        self.PsetEdit.psetWriter(self.configFilename())
216      
217          ## Select Splitting
218 <        if self.selectFilesPerJob: self.jobSplittingPerFiles()
219 <        elif self.selectEventsPerJob: self.jobSplittingPerEvents()
220 <        else:
221 <            msg = 'Don\'t know how to split...'
222 <            raise CrabException(msg)
218 >        if self.selectNoInput:
219 >            if self.pset == None: #CarlosDaniele
220 >                self.jobSplittingForScript()
221 >            else:
222 >                self.jobSplittingNoInput()
223 >        else: self.jobSplittingByBlocks(blockSites)
224  
225 +        # modify Pset
226 +        if self.pset != None: #CarlosDaniele
227 +            try:
228 +                if (self.datasetPath): # standard job
229 +                    # allow to processa a fraction of events in a file
230 +                    self.PsetEdit.inputModule("INPUT")
231 +                    self.PsetEdit.maxEvent("INPUTMAXEVENTS")
232 +                    self.PsetEdit.skipEvent("INPUTSKIPEVENTS")
233 +                else:  # pythia like job
234 +                    self.PsetEdit.maxEvent(self.eventsPerJob)
235 +                    if (self.sourceSeed) :
236 +                        self.PsetEdit.pythiaSeed("INPUT")
237 +                        if (self.sourceSeedVtx) :
238 +                            self.PsetEdit.pythiaSeedVtx("INPUTVTX")
239 +                self.PsetEdit.psetWriter(self.configFilename())
240 +            except:
241 +                msg='Error while manipuliating ParameterSet: exiting...'
242 +                raise CrabException(msg)
243  
244      def DataDiscoveryAndLocation(self, cfg_params):
245  
# Line 250 | Line 252 | class Cmssw(JobType):
252          dataTiers = dataTiersList.split(',')
253  
254          ## Contact the DBS
255 +        common.logger.message("Contacting DBS...")
256          try:
257 <            self.pubdata=DataDiscovery_EDM.DataDiscovery_EDM(datasetPath, dataTiers, cfg_params)
257 >            self.pubdata=DataDiscovery.DataDiscovery(datasetPath, dataTiers, cfg_params)
258              self.pubdata.fetchDBSInfo()
259  
260 <        except DataDiscovery_EDM.NotExistingDatasetError, ex :
260 >        except DataDiscovery.NotExistingDatasetError, ex :
261              msg = 'ERROR ***: failed Data Discovery in DBS : %s'%ex.getErrorMessage()
262              raise CrabException(msg)
263  
264 <        except DataDiscovery_EDM.NoDataTierinProvenanceError, ex :
264 >        except DataDiscovery.NoDataTierinProvenanceError, ex :
265              msg = 'ERROR ***: failed Data Discovery in DBS : %s'%ex.getErrorMessage()
266              raise CrabException(msg)
267 <        except DataDiscovery_EDM.DataDiscoveryError, ex:
267 >        except DataDiscovery.DataDiscoveryError, ex:
268              msg = 'ERROR ***: failed Data Discovery in DBS  %s'%ex.getErrorMessage()
269              raise CrabException(msg)
270  
# Line 269 | Line 272 | class Cmssw(JobType):
272          ## self.DBSPaths=self.pubdata.getDBSPaths()
273          common.logger.message("Required data are :"+self.datasetPath)
274  
275 <        filesbyblock=self.pubdata.getFiles()
276 <        self.AllInputFiles=filesbyblock.values()
277 <        self.files = self.AllInputFiles        
278 <
279 <        ## TEMP
280 <    #    self.filesTmp = filesbyblock.values()
278 <    #    self.files = []
279 <    #    locPath='rfio:cmsbose2.bo.infn.it:/flatfiles/SE00/cms/fanfani/ProdTest/'
280 <    #    locPath=''
281 <    #    tmp = []
282 <    #    for file in self.filesTmp[0]:
283 <    #        tmp.append(locPath+file)
284 <    #    self.files.append(tmp)
285 <        ## END TEMP
275 >        self.filesbyblock=self.pubdata.getFiles()
276 >        self.eventsbyblock=self.pubdata.getEventsPerBlock()
277 >        self.eventsbyfile=self.pubdata.getEventsPerFile()
278 >        # print str(self.filesbyblock)
279 >        # print 'self.eventsbyfile',len(self.eventsbyfile)
280 >        # print str(self.eventsbyfile)
281  
282          ## get max number of events
288        #common.logger.debug(10,"number of events for primary fileblocks %i"%self.pubdata.getMaxEvents())
283          self.maxEvents=self.pubdata.getMaxEvents() ##  self.maxEvents used in Creator.py
284 <        common.logger.message("\nThe number of available events is %s"%self.maxEvents)
284 >        common.logger.message("The number of available events is %s\n"%self.maxEvents)
285  
286 +        common.logger.message("Contacting DLS...")
287          ## Contact the DLS and build a list of sites hosting the fileblocks
288          try:
289 <            dataloc=DataLocation_EDM.DataLocation_EDM(filesbyblock.keys(),cfg_params)
289 >            dataloc=DataLocation.DataLocation(self.filesbyblock.keys(),cfg_params)
290              dataloc.fetchDLSInfo()
291 <        except DataLocation_EDM.DataLocationError , ex:
291 >        except DataLocation.DataLocationError , ex:
292              msg = 'ERROR ***: failed Data Location in DLS \n %s '%ex.getErrorMessage()
293              raise CrabException(msg)
294          
300        allsites=dataloc.getSites()
301        common.logger.debug(5,"sites are %s"%allsites)
302        sites=self.checkBlackList(allsites)
303        common.logger.debug(5,"sites are (after black list) %s"%sites)
304        sites=self.checkWhiteList(sites)
305        common.logger.debug(5,"sites are (after white list) %s"%sites)
295  
296 <        if len(sites)==0:
297 <            msg = 'No sites hosting all the needed data! Exiting... '
298 <            raise CrabException(msg)
296 >        sites = dataloc.getSites()
297 >        allSites = []
298 >        listSites = sites.values()
299 >        for list in listSites:
300 >            for oneSite in list:
301 >                allSites.append(oneSite)
302 >        allSites = self.uniquelist(allSites)
303  
304 <        common.logger.message("List of Sites hosting the data : "+str(sites))
305 <        common.logger.debug(6, "List of Sites: "+str(sites))
306 <        common.analisys_common_info['sites']=sites    ## used in SchedulerEdg.py in createSchScript
314 <        self.setParam_('TargetCE', ','.join(sites))
315 <        return
304 >        common.logger.message("Sites ("+str(len(allSites))+") hosting part/all of dataset: "+str(allSites))
305 >        common.logger.debug(6, "List of Sites: "+str(allSites))
306 >        return sites
307      
308 <    def jobSplittingPerFiles(self):
308 >    def jobSplittingByBlocks(self, blockSites):
309          """
310 <        Perform job splitting based on number of files to be accessed per job
311 <        """
312 <        common.logger.debug(5,'Splitting per input files')
313 <        common.logger.message('Required '+str(self.filesPerJob)+' files per job ')
314 <        common.logger.message('Required '+str(self.total_number_of_events)+' events in total ')
315 <
316 <        ## TODO: SL need to have (from DBS) a detailed list of how many events per each file
317 <        n_tot_files = (len(self.files[0]))
318 <        #print "n_tot_files = ", n_tot_files
319 <        ## SL: this is wrong if the files have different number of events
320 <        #print "self.maxEvents = ", self.maxEvents
321 <        evPerFile = int(self.maxEvents)/n_tot_files
322 <        #print "evPerFile = int(self.maxEvents)/n_tot_files =  ", evPerFile
323 <
324 <        common.logger.debug(5,'Events per File '+str(evPerFile))
325 <
326 <        ## if asked to process all events, do it
327 <        if self.total_number_of_events == -1:
328 <            self.total_number_of_events=self.maxEvents
329 <            self.total_number_of_jobs = int(n_tot_files)*1/int(self.filesPerJob)
330 <            check = int(n_tot_files) - (int(self.total_number_of_jobs)*self.filesPerJob)
331 <            if check > 0:
332 <                self.total_number_of_jobs =  self.total_number_of_jobs + 1
333 <                common.logger.message('Warning: last job will be created with '+str(check)+' files')
334 <            common.logger.message(str(self.total_number_of_jobs)+' jobs will be created for all available events '+str(self.total_number_of_events)+' events')
335 <        
310 >        Perform job splitting. Jobs run over an integer number of files
311 >        and no more than one block.
312 >        ARGUMENT: blockSites: dictionary with blocks as keys and list of host sites as values
313 >        REQUIRES: self.selectTotalNumberEvents, self.selectEventsPerJob, self.selectNumberofJobs,
314 >                  self.total_number_of_events, self.eventsPerJob, self.theNumberOfJobs,
315 >                  self.maxEvents, self.filesbyblock
316 >        SETS: self.jobDestination - Site destination(s) for each job (a list of lists)
317 >              self.total_number_of_jobs - Total # of jobs
318 >              self.list_of_args - File(s) job will run on (a list of lists)
319 >        """
320 >
321 >        # ---- Handle the possible job splitting configurations ---- #
322 >        if (self.selectTotalNumberEvents):
323 >            totalEventsRequested = self.total_number_of_events
324 >        if (self.selectEventsPerJob):
325 >            eventsPerJobRequested = self.eventsPerJob
326 >            if (self.selectNumberOfJobs):
327 >                totalEventsRequested = self.theNumberOfJobs * self.eventsPerJob
328 >
329 >        # If user requested all the events in the dataset
330 >        if (totalEventsRequested == -1):
331 >            eventsRemaining=self.maxEvents
332 >        # If user requested more events than are in the dataset
333 >        elif (totalEventsRequested > self.maxEvents):
334 >            eventsRemaining = self.maxEvents
335 >            common.logger.message("Requested "+str(self.total_number_of_events)+ " events, but only "+str(self.maxEvents)+" events are available.")
336 >        # If user requested less events than are in the dataset
337          else:
338 <            #print "self.total_number_of_events = ", self.total_number_of_events
339 <            #print "evPerFile = ", evPerFile
340 <            self.total_number_of_files = int(self.total_number_of_events/evPerFile)
341 <            #print "self.total_number_of_files = int(self.total_number_of_events/evPerFile) = " , self.total_number_of_files
342 <
343 <            ## SL: round the number of files to be processed to the ceiling
344 <            rem = self.total_number_of_events - self.total_number_of_files*evPerFile
345 <            if rem>0:
354 <                self.total_number_of_files = self.total_number_of_files + 1
355 <
356 <            ## SL: if ask for less event than what is computed to be available on a
357 <            ##     file, process the first file anyhow.
358 <            if self.total_number_of_files == 0:
359 <                self.total_number_of_files = self.total_number_of_files + 1
360 <                
338 >            eventsRemaining = totalEventsRequested
339 >
340 >        # If user requested more events per job than are in the dataset
341 >        if (self.selectEventsPerJob and eventsPerJobRequested > self.maxEvents):
342 >            eventsPerJobRequested = self.maxEvents
343 >
344 >        # For user info at end
345 >        totalEventCount = 0
346  
347 <            common.logger.debug(5,'N files  '+str(self.total_number_of_files))
347 >        if (self.selectTotalNumberEvents and self.selectNumberOfJobs):
348 >            eventsPerJobRequested = int(eventsRemaining/self.theNumberOfJobs)
349  
350 <            check = 0
350 >        if (self.selectNumberOfJobs):
351 >            common.logger.message("May not create the exact number_of_jobs requested.")
352 >
353 >        if ( self.ncjobs == 'all' ) :
354 >            totalNumberOfJobs = 999999999
355 >        else :
356 >            totalNumberOfJobs = self.ncjobs
357              
366            ## Compute the number of jobs
367            #self.total_number_of_jobs = int(n_tot_files)*1/int(self.filesPerJob)
368            #print "self.total_number_of_files = ", self.total_number_of_files
369            #print "self.filesPerJob = ", self.filesPerJob
370            self.total_number_of_jobs = int(self.total_number_of_files/self.filesPerJob)
371            #print "self.total_number_of_jobs = ", self.total_number_of_jobs
372            common.logger.debug(5,'N jobs  '+str(self.total_number_of_jobs))
373
374            ## is there any remainder?
375            check = int(self.total_number_of_files) - (int(self.total_number_of_jobs)*self.filesPerJob)
376
377            common.logger.debug(5,'Check  '+str(check))
378
379            if check > 0:
380                self.total_number_of_jobs =  self.total_number_of_jobs + 1
381                common.logger.message('Warning: last job will be created with '+str(check)+' files')
358  
359 <            common.logger.message(str(self.total_number_of_jobs)+' jobs will be created for a total of '+str((self.total_number_of_jobs-check)*self.filesPerJob*evPerFile + check*evPerFile)+' events')
360 <            pass
359 >        blocks = blockSites.keys()
360 >        blockCount = 0
361 >        # Backup variable in case self.maxEvents counted events in a non-included block
362 >        numBlocksInDataset = len(blocks)
363  
364 +        jobCount = 0
365          list_of_lists = []
366 <        for i in xrange(0, int(n_tot_files), self.filesPerJob):
367 <            parString = "\\{"
368 <            
369 <            params = self.files[0][i: i+self.filesPerJob]
370 <            for i in range(len(params) - 1):
371 <                parString += '\\\"' + params[i] + '\\\"\,'
366 >
367 >        # ---- Iterate over the blocks in the dataset until ---- #
368 >        # ---- we've met the requested total # of events    ---- #
369 >        while ( (eventsRemaining > 0) and (blockCount < numBlocksInDataset) and (jobCount < totalNumberOfJobs)):
370 >            block = blocks[blockCount]
371 >            blockCount += 1
372              
394            parString += '\\\"' + params[len(params) - 1] + '\\\"\\}'
395            #print parString
396            list_of_lists.append([parString])
397            #print list_of_lists
398            pass
373  
374 +            numEventsInBlock = self.eventsbyblock[block]
375 +            common.logger.debug(5,'Events in Block File '+str(numEventsInBlock))
376 +            
377 +            files = self.filesbyblock[block]
378 +            numFilesInBlock = len(files)
379 +            if (numFilesInBlock <= 0):
380 +                continue
381 +            fileCount = 0
382 +
383 +            # ---- New block => New job ---- #
384 +            parString = "\\{"
385 +            # counter for number of events in files currently worked on
386 +            filesEventCount = 0
387 +            # flag if next while loop should touch new file
388 +            newFile = 1
389 +            # job event counter
390 +            jobSkipEventCount = 0
391 +            
392 +            # ---- Iterate over the files in the block until we've met the requested ---- #
393 +            # ---- total # of events or we've gone over all the files in this block  ---- #
394 +            while ( (eventsRemaining > 0) and (fileCount < numFilesInBlock) and (jobCount < totalNumberOfJobs) ):
395 +                file = files[fileCount]
396 +                if newFile :
397 +                    try:
398 +                        numEventsInFile = self.eventsbyfile[file]
399 +                        common.logger.debug(6, "File "+str(file)+" has "+str(numEventsInFile)+" events")
400 +                        # increase filesEventCount
401 +                        filesEventCount += numEventsInFile
402 +                        # Add file to current job
403 +                        parString += '\\\"' + file + '\\\"\,'
404 +                        newFile = 0
405 +                    except KeyError:
406 +                        common.logger.message("File "+str(file)+" has unknown number of events: skipping")
407 +                        
408 +
409 +                # if less events in file remain than eventsPerJobRequested
410 +                if ( filesEventCount - jobSkipEventCount < eventsPerJobRequested ) :
411 +                    # if last file in block
412 +                    if ( fileCount == numFilesInBlock-1 ) :
413 +                        # end job using last file, use remaining events in block
414 +                        # close job and touch new file
415 +                        fullString = parString[:-2]
416 +                        fullString += '\\}'
417 +                        list_of_lists.append([fullString,str(-1),str(jobSkipEventCount)])
418 +                        common.logger.debug(3,"Job "+str(jobCount+1)+" can run over "+str(filesEventCount - jobSkipEventCount)+" events (last file in block).")
419 +                        self.jobDestination.append(blockSites[block])
420 +                        common.logger.debug(5,"Job "+str(jobCount+1)+" Destination: "+str(self.jobDestination[jobCount]))
421 +                        # reset counter
422 +                        jobCount = jobCount + 1
423 +                        totalEventCount = totalEventCount + filesEventCount - jobSkipEventCount
424 +                        eventsRemaining = eventsRemaining - filesEventCount + jobSkipEventCount
425 +                        jobSkipEventCount = 0
426 +                        # reset file
427 +                        parString = "\\{"
428 +                        filesEventCount = 0
429 +                        newFile = 1
430 +                        fileCount += 1
431 +                    else :
432 +                        # go to next file
433 +                        newFile = 1
434 +                        fileCount += 1
435 +                # if events in file equal to eventsPerJobRequested
436 +                elif ( filesEventCount - jobSkipEventCount == eventsPerJobRequested ) :
437 +                    # close job and touch new file
438 +                    fullString = parString[:-2]
439 +                    fullString += '\\}'
440 +                    list_of_lists.append([fullString,str(eventsPerJobRequested),str(jobSkipEventCount)])
441 +                    common.logger.debug(3,"Job "+str(jobCount+1)+" can run over "+str(eventsPerJobRequested)+" events.")
442 +                    self.jobDestination.append(blockSites[block])
443 +                    common.logger.debug(5,"Job "+str(jobCount+1)+" Destination: "+str(self.jobDestination[jobCount]))
444 +                    # reset counter
445 +                    jobCount = jobCount + 1
446 +                    totalEventCount = totalEventCount + eventsPerJobRequested
447 +                    eventsRemaining = eventsRemaining - eventsPerJobRequested
448 +                    jobSkipEventCount = 0
449 +                    # reset file
450 +                    parString = "\\{"
451 +                    filesEventCount = 0
452 +                    newFile = 1
453 +                    fileCount += 1
454 +                    
455 +                # if more events in file remain than eventsPerJobRequested
456 +                else :
457 +                    # close job but don't touch new file
458 +                    fullString = parString[:-2]
459 +                    fullString += '\\}'
460 +                    list_of_lists.append([fullString,str(eventsPerJobRequested),str(jobSkipEventCount)])
461 +                    common.logger.debug(3,"Job "+str(jobCount+1)+" can run over "+str(eventsPerJobRequested)+" events.")
462 +                    self.jobDestination.append(blockSites[block])
463 +                    common.logger.debug(5,"Job "+str(jobCount+1)+" Destination: "+str(self.jobDestination[jobCount]))
464 +                    # increase counter
465 +                    jobCount = jobCount + 1
466 +                    totalEventCount = totalEventCount + eventsPerJobRequested
467 +                    eventsRemaining = eventsRemaining - eventsPerJobRequested
468 +                    # calculate skip events for last file
469 +                    # use filesEventCount (contains several files), jobSkipEventCount and eventsPerJobRequest
470 +                    jobSkipEventCount = eventsPerJobRequested - (filesEventCount - jobSkipEventCount - self.eventsbyfile[file])
471 +                    # remove all but the last file
472 +                    filesEventCount = self.eventsbyfile[file]
473 +                    parString = "\\{"
474 +                    parString += '\\\"' + file + '\\\"\,'
475 +                pass # END if
476 +            pass # END while (iterate over files in the block)
477 +        pass # END while (iterate over blocks in the dataset)
478 +        self.ncjobs = self.total_number_of_jobs = jobCount
479 +        if (eventsRemaining > 0 and jobCount < totalNumberOfJobs ):
480 +            common.logger.message("Could not run on all requested events because some blocks not hosted at allowed sites.")
481 +        common.logger.message("\n"+str(jobCount)+" job(s) can run on "+str(totalEventCount)+" events.\n")
482 +        
483          self.list_of_args = list_of_lists
401 #        print self.list_of_args
484          return
485  
486 <    def jobSplittingPerEvents(self):
486 >    def jobSplittingNoInput(self):
487          """
488          Perform job splitting based on number of event per job
489          """
490          common.logger.debug(5,'Splitting per events')
491          common.logger.message('Required '+str(self.eventsPerJob)+' events per job ')
492 +        common.logger.message('Required '+str(self.theNumberOfJobs)+' jobs in total ')
493          common.logger.message('Required '+str(self.total_number_of_events)+' events in total ')
494  
495          if (self.total_number_of_events < 0):
496              msg='Cannot split jobs per Events with "-1" as total number of events'
497              raise CrabException(msg)
498  
499 <        self.total_number_of_jobs = int(self.total_number_of_events/self.eventsPerJob)
499 >        if (self.selectEventsPerJob):
500 >            self.total_number_of_jobs = int(self.total_number_of_events/self.eventsPerJob)
501 >        elif (self.selectNumberOfJobs) :
502 >            self.total_number_of_jobs = self.theNumberOfJobs
503 >            self.eventsPerJob = int(self.total_number_of_events/self.total_number_of_jobs)
504  
418        # print "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
419        # print "self.total_number_of_events = ", self.total_number_of_events
420        # print "self.eventsPerJob = ", self.eventsPerJob
421        # print "self.total_number_of_jobs = ", self.total_number_of_jobs
422        # print "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
423        
505          common.logger.debug(5,'N jobs  '+str(self.total_number_of_jobs))
506  
507          # is there any remainder?
# Line 428 | Line 509 | class Cmssw(JobType):
509  
510          common.logger.debug(5,'Check  '+str(check))
511  
512 +        common.logger.message(str(self.total_number_of_jobs)+' jobs can be created, each for '+str(self.eventsPerJob)+' for a total of '+str(self.total_number_of_jobs*self.eventsPerJob)+' events')
513          if check > 0:
514 <            common.logger.message('Warning: asked '+self.total_number_of_events+' but will do only '+(int(self.total_number_of_jobs)*self.eventsPerJob))
433 <
434 <        common.logger.message(str(self.total_number_of_jobs)+' jobs will be created for a total of '+str(self.total_number_of_jobs*self.eventsPerJob)+' events')
514 >            common.logger.message('Warning: asked '+str(self.total_number_of_events)+' but can do only '+str(int(self.total_number_of_jobs)*self.eventsPerJob))
515  
516          # argument is seed number.$i
517          self.list_of_args = []
518          for i in range(self.total_number_of_jobs):
519 <            self.list_of_args.append([int(str(self.sourceSeed)+str(i))])
519 >            ## Since there is no input, any site is good
520 >           # self.jobDestination.append(["Any"])
521 >            self.jobDestination.append([""]) #must be empty to write correctly the xml
522 >            if (self.sourceSeed):
523 >                if (self.sourceSeedVtx):
524 >                    ## pythia + vtx random seed
525 >                    self.list_of_args.append([
526 >                                              str(self.sourceSeed)+str(i),
527 >                                              str(self.sourceSeedVtx)+str(i)
528 >                                              ])
529 >                else:
530 >                    ## only pythia random seed
531 >                    self.list_of_args.append([(str(self.sourceSeed)+str(i))])
532 >            else:
533 >                ## no random seed
534 >                self.list_of_args.append([str(i)])
535          #print self.list_of_args
536  
537          return
538  
539 +
540 +    def jobSplittingForScript(self):#CarlosDaniele
541 +        """
542 +        Perform job splitting based on number of job
543 +        """
544 +        common.logger.debug(5,'Splitting per job')
545 +        common.logger.message('Required '+str(self.theNumberOfJobs)+' jobs in total ')
546 +
547 +        self.total_number_of_jobs = self.theNumberOfJobs
548 +
549 +        common.logger.debug(5,'N jobs  '+str(self.total_number_of_jobs))
550 +
551 +        common.logger.message(str(self.total_number_of_jobs)+' jobs can be created')
552 +
553 +        # argument is seed number.$i
554 +        self.list_of_args = []
555 +        for i in range(self.total_number_of_jobs):
556 +            ## Since there is no input, any site is good
557 +           # self.jobDestination.append(["Any"])
558 +            self.jobDestination.append([""])
559 +            ## no random seed
560 +            self.list_of_args.append([str(i)])
561 +        return
562 +
563      def split(self, jobParams):
564  
565          common.jobDB.load()
# Line 456 | Line 575 | class Cmssw(JobType):
575              # print str(arglist[job])
576              # print jobParams[job]
577              common.jobDB.setArguments(job, jobParams[job])
578 +            common.logger.debug(5,"Job "+str(job)+" Destination: "+str(self.jobDestination[job]))
579 +            common.jobDB.setDestination(job, self.jobDestination[job])
580  
581          common.jobDB.save()
582          return
# Line 470 | Line 591 | class Cmssw(JobType):
591          # Fabio
592          return self.total_number_of_jobs
593  
473    def checkBlackList(self, allSites):
474        if len(self.reCEBlackList)==0: return allSites
475        sites = []
476        for site in allSites:
477            common.logger.debug(10,'Site '+site)
478            good=1
479            for re in self.reCEBlackList:
480                if re.search(site):
481                    common.logger.message('CE in black list, skipping site '+site)
482                    good=0
483                pass
484            if good: sites.append(site)
485        if len(sites) == 0:
486            common.logger.debug(3,"No sites found after BlackList")
487        return sites
488
489    def checkWhiteList(self, allSites):
490
491        if len(self.reCEWhiteList)==0: return allSites
492        sites = []
493        for site in allSites:
494            good=0
495            for re in self.reCEWhiteList:
496                if re.search(site):
497                    common.logger.debug(5,'CE in white list, adding site '+site)
498                    good=1
499                if not good: continue
500                sites.append(site)
501        if len(sites) == 0:
502            common.logger.message("No sites found after WhiteList\n")
503        else:
504            common.logger.debug(5,"Selected sites via WhiteList are "+str(sites)+"\n")
505        return sites
506
594      def getTarBall(self, exe):
595          """
596          Return the TarBall with lib and exe
# Line 599 | Line 686 | class Cmssw(JobType):
686          txt += 'if [ $middleware == LCG ]; then \n'
687          txt += self.wsSetupCMSLCGEnvironment_()
688          txt += 'elif [ $middleware == OSG ]; then\n'
689 <        txt += '    time=`date -u +"%s"`\n'
690 <        txt += '    WORKING_DIR=$OSG_WN_TMP/cms_$time\n'
604 <        txt += '    echo "Creating working directory: $WORKING_DIR"\n'
605 <        txt += '    /bin/mkdir -p $WORKING_DIR\n'
689 >        txt += '    WORKING_DIR=`/bin/mktemp  -d $OSG_WN_TMP/cms_XXXXXXXXXXXX`\n'
690 >        txt += '    echo "Created working directory: $WORKING_DIR"\n'
691          txt += '    if [ ! -d $WORKING_DIR ] ;then\n'
692          txt += '        echo "SET_CMS_ENV 10016 ==> OSG $WORKING_DIR could not be created on WN `hostname`"\n'
693          txt += '        echo "JOB_EXIT_STATUS = 10016"\n'
# Line 659 | Line 744 | class Cmssw(JobType):
744          txt += "\n"
745          txt += "## number of arguments (first argument always jobnumber)\n"
746          txt += "\n"
747 <        txt += "narg=$#\n"
748 <        txt += "if [ $narg -lt 2 ]\n"
747 > #        txt += "narg=$#\n"
748 >        txt += "if [ $nargs -lt 2 ]\n"
749          txt += "then\n"
750 <        txt += "    echo 'SET_EXE_ENV 1 ==> ERROR Too few arguments' +$narg+ \n"
750 >        txt += "    echo 'SET_EXE_ENV 1 ==> ERROR Too few arguments' +$nargs+ \n"
751          txt += '    echo "JOB_EXIT_STATUS = 50113"\n'
752          txt += '    echo "JobExitCode=50113" | tee -a $RUNTIME_AREA/$repo\n'
753          txt += '    dumpStatus $RUNTIME_AREA/$repo\n'
# Line 690 | Line 775 | class Cmssw(JobType):
775  
776          # Prepare job-specific part
777          job = common.job_list[nj]
778 <        pset = os.path.basename(job.configFilename())
779 <        txt += '\n'
780 <        if (self.datasetPath): # standard job
781 <            txt += 'InputFiles=$2\n'
782 <            txt += 'echo "Inputfiles:<$InputFiles>"\n'
783 <            txt += 'sed "s#{\'INPUT\'}#$InputFiles#" $RUNTIME_AREA/'+pset+' > pset.cfg\n'
784 <        else:  # pythia like job
785 <            txt += 'Seed=$2\n'
786 <            txt += 'echo "Seed: <$Seed>"\n'
787 <            txt += 'sed "s#INPUT#$Seed#" $RUNTIME_AREA/'+pset+' > pset.cfg\n'
778 >        if self.pset != None: #CarlosDaniele
779 >            pset = os.path.basename(job.configFilename())
780 >            txt += '\n'
781 >            if (self.datasetPath): # standard job
782 >                #txt += 'InputFiles=$2\n'
783 >                txt += 'InputFiles=${args[1]}\n'
784 >                txt += 'MaxEvents=${args[2]}\n'
785 >                txt += 'SkipEvents=${args[3]}\n'
786 >                txt += 'echo "Inputfiles:<$InputFiles>"\n'
787 >                txt += 'sed "s#{\'INPUT\'}#$InputFiles#" $RUNTIME_AREA/'+pset+' > pset_tmp_1.cfg\n'
788 >                txt += 'echo "MaxEvents:<$MaxEvents>"\n'
789 >                txt += 'sed "s#INPUTMAXEVENTS#$MaxEvents#" pset_tmp_1.cfg > pset_tmp_2.cfg\n'
790 >                txt += 'echo "SkipEvents:<$SkipEvents>"\n'
791 >                txt += 'sed "s#INPUTSKIPEVENTS#$SkipEvents#" pset_tmp_2.cfg > pset.cfg\n'
792 >            else:  # pythia like job
793 >                if (self.sourceSeed):
794 > #                    txt += 'Seed=$2\n'
795 >                    txt += 'Seed=${args[1]}\n'
796 >                    txt += 'echo "Seed: <$Seed>"\n'
797 >                    txt += 'sed "s#\<INPUT\>#$Seed#" $RUNTIME_AREA/'+pset+' > tmp.cfg\n'
798 >                    if (self.sourceSeedVtx):
799 > #                        txt += 'VtxSeed=$3\n'
800 >                        txt += 'VtxSeed=${args[2]}\n'
801 >                        txt += 'echo "VtxSeed: <$VtxSeed>"\n'
802 >                        txt += 'sed "s#INPUTVTX#$VtxSeed#" tmp.cfg > pset.cfg\n'
803 >                    else:
804 >                        txt += 'mv tmp.cfg pset.cfg\n'
805 >                else:
806 >                    txt += '# Copy untouched pset\n'
807 >                    txt += 'cp $RUNTIME_AREA/'+pset+' pset.cfg\n'
808 >
809  
810          if len(self.additional_inbox_files) > 0:
811              for file in self.additional_inbox_files:
812 <                txt += 'if [ -e $RUNTIME_AREA/'+file+' ] ; then\n'
813 <                txt += '   cp $RUNTIME_AREA/'+file+' .\n'
814 <                txt += '   chmod +x '+file+'\n'
812 >                relFile = file.split("/")[-1]
813 >                txt += 'if [ -e $RUNTIME_AREA/'+relFile+' ] ; then\n'
814 >                txt += '   cp $RUNTIME_AREA/'+relFile+' .\n'
815 >                txt += '   chmod +x '+relFile+'\n'
816                  txt += 'fi\n'
817              pass
818  
819 <        txt += 'echo "### END JOB SETUP ENVIRONMENT ###"\n\n'
820 <
821 <        txt += '\n'
822 <        txt += 'echo "***** cat pset.cfg *********"\n'
823 <        txt += 'cat pset.cfg\n'
824 <        txt += 'echo "****** end pset.cfg ********"\n'
825 <        txt += '\n'
826 <        # txt += 'echo "***** cat pset1.cfg *********"\n'
827 <        # txt += 'cat pset1.cfg\n'
828 <        # txt += 'echo "****** end pset1.cfg ********"\n'
819 >        if self.pset != None: #CarlosDaniele
820 >            txt += 'echo "### END JOB SETUP ENVIRONMENT ###"\n\n'
821 >        
822 >            txt += '\n'
823 >            txt += 'echo "***** cat pset.cfg *********"\n'
824 >            txt += 'cat pset.cfg\n'
825 >            txt += 'echo "****** end pset.cfg ********"\n'
826 >            txt += '\n'
827 >            # txt += 'echo "***** cat pset1.cfg *********"\n'
828 >            # txt += 'cat pset1.cfg\n'
829 >            # txt += 'echo "****** end pset1.cfg ********"\n'
830          return txt
831  
832      def wsBuildExe(self, nj):
# Line 767 | Line 875 | class Cmssw(JobType):
875          """
876          
877      def executableName(self):
878 <        return self.executable
878 >        if self.pset == None: #CarlosDaniele
879 >            return "sh "
880 >        else:
881 >            return self.executable
882  
883      def executableArgs(self):
884 <        return " -p pset.cfg"
884 >        if self.pset == None:#CarlosDaniele
885 >            return   self.scriptExe + " $NJob"
886 >        else:
887 >            return " -p pset.cfg"
888  
889      def inputSandbox(self, nj):
890          """
# Line 783 | Line 897 | class Cmssw(JobType):
897          if os.path.isfile(self.tgzNameWithPath):
898              inp_box.append(self.tgzNameWithPath)
899          ## config
900 <        inp_box.append(common.job_list[nj].configFilename())
900 >        if not self.pset is None: #CarlosDaniele
901 >            inp_box.append(common.job_list[nj].configFilename())
902          ## additional input files
903          #for file in self.additional_inbox_files:
904          #    inp_box.append(common.work_space.cwdDir()+file)
# Line 826 | Line 941 | class Cmssw(JobType):
941              txt += '\n'
942              txt += '# check output file\n'
943              txt += 'ls '+fileWithSuffix+'\n'
944 <            txt += 'exe_result=$?\n'
945 <            txt += 'if [ $exe_result -ne 0 ] ; then\n'
946 <            txt += '   echo "ERROR: No output file to manage"\n'
947 <            txt += '   echo "JOB_EXIT_STATUS = $exe_result"\n'
948 <            txt += '   echo "JobExitCode=60302" | tee -a $RUNTIME_AREA/$repo\n'
949 <            txt += '   dumpStatus $RUNTIME_AREA/$repo\n'
950 <            txt += '   rm -f $RUNTIME_AREA/$repo \n'
836 <            txt += '   echo "MonitorJobID=`echo $MonitorJobID`" | tee -a $RUNTIME_AREA/$repo \n'
837 <            txt += '   echo "MonitorID=`echo $MonitorID`" | tee -a $RUNTIME_AREA/$repo\n'
944 >            txt += 'ls_result=$?\n'
945 >            #txt += 'exe_result=$?\n'
946 >            txt += 'if [ $ls_result -ne 0 ] ; then\n'
947 >            txt += '   echo "ERROR: Problem with output file"\n'
948 >            #txt += '   echo "JOB_EXIT_STATUS = $exe_result"\n'
949 >            #txt += '   echo "JobExitCode=60302" | tee -a $RUNTIME_AREA/$repo\n'
950 >            #txt += '   dumpStatus $RUNTIME_AREA/$repo\n'
951              ### OLI_DANIELE
952              if common.scheduler.boss_scheduler_name == 'condor_g':
953                  txt += '    if [ $middleware == OSG ]; then \n'
# Line 848 | Line 961 | class Cmssw(JobType):
961          txt += 'cd $RUNTIME_AREA\n'
962          file_list=file_list[:-1]
963          txt += 'file_list="'+file_list+'"\n'
964 +        txt += 'cd $RUNTIME_AREA\n'
965          ### OLI_DANIELE
966          txt += 'if [ $middleware == OSG ]; then\n'  
967          txt += '    cd $RUNTIME_AREA\n'
# Line 878 | Line 992 | class Cmssw(JobType):
992          # add "_txt"
993          if len(p)>1:
994            ext = p[len(p)-1]
881          #result = name + '_' + str(txt) + "." + ext
995            result = name + '_' + txt + "." + ext
996          else:
884          #result = name + '_' + str(txt)
997            result = name + '_' + txt
998          
999          return result
# Line 891 | Line 1003 | class Cmssw(JobType):
1003          return job requirements to add to jdl files
1004          """
1005          req = ''
1006 <        if common.analisys_common_info['sw_version']:
1006 >        if self.version:
1007              req='Member("VO-cms-' + \
1008 <                 common.analisys_common_info['sw_version'] + \
1008 >                 self.version + \
1009                   '", other.GlueHostApplicationSoftwareRunTimeEnvironment)'
1010 <        if common.analisys_common_info['sites']:
1011 <            if len(common.analisys_common_info['sites'])>0:
1012 <                req = req + ' && ('
901 <                for i in range(len(common.analisys_common_info['sites'])):
902 <                    req = req + 'other.GlueCEInfoHostName == "' \
903 <                         + common.analisys_common_info['sites'][i] + '"'
904 <                    if ( i < (int(len(common.analisys_common_info['sites']) - 1)) ):
905 <                        req = req + ' || '
906 <            req = req + ')'
907 <        #print "req = ", req
1010 >
1011 >        req = req + ' && (other.GlueHostNetworkAdapterOutboundIP)'
1012 >
1013          return req
1014  
1015      def configFilename(self):
# Line 922 | Line 1027 | class Cmssw(JobType):
1027          txt += '   if [ -f $GRID3_APP_DIR/cmssoft/cmsset_default.sh ] ;then\n'
1028          txt += '      # Use $GRID3_APP_DIR/cmssoft/cmsset_default.sh to setup cms software\n'
1029          txt += '       source $GRID3_APP_DIR/cmssoft/cmsset_default.sh '+self.version+'\n'
1030 <        txt += '   elif [ -f $OSG_APP/cmssoft/cmsset_default.sh ] ;then\n'
1031 <        txt += '      # Use $OSG_APP/cmssoft/cmsset_default.sh to setup cms software\n'
1032 <        txt += '       source $OSG_APP/cmssoft/cmsset_default.sh '+self.version+'\n'
1030 >        txt += '   elif [ -f $OSG_APP/cmssoft/cms/cmsset_default.sh ] ;then\n'
1031 >        txt += '      # Use $OSG_APP/cmssoft/cms/cmsset_default.sh to setup cms software\n'
1032 >        txt += '       source $OSG_APP/cmssoft/cms/cmsset_default.sh '+self.version+'\n'
1033          txt += '   else\n'
1034 <        txt += '       echo "SET_CMS_ENV 10020 ==> ERROR $GRID3_APP_DIR/cmssoft/cmsset_default.sh and $OSG_APP/cmssoft/cmsset_default.sh file not found"\n'
1034 >        txt += '       echo "SET_CMS_ENV 10020 ==> ERROR $GRID3_APP_DIR/cmssoft/cmsset_default.sh and $OSG_APP/cmssoft/cms/cmsset_default.sh file not found"\n'
1035          txt += '       echo "JOB_EXIT_STATUS = 10020"\n'
1036          txt += '       echo "JobExitCode=10020" | tee -a $RUNTIME_AREA/$repo\n'
1037          txt += '       dumpStatus $RUNTIME_AREA/$repo\n'
# Line 939 | Line 1044 | class Cmssw(JobType):
1044          txt += '       cd $RUNTIME_AREA\n'
1045          txt += '       /bin/rm -rf $WORKING_DIR\n'
1046          txt += '       if [ -d $WORKING_DIR ] ;then\n'
1047 <        txt += '            echo "SET_CMS_ENV 10017 ==> OSG $WORKING_DIR could not be deleted on WN `hostname` after $GRID3_APP_DIR/cmssoft/cmsset_default.sh and $OSG_APP/cmssoft/cmsset_default.sh file not found"\n'
1047 >        txt += '            echo "SET_CMS_ENV 10017 ==> OSG $WORKING_DIR could not be deleted on WN `hostname` after $GRID3_APP_DIR/cmssoft/cmsset_default.sh and $OSG_APP/cmssoft/cms/cmsset_default.sh file not found"\n'
1048          txt += '            echo "JOB_EXIT_STATUS = 10017"\n'
1049          txt += '            echo "JobExitCode=10017" | tee -a $RUNTIME_AREA/$repo\n'
1050          txt += '            dumpStatus $RUNTIME_AREA/$repo\n'
# Line 1032 | Line 1137 | class Cmssw(JobType):
1137          
1138      def getTaskid(self):
1139          return self._taskId
1140 +
1141 + #######################################################################
1142 +    def uniquelist(self, old):
1143 +        """
1144 +        remove duplicates from a list
1145 +        """
1146 +        nd={}
1147 +        for e in old:
1148 +            nd[e]=0
1149 +        return nd.keys()

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines