jira.codehaus.org

  • Log In Access more options
    • Online Help
    • Keyboard Shortcuts
    • About JIRA
    • JIRA Credits
    • What?s New
  • Dashboards Access more options (Alt+d)
  • Projects Access more options (Alt+p)
  • Issues Access more options (Alt+i)
  • castor
  • CASTOR-241

ObjectNotFoundException during load() appears to not release in-memory read lock

  • Log In
  • Views
    • XML
    • Word
    • Printable

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 0.9.4
  • Fix Version/s: 1.3.1
  • Component/s: JDO
  • Labels:
    None
  • Environment:
    Operating System: Windows 2000
    Platform: PC
  • Bugzilla Id:
    1097

Description

A code snippet similar to the following should recreate the problem:

Database database = jdo.getDatabase();
database.begin();
Foo foo = null;
try {
foo = (Foo) database.load(Foo.class, new Integer(1));
} catch (ObjectNotFoundException e) {
foo = new Foo();
database.create(foo);
}
database.commit();
database.close();

When using a key-generator="IDENTITY" mapping the create() following the
unsuccessful load() will cause the following exception when '1' happens to be
the next identity key to be generated:

org.exolab.castor.jdo.PersistenceException: Nested error: Key Generator
Failure. Duplicated Identity is generated!
at org.exolab.castor.persist.LockEngine.create(Unknown Source)
at org.exolab.castor.persist.TransactionContext.create(Unknown Source)
at org.exolab.castor.jdo.engine.DatabaseImpl.create(Unknown Source)

At the same time, the following exception is printed to the console:

org.exolab.castor.jdo.LockNotGrantedException: Lock is already existed for the
new oid.
at org.exolab.castor.persist.LockEngine$TypeInfo.rename(Unknown Source)
at org.exolab.castor.persist.LockEngine$TypeInfo.access$400(Unknown
Source)
at org.exolab.castor.persist.LockEngine.create(Unknown Source)
at org.exolab.castor.persist.TransactionContext.create(Unknown Source)
at org.exolab.castor.jdo.engine.DatabaseImpl.create(Unknown Source)

  • Options
    • Sort By Name
    • Sort By Date
    • Ascending
    • Descending
    • Download All

Attachments

  1. Text File
    patch-1097.txt
    09/Sep/05 3:21 PM
    1 kB
    Ralf Joachim
  2. Text File
    patch-C241-20090220.txt
    20/Feb/09 2:49 PM
    9 kB
    Ralf Joachim

Activity

Ascending order - Click to sort in descending order
  • All
  • Comments
  • Work Log
  • History
  • Activity
Hide
Permalink
mguessan added a comment - 13/Dec/02 3:14 AM

I reproduced the problem with a simple class and the MAX generator.

The sequence is

  • LockEngine.load calls typeInfo.acquire to create the lock
  • ObjectNotFoundException is thrown
  • LockEngine.load calls lock.confirm( tx, false ) => the lock is
    no longer active, but still in the locks Map
  • When the new Object is created, its temporary OID (before key
    generation) must be converted to the new one, which happen to be
    equals to the one generated by the load call
    => crash in TypeInfo.rename

I first tried to remove the lock when catching the first exception,
but some test cases are broken by this.
The next thing to try is to use a more precise test in TypeInfo.rename, I
tried :

if ( newentry != null && !newentry.isDisposable())
throw new LockNotGrantedException("Lock is already existed for the new oid.");

All tests are OK with this one but I'm not yet sure of the validity of this
patch... Some more work on this is needed.

Show
mguessan added a comment - 13/Dec/02 3:14 AM I reproduced the problem with a simple class and the MAX generator. The sequence is
  • LockEngine.load calls typeInfo.acquire to create the lock
  • ObjectNotFoundException is thrown
  • LockEngine.load calls lock.confirm( tx, false ) => the lock is no longer active, but still in the locks Map
  • When the new Object is created, its temporary OID (before key generation) must be converted to the new one, which happen to be equals to the one generated by the load call => crash in TypeInfo.rename
