| Summary: | rpm upgrade leaves package removal broken | ||
|---|---|---|---|
| Product: | [Build System, Metadata & Runtime] OE-Core | Reporter: | Richard Purdie <richard.purdie> |
| Component: | deployment | Assignee: | Mark Hatle <mark.hatle> |
| Status: | VERIFIED FIXED | QA Contact: | Bogdan Alexandru Voiculescu <bogdanx.a.voiculescu> |
| Severity: | normal | ||
| Priority: | Medium+ | CC: | bogdanx.a.voiculescu, n3npq |
| Version: | 2.1 | ||
| Target Milestone: | 2.1 M3 | ||
| Hardware: | x86 | ||
| OS: | Multiple | ||
| Whiteboard: | |||
| OS type for building Yocto: | --- | Type of Regression: | --- |
| Verified: | Documentation change: | No (bug/feature does not impact docs) | |
|
Description
Richard Purdie
2016-03-01 18:06:31 UTC
I have identified the cause of the failure, but am still not sure how to fix it. Below is an email I've sent to the RPM5 maintainer asking for guidance.
I found the cause of the python erase failure.
The old code effectively did:
rpmts_AddErase(rpmtsObject * s, PyObject * args, PyObject * kwds)
mi = rpmtsInitIterator(s->ts, RPMTAG_NVRA, name, 0);
or
mi = rpmtsInitIterator(s->ts, RPMDBI_PACKAGES, &instance, sizeof(instance));
Header h;
while ((h = rpmmiNext(mi)) != NULL) {
uint32_t hdrNum = rpmmiInstance(mi);
if (hdrNum)
rpmtsAddEraseElement(s->ts, h, hdrNum);
break;
}
The new code though is very different:
(in python) it converts everything into a header.
def addErase(self, item):
hdrs = []
if isinstance(item, rpm.hdr):
hdrs = [item]
elif isinstance(item, rpm.mi):
hdrs = item
elif isinstance(item, int):
hdrs = self.dbMatch(rpm.RPMDBI_PACKAGES, item)
elif isinstance(item, str):
hdrs = self.dbMatch(rpm.RPMDBI_LABEL, item)
else:
raise TypeError("invalid type %s" % type(item))
for h in hdrs:
if not _rpmts.addErase(self, h):
raise rpm.error("package not installed")
The python chunk then calls rpmts_AddErase which all it does is:
return PyBool_FromLong(rpmtsAddEraseElement(s->ts, h, -1) == 0);
So the third item, 'hdrNum' is always set to -1, which appears to trigger the
silent failure. (Looking at the current RPM 4.X code, the third parameter for
calls to rpmtsAddEraseElement is always ignored.)
Since the code is passing in a header already computed, I can't use the hdrNum =
rpmmiInstance(mi) as far as I can tell. I did try to replace it with:
return PyBool_FromLong(rpmtsAddEraseElement(s->ts, h, headerGetInstance(h)) == 0);
It appears to be working, but I'm not sure if the value returned by
'headerGetInstance' is reasonable or not.
So I think we have two differences here. One is at the RPM API level. One is
at the python level. Is there any reason the RPM 5 API could not be modified to
always define it's own 'hdrNum' -- or does RPM 5 always need a specific hdrNum,
if so -- is calling headerGetInstance(h) correct to generate one or is there
some other method that should be used?
Yes headerGetInstance() is correct for any header retrieved from an rpmdb. The hdrNum (always positive) is set when the header is read from an rpmdb (and is likely zero/negative for headers that did not come from an rpmdb). The underlying API issue is that the join keys which attach secondary indices to the primary Packages store need to remain opaque and should *NOT* be exposed to applications so that, say, the join key could become an uint64_t or a UUID or even a string in some relational db without having to change every application. Meanwhile, the hdrNum exposed by rpm.org (and older rpm) was a simple native endian uint32_t. rpm5.org still uses a network endian uint32_t and the value is always monotonically increasing and transactionally protected in /var/lib/rpm/Seqno. This was fixed in the final version of the rpm upgrade patchset: http://git.yoctoproject.org/cgit.cgi/poky/commit/?id=007c284cb83cf5d98f3e4f605244ca6f1d46caea Verified on master: master:f7b520878babbaa7527151f22c031ae160512753 smart remove -y psplash-default --log-level=debug Loading cache... Updating cache... ############################################ [100%] Computing transaction... Removing packages (1): psplash-default-0.1+git0+88343ad23c-r15@i586 50.1kB will be freed. Committing transaction... Preparing... ############################################ [ 0%] update-alternatives: removing /usr/bin/psplash as no more alternatives exist for it 1:Removing psplash-default ############################################ [100%] |