2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-08-03 16:07:00 +00:00

Fingerprint installation media off the event loop

scan_iso walks an entire ISO with blocking libarchive reads, yielding
only once per entry, and the header-sum branch of fingerprint reads the
whole file with no yield at all.  Both run in the daemon, reached from
MediaImporter.init on every fingerprint and importing request.

The scan costs about 8us per entry and is indifferent to media size,
since libarchive seeks past file data rather than reading it: measured
at 80ms for 10k entries whether the image is 0.2 GB or 8.8 GB, and at
310ms for 40k.  The header-sum branch is the one that scales with size,
reading a multi-gigabyte image end to end.

Make the pair plain functions and hand them to a thread instead.
This commit is contained in:
Markus Hilger
2026-07-27 06:52:37 +02:00
parent 547ecf16d4
commit f2c74b0be3
+5 -6
View File
@@ -834,7 +834,7 @@ def fingerprint_initramfs(archive):
return None
async def scan_iso(archive):
def scan_iso(archive):
scanudf = False
filesizes = {}
filecontents = {}
@@ -845,7 +845,6 @@ async def scan_iso(archive):
for ent in reader:
if str(ent).endswith('TRANS.TBL'):
continue
await asyncio.sleep(0)
filesizes[str(ent)] = ent.size
if str(ent) == 'README.TXT':
readmecontents = b''
@@ -909,13 +908,13 @@ def parse_bfb(archive):
archive.seek(currsize, os.SEEK_CUR)
return None
async def fingerprint(archive):
def fingerprint(archive):
archive.seek(0)
header = archive.read(32768)
archive.seek(32769)
if archive.read(6) == b'CD001\x01':
# ISO image
isoinfo = await scan_iso(archive)
isoinfo = scan_iso(archive)
name = None
for fun in globals():
if fun.startswith('check_'):
@@ -947,7 +946,7 @@ async def import_image(filename, callback, backend=False, mfd=None, custtargpath
archive = os.fdopen(int(mfd), 'rb')
else:
archive = open(filename, 'rb')
identity = await fingerprint(archive)
identity = await asyncio.to_thread(fingerprint, archive)
if not identity:
return -1
identity, imginfo, funname = identity
@@ -1207,7 +1206,7 @@ class MediaImporter(object):
else:
medfile = open(media, 'rb')
try:
identity = await fingerprint(medfile)
identity = await asyncio.to_thread(fingerprint, medfile)
finally:
if not self.medfile:
medfile.close()