Re: Transaction Set clean does not actually clean
Jeff Johnson <[email protected]> Fri, 7 Dec 2007 18:50:33 -0500
| Newsgroups | gmane.linux.redhat.rpm.python |
|---|---|
| Message-ID | <[email protected]> |
On Dec 7, 2007, at 6:26 PM, Mitko Haralanov wrote: > On Fri, 7 Dec 2007 18:08:42 -0500 > Jeff Johnson <[email protected]> wrote: > >> OK, so you want ts.clean() to "work". >> >> Translating python -> C, the binding is just a wrapper onto >> rpmtsClean(). >> >> Why do you think rpmtsClean is not "cleaning", as in removing >> all the references from the transaction set to the transaction >> elements >> (aka packages) in the transaction set? > > First off, let me say that I agree with you that getting this to work > the way I am going about it is swimming against a current! > > However, I went that route because I can't seem to get ts.clean() to > "work". I looked at the C code for the Python module and, yes, > rpmtsClean should be doing the right thing. > > However, I believe it isn't: I have an application that creates an > instance of my rpm wrapper class and sits there waiting for > "commands". > If I ask the application to install a set of rpms (which it does > successfully) and then, at a later time, ask it to install a new > version of the previous set, I get TransactionSet conflicts because > the > TransactionSet is attempting to install the same files from two > different versions of the same rpm (in the same transaction). In other > words, I get the same error that I would get if I try to do the > following on the command line: > rpm -Uv rpmA-1.2.rpm rpmA-1.3.rpm > Ah, here's the likely issue: rpmtsClean() should be used between repeated calls to ts.check() or ts.order() with the *same* or additional elements added. What you expect is a wrapper to rpmtsEmpty(), which will also remove the rpmte transaction elements. That also assumes no other references to the underlying rpmte objects. Apologies for not looking at the C code sooner. The reason for not adding a ts.empty() method (as in my original intention) was that rpmts objects are easily discarded and regenerated. There's quite a bit of complexity mapping python <-> rpmlib reference counts accurately and precisely, easier to just trash and burn the transaction set, transaction set creation is not an expensive operation. You certainly could keep your threads happy by wrapping a transaction set, but discard the underlying ts object to get rid of the attached elements when a "clean" operation is needed. I'd also suggest creating a single transaction set object once for each rpmdb path that you are setting. The reason for that is to keep the rpmdb open persistently. Opening/closing a Berkeley DB is by no means a lightweight operation. > The only way that this could be happening is if the ts.clean() > which is > done after every "install" command doesn't actually clean the > TransasctionSet. > > On a different note: is there a way that I could print out the content > of the current TransactionSet before I run the run() method? That way, > I could verify whether I really have stale transactions. > Iterate over the transaction set, transaction elements are returned, which have attached methods for displaying, say package name, version, etc. I'm pretty sure that the rpmte print method Does The Right Thing as well. Checking python/rpmte-py.c ... yes: ... static int rpmte_print(rpmteObject * s, FILE * fp, /*@unused@*/ int flags) /*@globals fileSystem @*/ /*@modifies fp, fileSystem @*/ { const char * tstr; if (!(s && s->te)) return -1; switch (rpmteType(s->te)) { case TR_ADDED: tstr = "++"; break; case TR_REMOVED: tstr = "--"; break; default: tstr = "??"; break; } fprintf(fp, "%s %s %s", tstr, rpmteNEVR(s->te), rpmteA(s->te)); return 0; } ... (printfunc) rpmte_print, /* tp_print */ ... > Thanks for all your help! Thanks for thanks ;-) 73 de Jeff