3 The script compares two releases, generates SQLite3 database file with release
4 comparison information.
6 Author: Albertas Gimbutas, Vilnius University (LT)
7 e-mail: albertasgim@gmail.com
9 Note: default Pool size for file comparison is 7.
10 Note: did NOT finish static HTML generation implementation.
13 from datetime
import datetime
14 from multiprocessing
import Pool, Queue, Process
15 from subprocess
import call
16 from optparse
import OptionParser, OptionGroup
17 from os
import makedirs, remove
18 from os.path
import basename, join, exists
21 from compare_using_files_v2
import RootFileComparison
25 parser = OptionParser(usage=
'Usage: %prog --re1 RELEASE1 [--f1 FR,FR,..] ' +
26 '--re2 RELEASE2 [--f2 FR,FR,..] [--st ST_TESTS] [options]')
27 parser.add_option(
'--re1', action=
'store', dest=
'release1', default=
None,
28 help=
'First CMSSW release for release comparison, e.g. CMSSW_5_3_2_pre7.')
29 parser.add_option(
'--re2', action=
'store', dest=
'release2', default=
None,
30 help=
'Second CMSSW release for release comparison.')
31 parser.add_option(
'--f1', action=
'store', dest=
'fragments1', default=
'',
32 help=
'Comma separated filename fragments that have or have not to be ' +
33 'in RELEASE1 filenames. For "not include" use `!` before fragment, ' +
34 'e.g. `--f1 FullSim,!2012`.''')
35 parser.add_option('--f2', action='store', dest='fragments2', default='',
36 help='Comma separated filename fragments that have or have not to be ' +
37 'in RELEASE2 filenames. For "not include" use `!` before fragment.''')
39 optional_group = OptionGroup(parser,
'Optional')
40 optional_group.add_option(
'--st', action=
'store', dest=
'st_tests', default=
'KS',
41 help=
'Comma separated statistical tests to use. \nAvailable: KS, Chi2. Default: %default.')
42 optional_group.add_option(
'--title', action=
'store', dest=
'title', default=
None,
43 help=
'Release comparison title.')
44 optional_group.add_option(
'--dir', action=
'store', dest=
'dir', default=
None,
45 help=
'Directory to download and compare files in.')
46 optional_group.add_option(
'--url', action=
'store', dest=
'url', default=
None,
47 help=
'URL to fetch ROOT files from. File search is recursive ' +
48 'for links in given URL.')
49 optional_group.add_option(
'--no-url', action=
'store_true', dest=
'no_url', default=
False,
50 help=
'Search for files in DIR (specified by --dir option), ' +
51 'do NOT browse for files online.')
52 optional_group.add_option(
'--db', action=
'store', dest=
'db_name', default=
None,
53 help=
'SQLite3 .db filename to use for the comparison. Default: auto-generated SQLite3 .db file.')
54 optional_group.add_option(
'--cl', action=
'store_true', dest=
'clear_db', default=
False,
55 help=
'Clean DB before comparison.')
56 optional_group.add_option(
'--dry', action=
'store_true', dest=
'dry', default=
False,
57 help=
'Do not download or compare files, just show the progress.')
58 optional_group.add_option(
'--html', action=
'store_true', dest=
'html', default=
False,
59 help=
'Generate static html. Default: %default.')
60 parser.add_option_group(optional_group)
64 file1, file2, work_path, db_name, clear_db = args
65 command = [
'./compare_using_files_v2.py',
join(work_path, file1),
join(work_path, file2),
'--db', db_name]
67 command.append(
'--cl')
71 """Generates temporary database name."""
72 return '%s___%d.db' % (db_name.strip(
'.db'), i + 1)
75 conn = sqlite3.connect(main_db)
79 c.execute(
'''SELECT * FROM Directory limit 1;''')
80 directory_row = c.fetchall()
83 rel_cmp_offset, file_cmp_offset, directory_offset, hist_cmp_offset = 0, 0, 0, 0
85 c.execute(
'''SELECT count(*) FROM ReleaseComparison;''')
86 rel_cmp_offset = c.fetchone()[0]
87 c.execute(
'''SELECT count(*) FROM RootFileComparison;''')
88 file_cmp_offset = c.fetchone()[0]
89 c.execute(
'''SELECT max(id) FROM Directory;''')
90 directory_offset = c.fetchone()[0]
91 c.execute(
'''SELECT max(id) FROM HistogramComparison;''')
92 hist_cmp_offset = c.fetchone()[0]
96 ATTACH '{0}' AS partial;
99 INSERT INTO ReleaseComparison (title, release1, release2, statistical_test)
100 SELECT title, release1, release2, statistical_test FROM partial.ReleaseComparison;
102 INSERT INTO RootFileComparison (filename1, filename2, release_comparison_id, directory_id)
103 SELECT filename1, filename2, release_comparison_id+{1}, directory_id+{3} FROM partial.RootFileComparison;
105 INSERT INTO Directory (id, name, parent_id, from_histogram_id, till_histogram_id)
106 SELECT id+{3}, name, parent_id+{3}, from_histogram_id+{4}, till_histogram_id+{4} FROM partial.Directory;
108 INSERT INTO HistogramComparison (name, p_value, directory_id)
109 SELECT name, p_value, directory_id+{3} FROM partial.HistogramComparison;
111 COMMIT;""".
format(partial_db, rel_cmp_offset, file_cmp_offset, directory_offset, hist_cmp_offset))
114 c.execute(
'''SELECT max(id) FROM RootFileComparison;''')
115 max_file_cmp_id = c.fetchone()[0]
117 return max_file_cmp_id
121 """Generates release comparison information and stores it on SQLite3 .db file."""
122 def __init__(self, work_path=None, db_name=None, clear_db=False, dry=False, no_url=False, use_external=False):
131 conn = sqlite3.connect(self.
db_name)
133 c.execute(
'''SELECT id FROM ReleaseComparison WHERE release1=? AND
134 release2=? AND statistical_test=?''', (release1, release2, st_test_name))
135 release_comparison_id = c.fetchone()
137 if release_comparison_id:
138 return release_comparison_id[0]
141 def compare(self, rel1, frags1, rel2, frags2, st_tests, url=None, title=None):
142 print '\n################# Searching for files ###################'
144 print 'Searching for files on disk at %s' % (self.
work_path)
148 print 'Searching for files online at:'
151 files_with_urls1.update(files_with_urls2)
152 files1, files2 =
list(zip(*file_pairs))
153 paired_files_with_urls = [(file, files_with_urls1[file])
for file
in files1 + files2]
156 print 'DRY: nothing to do. Exiting.'
166 print '\n################### Preparing directory ###################'
167 print 'Creating working directory: %s ...' % self.
work_path,
171 print '\n################# Downloading the files ###################'
177 show_status_bar.q = q
178 auth_download_file.q = q
179 auth_download_file.work_dir = self.
work_path
181 Process(target=show_status_bar, args=(total_size,)).
start()
182 Pool(2).map(auth_download_file, files_to_download)
187 print '\n################# Preparing Database ###################'
192 print 'Clearing DB: %s...' % self.
db_name,
200 for st_test_name
in st_tests.split(
','):
201 print '\n################# Comparing Releases (%s) ###################' % st_test_name
202 st_test = tests[st_test_name]()
204 some_files_compared =
False
205 file_comparison_ids = []
209 self.
clear_db]
for i, pair
in enumerate(file_pairs)]
211 pool.map(call_compare_using_files, arg_list)
214 print '\n################# Merging DBs (%s) ###################' % st_test_name
215 for i, pair
in enumerate(file_pairs):
217 print 'Merging %s...' % (basename(tmp_db),),
221 some_files_compared =
True
225 for file1, file2
in file_pairs:
231 if not file_comparison.was_compared(file1, file2, st_test_name):
232 print "Comparing:\n%s\n%s\n" % (file1, file2)
233 file_comparison_id = file_comparison.compare(file1_path, file2_path, st_test)
234 file_comparison_ids.append(file_comparison_id)
235 some_files_compared =
True
237 print "Already compared:\n%s\n%s\n" % (file1, file2)
242 if some_files_compared:
243 release_comparison_id = self.
was_compared(release1, release2, st_test_name)
244 conn = sqlite3.connect(self.
db_name)
246 if not release_comparison_id:
247 print 'Inserting release "%s VS %s" description.\n' % (release1, release2)
249 title =
"%s__VS__%s" % (release1, release2)
250 c.execute(
'''INSERT INTO ReleaseComparison(title, release1, release2,
251 statistical_test) VALUES (?, ?, ?, ?)''', (title,
252 release1, release2, st_test_name))
253 release_comparison_id = c.lastrowid
254 c.executemany(
'''UPDATE RootFileComparison SET release_comparison_id = ?
255 WHERE id == ?''', [(release_comparison_id, fid)
for fid
in file_comparison_ids])
260 if __name__ ==
'__main__':
261 start = datetime.now()
262 opts, args = parser.parse_args()
263 if not opts.release1
or not opts.release2:
264 parser.error(
'Not all releases specified. Please check --re1 and --re2 options.')
266 rel_cmp =
ReleaseComparison(opts.dir, opts.db_name, opts.clear_db, opts.dry, opts.no_url, use_external=
True)
267 rel_cmp.compare(opts.release1, opts.fragments1, opts.release2,
268 opts.fragments2, opts.st_tests, opts.url, opts.title)
270 print '\n################# Generating static HTML #################'
271 print '\n Warrning!!! Did NOT finished the implementation. \n'
272 from Utilities.RelMon.web.dbfile2html
import dbfile2html
274 print '################# Execution time: %s #################\n' % (datetime.now() - start,)
def call_compare_using_files
use_external_script_to_compare_files
work_path
Create working directory if not given.
db_name
Download needed files.
static std::string join(char **cmd)
def recursive_search_online
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run