I first tried to remove the lock when catching the first exception, but some test cases are broken by this. The next thing to try is to use a more precise test in TypeInfo.rename, I tried : if ( newentry != null && !newentry.isDisposable()) throw new LockNotGrantedException("Lock is already existed for the new oid."); All tests are OK with this one but I'm not yet sure of the validity of this patch... Some more work on this is needed.
Hide
Permalink
Werner Guttmann added a comment - 10/May/04 7:42 AM

Michael, you wouldn't be able to attach a patch for the solution outlined below ?

Show
Werner Guttmann added a comment - 10/May/04 7:42 AM Michael, you wouldn't be able to attach a patch for the solution outlined below ?
Hide
Permalink
Werner Guttmann added a comment - 10/May/04 7:43 AM

Stein, is this bug about the same problem as bug 1519 ?

Show
Werner Guttmann added a comment - 10/May/04 7:43 AM Stein, is this bug about the same problem as bug 1519 ?
Hide
Permalink
Stein M. Hugubakken added a comment - 10/May/04 8:38 AM

Yes, it's the same as #1519.

Show
Stein M. Hugubakken added a comment - 10/May/04 8:38 AM Yes, it's the same as #1519.
Hide
Permalink
Werner Guttmann added a comment - 10/May/04 10:28 AM

In this case, can we close one and mark it as duplicate of the other ? E.g.
close this one and leave 1519 as valid accepted ? Or the other way around ?

Show
Werner Guttmann added a comment - 10/May/04 10:28 AM In this case, can we close one and mark it as duplicate of the other ? E.g. close this one and leave 1519 as valid accepted ? Or the other way around ?
Hide
Permalink
Stein M. Hugubakken added a comment - 10/May/04 10:33 AM

Keep the original and mark bug 1519 as duplicate.

Show
Stein M. Hugubakken added a comment - 10/May/04 10:33 AM Keep the original and mark bug 1519 as duplicate.
Hide
Permalink
Werner Guttmann added a comment - 10/May/04 11:03 AM
      • Bug 1519 has been marked as a duplicate of this bug. ***
Show
Werner Guttmann added a comment - 10/May/04 11:03 AM
      • Bug 1519 has been marked as a duplicate of this bug. ***
Hide
Permalink
Stein M. Hugubakken added a comment - 10/May/04 12:02 PM

Created an attachment (id=504)
Demonstration patch

Show
Stein M. Hugubakken added a comment - 10/May/04 12:02 PM Created an attachment (id=504) Demonstration patch
Hide
Permalink
Stein M. Hugubakken added a comment - 10/May/04 12:10 PM

In my original bug 1519 I didn't have a problem with the key-generator, I just
observed the item in locks was not removed.

Perhaps we shouldn't have made it a dup?

The patch I attached prints true or false if the item is in the locks, do we
agree that this is the problem?

Show
Stein M. Hugubakken added a comment - 10/May/04 12:10 PM In my original bug 1519 I didn't have a problem with the key-generator, I just observed the item in locks was not removed. Perhaps we shouldn't have made it a dup? The patch I attached prints true or false if the item is in the locks, do we agree that this is the problem?
Hide
Permalink
Werner Guttmann added a comment - 11/May/04 2:54 AM

> The patch I attached prints true or false if the item is in the
> locks, do we agree that this is the problem?
Yes, I think this is the problem.

Show
Werner Guttmann added a comment - 11/May/04 2:54 AM > The patch I attached prints true or false if the item is in the > locks, do we agree that this is the problem? Yes, I think this is the problem.
Hide
Permalink
Werner Guttmann added a comment - 11/May/04 2:56 AM

Can we attach a small JUnit test case that e.g. insert a couple of recores to a
table, then tries to load an object instance that does not exist, etc? Just for
the sake of this discussion .. .

