Hi Matthew,

On Apr 13, 2007, at 2:50 PM, Matthew Adams wrote:

If the current transaction is optimistic and active, then getDataStoreConnection() should cause the optimistic transaction to be converted to a datastore transaction and the returned object will be enlisted in the newly begun datastore transaction.

I'm not completely sure about your proposed wording, since there are interrogatives that allow you to ask whether the transaction is optimistic or datastore, so "converting the optimistic transaction to datastore" might not be the right wording. Were you thinking that after flush, getOptimistic() would return true or false?

But I agree with the intent. That is, after flush() or getDataStoreConnection(true) the connection to the datastore will be enlisted in a native datastore transaction until the end of the JDO transaction.

Craig

This is a result that is consistent with the proposal but should probably be made explicit in the first paragraph of the proposal. Here's the updated one:

<proposed updated-by="matthew">
Connection getDataStoreConnection()

This method is equivalent to getDataStoreConnection
(pm.currentTransaction().isActive()). That is, it defaults to
getDataStoreConnection(true) if a JDO transaction is active, and
getDataStoreConnection(false) if not.  If the JDO transaction is
optimistic and active, then it is converted to a datastore
transaction and the returned object is enlisted in the newly
begun datastore transaction.

JDOConnection getDataStoreConnection(boolean enlist)

This method returns either a JDOConnection whose underlying native
connection is enlisted in the native datastore transaction in use by
the persistence manager; or a JDOConnection whose underlying native
connection is not enlisted in any native transaction. An unenlisted
connection is set to auto-commit if using a data source that has this
concept (e.g. JDBC).

If this method is called outside an active transaction, with the
enlist parameter false, the object returned will not be enlisted in
any transaction. If this method is called outside an active
transaction, with the enlist parameter true, JDOUserException is thrown.

If this method is called while a datastore transaction is active,
with the enlist parameter false, the object returned will not be
enlisted in any transaction. If this method is called while a
datastore transaction is active, with the enlist parameter true, the
object returned will be enlisted in the current native datastore
transaction.

If this method is called while an optimistic transaction is active,
with the enlist parameter false, the object returned will not be
enlisted in any transaction. If this method is called while an
optimistic transaction is active, and the enlist parameter is true, a
native datastore transaction is begun if not already begun, and the
object returned will be enlisted in the current native datastore
transaction.

</proposed>

-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
Sent: Friday, April 13, 2007 11:36 AM
To: Apache JDO project; JDO Expert Group
Subject: Re: enlistment of native connections for optimistic txs

Hi Guido,

A new proposal is attached below.

On Apr 10, 2007, at 2:03 AM, Guido Anzuoni wrote:

Craig L Russell wrote:
Hi Erik,

Thanks for clarifying your proposal.

I agree that this improves portability, but with a penalty. You
can no
longer use optimistic concurrency once you decide to do some native
SQL, even if you don't ever perform any INSERT, DELETE, or UPDATE
statements. And this will have negative performance consequences for
some applications.

While backward compatibility is important, I would agree with you
that
correctness is even more important. So it doesn't bother me too much
if we change the semantic so that by default, getting a datastore
connection is equivalent to doing a flush in an optimistic
transaction. But I'd still like to give the user the ability to get
the same level of performance they now enjoy by deferring the
enlistment in the datastore transaction to flush or commit.

So how about adding a flag that defaults to true if not specified to
enlist the datastore connection in the datastore transaction?

<proposed>
Connection getDataStoreConnection()

This method is equivalent to getDataStoreConnection(true).

Seems like the default should be different based on whether you are
in a JDO transaction.

So maybe the default should be getDataStoreConnection
(pm.currentTransaction().isActive())

Connection getDataStoreConnection(boolean enlist)

If this method is called outside an active transaction, the object
returned will not be enlisted in any
transaction, regardless of the setting of the enlist parameter.
In this case, the user does not know that his request has not been
honored.

Maybe it makes sense to throw a JDOUserException, since there is no
transaction in which to enlist the connection, and the default is
false. A user can only get the exception by asking for something that
is impossible.


If it is called while a datastore transaction is active, the object
returned will be enlisted in the current transaction, regardless of
the setting of the enlist parameter.

Again, the implementation might do something different from what
requested.

Right, either a non-enlisted connection (enlist==false) or the
connection enlisted in the current transaction.

The use case for this is to grab a non-enlisted connection that is
used e.g. to get a sequence number that will never be rolled back.

If it is called while an optimistic transaction is active, and the
enlist parameter is true, a datastore transaction is begun if not
already begun, and the object returned will be enlisted in the
current
datastore transaction.

If it is called while an optimistic transaction is active,
the enlist
parameter is false, and a datastore transaction is already
begun, the
object returned will be enlisted in the datastore transaction.
Same as above

Right, either a separate non-enlisted connection (enlist==false) or
the connection enlisted in the current transaction (enlist==true).


