[Zope-dev] CORBA-ZODB: Is replacing global get_transaction() the only way...

John D. Heintz jheintz@isogen.com
Wed, 04 Oct 2000 17:09:39 -0500


Hi Jim!

Glad to here from you.  I don't think I'm clearly sharing the problem
I'm having.

See my comments below.

John Heintz

Jim Fulton wrote:
> 
> "John D.Heintz" wrote:
> >
> > Hi all,
> >
> > I am about to embark on integrating ZODB with CORBA,
> 
> Woo hoo!
> 
> > and am in the deep
> > thinking phase of the endeavor.  ;-)
> >
> > What I want to do is _explicitly_ manage connections and transactions
> > without being able to depend on what thread is running.  I know that
> > this is _not_ the way that Zope works,
> 
> That depends on your point of view.  The Zope publisher (ORB) largely
> automates transaction management for application programmers, so they
> don't have to deal with identifying transaction boundaries. So,
> from an application point of voew, these details are hidden.

First issue I need to clarify: I am not integrating ZPublisher, just
ZODB expose objects.  I want to do this because we are using ZODB to
persist complicated Python object (great database!) but are not
publishing them to the web.

> 
> >From a system point of view, Zope does manage per-thread transaction data.
> This is something a CORBA interface could provide as well.

CORBA provides two threading policies, and either could be used in a
thread/Connection per request model.  I am not intending on doing
Connection per request, I would rather manage Connections as longer
running activities so that I don't have to create servants more often
than necessary.

> 
> IMPORTANT NOTE: The ZODB-provided transaction manager automatically
> manages per-thread transaction information.
> 
> Were you aware of this? This sounds like what you need.

Yes, I'm pretty aware of this.  I have even studied the cPersistence.c
code, specifically the changed() function that calls the global
get_transaction() python function.
 
> > but if I want to use standard
> > CORBA I think I have only two choices:
> > 1) Explicitly associate Connections with Transactions in my CORBA
> > layer.  What I need to do is allow any thread to change a Persistent
> > object from some Connection,
> 
> This would be nice. Basically, you want to open a ZODB database
> connection and begin a transaction at the beginning of the request.
> At the end of the request, you want to commit or abort the transaction,
> depending on whether an error occurred, and close the connection.

This is the Zope publisher model.  I want to rather keep a persistent
reference to objects in the Database (from a Connection) across CORBA
Requests.  This is the core reason that I am trying to manage
Transactions/threads/Connections explicitly.
 
> > and make sure that the right transaction is
> > called for "register".
> 
> If I understand your requirements, then the standard transaction
> machinery should do this for you.

Except that I'm not committing or aborting necessarily at the end of a
CORBA Request.  I plan on having users login to the server and get back
a Session object that provides access to other objects in the system. 
That returned Session object will have a ZODB Connection and a
Transaction cached.  It also will expose through CORBA a commit() and
abort() method that delegates to the ZODB Transaction.

All this because I want to keep object from the ZODB Connection cache
around for a while.
 
> > 2) Build a complete wrapping adapter layer that does thread
> > synchronization to the actual Persistent objects and proper thread for
> > the transaction.
> >         - Lots of overhead and redundant coding - tricks with ExtensionClass
> > might make this adaptation simpler to code, but still it won't be easy.
> 
> I'm not sure what this is, but I think it probably isn't necessary.

This layer would exist to ensure that, across CORBA Requests, the
correct thread would be running.  The correct thread is the one that was
created in the CORBA Session object that open()ed the ZODB Connection.
 
> > Obviously number one is my preferred choice.  In order to accomplish
> > that, I see only two ways:
> > 1) Modify ZODB to maintain a Connection to Transaction link, and modify
> > cPersistence.c to use that link in the changed() function instead of
> > relying on the standard get_transaction() thread index.
> 
> Is there a one-to-one relation between threads and connections
> (or, more precisely, is it the case that there is never more than
> one simultaneous connection per thread)? If so, then get_transaction()
> should do the right thing.

There would not be any predictable mapping from threads to connections
for any two CORBA Requests if I don't throw away the connections after a
commit() or abort().
 
> > 2) Replace the get_transaction() in globals to return the appropriate
> > Transaction regardless of thread.
> 
> It currently returns a different transaction depending on the thread.

In the CORBA exposure I would never call get_transaction().  I would use
the reference to a transaction from the CORBA Session object that
originally open()ed a database connection.
 
> > Again, my preference is number one.  After going over the ZODB code, I
> > _think_ that a Connection is always associated with one Transaction.  If
> > this assumption is true, then it should be safe to make the change I'm
> > proposing. If not, then I need to understand why so that I can rethink
> > how to solve my problem. ;-)
> >
> > I hope that I've made my problems and ideas for solutions clear, if not
> > please let me know.
> 
> I dunno. You'll probably be able to tell from my response. :)

Only the difference between thread/Connection/transaction per request
versus exposing the same cached object across multiple CORBA requests.
 
> > Also, I think that I should be able to make the
> > changes to ZODB myself within the next few week, but only if there is
> > the _possibility_ of folding them back into the main Zope codebase.
> 
> I sincerely hope that no ZODB changes are necessary.

This is, in Python, the changes to Persistent that I feel would solve my
problem.  I think that in general this code would allow multiple thread
to modify ZODB objects while still keeping the right transaction up to
date.

import ZODB
from Persistence import Persistent
class TestPersistent(Persistent):
  self __changed__(self):
    "Completely ignoring self->state from c code..."
    
    if self._p_jar:
      self._p_jar.transaction.register(self)

and then in DB.py the open() method must add a transaction attribute to
the connection before returning.

I've got one more question.  What happens if I:
- make a connection to a database
- navigate to some objects and store references to them
- make some changes to these objects
- call get_transaction().abort()
- make some changes to the same objects (that I have references to)
- call get_transaction().commit()

Will everything do what I expect in this case?

Thanks so much for you time,
John Heintz


 
> > Thanks for any help,
> > John D. Heintz
> >
> > CORBA Threading description:
> > CORBA defines the POA, which has two standard threading policies:
> > ORB Controlled Model
> > Single Threaded Model
> >
> > The POA is basically a controller for requests to one or more
> > distributed objects, with thread policy as one of its parameters.
> >
> > The first threading policy means whatever the ORB gives you - single or
> > multi, and you have to deal with all synchronizations.
> >
> > The second I consider a mis-nomer because there can be many threads, but
> > only one at a time will access objects for a given POA.  (This is the
> > model that I perceive being used by default for ZODB object from a
> > specific Connection.)
> 
> No. Multiple threads can be accessing the same logical object.
> Each thread has it's own copy (and DB connection and transaction).
> 
> Jim
> 
> --
> Jim Fulton           mailto:jim@digicool.com   Python Powered!
> Technical Director   (888) 344-4332            http://www.python.org
> Digital Creations    http://www.digicool.com   http://www.zope.org
> 
> Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
> address may not be added to any commercial mail list with out my
> permission.  Violation of my privacy with advertising or SPAM will
> result in a suit for a MINIMUM of $500 damages/incident, $1500 for
> repeats.

-- 
John D. Heintz
DataChannel, Inc.
Senior Engineer
512-633-1198
jheintz@isogen.com