Hi Ralf,

Yes, I'd seen that. It looks quite similar to the thread that I quoted in my initial post! I wasn't too thorough in listing the steps that I'd already taken to understand the problem before turning to the list, sorry about that.

I was posting in the hope that someone might be familiar with the part of the code that consistently deadlocks and have a list of scenarios that hit that code path which I would be able to then avoid.

        } else {
            LinkedTx lock;

            lock = _readLock;
            while ( lock != null ) {
                // T1 trying to acquire lock on O1, which is locked by T2
                // T2 trying to acauire lock on O1, T1 is waiting on O1

// lock is the blocking transaction. We are only interested in
                // a blocked transacrtion.
                waitOn = lock.tx.getWaitOnLock();
                if ( waitOn != null && lock.tx != waitingTx ) {
                    LinkedTx read;

                    if ( waitOn._writeLock == waitingTx ) {
throw new LockNotGrantedException( Messages.message ("persist.deadlock") );
                    }
                    read = waitOn._readLock;
                    while ( read != null ) {
                        if ( read.tx == waitingTx )
throw new LockNotGrantedException( Messages.message ("persist.deadlock") );
                        read = read.next;
                    }
                    waitOn.detectDeadlock( waitingTx, numOfRec - 1 );
                }
                lock = lock.next;
            }
        }

It is always the line

if (read.txt == waitingTx)

that is true and the deadlock is detected there.

The application I'm working on is inherited code (isn't it always!), and it wraps Castor in an adapter which doesn't expose the full API; i.e. no read-only for starters. I suspect that it will be a quite involved process to examine the parts that are deadlocking, and work out how to avoid that problem in the application.

As previously mentioned, I've tried upgrading, but get problems when the XML mapping file is parsed due to NullPointerException. I'll try to create a test case for this later, but it seems to be due to having a class hierarchy like this:

public class Foo {
    private String theField;

    public String getField() {
        return this.theField;
    }

    public void setField(String theField) {
         this.theField = theField;
    }
}

public class Bar extends Foo {}

<class name="Foo">
    <map-to table="FOO" />
    <field name="theField" type="string">
      <sql name="theField" />
      <bind-xml name="theField" />
    </field>
</class>
<class name="Bar" extends="Foo">
    <map-to table="BAR" />
</class>

The fact that the Bar subclass doesn't have any new fields is what seems to cause the NPE, but I'll try to create a test case to confirm that it isn't just me missing something obvious.

Cheers,

James

Ralf Joachim wrote:
Hi James,

have you seen following document on best practice?

http://castor.codehaus.org/jdo-best-practice.html


I am also using castor together with oracle in a servlet context. In my
application I initialize JDOManager once with one of the
JDOManager.loadConfiguration() methods and call
JDOManager.createInstance("dbname") in the service method of my
servlets. This is save as JDOManager only creates a JDOManager instance
once and caches it in an internal map. In the service methods you can
call jdom.getDatabase() once and reuse it for all transactions of this
single thread. Never use a database instance at more then one thread.
But you are also open to use more then one database instance in one
service call. To prevent locking problems use AccessMode.ReadOnly
wherever possible and keep your transactions as short as possible. This
means, never keep transactions open while waiting for user response.

Having said that I suggest to upgrad to one of the new releases (e.g.
1.0.4) and move from JDO to JDOManager as we intend to remove JDO at one
of the next releases.

Hope this helps a bit.

Regards
Ralf


James Abley schrieb:
Werner,

I'm using Oracle 9.2. Sorry, I didn't make it clear enough in my
original mail. The existing code currently creates a JDO instance per
request and I am re-working it to put the JDO instance in the
ServletContext or similar.

I was just hoping that I might get some hints as to what else I should
be looking for when I get to that point, but I'm also happy to get
there, measure the effect and then see what new information I can
provide about this problem.

Cheers,

James

Werner Guttmann wrote:

James,

what RDBMS are you using ? And with regards to your last question, let
me just add that you should not create new JDO instances (or JDOManager
instances, as they are named with more recent releases) in a
multi-threaded, heavy-load application.

Just create a JDO instance once, and then call JDO.getDatabase()
whenever you've got something to do against the database, e.g. pesist an
entity, load an entity, etc.

Werner

James Abley wrote:

Hi,

I am having some problems with deadlocks in my application. It works
fine with a single client and I have functional tests which exercise
this part of the application, but once I start cranking up the number of
clients, I rapidly see lots of these:

Caused by: org.exolab.castor.jdo.TransactionAbortedException: Nested
error: org.exolab.castor.jdo.LockNotGrantedException: Deadlock has been
detected while attempting to acquire a lock: Deadlock has been detected
while attempting to acquire a lock
        at
org.exolab.castor.persist.TransactionContext.prepare(TransactionContext.java:1654)


        at
org.exolab.castor.jdo.engine.DatabaseImpl.commit(DatabaseImpl.java:545)
vola         ... 34 more
Caused by: org.exolab.castor.jdo.LockNotGrantedException: Deadlock has
been detected while attempting to acquire a lock
        at
org.exolab.castor.persist.ObjectLock.detectDeadlock(ObjectLock.java:983)
        at
org.exolab.castor.persist.ObjectLock.upgrade(ObjectLock.java:770)
        at
org.exolab.castor.persist.LockEngine$TypeInfo.upgrade(LockEngine.java:1324)

        at
org.exolab.castor.persist.LockEngine$TypeInfo.access$600(LockEngine.java:1055)


        at
org.exolab.castor.persist.LockEngine.writeLock(LockEngine.java:801)
        at
org.exolab.castor.persist.TransactionContext.writeLock(TransactionContext.java:1344)


        at
org.exolab.castor.persist.ClassMolder.preStore(ClassMolder.java:1547)
        at
org.exolab.castor.persist.LockEngine.preStore(LockEngine.java:718)
        at
org.exolab.castor.persist.TransactionContext.prepare(TransactionContext.java:1521)


        ... 36 more

I am using Castor 0.9.6. I tried upgrading to 1.0.3 but got
NullPointerExceptions (I'll create a test case separately to see if it's
a bug, or more probably, a problem with my mapping file), so I'm
sticking with 0.9.6 currently and trying to understand how I'm misusing
Castor and what I should do to eliminate, or at least minimise these
deadlocks.

The only related thread that I have found so far on the mailing list
archive is this:

http://www.mail-archive.com/[email protected]/msg00205.html

There are a couple of the suggested issues present in the codebase that
I am currently working on fixing; notably a new JDO instance is being
created each request:

    JDO newJdo = new JDO();
    newJdo.setDatabaseName(databaseName);

    // We resolve the full config URI
    URL u = getClass().getResource(configurationURI);
    if (u == null) {
        throw new RepositoryException(
        "Unable to locate config file " + configurationURI);
    }

    newJdo.setConfiguration(u.toString());

But I was wondering if people might be able to comment on any other
fruitful avenues to pursue?

Regards,

James

---------------------------------------------------------------------
To unsubscribe from this list please visit:

   http://xircles.codehaus.org/manage_email



---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


---------------------------------------------------------------------
To unsubscribe from this list please visit:

   http://xircles.codehaus.org/manage_email



---------------------------------------------------------------------
To unsubscribe from this list please visit:

   http://xircles.codehaus.org/manage_email

Reply via email to