If it is called while an optimistic transaction is active,
the enlist
parameter is false, and a datastore transaction is not
already begun,
the object returned will not be enlisted in any datastore
transaction.
</proposed>
What if the user issues some INSERT, DELETE, UPDATE ?

This is the user's choice, which is not a default behavior, but
something explicitly asked for. The default will always be to get an
enlisted connection, and the only way to get a non-enlisted
connection is to ask for it.

Is it possible to call conn.commit() ?

Yes, the non-enlisted connection changes were already committed (auto-
commit). We should add this to the spec, that the non-enlisted
connection is auto-commit.

I agree that there is a potential penalty in optimistic
transactions if
we blindly enlist native connections but, if we let the user know
exactly what is going on,
an aware decision can be taken.
getDataStoreConnection() will always return the enlisted
connection if
any, otherwise null is returned (maybe getNativeConnection() could
return null).

I think that returning null is never the right behavior.

Now, if the user wants to access a consistent backend, he HAVE to
flush(), triggering connection enlistment (what if there are no
pending
updates ?).
If the user wants to operate on an independent connection to the same
datastore used by the PM he could use what is configured in the PMF
(OK, some helper methods might...help).

I think that inventing a parallel mechanism is overkill if we can
give users what the need from this one.

It could be also achieved with a different handling of the proposed
enlist flag for the 'false' scenarios, but it would be strange to
request to the
PM a datastore connection the PM is not using at all !!!. It would
look
like a data source.

Yes, that's the intent. There is no need for the user to somehow go
behind the scenes to figure out how the PMF is configured and get a
connection from that same data source.

Craig

<proposed>
Connection getDataStoreConnection()

This method is equivalent to getDataStoreConnection
(pm.currentTransaction().isActive()). That is, it defaults to
getDataStoreConnection(true) is a JDO transaction is active, and
getDataStoreConnection(false) if not.

JDOConnection getDataStoreConnection(boolean enlist)

This method returns either a JDOConnection whose underlying native
connection is enlisted in the native datastore transaction in use by
the persistence manager; or a JDOConnection whose underlying native
connection is not enlisted in any native transaction. An unenlisted
connection is set to auto-commit if using a data source that has this
concept (e.g. JDBC).

If this method is called outside an active transaction, with the
enlist parameter false, the object returned will not be enlisted in
any transaction. If this method is called outside an active
transaction, with the enlist parameter true, JDOUserException
is thrown.

If this method is called while a datastore transaction is active,
with the enlist parameter false, the object returned will not be
enlisted in any transaction. If this method is called while a
datastore transaction is active, with the enlist parameter true, the
object returned will be enlisted in the current native datastore
transaction.

If this method is called while an optimistic transaction is active,
with the enlist parameter false, the object returned will not be
enlisted in any transaction. If this method is called while an
optimistic transaction is active, and the enlist parameter is true, a
native datastore transaction is begun if not already begun, and the
object returned will be enlisted in the current native datastore
transaction.

</proposed>

Craig


Guido.

Craig

On Apr 8, 2007, at 1:49 PM, Erik Bengtson wrote:


Hi,

This is a change proposal to the spec with regards to enlistment of
native
connections when optimistic transactions are used.

The enlistment of native connections into a JDO transaction is
conditioned to
the fact that a flush call has been performed before the
connection is
obtained.

The flush call is a JDO implementation decision which can differ
between
different implementations. See the example:

1. tx.begin();
2. //more operations here....
3. JDOConnection conn = pm.getDataStoreConnection();
4. Connection sqlconn = (Connection) conn.getNativeConnection();
5. sqlconn.execute("DELETE FROM ANIMAL WHERE NAME = 'CAT'")
5. conn.close();
6. tx.rollback();

There are two possible behaviors:

- The JDO implementation decides to perform a flush between 1 and
3: the
connection is enlisted, and DELETE all CATS from ANIMAL is rolled
back
- The JDO implementation decides to NOT perform a flush between 1
and
3: the
connection is not enlisted, and DELETE all CATS from ANIMAL is not
rolled back

As you can see, this is not portable and not ACID, so I would
like to
propose
that enlistment of connections is done whenever a transaction is
opened.

The change is to the following paragraph:

The JDO spec ยง12.16 - getDataStoreConnection:

"If this method is called while a datastore transaction is active,
the object
returned will be enlisted in the current transaction. If called
in an
optimistic transaction before flush has been called, or outside an
active
transaction, the object returned will not be enlisted in any
transaction."

AS:

"If this method is called while a datastore or optimistc
transaction
is active,
the object returned will be enlisted in the current transaction. If
called
outside an active transaction, the object returned will not be
enlisted in any
transaction."



Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/
jdo
408 276-5638 mailto:[EMAIL PROTECTED]
P.S. A good JDO? O, Gasp!



Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/ jdo
408 276-5638 mailto:[EMAIL PROTECTED]
P.S. A good JDO? O, Gasp!



Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:[EMAIL PROTECTED]
P.S. A good JDO? O, Gasp!

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to