Show
Werner Guttmann added a comment - 11/May/04 2:56 AM Can we attach a small JUnit test case that e.g. insert a couple of recores to a table, then tries to load an object instance that does not exist, etc? Just for the sake of this discussion .. .
Hide
Permalink
Werner Guttmann added a comment - 11/Oct/04 2:04 PM

Gregory, just wondering whether this sounds familiar to you ?
ObjectNotFoundExceptions not releasing a lock ... or am I confusing two
completely unrelated things ?

Show
Werner Guttmann added a comment - 11/Oct/04 2:04 PM Gregory, just wondering whether this sounds familiar to you ? ObjectNotFoundExceptions not releasing a lock ... or am I confusing two completely unrelated things ?
Hide
Permalink
gblock@ctoforaday.com added a comment - 12/Oct/04 12:51 AM

No, feels the same to me. I've just got gut feelings about this...

The issue, if I'm going to make a guess, is going to be the same issue I have with
persist.TransactionManager's explicit unlock()ing....

It would be really, really nice if locks were always safe to call release on, and release() was always
called 100% of the time, regardless of reason, and all statements in TransactionManager did a catch
Throwable to ensure that those releases took place appropriately, regardless of the exception or
throwable in the underlying code, and preventing the locks from getting into a complete state.

Again, I don't know enough about this code to be sure - but I'm familiar enough with locking semantics
to get a pretty good feel for what looks like pretty bad behavior. Not only do we not call release() often
enough, but rollback() doesn't look like it will behave properly if a problem happens during
revertObject() - the lock never gets released, and all we do is print the exception. (And that shouldn't
be an except.printStackTrace(), either)

I'd like to see better safety in that class.

