Uploaded image for project: 'OpenJPA'
  1. OpenJPA
  2. OPENJPA-2472

Concurrency issue in ClassMetaData.getPkAndNonPersistentManagedFmdIndexes()

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 2.2.2, 2.3.0
    • Fix Version/s: 2.2.1.1, 2.2.3, 2.4.0
    • Component/s: kernel
    • Labels:
      None

      Description

      In a scenario where brand new entity instances of the same class get inserted concurrently, we noticed sporadic failures like this:

      Caused by: <openjpa-2.3.0-r422266:1540826 fatal store error> org.apache.openjpa.persistence.EntityNotFoundException: The transaction has been rolled back. See the nested exceptions for details on the errors that occurred.
      at org.apache.openjpa.kernel.BrokerImpl.newFlushException(BrokerImpl.java:2370)
      at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2207)
      at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2105)
      at org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2023)
      at org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
      at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1528)
      at org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:933)
      at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:570)
      ... 2 more
      Caused by: <openjpa-2.3.0-r422266:1540826 nonfatal store error> org.apache.openjpa.persistence.EntityNotFoundException: The instance of type "class ..." with oid "ec2cfaa9e2f04b628d7e1991e65751dc" no longer exists in the data store. This may mean that you deleted the instance in a separate transaction, but this context still has a cached version.
      at org.apache.openjpa.kernel.StateManagerImpl.loadFields(StateManagerImpl.java:3109)
      at org.apache.openjpa.kernel.StateManagerImpl.loadField(StateManagerImpl.java:3188)
      at org.apache.openjpa.kernel.StateManagerImpl.fetchStringField(StateManagerImpl.java:2474)
      at org.apache.openjpa.kernel.StateManagerImpl.fetchString(StateManagerImpl.java:2464)
      at org.apache.openjpa.jdbc.meta.strats.StringFieldStrategy.insert(StringFieldStrategy.java:105)
      at org.apache.openjpa.jdbc.meta.FieldMapping.insert(FieldMapping.java:623)
      at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.insert(AbstractUpdateManager.java:238)
      at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.populateRowManager(AbstractUpdateManager.java:165)
      at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:96)
      at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:77)
      at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:732)
      at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
      ... 9 more

      The primary ID of each entity is set manually by the app prior to insertion.

      Debugging led me to ClassMetaData.getPkAndNonPersistentManagedFmdIndexes() which is called from StateManagerImpl.initialize() to set up the _loaded bit set. When the above exception occurs, all bits in that set are zero. This ultimately caused the erroneous loadField() call that fails the insertion.

      The following line in getPkAndNonPersistentManagedFmdIndexes() disturbs the thread-safety:

      _pkAndNonPersistentManagedFmdIndexes = new int[idsSize];

      Once this has executed, another thread which executes the if (_pkAndNonPersistentManagedFmdIndexes == null) in line 2778 can read the array before the first thread has finished the loop that initializes its values.

      The line following "// Default to FALSE, until proven true." in hasPKFieldsFromAbstractClass() looks equally troublesome, setting an instance variable to a temp value. Somebody whose more familar with the codebase might want to check for more occurrences of this pattern.

      1. OPENJPA-2472.txt
        8 kB
        Dalia Abo Sheasha

        Activity

        Hide
        dalia Dalia Abo Sheasha added a comment -

        I have attached a patch where I solve this issue by using a temporary variable to store the field's data we're interested in and populate it. Then after the temporary variable is finished being populated, the field is assigned to the temporary variable.
        I also attached the tests I used to make sure the problem is solved using this solution.

        Show
        dalia Dalia Abo Sheasha added a comment - I have attached a patch where I solve this issue by using a temporary variable to store the field's data we're interested in and populate it. Then after the temporary variable is finished being populated, the field is assigned to the temporary variable. I also attached the tests I used to make sure the problem is solved using this solution.
        Hide
        jira-bot ASF subversion and git services added a comment -

        Commit 1564989 from Rick Curtis in branch 'openjpa/trunk'
        [ https://svn.apache.org/r1564989 ]

        OPENJPA-2472: Fix concurrency bug in ClassMetaData. Patch contributed by Dalia Abo Sheasha.

        Show
        jira-bot ASF subversion and git services added a comment - Commit 1564989 from Rick Curtis in branch 'openjpa/trunk' [ https://svn.apache.org/r1564989 ] OPENJPA-2472 : Fix concurrency bug in ClassMetaData. Patch contributed by Dalia Abo Sheasha.
        Hide
        curtisr7 Rick Curtis added a comment -

        Committed revision 1564989 to trunk. Thanks for the patch Dalia!

        I'll note that I excluded your contributed test as recreating this timing window is very machine dependent.

        Show
        curtisr7 Rick Curtis added a comment - Committed revision 1564989 to trunk. Thanks for the patch Dalia! I'll note that I excluded your contributed test as recreating this timing window is very machine dependent.
        Hide
        jira-bot ASF subversion and git services added a comment -

        Commit 1713741 from Heath Thomann in branch 'openjpa/branches/2.2.1.x'
        [ https://svn.apache.org/r1713741 ]

        OPENJPA-2472: Fix concurrency bug in ClassMetaData. Patch contributed by Dalia Abo Sheasha - back ported to 2.2.1.x Dalia's trunk changes.

        Show
        jira-bot ASF subversion and git services added a comment - Commit 1713741 from Heath Thomann in branch 'openjpa/branches/2.2.1.x' [ https://svn.apache.org/r1713741 ] OPENJPA-2472 : Fix concurrency bug in ClassMetaData. Patch contributed by Dalia Abo Sheasha - back ported to 2.2.1.x Dalia's trunk changes.
        Hide
        jira-bot ASF subversion and git services added a comment -

        Commit 1713742 from Heath Thomann in branch 'openjpa/branches/2.2.x'
        [ https://svn.apache.org/r1713742 ]

        OPENJPA-2472: Fix concurrency bug in ClassMetaData. Patch contributed by Dalia Abo Sheasha - back ported to 2.2.x Dalia's trunk changes.

        Show
        jira-bot ASF subversion and git services added a comment - Commit 1713742 from Heath Thomann in branch 'openjpa/branches/2.2.x' [ https://svn.apache.org/r1713742 ] OPENJPA-2472 : Fix concurrency bug in ClassMetaData. Patch contributed by Dalia Abo Sheasha - back ported to 2.2.x Dalia's trunk changes.

          People

          • Assignee:
            curtisr7 Rick Curtis
            Reporter:
            bentmann Benjamin Bentmann
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development