[ZODB-Dev] Re: session problems
Florent Guillaume
fg at nuxeo.com
Mon Jan 9 10:26:16 EST 2006
FWIW: this code was checked in just in time for Zope 2.9.0.
A cleaner version is included in 2.9.1 and trunk:
def _getMountedConnection(self, anyjar):
# This creates the DB if it doesn't exist yet and adds it
# to the multidatabase
self._getDB()
# Return a new or existing connection linked to the multidatabase set
return anyjar.get_connection(self._getDBName())
along with a unit test.
But the code that's in 2.9.0 is just as effective.
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) CTO, Director of R&D
+33 1 40 33 71 59 http://nuxeo.com fg at nuxeo.com
More information about the ZODB-Dev
mailing list