Re: [Modeling-users] Partial dispose
Status: Abandoned
Brought to you by:
sbigaret
From: Sebastien B. <sbi...@us...> - 2003-03-26 21:23:08
|
soif> Is there a way to do a partial dispose. In fact soif> I have a problem with my EditingContext, as : soif> - The EC is never disposed to avoid fetching objects soif> at each web application request. (better performance) soif> - The only way to stop this is to call a ec.dispose() soif> but this drop all objects. soif> soif> After severals searches, I think the best for me, is soif> to do a partial dispose . Let's say object that are soif> in EC older than 10 minutes should be forget. soif> soif> Is there any plans to support things like this ? mario> I think Sebastien is waiting for real requests for this todo mario> item, to bump up its priority ;) Look at section 6.3.1 in the mario> users guide... Mario answered for me ;) soif> I tried to call ec.forgetObject(object) if object soif> is older than X min, but i get some really strange soif> AttributeError when i try to access objects that soif> i have forget. Woo-oo, you didn't read forgetObject()'s docstring, did you ?) It shouldn't be called. What you need is refaultObject() for which you'll find a patch at the end of the message. This is a somewhat dirty implementation, especially in DBContext.refaultObject(), but it works in a simple test also included at the end of the mail. Instruction of use: - do NOT call DabaseContext.refaultObject(), just ec.refaultObject - do NOT try to call it on inserted, updated or deleted objects, API: either ec.refaultObject(obj) or ec.refaultObject(anObject=obj) or ec.refaultObject(aGlobalID=gid) Last, when refaulting an object, all its properties are cleared (__init__ is called), hence you should not expect to find any attribute after it's been refaulted. This will probably not stay as-is, this is rude and dirty ; please experiment and tell what you think. BTW this is the first step towards what is exposed at the end of section 6.3.1 -- Sebastien. Index: EditingContext.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/EditingContext.py,v retrieving revision 1.21 diff -c -r1.21 EditingContext.py *** EditingContext.py 12 Mar 2003 15:45:54 -0000 1.21 --- EditingContext.py 26 Mar 2003 21:01:31 -0000 *************** *** 1013,1019 **** except AttributeError: return 0 ! def faultForGlobalID(self, aGlobalID, anEditingContext): """ Searches for an object registered within the EditingContext with the supplied GlobalID, and returns it if it is found. If not, forwards the --- 1013,1019 ---- except AttributeError: return 0 ! def faultForGlobalID(self, aGlobalID, anEditingContext=None): """ Searches for an object registered within the EditingContext with the supplied GlobalID, and returns it if it is found. If not, forwards the *************** *** 1021,1026 **** --- 1021,1029 ---- If anEditingContext is a child of self, """ + if anEditingContext is None: + anEditingContext=self + if anEditingContext.isaChildOf(self): # One of our child ECs forwarded the message if aGlobalID.isTemporary(): *************** *** 1215,1220 **** --- 1218,1252 ---- """ return self.parentObjectStore().ownsObject(anObject) + def refaultObject(self, anObject=None, aGlobalID=None, ec=None): + "TBD docstring refaultObject" + if ec is None: ec=self + + if ec is not self: + return self.parentObjectStore().refaultObject(anObject, aGlobalID, ec) + + obj=anObject ; gid=aGlobalID + if ( obj is None and gid is None ) or \ + ( obj is not None and gid is not None ): + raise ValueError, "Either parameter 'anObject' or 'aGlobalID' should be provided --not both" + if obj is None: + obj=self.objectForGlobalID(gid) + else: + gid=self.globalIDForObject(obj) + + if gid is None: + raise ObjectNotRegisteredError + if gid.isTemporary(): + raise ValueError, 'Cannot refault an newly created/inserted object' + + if gid in self._pendingUpdatedObjects+self._updatedObjects: + raise ValueError, 'Cannot refault a modified object' + if gid in self._pendingDeletedObjects+self._deletedObjects: + raise ValueError, 'Cannot refault a deleted object' + + #self.forgetObject(obj) + return self.parentObjectStore().refaultObject(obj, gid, self) + def saveChangesInEditingContext(self, anEditingContext): """ Called on the parent EditingContext when a child EditingContext saves *************** *** 1360,1365 **** --- 1392,1404 ---- self.recordObject(obj, key_gid) db=self.rootObjectStore().objectStoreForObject(obj).database() db.incrementSnapshotCountForGlobalID(key_gid) + # time to update object's PK if a PK is set as class properties + from ModelSet import defaultModelSet + entity=defaultModelSet().entityNamed(obj.entityName()) + pk_values=key_gid.keyValues() + for pk in entity.primaryKeyAttributes(): + if pk.isClassProperty(): + obj.takeStoredValueForKey(pk_values[pk.name()], pk.name()) else: obj=self.objectForGlobalID(gid) new_gid=notification.userInfo().get(gid) Index: ObjectStoreCoordinator.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/ObjectStoreCoordinator.py,v retrieving revision 1.9 diff -c -r1.9 ObjectStoreCoordinator.py *** ObjectStoreCoordinator.py 14 Mar 2003 11:40:09 -0000 1.9 --- ObjectStoreCoordinator.py 26 Mar 2003 21:01:34 -0000 *************** *** 486,492 **** self.lock() try: store=self.objectStoreForObject(anObject) ! store.refaultObject(anObject, aGlobalID, anEditingContext) finally: self.unlock() --- 486,492 ---- self.lock() try: store=self.objectStoreForObject(anObject) ! return store.refaultObject(anObject, aGlobalID, anEditingContext) finally: self.unlock() Index: DatabaseContext.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/DatabaseContext.py,v retrieving revision 1.14 diff -c -r1.14 DatabaseContext.py *** DatabaseContext.py 14 Mar 2003 11:40:07 -0000 1.14 --- DatabaseContext.py 26 Mar 2003 21:01:52 -0000 *************** *** 1489,1496 **** def refaultObject(self, aDatabaseObject, aGlobalID, anEditingContext): """ """ ! self.__unimplemented__() def rootObjectStore(self): """ --- 1489,1524 ---- def refaultObject(self, aDatabaseObject, aGlobalID, anEditingContext): """ + Do not call by hand -- please call EditingContext.refaultObject() + instead """ ! ## TBD roughly copy/pasted from faultForGlobalID() ! ## TBD It should be fixed -- we do not check anything wrt the ec and ! ## TBD Should we also really clear properties? We'll see ! try: ! entityName=aGlobalID.entityName() ! except AttributeError: ! raise ValueError, \ ! "Parameter aGlobalID does not responds to message 'entityName()'" ! cd=ClassDescription.classDescriptionForName(entityName) ! ! cd_root=cd.rootClassDescription() ! root_keyGlobalID=KeyGlobalID(cd_root.entityName(), aGlobalID.keyValues()) ! ! anEditingContext.forgetObject(aDatabaseObject) ! faultHandler=AccessFaultHandler(root_keyGlobalID, self, ! anEditingContext) ! #aDatabaseObject.clearProperties() ! aDatabaseObject.__init__() ! aDatabaseObject.turnIntoFault(faultHandler) ! trace('Registering fault w/ GlobalID: %s'%str(root_keyGlobalID)) ! anEditingContext.recordObject(aDatabaseObject, root_keyGlobalID) ! # inheritance support ! trace('Adding ec as an observer for GlobalIDChangedNotification & GlobalID: %s'%root_keyGlobalID) ! NC.addObserver(anEditingContext, EditingContext.handleNotification, ! GlobalIDChangedNotification, root_keyGlobalID) ! return aDatabaseObject ! def rootObjectStore(self): """ ------------------------------------------------------------------------ Optionally, add this to tests/test_EditingContext_Global.py def test_19_refaultObject(self): "[EditingContext] refaultObject()" ec=EditingContext() qualifier=qualifierWithQualifierFormat('lastName=="Rabelais"') fetchSpec=FetchSpecification(entityName='Writer', qualifier=qualifier) rabelais=ec.objectsWithFetchSpecification(fetchSpec)[0] db=ec.rootObjectStore().objectStoreForObject(rabelais).database() gid=ec.globalIDForObject(rabelais) lastName=rabelais.getLastName() # trigger fault self.failIf(rabelais.isFault()) self.failUnless(db.snapshotForGlobalID(gid)) ec.refaultObject(rabelais) self.failUnless(rabelais.isFault()) self.failIf(db.snapshotForGlobalID(gid)) lastName=rabelais.getLastName() # trigger fault again self.failIf(rabelais.isFault()) ------------------------------------------------------------------------ |