I suppose "folks" includes me. ;-) I'll try to have a look this
week... Sorry, I've been avoiding any actual work over the last week
or so.
- C
On Jan 1, 2006, at 10:23 PM, Florent Guillaume wrote:
Could folks have a look and tell me what they think of the proposed
patch? Actually it is my belief this is a concern of DB or
Connection, not MountedObject, and the code shouldn't be in
MountedObject but that's the easiest workaround for now.
Florent
Florent Guillaume wrote:
Ok I've dug deeper and now understand the problem. The root cause
is in the multi-databases support.
The problem is that the Zope startup only closes the main
connection it had on the root database. The first connection to
the TemporaryStorage, created and opened during Zope startup, is
never closed, so still is a synchronizer in its original
transaction, but is nevertheless reused in other transactins,
without a proper synchronizer set up.
When a MountedObject needs to be traversed, it tries to find an
existing connection for the new database by doing:
conn = anyjar.get_connection(db_name)
where anyjar is the "parent" connection. If there's a linked
connection for that database, it's returned, otherwise if the
multi- database already has seen the wanted database, it opens a
connection from it, then adds it to the "linked" connections
attribute (conn.connections) and shares this attribute between
the two connections.
I that fails, because the connection has never been linked to the
new database (which is the case during startup code), then the
MountedObject code does:
conn = self._getDB().open()
Here _getDB() correctly returns a newly instanciated database,
which has been linked to the other ones in the multi-databases
setup (shared "databases" dictionnary attribute, ultimately
coming from Zope2.Startup.datatypes.DBTab.databases).
Then open() returns a new opened connection for that database.
*BUT* this new connection is not "linked" to the others (using
their .connections attribute). This code from get_connections is
needed:
self.connections.update(new_con.connections)
new_con.connections = self.connections
which would be written, in the context of code executing in
MountedObject (in _getMountedConnection):
except KeyError:
conn = self._getDB().open()
anyjar.connections.update(conn.connections)
conn.connections = anyjar.connections
return conn
But of course really this code doesn't belong to MountedObject.
This is just the simplest way I could find, if others want to
test it.
The ".connections" sharing is really funky, apparently all the
connections opened in the context of the same multi-databases
support are intended to be present in it. Why is this access not
indirected through the multi-databases support in DB itself? Also
I don't understand why open()'s "delegate" attribute is not
stored as a connection attribute, and close() should reuse it
instead of obeying a "primary" attribute. Anyway, I guess
historical code, etc.
I'll let specialistst of the multi-databases decide what to do :)
Florent
--
Florent Guillaume, Nuxeo (Paris, France) Director of R&D
+33 1 40 33 71 59 http://nuxeo.com [EMAIL PROTECTED]
_______________________________________________
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/
ZODB-Dev mailing list - ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev
_______________________________________________
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/
ZODB-Dev mailing list - ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev