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())
------------------------------------------------------------------------
|