[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: All installs, and then all erases...

On Wed, Jun 04, 2003 at 05:01:49PM -0400, James Olin Oden wrote:
> OK, started adding debug code to the psm, and I have come the conclusion
> that rpm does all the installs and then all the erases.  I had had the 

Yup. As currently implemented, there are no ordering constraints
on erasured packages other than install-before-erase.

Having all erased packages at the end of the transaction can/will be a
performance win because there is a point (usually about 1/3 of the way through)
where all prerequisite conditions are known to be satisfied. That means
that there are no further constrainst on install order, they can be installed
in any order whatsoever, even in parallel.

OTOH, the current CLIS feedback is somewhat confusing, as it looks like
rpm is "hung" at 100% when in actuality packages are being erased.

> wrong assumption that it would on an upgrade install a pkg and erase the
> old one in one atomic transaction.  So that was wrong I guess.

Yup, addInstall pretends to have atomic upgrade, but rpmtsRun only
promises to not remove if matching install fails.

> Now that I know this, I need to figure out how to make rollback 
> transaction for a failed transaction do the right thing...sigh.
> Here is the first scenario:
> 	An install element complets.
> 	You figure out that it had a complementary repackaged package.
> 	So you add an install element for the repackaged package to the
> 		rollback transaction, and add a complimentary erase 
> 		element to remove the new package header should a rollback 
> 		need to occur.

Sounds right, here's my translation:

Basically a transaction is a set of install/erase elements which can fail.

After a transaction completes with possible failures, the side effects
(i.e. database entries) for failed items need to be reverted.

Remove element failures are rather unlikely (remove is not done if install
fails) and mostly harmless (i.e. file wasn't there when you attempted
remove), so the install element failure side effects that need reverting are
	a) removing duplicate rpmdb entry.
	b) restoring the bits on the file system from the repackaged package.

> At this point, though the I still have a problem and that is the
> old package header has not been removed yet, and if there are multiple
> install elements in the running transaction it won't get erased until
> they have completed.  If they don't complete then I still have the 
> previous packages header around?  How would one handle this?

Removing the duplicate database entry is best done by calling rpmdbRemove()
directly, basically because control bits are per-transaction, not per-package.
You will need the instance number(s) you've previously saved from rpmdbAdd()
during the failed install attempt.

Then the rollback transaction is pure install, basically put the bits back
on the file system with (essentially) --force bits on the transaction.
There's a possibility of rpmtsRun() failure here, too, but let's not go
there, it's unlikely.

There's also the problem that dependencies were checked on the original,
not the failure substituted, set of install/erase elements. I suspect
that you can ignore that problem if you wish, as package dependencies
are often slowly changing.

A more correct approach would be to take all the install elements
from the original transaction, substitute for the failures with the
repackaged packages, and rerun rpmtsCHeck(), rpmtsOrder(), rpmtsRun()
with essentially --install --force flags. The difficulty here is
that if you find that the substituted rollback transaction has
dependency problems, you're in deep doo-doo, the only way out of
the mess is to attempt a full blown dependency solver to reconstitute
a closed rollback transaction.

So that leaves rolling back the original transaction "atomically" to
avoid concepts like partial rollbacks (i.e. having to call rpmtsCheck()
again). That's as simple as swapping install/erase elements, except
for the failed elements, where rpmdbRemove() is simpler, as control bits
are per-transaction, not per-package.

(aside: There is still the possibility of side effects from partially
completed %post scriptlets, but that's really, really, hard to get right,
scriptlets are opaque to rpm, have only a boolean return code).

> Do I need another transaction to run before I do the rollback that 
> removes the old header?  Or should I always run the rollback with a
> force (this scares me)?  Any ideas are really really apreciated (
> Jeff your going to have to start charging me (-;).

Rollbacks with --force shouldn't scare you. Rollbacks are retracing
a known path step-by-step, where closure on dependencies and package ordering
are the criteria that can be assumed at each step, been there, done that.

Kinda like following bread crumbs in the forest, as long as the crows
haven't nibbled at the repackaged packages ;-)


73 de Jeff

Jeff Johnson	ARS N3NPQ
jbj@redhat.com (jbj@jbj.org)
Chapel Hill, NC

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] []