[ZODB-Dev] How to predict George Bailey?

Jeff Sasmor jsasmor@gte.net
Sat, 2 Nov 2002 22:57:00 -0500


>From: Magnus Lycka <magnus@thinkware.se>
>Subject: [ZODB-Dev] How to predict George Bailey?

>How can I predict whether an undo operation will cause
>objects to be uncreated?

>I *could* do something along this line:

>1. Before undo, let every window get a copy of the objects
>    application specific OID (Not ZODB's.)
>2. Undo/commit/sync.
>3. Let every open window search for the OID in the database.
>4. Close window if OID not found.

I have to pipe up and mention that I spent a lot of time dealing with 
this issue in the app I am working on, and I found that it can become
impractical to try to uncover everyplace where a problem can occur
after an undo.  For example, if you have multiple windows with multiple
refs to objects; tree controls, list controls and such it is really impractical 
to try to check everything during runtime. And if you miss something and 
you're using a C++ gui lib like wxPython/wxWindows you can get all 
sorts of errors when you don't expect them; minutes or hours later.

I had built in methods to completely rebuild all windows, tree displays
etc., i.e. a 'Refresh' menu item.  When an undo is performed, I just
rebuild everything (which includes an underlying ZODB disconnect
and reconnect).  And it's not really that big of a deal that it takes a second
or two -- how often does someone undo something? Usually not that often.
I have found that this approach works flawlessly.

I'll pass along this code snippet as an example, but I doubt that it will
really make much sense to anyone else; sorry ... But it does show the need
to re-establish all important object refs after a reconnect; in my case 
only a few system wide variables such as a 'rootfolder' and some often
used folders and such that are held in a system registry.

  def reconnect(self):
    """ close the current connection and reopen it."""
    self.connection.close()
    self.connection = self.db.open()
    self.root = self.connection.root()

    #reset the built-in rootfolder
    rfId = sysinfo.get('rootfolderId','rootFolder')
    rf = self.root[rfId]
    rf = rf.__of__(self.root)
    delattr(rf,'aq_parent')  #indicates that this is the root folder
    rf.install()
    Reggie.setRootFolder(rf)
    
    #reset the prefsFolder into the registry
    prefsFolder = getattr(rf,sysinfo['PrefsFolderId'],None)
    Reggie.setPrefsFolder(prefsFolder)
    
    #reset the systemFolder into the registry
    systemFolder = getattr(rf,sysinfo['SystemFolderId'],None) 
    Reggie.setSystemFolder(systemFolder)
    
    #reset the system catalog into the registry
    systemCatalog = getattr(rf,sysinfo['catalogId'],None) 
    Reggie.setSystemCatalog(systemCatalog)
    
    #reset the system preferences obj into the registry (note this is in the SystemFolder)
    prefs = getattr(systemFolder,sysinfo['systemFolderPropSheetId'],None)
    Reggie.setSystemPrefs(prefs)  #set this as the system properties sheet.

HTH
#--------------------------------
Jeff Sasmor
jeff@sasmor.com