[Zope-dev] RE: Why missing connection._storage.load?

Martijn Pieters mj@digicool.com
Mon, 28 Feb 2000 11:12:05 -0500


From: Loren Stafford [mailto:lstaffor@dynalogic.com]
> 
> My product's initialize(context) procedure creates a ZCatalog if that
> catalog doesn't already exist. I've defined an additional method
> armed_event() for the Catalog object. Later, the same product 
> _init_.py
> module calls armed_event() (OK -- it's called from a thread spawned by
> initialize(context)).

Do you create a new DB connection?

> 
> When the catalog is created in the same product load process, 
> the call to
> the catalog method armed_event() yields this output from pdb:
> 
>   > 
> C:/Zope214\lib\python\Products\ZScheduler\ZSchedule.py(47)arme
> d_event()
> 
> ...which is what I would expect.
> 
> However, when the catalog already exists (from a previous 
> product load),
> the call to the catalog method yields this output:
> 
>   > C:\Zope214\lib\python\ZODB\Connection.py(386)setstate()
> 
> I didn't write any setstate methods, so I presume this is 
> extension class or
> persistence voodoo. If so, the fact that pdb doesn't show how 
> it got to
> setstate must be due to the fact that that logic is written 
> in C. Somewhere,
> somehow, (perhaps via an inherited __setstate__ method) Zope 
> has figured out
> that the catalog object has to be loaded from the ZOSB before it can
> proceed, and calls on Connection.py\setstate to help do so. 
> Right, so far?
> 

Indeed, via the Persistence class, the ZODB is asked to retrieve the
object. How do you access the Catalog? You should obtain a new Root
object for your new thread, and traverse to the Catalog via that
reference.

When you use the ZServer Monitor, you have to do the same thing:

  import Zope
  app=Zope.app()

You then have your own connection to the database. When you are done
with it (basically every time you go to sleep in the thread), you close
it again:

  app._p_jar.close()
  del app

This way you keep conflicts down, performance up.

> OK, tracing along in setstate(), we get to this statement and 
> exception:
> 
>  > C:\Zope214\lib\python\ZODB\Connection.py(391)setstate()
>  -> p, serial = self._storage.load(oid, self._version)
>  (Pdb) s
>  AttributeError: "'None' objec...ribute 'load'"
>  > C:\Zope214\lib\python\ZODB\Connection.py(391)setstate()
>  -> p, serial = self._storage.load(oid, self._version)
>  (Pdb)
> 
> OOps! This connection's storage object has no load method. 
> How can that
> happen? Because pdb isn't showing how it got here, it's hard 
> to see what the
> cause is. Can someone who's been here before help me out?
> 
> Was the Catalog object not defined properly or not 
> initialized properly? If
> not, how is the Catalog storage object supposed to be initialized?

The storage is not defined. Probably because the Conection has been
closed in the meantime, which is what happens as soon as initialisation
of products is done. See lib/python/Zope/__init__.py

HTH

-- 
Martijn Pieters, Software Engineer 
| Digital Creations http://www.digicool.com 
| Creators of Zope      http://www.zope.org 
| mailto:mj@digicool.com       ICQ: 4532236
| PGP:
http://wwwkeys.nl.pgp.net:11371/pks/lookup?op=get&search=0xA8A32149 
-------------------------------------------