SequencingCallbackImpl getCallbackImpl(AbstractSession writeSession, Accessor accessor) {
   SequencingCallbackImpl seqCallbackImpl;
   if (writeSession.hasExternalTransactionController()) {
     // note that controller obtained from writeSession (not from ownerSession) -
     // the difference is important in case of ownerSession being a member of SessionBroker:
     // in that case only writeSession (which is either ClientSession or DatabaseSession) always
     // has
     // the correct controller.
     seqCallbackImpl =
         (SequencingCallbackImpl)
             writeSession
                 .getExternalTransactionController()
                 .getActiveSequencingCallback(getOwnerSession(), getSequencingCallbackFactory());
   } else {
     seqCallbackImpl =
         (SequencingCallbackImpl) accessor.getSequencingCallback(getSequencingCallbackFactory());
   }
   return seqCallbackImpl;
 }
 public Object getNextValue(Sequence sequence, AbstractSession writeSession) {
   String seqName = sequence.getName();
   if (sequence.getPreallocationSize() > 1) {
     Queue sequencesForName = getPreallocationHandler().getPreallocated(seqName);
     // First try to get the next sequence value without locking.
     Object sequenceValue = sequencesForName.poll();
     if (sequenceValue != null) {
       return sequenceValue;
     }
     // Sequences are empty, so must lock and allocate next batch of sequences.
     acquireLock(seqName);
     try {
       sequenceValue = sequencesForName.poll();
       if (sequenceValue != null) {
         return sequenceValue;
       }
       // note that accessor.getLogin().shouldUseExternalTransactionController()
       // should be set to false
       Accessor accessor = getConnectionHandler().acquireAccessor();
       try {
         accessor.beginTransaction(writeSession);
         try {
           Vector sequences = sequence.getGeneratedVector(accessor, writeSession);
           accessor.commitTransaction(writeSession);
           // Remove the first value before adding to the global cache to ensure this thread gets
           // one.
           sequenceValue = sequences.remove(0);
           // copy remaining values to global cache.
           getPreallocationHandler().setPreallocated(seqName, sequences);
           logDebugPreallocation(seqName, sequenceValue, sequences);
         } catch (RuntimeException ex) {
           try {
             // make sure to rollback the transaction we've begun
             accessor.rollbackTransaction(writeSession);
           } catch (Exception rollbackException) {
             // ignore rollback exception
           }
           // don't eat the original exception
           throw ex;
         }
       } finally {
         getConnectionHandler().releaseAccessor(accessor);
       }
     } finally {
       releaseLock(seqName);
     }
     return sequenceValue;
   } else {
     // note that accessor.getLogin().shouldUseExternalTransactionController()
     // should be set to false
     Accessor accessor = getConnectionHandler().acquireAccessor();
     try {
       accessor.beginTransaction(writeSession);
       try {
         // preallocation size is 1 - just return the first (and only) element of the allocated
         // vector.
         Object sequenceValue =
             sequence.getGeneratedVector(accessor, writeSession).firstElement();
         accessor.commitTransaction(writeSession);
         return sequenceValue;
       } catch (RuntimeException ex) {
         try {
           // make sure to rollback the transaction we've begun
           accessor.rollbackTransaction(writeSession);
         } catch (Exception rollbackException) {
           // ignore rollback exception
         }
         // don't eat the original exception
         throw ex;
       }
     } finally {
       getConnectionHandler().releaseAccessor(accessor);
     }
   }
 }