Program: 68264
Project: 68264
Buggy source:
/** 
 * INTERNAL: This method will be the entry point for threads attempting to acquire locks for all objects that have a changeset.  This method will hand off the processing of the deadlock algorithm to other member methods.  The mergeManager must be the active mergemanager for the calling thread. Returns true if all required locks were acquired
 */
public void acquireRequiredLocks(MergeManager mergeManager,UnitOfWorkChangeSet changeSet){
  if (!MergeManager.LOCK_ON_MERGE) {
    return;
  }
  boolean locksToAcquire=true;
  boolean isForDistributedMerge=false;
  try {
    AbstractSession session=mergeManager.getSession();
    if (session.isUnitOfWork()) {
      session=((UnitOfWorkImpl)session).getParent();
    }
 else {
      isForDistributedMerge=true;
    }
    while (locksToAcquire) {
      locksToAcquire=false;
      Iterator classIterator=changeSet.getObjectChanges().keySet().iterator();
      while (classIterator.hasNext()) {
        String objectClassName=(String)classIterator.next();
        Hashtable changeSetTable=(Hashtable)changeSet.getObjectChanges().get(objectClassName);
        Iterator changeSetIterator=changeSetTable.keySet().iterator();
        Class objectClass=null;
        while (changeSetIterator.hasNext()) {
          ObjectChangeSet objectChangeSet=(ObjectChangeSet)changeSetIterator.next();
          if (objectChangeSet.getCacheKey() == null) {
            continue;
          }
          if (objectClass == null) {
            objectClass=objectChangeSet.getClassType(session);
          }
          ClassDescriptor descriptor=session.getDescriptor(objectClass);
          if (descriptor.shouldIsolateObjectsInUnitOfWork()) {
            break;
          }
          CacheKey activeCacheKey=attemptToAcquireLock(objectClass,objectChangeSet.getCacheKey(),session);
          if (activeCacheKey == null) {
            if (this.prevailingQueue.getFirst() == mergeManager) {
              activeCacheKey=waitOnObjectLock(objectClass,objectChangeSet.getCacheKey(),session);
              mergeManager.getAcquiredLocks().add(activeCacheKey);
            }
 else {
              releaseAllAcquiredLocks(mergeManager);
              activeCacheKey=session.getIdentityMapAccessorInstance().getCacheKeyForObject(objectChangeSet.getCacheKey().getKey(),objectClass,descriptor);
              if (session.shouldLog(SessionLog.FINER,SessionLog.CACHE)) {
                Object[] params=new Object[3];
                params[0]=objectClass;
                params[1]=objectChangeSet.getCacheKey() != null ? objectChangeSet.getCacheKey().getKey() : new Vector();
                params[2]=Thread.currentThread().getName();
                session.log(SessionLog.FINER,SessionLog.CACHE,"String_Node_Str",params,null,true);
              }
              if (mergeManager.getWriteLockQueued() == null) {
                mergeManager.setQueueNode(this.prevailingQueue.addLast(mergeManager));
              }
              mergeManager.setWriteLockQueued(objectChangeSet.getCacheKey());
              try {
                if (activeCacheKey != null) {
synchronized (activeCacheKey.getMutex()) {
                    if (activeCacheKey.getMutex().isAcquired() && (activeCacheKey.getMutex().getActiveThread() != Thread.currentThread())) {
                      activeCacheKey.getMutex().wait();
                    }
                  }
                }
              }
 catch (              InterruptedException exception) {
                throw org.eclipse.persistence.exceptions.ConcurrencyException.waitWasInterrupted(exception.getMessage());
              }
              locksToAcquire=true;
              break;
            }
          }
 else {
            objectChangeSet.setActiveCacheKey(activeCacheKey);
            mergeManager.getAcquiredLocks().add(activeCacheKey);
          }
        }
        if (locksToAcquire) {
          break;
        }
      }
    }
  }
 catch (  RuntimeException exception) {
    releaseAllAcquiredLocks(mergeManager);
    throw exception;
  }
 finally {
    if (mergeManager.getWriteLockQueued() != null) {
      this.prevailingQueue.remove(mergeManager.getQueueNode());
      mergeManager.setWriteLockQueued(null);
    }
  }
}

