Re: Transaction Set clean does not actually clean
Mitko Haralanov <[email protected]> Fri, 7 Dec 2007 13:45:16 -0800
| Newsgroups | gmane.linux.redhat.rpm.python |
|---|---|
| Organization | QLogic Corporation |
| Message-ID | <[email protected]> |
On Fri, 7 Dec 2007 15:12:31 -0500 Jeff Johnson <[email protected]> wrote: > Calling closeDB() (or doing any operation on a rpmdb) explicitly is not > recommended. Delete the transaction set and create a new transaction > instead. The reason is that there are global aspects to concurrent > access of an rpmdb that few application programs are prepared to > implement properly. I tried that, however, this creates problems with multi-threaded applications. If one of the threads deletes the TransactionSet instance, then the other threads throw exceptions. Lock and unlocking the TransactionSet instance doesn't really help since holding a lock does not guarantee that the instance will exist. What I did try is to create a wrapper class around the TransactionSet instance (pasted below) that will try to do the right thing. Unfortunately, this does not work either in cases where the TransactionSet operation returns a match object (for example), since working with the match object does depend on the TransactionSet instance to still be around. class Transaction: def __init__ (self, db=None): self.ts = None self.ts_lock = Lock () self.db = db self.func = None def __call__ (self, *args): return False # This method will acquire the lock, record the TransactionSet # method being called by the caller and return the pointer to # the call_ts_func () function, which will do all the work. def __getattr__ (self, name): self.ts_lock.acquire () self.func = name return self.call_ts_func # This method serves as a wrapper around the actual TransactionSet # method being called. It will open the database, call the # TransactionSet method, close the databse, and then release the # lock acquired in the __getattr__ () function. def call_ts_func (self, *args): if not self.ts: if self.db: rpm.addMacro ("_dbpath", self.db) self.ts = rpm.TransactionSet () self.ts.openDB () if self.db: rpm.delMacro ("_dbpath") func = self.ts.__getattribute__ (self.func) rs = func (*args) self.func = None self.ts.clean () self.ts.closeDB () del self.ts self.ts = None self.ts_lock.release () return rs -- Mitko Haralanov [email protected] Senior Software Engineer 650.934.8064 System Interconnect Group http://www.qlogic.com ========================================== We need to teach Linus about "taste" in drivers. His core code taste is impeccable, but I'm not fond of his driver taste ;) - Alan Cox on linux-kernel