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. 12 from __future__
import print_function
14 from datetime
import datetime
15 from multiprocessing
import Pool, Queue, Process
16 from subprocess
import call
17 from optparse
import OptionParser, OptionGroup
18 from os
import makedirs, remove
19 from os.path
import basename, join, exists
22 from compare_using_files_v2
import RootFileComparison
26 parser = OptionParser(usage=
'Usage: %prog --re1 RELEASE1 [--f1 FR,FR,..] ' +
27 '--re2 RELEASE2 [--f2 FR,FR,..] [--st ST_TESTS] [options]')
28 parser.add_option(
'--re1', action=
'store', dest=
'release1', default=
None,
29 help=
'First CMSSW release for release comparison, e.g. CMSSW_5_3_2_pre7.')
30 parser.add_option(
'--re2', action=
'store', dest=
'release2', default=
None,
31 help=
'Second CMSSW release for release comparison.')
32 parser.add_option(
'--f1', action=
'store', dest=
'fragments1', default=
'',
33 help=
'Comma separated filename fragments that have or have not to be ' +
34 'in RELEASE1 filenames. For "not include" use `!` before fragment, ' +
35 'e.g. `--f1 FullSim,!2012`.''') 36 parser.add_option('--f2', action='store', dest='fragments2', default='', 37 help='Comma separated filename fragments that have or have not to be ' + 38 'in RELEASE2 filenames. For "not include" use `!` before fragment.''')
40 optional_group = OptionGroup(parser,
'Optional')
41 optional_group.add_option(
'--st', action=
'store', dest=
'st_tests', default=
'KS',
42 help=
'Comma separated statistical tests to use. \nAvailable: KS, Chi2. Default: %default.')
43 optional_group.add_option(
'--title', action=
'store', dest=
'title', default=
None,
44 help=
'Release comparison title.')
45 optional_group.add_option(
'--dir', action=
'store', dest=
'dir', default=
None,
46 help=
'Directory to download and compare files in.')
47 optional_group.add_option(
'--url', action=
'store', dest=
'url', default=
None,
48 help=
'URL to fetch ROOT files from. File search is recursive ' +
49 'for links in given URL.')
50 optional_group.add_option(
'--no-url', action=
'store_true', dest=
'no_url', default=
False,
51 help=
'Search for files in DIR (specified by --dir option), ' +
52 'do NOT browse for files online.')
53 optional_group.add_option(
'--db', action=
'store', dest=
'db_name', default=
None,
54 help=
'SQLite3 .db filename to use for the comparison. Default: auto-generated SQLite3 .db file.')
55 optional_group.add_option(
'--cl', action=
'store_true', dest=
'clear_db', default=
False,
56 help=
'Clean DB before comparison.')
57 optional_group.add_option(
'--dry', action=
'store_true', dest=
'dry', default=
False,
58 help=
'Do not download or compare files, just show the progress.')
59 optional_group.add_option(
'--html', action=
'store_true', dest=
'html', default=
False,
60 help=
'Generate static html. Default: %default.')
61 parser.add_option_group(optional_group)
65 file1, file2, work_path, db_name, clear_db = args
66 command = [
'./compare_using_files_v2.py',
join(work_path, file1),
join(work_path, file2),
'--db', db_name]
68 command.append(
'--cl')
72 """Generates temporary database name.""" 73 return '%s___%d.db' % (db_name.strip(
'.db'), i + 1)
76 conn = sqlite3.connect(main_db)
80 c.execute(
'''SELECT * FROM Directory limit 1;''')
81 directory_row = c.fetchall()
84 rel_cmp_offset, file_cmp_offset, directory_offset, hist_cmp_offset = 0, 0, 0, 0
86 c.execute(
'''SELECT count(*) FROM ReleaseComparison;''')
87 rel_cmp_offset = c.fetchone()[0]
88 c.execute(
'''SELECT count(*) FROM RootFileComparison;''')
89 file_cmp_offset = c.fetchone()[0]
90 c.execute(
'''SELECT max(id) FROM Directory;''')
91 directory_offset = c.fetchone()[0]
92 c.execute(
'''SELECT max(id) FROM HistogramComparison;''')
93 hist_cmp_offset = c.fetchone()[0]
97 ATTACH '{0}' AS partial; 100 INSERT INTO ReleaseComparison (title, release1, release2, statistical_test) 101 SELECT title, release1, release2, statistical_test FROM partial.ReleaseComparison; 103 INSERT INTO RootFileComparison (filename1, filename2, release_comparison_id, directory_id) 104 SELECT filename1, filename2, release_comparison_id+{1}, directory_id+{3} FROM partial.RootFileComparison; 106 INSERT INTO Directory (id, name, parent_id, from_histogram_id, till_histogram_id) 107 SELECT id+{3}, name, parent_id+{3}, from_histogram_id+{4}, till_histogram_id+{4} FROM partial.Directory; 109 INSERT INTO HistogramComparison (name, p_value, directory_id) 110 SELECT name, p_value, directory_id+{3} FROM partial.HistogramComparison; 112 COMMIT;""".
format(partial_db, rel_cmp_offset, file_cmp_offset, directory_offset, hist_cmp_offset))
115 c.execute(
'''SELECT max(id) FROM RootFileComparison;''')
116 max_file_cmp_id = c.fetchone()[0]
118 return max_file_cmp_id
122 """Generates release comparison information and stores it on SQLite3 .db file.""" 123 def __init__(self, work_path=None, db_name=None, clear_db=False, dry=False, no_url=False, use_external=False):
132 conn = sqlite3.connect(self.
db_name)
134 c.execute(
'''SELECT id FROM ReleaseComparison WHERE release1=? AND 135 release2=? AND statistical_test=?''', (release1, release2, st_test_name))
136 release_comparison_id = c.fetchone()
138 if release_comparison_id:
139 return release_comparison_id[0]
142 def compare(self, rel1, frags1, rel2, frags2, st_tests, url=None, title=None):
143 print(
'\n################# Searching for files ###################')
149 print(
'Searching for files online at:')
152 files_with_urls1.update(files_with_urls2)
153 files1, files2 = list(
zip(*file_pairs))
154 paired_files_with_urls = [(file, files_with_urls1[file])
for file
in files1 + files2]
157 print(
'DRY: nothing to do. Exiting.')
167 print(
'\n################### Preparing directory ###################')
168 print(
'Creating working directory: %s ...' % self.
work_path, end=
' ')
172 print(
'\n################# Downloading the files ###################')
178 show_status_bar.q = q
179 auth_download_file.q = q
180 auth_download_file.work_dir = self.
work_path 182 Process(target=show_status_bar, args=(total_size,)).
start()
183 Pool(2).
map(auth_download_file, files_to_download)
188 print(
'\n################# Preparing Database ###################')
201 for st_test_name
in st_tests.split(
','):
202 print(
'\n################# Comparing Releases (%s) ###################' % st_test_name)
203 st_test = tests[st_test_name]()
205 some_files_compared =
False 206 file_comparison_ids = []
210 self.
clear_db]
for i, pair
in enumerate(file_pairs)]
212 pool.map(call_compare_using_files, arg_list)
215 print(
'\n################# Merging DBs (%s) ###################' % st_test_name)
216 for i, pair
in enumerate(file_pairs):
218 print(
'Merging %s...' % (basename(tmp_db),), end=
' ')
222 some_files_compared =
True 226 for file1, file2
in file_pairs:
232 if not file_comparison.was_compared(file1, file2, st_test_name):
233 print(
"Comparing:\n%s\n%s\n" % (file1, file2))
234 file_comparison_id = file_comparison.compare(file1_path, file2_path, st_test)
235 file_comparison_ids.append(file_comparison_id)
236 some_files_compared =
True 238 print(
"Already compared:\n%s\n%s\n" % (file1, file2))
243 if some_files_compared:
244 release_comparison_id = self.
was_compared(release1, release2, st_test_name)
245 conn = sqlite3.connect(self.
db_name)
247 if not release_comparison_id:
248 print(
'Inserting release "%s VS %s" description.\n' % (release1, release2))
250 title =
"%s__VS__%s" % (release1, release2)
251 c.execute(
'''INSERT INTO ReleaseComparison(title, release1, release2, 252 statistical_test) VALUES (?, ?, ?, ?)''', (title,
253 release1, release2, st_test_name))
254 release_comparison_id = c.lastrowid
255 c.executemany(
'''UPDATE RootFileComparison SET release_comparison_id = ? 256 WHERE id == ?''', [(release_comparison_id, fid)
for fid
in file_comparison_ids])
261 if __name__ ==
'__main__':
262 start = datetime.now()
263 opts, args = parser.parse_args()
264 if not opts.release1
or not opts.release2:
265 parser.error(
'Not all releases specified. Please check --re1 and --re2 options.')
267 rel_cmp =
ReleaseComparison(opts.dir, opts.db_name, opts.clear_db, opts.dry, opts.no_url, use_external=
True)
268 rel_cmp.compare(opts.release1, opts.fragments1, opts.release2,
269 opts.fragments2, opts.st_tests, opts.url, opts.title)
271 print(
'\n################# Generating static HTML #################')
272 print(
'\n Warrning!!! Did NOT finished the implementation. \n')
273 from Utilities.RelMon.web.dbfile2html
import dbfile2html
275 print(
'################# Execution time: %s #################\n' % (datetime.now() - start,))
def make_file_pairs(files1, files2)
def call_compare_using_files(args)
def partial_db_name(db_name, i)
def __init__(self, work_path=None, db_name=None, clear_db=False, dry=False, no_url=False, use_external=False)
def recursive_search_online(url, rel1, frags1, rel2, frags2)
use_external_script_to_compare_files
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
def get_size_to_download(work_path, files_with_urls)
work_path
Create working directory if not given.
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
db_name
Download needed files.
def search_on_disk(work_path, rel1, frags1, rel2, frags2)
static std::string join(char **cmd)
def was_compared(self, release1, release2, st_test_name)
def remove(d, key, TELL=False)
def check_disk_for_space(work_path, size_needed)
def compare(self, rel1, frags1, rel2, frags2, st_tests, url=None, title=None)
def init_database(db_path)
Utils.
def dbfile2html(db_name, work_path, threshold=1e-5)
def merge_dbs(main_db, partial_db)