Fixed version (ground truth):
/** 
 * INTERNAL: This method will be the entry point for threads attempting to acquire locks for all objects that have a changeset.  This method will hand off the processing of the deadlock algorithm to other member methods.  The mergeManager must be the active mergemanager for the calling thread. Returns true if all required locks were acquired
 */
public void acquireRequiredLocks(MergeManager mergeManager,UnitOfWorkChangeSet changeSet){
  if (!MergeManager.LOCK_ON_MERGE) {
    return;
  }
  boolean locksToAcquire=true;
  boolean isForDistributedMerge=false;
  try {
    AbstractSession session=mergeManager.getSession();
    if (session.isUnitOfWork()) {
      session=((UnitOfWorkImpl)session).getParent();
    }
 else {
      isForDistributedMerge=true;
    }
    while (locksToAcquire) {
      locksToAcquire=false;
      Iterator classIterator=changeSet.getObjectChanges().keySet().iterator();
      while (classIterator.hasNext()) {
        String objectClassName=(String)classIterator.next();
        Hashtable changeSetTable=(Hashtable)changeSet.getObjectChanges().get(objectClassName);
        Iterator changeSetIterator=changeSetTable.keySet().iterator();
        Class objectClass=null;
        while (changeSetIterator.hasNext()) {
          ObjectChangeSet objectChangeSet=(ObjectChangeSet)changeSetIterator.next();
          if (objectChangeSet.getCacheKey() == null) {
            continue;
          }
          if (objectClass == null) {
            objectClass=objectChangeSet.getClassType(session);
          }
          ClassDescriptor descriptor=session.getDescriptor(objectClass);
          if (descriptor.shouldIsolateObjectsInUnitOfWork()) {
            break;
          }
          CacheKey activeCacheKey=attemptToAcquireLock(objectClass,objectChangeSet.getCacheKey(),session);
          if (activeCacheKey == null) {
            if (this.prevailingQueue.getFirst() == mergeManager) {
              activeCacheKey=waitOnObjectLock(objectClass,objectChangeSet.getCacheKey(),session);
              mergeManager.getAcquiredLocks().add(activeCacheKey);
            }
 else {
              releaseAllAcquiredLocks(mergeManager);
              activeCacheKey=session.getIdentityMapAccessorInstance().getCacheKeyForObject(objectChangeSet.getCacheKey().getKey(),objectClass,descriptor);
              if (session.shouldLog(SessionLog.FINER,SessionLog.CACHE)) {
                Object[] params=new Object[3];
                params[0]=objectClass;
                params[1]=objectChangeSet.getCacheKey() != null ? objectChangeSet.getCacheKey().getKey() : new Vector();
                params[2]=Thread.currentThread().getName();
                session.log(SessionLog.FINER,SessionLog.CACHE,"String_Node_Str",params,null,true);
              }
              if (mergeManager.getWriteLockQueued() == null) {
synchronized (this.prevailingQueue) {
                  mergeManager.setQueueNode(this.prevailingQueue.addLast(mergeManager));
                }
              }
              mergeManager.setWriteLockQueued(objectChangeSet.getCacheKey());
              try {
                if (activeCacheKey != null) {
synchronized (activeCacheKey.getMutex()) {
                    if (activeCacheKey.getMutex().isAcquired() && (activeCacheKey.getMutex().getActiveThread() != Thread.currentThread())) {
                      activeCacheKey.getMutex().wait();
                    }
                  }
                }
              }
 catch (              InterruptedException exception) {
                throw org.eclipse.persistence.exceptions.ConcurrencyException.waitWasInterrupted(exception.getMessage());
              }
              locksToAcquire=true;
              break;
            }
          }
 else {
            objectChangeSet.setActiveCacheKey(activeCacheKey);
            mergeManager.getAcquiredLocks().add(activeCacheKey);
          }
        }
        if (locksToAcquire) {
          break;
        }
      }
    }
  }
 catch (  RuntimeException exception) {
    releaseAllAcquiredLocks(mergeManager);
    throw exception;
  }
 finally {
    if (mergeManager.getWriteLockQueued() != null) {
synchronized (this.prevailingQueue) {
        this.prevailingQueue.remove(mergeManager.getQueueNode());
      }
      mergeManager.setWriteLockQueued(null);
    }
  }
}