This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
View | Details | Raw Unified | Return to bug 259993 | Differences between
and this patch

Collapse All | Expand All

(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/helper/WriteLockManager.java (-2 / +15 lines)
Lines 64-69 Link Here
64
        IdentityHashMap lockedObjects = new IdentityHashMap();
64
        IdentityHashMap lockedObjects = new IdentityHashMap();
65
        IdentityHashMap refreshedObjects = new IdentityHashMap();
65
        IdentityHashMap refreshedObjects = new IdentityHashMap();
66
        try {
66
        try {
67
            // initialize the MergeManager
68
            if(null != unitOfWork.getMergeManager()) { // may be null on a em.getReference() call
69
                unitOfWork.getMergeManager().setLockThread(Thread.currentThread());
70
            }
71
            
67
            // if the descriptor has indirection for all mappings then wait as there will be no deadlock risks
72
            // if the descriptor has indirection for all mappings then wait as there will be no deadlock risks
68
            CacheKey toWaitOn = acquireLockAndRelatedLocks(objectForClone, lockedObjects, refreshedObjects, cacheKey, descriptor, session, unitOfWork);
73
            CacheKey toWaitOn = acquireLockAndRelatedLocks(objectForClone, lockedObjects, refreshedObjects, cacheKey, descriptor, session, unitOfWork);
69
            int tries = 0;
74
            int tries = 0;
Lines 118-123 Link Here
118
        if (!refreshedObjects.containsKey(objectForClone) && this.checkInvalidObject(objectForClone, cacheKey, descriptor, unitOfWork)) {
123
        if (!refreshedObjects.containsKey(objectForClone) && this.checkInvalidObject(objectForClone, cacheKey, descriptor, unitOfWork)) {
119
            return cacheKey;
124
            return cacheKey;
120
        }
125
        }
126
        // initialize the MergeManager
127
        if(null != unitOfWork.getMergeManager()) { // may be null on a em.getReference() call        
128
            unitOfWork.getMergeManager().setLockThread(Thread.currentThread());
129
        }
130
121
        // Attempt to get a read-lock, null is returned if cannot be read-locked.
131
        // Attempt to get a read-lock, null is returned if cannot be read-locked.
122
        if (cacheKey.acquireReadLockNoWait()) {
132
        if (cacheKey.acquireReadLockNoWait()) {
123
            if (cacheKey.getObject() == null) {
133
            if (cacheKey.getObject() == null) {
Lines 126-133 Link Here
126
            } else {
136
            } else {
127
                objectForClone = cacheKey.getObject();
137
                objectForClone = cacheKey.getObject();
128
                if (lockedObjects.containsKey(objectForClone)) {
138
                if (lockedObjects.containsKey(objectForClone)) {
129
                    // This is a check for loss of identity, the orignal check in
139
                    // This is a check for loss of identity, the original check in
130
                    // checkAndLockObject() will shortcircut in the usual case.
140
                    // checkAndLockObject() will shortcircuit in the usual case.
131
                    cacheKey.releaseReadLock();
141
                    cacheKey.releaseReadLock();
132
                    return null;
142
                    return null;
133
                }
143
                }
Lines 234-239 Link Here
234
244
235
        //while that thread has locks to acquire continue to loop.
245
        //while that thread has locks to acquire continue to loop.
236
        try {
246
        try {
247
            // initialize the MergeManager during this commit or merge
248
            mergeManager.setLockThread(Thread.currentThread());
249
237
            AbstractSession session = mergeManager.getSession();
250
            AbstractSession session = mergeManager.getSession();
238
            if (session.isUnitOfWork()) {
251
            if (session.isUnitOfWork()) {
239
                session = ((UnitOfWorkImpl)session).getParent();
252
                session = ((UnitOfWorkImpl)session).getParent();
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/localization/i18n/TraceLocalizationResource.java (-1 / +2 lines)
Lines 306-312 Link Here
306
                                            { "registered_mbean", "Registered MBean: {0}" },
306
                                            { "registered_mbean", "Registered MBean: {0}" },
307
                                            { "unregistering_mbean", "Unregistering MBean: {0}" },
307
                                            { "unregistering_mbean", "Unregistering MBean: {0}" },
308
                                            { "mbean_get_application_name", "The applicationName for the MBean attached to session [{0}] is [{1}]" },
308
                                            { "mbean_get_application_name", "The applicationName for the MBean attached to session [{0}] is [{1}]" },
309
                                            { "mbean_get_module_name", "The moduleName for the MBean attached to session [{0}] is [{1}]" }                                            
309
                                            { "mbean_get_module_name", "The moduleName for the MBean attached to session [{0}] is [{1}]" },
310
                                            { "active_thread_is_different_from_current_thread", "Forcing the activeThread \"{0}\" on the mergeManager \"{1}\" to be the currentThread \"{2}\" because they are different." }                                            
310
    };
311
    };
311
312
312
    /**
313
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/MergeManager.java (-1 / +21 lines)
Lines 88-93 Link Here
88
    /** records that deferred locks have been employed for the merge process */
88
    /** records that deferred locks have been employed for the merge process */
89
    protected boolean isTransitionedToDeferredLocks = false;
89
    protected boolean isTransitionedToDeferredLocks = false;
90
90
91
    /** save the currentThread for later comparison to the activeThread in case they don't match */
92
    protected Thread lockThread;
93
    
91
    public MergeManager(AbstractSession session) {
94
    public MergeManager(AbstractSession session) {
92
        this.session = session;
95
        this.session = session;
93
        this.mergedNewObjects = new IdentityHashMap();
96
        this.mergedNewObjects = new IdentityHashMap();
Lines 247-253 Link Here
247
        if (getObjectsAlreadyMerged().containsKey(object)) {
250
        if (getObjectsAlreadyMerged().containsKey(object)) {
248
            return object;
251
            return object;
249
        }
252
        }
250
253
        
251
        // Put the object to be merged in the set.
254
        // Put the object to be merged in the set.
252
        getObjectsAlreadyMerged().put(object, object);
255
        getObjectsAlreadyMerged().put(object, object);
253
256
Lines 1048-1052 Link Here
1048
        }
1051
        }
1049
1052
1050
    }
1053
    }
1054
1055
    /**
1056
     * INTERNAL:
1057
     * @return lockThread
1058
     */
1059
    public Thread getLockThread() {
1060
        return lockThread;
1061
    }
1062
1063
    /**
1064
     * INTERNAL:
1065
     * Save the currentThread for later comparison to the activeThread in case they don't match
1066
     * @param lockThread
1067
     */
1068
    public void setLockThread(Thread lockThread) {
1069
        this.lockThread = lockThread;
1070
    }
1051
    
1071
    
1052
}
1072
}
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkImpl.java (-6 / +63 lines)
Lines 14-19 Link Here
14
 *        The class was amended to allow it to instantiate ValueHolders after release method has been called
14
 *        The class was amended to allow it to instantiate ValueHolders after release method has been called
15
 *        (internalExecuteQuery method no longer throws exception if the uow is dead).
15
 *        (internalExecuteQuery method no longer throws exception if the uow is dead).
16
 *        Note that release method clears change sets but keeps the cache.
16
 *        Note that release method clears change sets but keeps the cache.
17
 *     02/10/2009-1.1 Michael O'Brien 
18
 *        - 259993: Defer a clear() call to release() if uow lifecycle is 1,2 or 4 (*Pending).
17
 ******************************************************************************/  
19
 ******************************************************************************/  
18
package org.eclipse.persistence.internal.sessions;
20
package org.eclipse.persistence.internal.sessions;
19
21
Lines 33-38 Link Here
33
import org.eclipse.persistence.internal.sequencing.Sequencing;
35
import org.eclipse.persistence.internal.sequencing.Sequencing;
34
import org.eclipse.persistence.sessions.coordination.MergeChangeSetCommand;
36
import org.eclipse.persistence.sessions.coordination.MergeChangeSetCommand;
35
import org.eclipse.persistence.sessions.factories.ReferenceMode;
37
import org.eclipse.persistence.sessions.factories.ReferenceMode;
38
import org.eclipse.persistence.logging.AbstractSessionLog;
36
import org.eclipse.persistence.logging.SessionLog;
39
import org.eclipse.persistence.logging.SessionLog;
37
import org.eclipse.persistence.mappings.DatabaseMapping;
40
import org.eclipse.persistence.mappings.DatabaseMapping;
38
import org.eclipse.persistence.internal.localization.LoggingLocalization;
41
import org.eclipse.persistence.internal.localization.LoggingLocalization;
Lines 3195-3200 Link Here
3195
     * for synchronized units of work, merge changes into parent
3198
     * for synchronized units of work, merge changes into parent
3196
     */
3199
     */
3197
    public void mergeClonesAfterCompletion() {
3200
    public void mergeClonesAfterCompletion() {
3201
        // Before we merge
3202
        // Check that the current thread is the active thread on all lock managers by checking the cached lockThread on the mergeManager.
3203
        // If we find that these 2 threads are different - then all threads in the acquired locks list are different.
3204
        // Switch the activeThread on the mutex to this current thread for each lock
3205
        Thread currentThread = Thread.currentThread();
3206
        if(null != this.getMergeManager()) { // mergeManager may be null in a com.ibm.tx.jta.RegisteredSyncs.coreDistributeAfter() afterCompletion() callback
3207
            Thread lockThread = this.getMergeManager().getLockThread();
3208
            if(currentThread != lockThread) {
3209
                ArrayList<CacheKey> locks = this.getMergeManager().getAcquiredLocks();        
3210
                if(null != locks) {                
3211
                    Iterator<CacheKey> locksIterator = locks.iterator();
3212
                    AbstractSessionLog.getLog().log(SessionLog.FINER, "active_thread_is_different_from_current_thread", 
3213
                        lockThread, this.getMergeManager(), currentThread);                                
3214
                    while(locksIterator.hasNext()) {
3215
                        ConcurrencyManager lockMutex = locksIterator.next().getMutex();
3216
                        if(null != lockMutex) {
3217
                            Thread activeThread = lockMutex.getActiveThread();
3218
                            // check for different acquire and release threads
3219
                            if(currentThread != activeThread) {
3220
                                // Switch activeThread to currentThread - we will release the lock later
3221
                                lockMutex.setActiveThread(currentThread);
3222
                            }
3223
                        }
3224
                    }
3225
                }
3226
            }
3227
        }
3228
        
3198
        mergeChangesIntoParent();
3229
        mergeChangesIntoParent();
3199
        // CR#... call event and log.
3230
        // CR#... call event and log.
3200
        getEventManager().postCommitUnitOfWork();
3231
        getEventManager().postCommitUnitOfWork();
Lines 5289-5305 Link Here
5289
        this.optimisticReadLockObjects = null;
5320
        this.optimisticReadLockObjects = null;
5290
        this.batchReadObjects = null;
5321
        this.batchReadObjects = null;
5291
        if(shouldClearCache) {
5322
        if(shouldClearCache) {
5292
            this.getIdentityMapAccessor().initializeIdentityMaps();
5323
            clearIdentityMapCache();
5293
            if (this.getParent() instanceof IsolatedClientSession) {
5294
                this.getParent().getIdentityMapAccessor().initializeIdentityMaps();
5295
            }
5296
        }
5324
        }
5297
    }
5325
    }
5326
5327
    /**
5328
     * INTERNAL:
5329
     * Clear the identityMaps
5330
     */
5331
    private void clearIdentityMapCache() {
5332
        this.getIdentityMapAccessor().initializeIdentityMaps();
5333
        if (this.getParent() instanceof IsolatedClientSession) {
5334
            this.getParent().getIdentityMapAccessor().initializeIdentityMaps();
5335
        }
5336
    }
5298
    
5337
    
5299
    /**
5338
    /**
5300
     * INTERNAL:
5339
     * INTERNAL:
5301
     * Call this method if the uow will no longer used for committing transactions:
5340
     * Call this method if the uow will no longer be used for committing transactions:
5302
     * all the changes sets will be dereferenced, and (optionally) the cache cleared.
5341
     * all the change sets will be dereferenced, and (optionally) the cache cleared. 
5303
     * If the uow is not released, but rather kept around for ValueHolders, then identity maps shouldn't be cleared:
5342
     * If the uow is not released, but rather kept around for ValueHolders, then identity maps shouldn't be cleared:
5304
     * the parameter value should be 'false'. The lifecycle set to Birth so that uow ValueHolder still could be used.
5343
     * the parameter value should be 'false'. The lifecycle set to Birth so that uow ValueHolder still could be used.
5305
     * Alternatively, if called from release method then everything should go and therefore parameter value should be 'true'.
5344
     * Alternatively, if called from release method then everything should go and therefore parameter value should be 'true'.
Lines 5307-5314 Link Here
5307
     * The reason for calling this method from release is to free maximum memory right away:
5346
     * The reason for calling this method from release is to free maximum memory right away:
5308
     * the uow might still be referenced by objects using UOWValueHolders (though they shouldn't be around
5347
     * the uow might still be referenced by objects using UOWValueHolders (though they shouldn't be around
5309
     * they still might).
5348
     * they still might).
5349
     * We defer a clear() call to release() if the uow lifecycle is 1,2 or 4 (*Pending). 
5310
     */
5350
     */
5311
    public void clearForClose(boolean shouldClearCache) {
5351
    public void clearForClose(boolean shouldClearCache) {
5352
        // WebSphere 7.0 during a JPAEMPool.putEntityManager() may attempt to clear an entityManager 
5353
        // that is in the middle of a commit.  
5354
        // We only clear the entityManager if we are in the states 
5355
        // (Birth == 0, WriteChangesFailed==3, Death==5 or AfterExternalTransactionRolledBack==6).
5356
        // If we are in one of the following *Pending states we defer the clear() to the release() call later  
5357
        if(this.getLifecycle() == this.CommitPending 
5358
                || this.getLifecycle() == this.CommitTransactionPending 
5359
                || this.getLifecycle() == this.MergePending) {
5360
            // perform a partial clear() by clearing the identityMaps but leaving all other fields set
5361
            // later in release a clear(false) will clear everything else except the identityMaps
5362
            if(shouldClearCache) {
5363
                clearIdentityMapCache();
5364
            }
5365
            // We must exit before we perform a full clear
5366
            return;
5367
        }
5368
        
5312
        clear(shouldClearCache);
5369
        clear(shouldClearCache);
5313
        if(isActive()) {
5370
        if(isActive()) {
5314
            //Reset lifecycle
5371
            //Reset lifecycle

Return to bug 259993