Skip to content

Commit 1148625

Browse files
authored
Merge pull request #4569 from Flamefire/improve-speed
reuse pre-computed checksums
2 parents acb1ea2 + 66b82a1 commit 1148625

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

easybuild/framework/easyblock.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,14 +674,16 @@ def collect_exts_file_info(self, fetch_files=True, verify_checksums=True):
674674
src_fn = os.path.basename(src_path)
675675

676676
# report both MD5 and SHA256 checksums, since both are valid default checksum types
677+
src_checksums = {}
677678
for checksum_type in (CHECKSUM_TYPE_MD5, CHECKSUM_TYPE_SHA256):
678679
src_checksum = compute_checksum(src_path, checksum_type=checksum_type)
680+
src_checksums[checksum_type] = src_checksum
679681
self.log.info("%s checksum for %s: %s", checksum_type, src_path, src_checksum)
680682

681683
# verify checksum (if provided)
682684
self.log.debug('Verifying checksums for extension source...')
683685
fn_checksum = self.get_checksum_for(checksums, filename=src_fn, index=0)
684-
if verify_checksum(src_path, fn_checksum):
686+
if verify_checksum(src_path, fn_checksum, src_checksums):
685687
self.log.info('Checksum for extension source %s verified', src_fn)
686688
elif build_option('ignore_checksums'):
687689
print_warning("Ignoring failing checksum verification for %s" % src_fn)
@@ -700,12 +702,15 @@ def collect_exts_file_info(self, fetch_files=True, verify_checksums=True):
700702
ext_src.update({'patches': ext_patches})
701703

702704
if verify_checksums:
705+
computed_checksums = {}
703706
for patch in ext_patches:
704707
patch = patch['path']
708+
computed_checksums[patch] = {}
705709
# report both MD5 and SHA256 checksums,
706710
# since both are valid default checksum types
707711
for checksum_type in (CHECKSUM_TYPE_MD5, CHECKSUM_TYPE_SHA256):
708712
checksum = compute_checksum(patch, checksum_type=checksum_type)
713+
computed_checksums[patch][checksum_type] = checksum
709714
self.log.info("%s checksum for %s: %s", checksum_type, patch, checksum)
710715

711716
# verify checksum (if provided)
@@ -715,7 +720,7 @@ def collect_exts_file_info(self, fetch_files=True, verify_checksums=True):
715720
patch_fn = os.path.basename(patch)
716721

717722
checksum = self.get_checksum_for(checksums, filename=patch_fn, index=idx+1)
718-
if verify_checksum(patch, checksum):
723+
if verify_checksum(patch, checksum, computed_checksums[patch]):
719724
self.log.info('Checksum for extension patch %s verified', patch_fn)
720725
elif build_option('ignore_checksums'):
721726
print_warning("Ignoring failing checksum verification for %s" % patch_fn)

easybuild/tools/filetools.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,12 +1242,16 @@ def calc_block_checksum(path, algorithm):
12421242
return algorithm.hexdigest()
12431243

12441244

1245-
def verify_checksum(path, checksums):
1245+
def verify_checksum(path, checksums, computed_checksums=None):
12461246
"""
12471247
Verify checksum of specified file.
12481248
12491249
:param path: path of file to verify checksum of
1250-
:param checksums: checksum values (and type, optionally, default is MD5), e.g., 'af314', ('sha', '5ec1b')
1250+
:param checksums: checksum values to compare to
1251+
(and type, optionally, default is MD5), e.g., 'af314', ('sha', '5ec1b')
1252+
:param computed_checksums: Optional dictionary of (current) checksum(s) for this file
1253+
indexed by the checksum type (e.g. 'sha256').
1254+
Each existing entry will be used, missing ones will be computed.
12511255
"""
12521256

12531257
filename = os.path.basename(path)
@@ -1303,8 +1307,14 @@ def verify_checksum(path, checksums):
13031307
"2-tuple (type, value), or tuple of alternative checksum specs.",
13041308
checksum)
13051309

1306-
actual_checksum = compute_checksum(path, typ)
1307-
_log.debug("Computed %s checksum for %s: %s (correct checksum: %s)" % (typ, path, actual_checksum, checksum))
1310+
if computed_checksums is not None and typ in computed_checksums:
1311+
actual_checksum = computed_checksums[typ]
1312+
computed_str = 'Precomputed'
1313+
else:
1314+
actual_checksum = compute_checksum(path, typ)
1315+
computed_str = 'Computed'
1316+
_log.debug("%s %s checksum for %s: %s (correct checksum: %s)" %
1317+
(computed_str, typ, path, actual_checksum, checksum))
13081318

13091319
if actual_checksum != checksum:
13101320
return False

test/framework/filetools.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"""
3434
import datetime
3535
import glob
36+
import logging
3637
import os
3738
import re
3839
import shutil
@@ -297,10 +298,26 @@ def test_checksums(self):
297298
'b7297da8b547d5e74b851d7c4e475900cec4744df0f887ae5c05bf1757c224b4',
298299
}
299300

301+
old_log_level = ft._log.getEffectiveLevel()
302+
ft._log.setLevel(logging.DEBUG)
300303
# make sure checksums computation/verification is correct
301304
for checksum_type, checksum in known_checksums.items():
302305
self.assertEqual(ft.compute_checksum(fp, checksum_type=checksum_type), checksum)
303-
self.assertTrue(ft.verify_checksum(fp, (checksum_type, checksum)))
306+
with self.log_to_testlogfile():
307+
self.assertTrue(ft.verify_checksum(fp, (checksum_type, checksum)))
308+
self.assertIn('Computed ' + checksum_type, ft.read_file(self.logfile))
309+
# Passing precomputed checksums reuses it
310+
with self.log_to_testlogfile():
311+
computed_checksums = {checksum_type: checksum}
312+
self.assertTrue(ft.verify_checksum(fp, (checksum_type, checksum), computed_checksums))
313+
self.assertIn('Precomputed ' + checksum_type, ft.read_file(self.logfile))
314+
# If the type isn't contained the checksum will be computed
315+
with self.log_to_testlogfile():
316+
computed_checksums = {'doesnt exist': 'checksum'}
317+
self.assertTrue(ft.verify_checksum(fp, (checksum_type, checksum), computed_checksums))
318+
self.assertIn('Computed ' + checksum_type, ft.read_file(self.logfile))
319+
320+
ft._log.setLevel(old_log_level)
304321

305322
# default checksum type is MD5
306323
self.assertEqual(ft.compute_checksum(fp), known_checksums['md5'])

0 commit comments

Comments
 (0)