sstatesig/find_siginfo: unify a disjointed API

find_siginfo() returns two different data structures depending
on whether its third argument (list of hashes to find) is empty or
not:
- a dict of timestamps keyed by path
- a dict of paths keyed by hash

This is not a good API design; it's much better to return
a dict of dicts that include both timestamp and path, keyed by
hash. Then the API consumer can decide how they want to use these
fields, particularly for additional diagnostics or informational
output.

I also took the opportunity to add a binary field that
tells if the match came from sstate or local stamps dir, which
will help prioritize local stamps when looking up most
recent task signatures.

(From OE-Core rev: 8721c52041e910bd4d8a9235b52f274f4f02c8a3)

Signed-off-by: Alexander Kanavin <alex@linutronix.de>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Alexander Kanavin 2023-12-18 09:43:59 +01:00 committed by Richard Purdie
parent 71c0d311ba
commit c45ffa9e94
3 changed files with 19 additions and 24 deletions

View File

@ -562,7 +562,7 @@ def compare_siglists(a_blob, b_blob, taskdiff=False):
elif not hash2 in hashfiles:
out.append("Unable to find matching sigdata for %s with hash %s" % (desc, hash2))
else:
out2 = bb.siggen.compare_sigfiles(hashfiles[hash1], hashfiles[hash2], recursecb, collapsed=True)
out2 = bb.siggen.compare_sigfiles(hashfiles[hash1]['path'], hashfiles[hash2]['path'], recursecb, collapsed=True)
for line in out2:
m = hashlib.sha256()
m.update(line.encode('utf-8'))

View File

@ -349,7 +349,6 @@ def find_siginfo(pn, taskname, taskhashlist, d):
pn, taskname = key.split(':', 1)
hashfiles = {}
filedates = {}
def get_hashval(siginfo):
if siginfo.endswith('.siginfo'):
@ -357,6 +356,12 @@ def find_siginfo(pn, taskname, taskhashlist, d):
else:
return siginfo.rpartition('.')[2]
def get_time(fullpath):
try:
return os.stat(fullpath).st_mtime
except OSError:
return None
# First search in stamps dir
localdata = d.createCopy()
localdata.setVar('MULTIMACH_TARGET_SYS', '*')
@ -372,24 +377,21 @@ def find_siginfo(pn, taskname, taskhashlist, d):
filespec = '%s.%s.sigdata.*' % (stamp, taskname)
foundall = False
import glob
bb.debug(1, "Calling glob.glob on {}".format(filespec))
for fullpath in glob.glob(filespec):
match = False
if taskhashlist:
for taskhash in taskhashlist:
if fullpath.endswith('.%s' % taskhash):
hashfiles[taskhash] = fullpath
hashfiles[taskhash] = {'path':fullpath, 'sstate':False, 'time':get_time(fullpath)}
if len(hashfiles) == len(taskhashlist):
foundall = True
break
else:
try:
filedates[fullpath] = os.stat(fullpath).st_mtime
except OSError:
continue
hashval = get_hashval(fullpath)
hashfiles[hashval] = fullpath
hashfiles[hashval] = {'path':fullpath, 'sstate':False, 'time':get_time(fullpath)}
if not taskhashlist or (len(filedates) < 2 and not foundall):
if not taskhashlist or (len(hashfiles) < 2 and not foundall):
# That didn't work, look in sstate-cache
hashes = taskhashlist or ['?' * 64]
localdata = bb.data.createCopy(d)
@ -412,22 +414,15 @@ def find_siginfo(pn, taskname, taskhashlist, d):
localdata.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
filespec = '%s.siginfo' % localdata.getVar('SSTATE_PKG')
bb.debug(1, "Calling glob.glob on {}".format(filespec))
matchedfiles = glob.glob(filespec)
for fullpath in matchedfiles:
actual_hashval = get_hashval(fullpath)
if actual_hashval in hashfiles:
continue
hashfiles[hashval] = fullpath
if not taskhashlist:
try:
filedates[fullpath] = os.stat(fullpath).st_mtime
except:
continue
hashfiles[actual_hashval] = {'path':fullpath, 'sstate':True, 'time':get_time(fullpath)}
if taskhashlist:
return hashfiles
else:
return filedates
return hashfiles
bb.siggen.find_siginfo = find_siginfo

View File

@ -761,14 +761,14 @@ addtask tmptask2 before do_tmptask1
hashes = [hash1, hash2]
hashfiles = find_siginfo(key, None, hashes)
self.assertCountEqual(hashes, hashfiles)
bb.siggen.compare_sigfiles(hashfiles[hash1], hashfiles[hash2], recursecb)
bb.siggen.compare_sigfiles(hashfiles[hash1]['path'], hashfiles[hash2]['path'], recursecb)
for pn in pns:
recursecb_count = 0
filedates = find_siginfo(pn, "do_tmptask1")
self.assertGreaterEqual(len(filedates), 2)
latestfiles = sorted(filedates.keys(), key=lambda f: filedates[f])[-2:]
bb.siggen.compare_sigfiles(latestfiles[-2], latestfiles[-1], recursecb)
matches = find_siginfo(pn, "do_tmptask1")
self.assertGreaterEqual(len(matches), 2)
latesthashes = sorted(matches.keys(), key=lambda h: matches[h]['time'])[-2:]
bb.siggen.compare_sigfiles(matches[latesthashes[-2]]['path'], matches[latesthashes[-1]]['path'], recursecb)
self.assertEqual(recursecb_count,1)
class SStatePrintdiff(SStateBase):