Show
gblock@ctoforaday.com added a comment - 12/Oct/04 12:51 AM No, feels the same to me. I've just got gut feelings about this... The issue, if I'm going to make a guess, is going to be the same issue I have with persist.TransactionManager's explicit unlock()ing.... It would be really, really nice if locks were always safe to call release on, and release() was always called 100% of the time, regardless of reason, and all statements in TransactionManager did a catch Throwable to ensure that those releases took place appropriately, regardless of the exception or throwable in the underlying code, and preventing the locks from getting into a complete state. Again, I don't know enough about this code to be sure - but I'm familiar enough with locking semantics to get a pretty good feel for what looks like pretty bad behavior. Not only do we not call release() often enough, but rollback() doesn't look like it will behave properly if a problem happens during revertObject() - the lock never gets released, and all we do is print the exception. (And that shouldn't be an except.printStackTrace(), either) I'd like to see better safety in that class.
Hide
Permalink
Werner Guttmann added a comment - 12/Oct/04 5:42 AM

> It would be really, really nice if locks were always safe to call
> release on, and release() was always called 100% of the time, regardless
> of reason, and all statements in TransactionManager did a catch Throwable
> to ensure that those releases took place appropriately, regardless of
> the exception or throwable in the underlying code, and preventing the
> locks from getting into a complete state.
100% agreed. Most definitely. all exception handling should be converted to
catch Throwable, and if special behaviour is required, instanceof statements
should be used within the catch clause to selectively throw different
exceptions as a result of the original exception. Next, we should try to use
finally clauses wherever possible, making sure that locks are being released
properly despite exceptions being thrown elsewhere.

I'll come up with a to-do list as part of this bug, and let me see how much
spare time I can dedicate to this... .

Show
Werner Guttmann added a comment - 12/Oct/04 5:42 AM > It would be really, really nice if locks were always safe to call > release on, and release() was always called 100% of the time, regardless > of reason, and all statements in TransactionManager did a catch Throwable > to ensure that those releases took place appropriately, regardless of > the exception or throwable in the underlying code, and preventing the > locks from getting into a complete state. 100% agreed. Most definitely. all exception handling should be converted to catch Throwable, and if special behaviour is required, instanceof statements should be used within the catch clause to selectively throw different exceptions as a result of the original exception. Next, we should try to use finally clauses wherever possible, making sure that locks are being released properly despite exceptions being thrown elsewhere. I'll come up with a to-do list as part of this bug, and let me see how much spare time I can dedicate to this... .
Hide
Permalink
Werner Guttmann added a comment - 12/Oct/04 5:46 AM

To-do list:

  • replace all occurences of e.printStackTrace with calls to logging API.
  • Amend code to catch Throwable in all places.
  • Use finally clause wherever possible, making sure that a lock is released
    properly despite exceptions being thropwn elsewhere.
  • If special exception handling is required, implement this as part of the
    catch clause (using instanceof).

And I assume that we are talking about refactoring 'TransactionContext',
correct ?

Show
Werner Guttmann added a comment - 12/Oct/04 5:46 AM To-do list:
  • replace all occurences of e.printStackTrace with calls to logging API.
  • Amend code to catch Throwable in all places.
  • Use finally clause wherever possible, making sure that a lock is released properly despite exceptions being thropwn elsewhere.
  • If special exception handling is required, implement this as part of the catch clause (using instanceof).
And I assume that we are talking about refactoring 'TransactionContext', correct ?
Hide
Permalink
gblock@ctoforaday.com added a comment - 14/Oct/04 10:22 AM

Throwable's a bit of a funny one - because I think it catches out of memory exceptions as well, which, if
not thrown all the way, will result in weak referenced objects not getting garbage collected. Anything
that's a VirtualMachineError needs to be rethrown if you do that. Still good to release the lock before
rethrowing, of course.

Show
gblock@ctoforaday.com added a comment - 14/Oct/04 10:22 AM Throwable's a bit of a funny one - because I think it catches out of memory exceptions as well, which, if not thrown all the way, will result in weak referenced objects not getting garbage collected. Anything that's a VirtualMachineError needs to be rethrown if you do that. Still good to release the lock before rethrowing, of course.
Hide
Permalink
Ralf Joachim added a comment - 09/Sep/05 3:21 PM

Demonstration patch reattached from bugzilla.

Show
Ralf Joachim added a comment - 09/Sep/05 3:21 PM Demonstration patch reattached from bugzilla.
Hide
Permalink
Werner Guttmann added a comment - 11/Sep/05 9:18 AM

Okay, looking at his again .. . I think if somebody provided me with a complete test case (as set out in src/bugs/jdo/template), this would be absolutely great. The above to-do list still looks like quite a well-written recipe to me ... any volunteers (but Ralf and me) ? Greg ? Given your apparent familiarity in this area, this should be quite straight-forward to you .. .

Show
Werner Guttmann added a comment - 11/Sep/05 9:18 AM Okay, looking at his again .. . I think if somebody provided me with a complete test case (as set out in src/bugs/jdo/template), this would be absolutely great. The above to-do list still looks like quite a well-written recipe to me ... any volunteers (but Ralf and me) ? Greg ? Given your apparent familiarity in this area, this should be quite straight-forward to you .. .
Hide
Permalink
Ralf Joachim added a comment - 20/Feb/09 2:49 PM

Added test to verify that ObjectNotFoundException during load() releases in-memory read lock. As the test does not show any failure i'll commit this as is.

Show
Ralf Joachim added a comment - 20/Feb/09 2:49 PM Added test to verify that ObjectNotFoundException during load() releases in-memory read lock. As the test does not show any failure i'll commit this as is.

People

  • Assignee:
    Ralf Joachim
    Reporter:
    Levi Purvis
Vote (0)
Watch (0)

Dates

  • Created:
    02/Nov/02 4:27 PM
    Updated:
    30/Dec/09 4:21 AM
    Resolved:
    20/Feb/09 2:50 PM
  • Atlassian JIRA (v5.0.4#731-sha1:3aa7374)
  • Report a problem
  • Powered by a free Atlassian JIRA open source license for Codehaus. Try JIRA - bug tracking software for your team.