Program: 141515
Project: 141515
Buggy source:
/** 
 * {@inheritDoc}
 */
@Override public void pruneChanges(int keep,int mustBeExceededBy){
  try (Transaction tx=database.beginTx()){
    Relationship oldestChangeRel=getRoot().getSingleRelationship(_GA_CHANGEFEED_OLDEST_CHANGE,OUTGOING);
    if (oldestChangeRel != null) {
      Node oldestNode=oldestChangeRel.getEndNode();
      Node newestNode=getRoot().getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,OUTGOING).getEndNode();
      if (newestNode != null) {
        int changeCount=1;
        Node lastNodeToKeep=newestNode;
        Relationship nextRel=lastNodeToKeep.getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,OUTGOING);
        while (changeCount < keep && nextRel != null) {
          lastNodeToKeep=nextRel.getEndNode();
          changeCount++;
          nextRel=lastNodeToKeep.getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,OUTGOING);
        }
        if (changeCount < keep) {
          LOG.debug("String_Node_Str");
          tx.success();
          return;
        }
        int exceededCount=0;
        Relationship nextExceededByRel=nextRel;
        while (exceededCount < mustBeExceededBy && nextExceededByRel != null) {
          nextExceededByRel=nextExceededByRel.getEndNode().getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,OUTGOING);
          exceededCount++;
        }
        if (exceededCount < mustBeExceededBy) {
          LOG.debug("String_Node_Str");
          tx.success();
          return;
        }
        LOG.debug("String_Node_Str");
        if (nextRel != null) {
          Lock rootLock=tx.acquireWriteLock(getRoot());
          Lock oldestNodeLock=tx.acquireWriteLock(oldestNode);
          nextRel.delete();
          oldestChangeRel.delete();
          getRoot().createRelationshipTo(lastNodeToKeep,_GA_CHANGEFEED_OLDEST_CHANGE);
          oldestNodeLock.release();
          rootLock.release();
          Relationship previousChange=oldestNode.getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,INCOMING);
          while (previousChange != null) {
            Node newOldestNode=previousChange.getStartNode();
            previousChange.delete();
            oldestNode.delete();
            previousChange=newOldestNode.getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,INCOMING);
            oldestNode=newOldestNode;
          }
          oldestNode.delete();
        }
        LOG.debug("String_Node_Str");
      }
    }
    tx.success();
  }
 }

Fixed version (ground truth):
/** 
 * {@inheritDoc}
 */
@Override public void pruneChanges(int keep,int mustBeExceededBy){
  try (Transaction tx=database.beginTx()){
    tx.acquireWriteLock(getRoot());
    Relationship oldestChangeRel=getRoot().getSingleRelationship(_GA_CHANGEFEED_OLDEST_CHANGE,OUTGOING);
    if (oldestChangeRel != null) {
      Node oldestNode=oldestChangeRel.getEndNode();
      Node newestNode=getRoot().getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,OUTGOING).getEndNode();
      if (newestNode != null) {
        int changeCount=1;
        Node lastNodeToKeep=newestNode;
        Relationship nextRel=lastNodeToKeep.getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,OUTGOING);
        while (changeCount < keep && nextRel != null) {
          lastNodeToKeep=nextRel.getEndNode();
          changeCount++;
          nextRel=lastNodeToKeep.getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,OUTGOING);
        }
        if (changeCount < keep) {
          LOG.debug("String_Node_Str");
          tx.success();
          return;
        }
        int exceededCount=0;
        Relationship nextExceededByRel=nextRel;
        while (exceededCount < mustBeExceededBy && nextExceededByRel != null) {
          nextExceededByRel=nextExceededByRel.getEndNode().getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,OUTGOING);
          exceededCount++;
        }
        if (exceededCount < mustBeExceededBy) {
          LOG.debug("String_Node_Str");
          tx.success();
          return;
        }
        LOG.debug("String_Node_Str");
        if (nextRel != null) {
          nextRel.delete();
          oldestChangeRel.delete();
          getRoot().createRelationshipTo(lastNodeToKeep,_GA_CHANGEFEED_OLDEST_CHANGE);
          Relationship previousChange=oldestNode.getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,INCOMING);
          while (previousChange != null) {
            Node newOldestNode=previousChange.getStartNode();
            previousChange.delete();
            oldestNode.delete();
            previousChange=newOldestNode.getSingleRelationship(_GA_CHANGEFEED_NEXT_CHANGE,INCOMING);
            oldestNode=newOldestNode;
          }
          oldestNode.delete();
        }
        LOG.debug("String_Node_Str");
      }
    }
    tx.success();
  }
 }