/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.sequencing;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Queue;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.MultitenantPolicy;
import org.eclipse.persistence.descriptors.SchemaPerMultitenantPolicy;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.helper.ConcurrencyManager;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.sequencing.DefaultSequence;
import org.eclipse.persistence.sequencing.Sequence;
import org.eclipse.persistence.sequencing.SequencingControl;
import org.eclipse.persistence.sessions.Login;
import org.eclipse.persistence.sessions.server.ConnectionPool;
import org.eclipse.persistence.sessions.server.ExternalConnectionPool;
import org.eclipse.persistence.sessions.server.ServerSession;

/**
 * SequencingManager is private to EclipseLink.
 * It provides most of sequencing functionality.
 * It's accessed by DatabaseSession through getSequencingHome() method.
 *
 * Here's the lifecycle of SequencingManager.
 * InitialState: SequencingManager doesn't exist.
 *   Action: SequencingManager created -{@literal >} Not connected State.
 * State: Not connected.
 *        isConnected() returns false;
 *        getSequencingControl() could be used;
 *        getSequencing() == getSequencingServer() == getSequencingCallbackFactory() == null;
 *   Action: onConnect is called -{@literal >} Connected State.
 * State: Connected.
 *        isConnected() returns true;
 *        getSequencingControl() could be used;
 *        getSequencing() could be used;
 *        in case ownwerSession is a ServerSession getSequencingServer() could be used;
 *   Action: onDisconnect is called -{@literal >} Not connected State.
 *
 * Here's a sketch of SequencingManager architecture.
 * The main 4 objects comprising SessionManager are:
 *      valueGenarationPolicy;
 *      preallocationHandler;
 *      connectionHandler;
 *      state;
 *
 * That's how they evolve during lifetime of SequencingManager object:
 * Not connected State:
 *      preallocationHandler doesn't have any preallocated sequencing values.
 *      connectionHandler == null;
 *      state == null;
 *
 * Connected State:
 *      preallocationHandler may contain preallocated sequencing values.
 *      valueGenarationPolicy != null;
 *      state != null;
 *
 * The most important method of the class is onConnect():
 * that's where, using values of the attributes'(accessible through SequencingControl):
 *      shouldUseSeparateConnection;
 *      login;
 *      minPoolSize;
 *      maxPoolSize;
 * as well as boolean flags returned by valueGenerationPolicy methods:
 *      shouldAcquireValueAfterInsert();
 *      shouldUsePreallocation();
 *      shouldUseSeparateConnection();
 *      shouldUseTransaction();
 * one of implementors of inner interface State is created.
 *
 * Once in Connected State, neither changes to attributes, nor to returns of valueGenerationPolicy's
 * four should... methods can change the state object.
 * To change the state object, onDisconnect(), than onConnect() should be called.
 * There is no need to do it directly: each of the following methods
 * available through SequencingControl does that:
 *      setValueGenerationPolicy;
 *      setShouldUseNativeSequencing;
 *      setShouldUseTableSequencing;
 *      resetSequencing;
 */
class SequencingManager implements SequencingHome, SequencingServer, SequencingControl {
    private final DatabaseSessionImpl ownerSession;
    private SequencingConnectionHandler connectionHandler;
    private Map<String, PreallocationHandler> preallocationHandler;
    private int whenShouldAcquireValueForAll;
    private Vector<Sequence> connectedSequences;
    boolean atLeastOneSequenceShouldUseTransaction;
    boolean atLeastOneSequenceShouldUsePreallocation;

    // state ids
    private static final int NOPREALLOCATION = 0;
    private static final int PREALLOCATION_NOTRANSACTION = 1;
    private static final int PREALLOCATION_TRANSACTION_NOACCESSOR = 2;
    private static final int PREALLOCATION_TRANSACTION_ACCESSOR = 3;
    private static final int NUMBER_OF_STATES = 4;
    private State[] states;
    private Map<String, ConcurrencyManager> locks;
    private SequencingCallbackFactory callbackFactory;
    private SequencingServer server;
    private Sequencing seq;
    private boolean shouldUseSeparateConnection;
    private Login login;
    private int minPoolSize = -1;
    private int maxPoolSize = -1;
    private int initialPoolSize = -1;
    private ConnectionPool connectionPool;

    public SequencingManager(DatabaseSessionImpl ownerSession) {
        this.ownerSession = ownerSession;
    }

    protected DatabaseSessionImpl getOwnerSession() {
        return ownerSession;
    }

    protected void createConnectionHandler() {
        boolean isServerSession = getOwnerSession().isServerSession();

        if (getLogin() == null) {
            Login login;
            if (isServerSession) {
                login = ((ServerSession)getOwnerSession()).getReadConnectionPool().getLogin();
            } else {
                login = getOwnerSession().getDatasourceLogin();
            }
            setLogin(login);
        }

        if (getLogin() != null) {
            if (getLogin().shouldUseExternalTransactionController()) {
                throw ValidationException.invalidSequencingLogin();
            }
        }

        if (isServerSession) {
            ConnectionPool pool = null;
            if (this.connectionPool == null) {
                if (getLogin().shouldUseExternalConnectionPooling()) {
                    pool = new ExternalConnectionPool("sequencing", getLogin(), (ServerSession)getOwnerSession());
                } else {
                    if (getMinPoolSize() == -1) {
                        setMinPoolSize(2);
                    }
                    if (getMaxPoolSize() == -1) {
                        setMinPoolSize(2);
                    }
                    if (getInitialPoolSize() == -1) {
                        setInitialPoolSize(1);
                    }
                    pool = new ConnectionPool("sequencing", getLogin(), getInitialPoolSize(), getMinPoolSize(), getMaxPoolSize(), (ServerSession)getOwnerSession());
                }
            } else {
                pool = this.connectionPool;
            }

            setConnectionHandler(new ServerSessionConnectionHandler(pool));

        } else {
            setConnectionHandler(new DatabaseSessionConnectionHandler(getOwnerSession(), getLogin()));
        }
    }

    @Override
    public SequencingControl getSequencingControl() {
        return this;
    }

    protected void setSequencing(Sequencing sequencing) {
        this.seq = sequencing;
    }

    @Override
    public Sequencing getSequencing() {
        return seq;
    }

    protected void setSequencingServer(SequencingServer server) {
        this.server = server;
    }

    @Override
    public SequencingServer getSequencingServer() {
        return server;
    }

    protected void setSequencingCallbackFactory(SequencingCallbackFactory callbackFactory) {
        this.callbackFactory = callbackFactory;
    }

    @Override
    public boolean isSequencingCallbackRequired() {
        return this.callbackFactory != null;
    }

    @Override
    public boolean shouldUseSeparateConnection() {
        return shouldUseSeparateConnection;
    }

    @Override
    public void setShouldUseSeparateConnection(boolean shouldUseSeparateConnection) {
        this.shouldUseSeparateConnection = shouldUseSeparateConnection;
    }

    @Override
    public boolean isConnectedUsingSeparateConnection() {
        return isConnected() && (getConnectionHandler() != null);
    }

    @Override
    public Login getLogin() {
        return login;
    }

    @Override
    public void setLogin(Login login) {
        this.login = login;
    }

    @Override
    public int getMinPoolSize() {
        return minPoolSize;
    }

    @Override
    public void setMinPoolSize(int size) {
        this.minPoolSize = size;
    }

    @Override
    public int getMaxPoolSize() {
        return maxPoolSize;
    }

    @Override
    public void setMaxPoolSize(int size) {
        this.maxPoolSize = size;
    }

    public int getInitialPoolSize() {
        return this.initialPoolSize;
    }

    @Override
    public void setInitialPoolSize(int size) {
        this.initialPoolSize = size;
    }

    @Override
    public boolean isConnected() {
        return states != null;
    }

    // SequencingSetup
    protected SequencingConnectionHandler getConnectionHandler() {
        return connectionHandler;
    }

    protected void setConnectionHandler(SequencingConnectionHandler handler) {
        this.connectionHandler = handler;
    }

    @Override
    public ConnectionPool getConnectionPool() {
        if ((getConnectionHandler() != null) && (getConnectionHandler() instanceof ServerSessionConnectionHandler)) {
            return ((ServerSessionConnectionHandler)getConnectionHandler()).getPool();
        }
        return this.connectionPool;
    }

    @Override
    public Object getNextValue(Class<?> cls) {
        return getNextValue(getOwnerSession(), cls);
    }

    @Override
    public void initializePreallocated() {
        if (preallocationHandler != null) {
            for (PreallocationHandler handler : preallocationHandler.values()) {
                handler.initializePreallocated();
            }
        }
    }

    @Override
    public void initializePreallocated(String seqName) {
        if (preallocationHandler != null) {
            for (PreallocationHandler handler : preallocationHandler.values()) {
                handler.initializePreallocated(seqName);
            }
        }
    }

    protected void setLocks(Map<String, ConcurrencyManager> locks) {
        this.locks = locks;
    }

    protected Map<String, ConcurrencyManager> getLocks() {
        return locks;
    }

    /**
     * Acquire a lock for the sequence name.
     * A lock should be, and only be, acquired when allocating new sequences from the database.
     */
    protected ConcurrencyManager acquireLock(String sequenceName) {
        ConcurrencyManager manager = getLocks().get(sequenceName);
        if (manager == null) {
            synchronized (getLocks()) {
                manager = getLocks().get(sequenceName);
                if (manager == null) {
                    manager = new ConcurrencyManager();
                    getLocks().put(sequenceName, manager);
                }
            }
        }
        manager.acquire();
        return manager;
    }

    protected Sequence getSequence(Class<?> cls) {
        //** should check here that sequencing is used?
        String seqName = getOwnerSession().getDescriptor(cls).getSequenceNumberName();
        return getSequence(seqName);
    }

    protected void logDebugPreallocation(String seqName, Object firstSequenceValue, Vector<?> sequences) {
        if (getOwnerSession().shouldLog(SessionLog.FINEST, SessionLog.SEQUENCING)) {
            // the first value has been already removed from sequences vector
            Object[] args = { seqName, sequences.size() + 1, firstSequenceValue, sequences.lastElement() };
            getOwnerSession().log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_preallocation", args);
        }
    }

    protected void logDebugLocalPreallocation(AbstractSession writeSession, String seqName, Vector<?> sequences, Accessor accessor) {
        if (writeSession.shouldLog(SessionLog.FINEST, SessionLog.SEQUENCING)) {
            Object[] args = { seqName, sequences.size(), sequences.firstElement(), sequences.lastElement() };
            writeSession.log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_localPreallocation", args, accessor);
        }
    }

    static abstract class State {
        abstract Object getNextValue(Sequence sequence, AbstractSession writeSession);

        SequencingCallbackFactory getSequencingCallbackFactory() {
            return null;
        }

        @Override
        public String toString() {
            String name = getClass().getName();
            return name.substring(name.lastIndexOf('$') + 1);
        }
    }

    /**
     * Uses preallocation, uses transaction, no separate connection.
     * This is used for a DatabaseSession, or a ServerSession not using native sequencing,
     * and not using a sequence connection pool.
     * This is used by default for table sequencing, unless a sequence connection pool is specified,
     * however it should only be used if there is no non-JTA login available.
     * This will use the writeConnection, but use individual transactions per sequence allocation,
     * unless the unit of work is in an early transaction, or the connection is JTA (this may deadlock).
     */
    class Preallocation_Transaction_NoAccessor_State extends State implements SequencingCallbackFactory {

        final class SequencingCallbackImpl implements SequencingCallback {
            Map<String, Vector<?>> localSequences = new HashMap<>();
            String context;

            /**
            * INTERNAL:
            * Called after transaction has committed (commit in non-jta case; after completion - jta case).
            * Should not be called after rollback.
            */
            @Override
            public void afterCommit(Accessor accessor) {
                afterCommitInternal(context, localSequences, accessor);
            }

            public Map<String, Vector<?>> getPreallocatedSequenceValues() {
                return localSequences;
            }
        }

        @Override
        SequencingCallbackFactory getSequencingCallbackFactory() {
            return this;
        }

        /**
        * INTERNAL:
        * Creates SequencingCallback.
        */
        @Override
        public SequencingCallback createSequencingCallback() {
            return new SequencingCallbackImpl();
        }

        /**
         * Release any locally allocated sequence back to the global sequence pool.
         */
        void afterCommitInternal(String context, Map<String, Vector<?>> localSequences, Accessor accessor) {
            Iterator<Map.Entry<String, Vector<?>>> it = localSequences.entrySet().iterator();
            while(it.hasNext()) {
                Map.Entry<String, Vector<?>> entry = it.next();
                String seqName = entry.getKey();
                Vector<?> localSequenceForName = entry.getValue();
                if (!localSequenceForName.isEmpty()) {
                    getPreallocationHandler(context).setPreallocated(seqName, localSequenceForName);
                    // clear all localSequencesForName
                    localSequenceForName.clear();
                }
            }
            if(accessor != null) {
                getOwnerSession().log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_afterTransactionCommitted", null, accessor);
            } else {
                getOwnerSession().log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_afterTransactionCommitted", null);
            }
        }

        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());
            }
            seqCallbackImpl.context = getContext(writeSession);
            return seqCallbackImpl;
        }

        /**
         * Return the next sequence value.
         * First check the global pool, if empty then allocate new sequences locally.
         */
        @Override
        public Object getNextValue(Sequence sequence, AbstractSession writeSession) {
            String seqName = sequence.getName();
            if(sequence.getPreallocationSize() > 1) {
                Queue<Object> sequencesForName = getPreallocationHandler(getContext(writeSession)).getPreallocated(seqName);
                // First grab the first sequence value without locking, a lock is only required if empty.
                Object sequenceValue = sequencesForName.poll();
                if (sequenceValue != null) {
                    return sequenceValue;
                }
                // KeepLocked indicates whether the sequence lock should be kept for the whole duration of this method.
                // Of course the lock should be released in any case when the method returns or throws an exception.
                // This is only used if a sequence transaction was begun by the unit of work,
                // and will be committed before the unit of work commit.
                boolean keepLocked = false;
                ConcurrencyManager lock = null;
                if (!getOwnerSession().getDatasourceLogin().shouldUseExternalTransactionController() && !writeSession.isInTransaction()) {
                    // To prevent several threads from simultaneously allocating a separate bunch of
                    // sequencing numbers each. With keepLocked==true the first thread locks out others
                    // until it copies the obtained sequence numbers to the global storage.
                    // Note that this optimization possible only in non-jts case when there is no transaction.
                    lock = acquireLock(seqName);
                    try {
                        sequenceValue = sequencesForName.poll();
                        if (sequenceValue != null) {
                            return sequenceValue;
                        }
                        writeSession.beginTransaction();//write accessor is set in begin
                        keepLocked = true;
                    } finally {
                        if (!keepLocked) {
                            lock.release();
                        }
                    }
                }

                Accessor accessor;
                Vector<?> localSequencesForName;
                if (!keepLocked) {
                    writeSession.beginTransaction();//write accessor is set in begin
                }
                try {
                    accessor = writeSession.getAccessor();
                    SequencingCallbackImpl seqCallbackImpl = getCallbackImpl(writeSession, accessor);
                    Map<String, Vector<?>> localSequences = seqCallbackImpl.getPreallocatedSequenceValues();
                    localSequencesForName = localSequences.get(seqName);
                    if ((localSequencesForName == null) || localSequencesForName.isEmpty()) {
                        localSequencesForName = sequence.getGeneratedVector(null, writeSession);
                        localSequences.put(seqName, localSequencesForName);
                        logDebugLocalPreallocation(writeSession, seqName, localSequencesForName, accessor);
                    }
                } catch (RuntimeException ex) {
                    if (keepLocked) {
                        lock.release();
                    }
                    try {
                        // make sure to rollback the transaction we've begun
                        writeSession.rollbackTransaction();
                    } catch (Exception rollbackException) {
                        // ignore rollback exception
                    }

                    // don't eat the original exception
                    throw ex;
                }

                try {
                    try {
                        // commitTransaction may copy preallocated sequence numbers
                        // from localSequences to preallocationHandler: that happens
                        // if it isn't a nested transaction, and sequencingCallback.afterCommit
                        // method has been called.
                        // In this case:
                        // 1. localSequences corresponding to the accessor
                        //    has been removed from accessorToPreallocated;
                        // 2. All its members are empty (therefore localSequenceForName is empty).
                        writeSession.commitTransaction();
                    } catch (DatabaseException ex) {
                        try {
                            // make sure to rollback the transaction we've begun
                            writeSession.rollbackTransaction();
                        } catch (Exception rollbackException) {
                            // ignore rollback exception
                        }
                        // don't eat the original exception
                        throw ex;
                    }

                    if (!localSequencesForName.isEmpty()) {
                        // localSeqencesForName is not empty, that means
                        // sequencingCallback has not been called.
                        sequenceValue = localSequencesForName.remove(0);
                        return sequenceValue;
                    } else {
                        // localSeqencesForName is empty, that means
                        // sequencingCallback has been called.
                        sequenceValue = sequencesForName.poll();
                        if (sequenceValue != null) {
                            return sequenceValue;
                        }
                        return getNextValue(sequence, writeSession);
                    }
                } finally {
                    if(keepLocked) {
                        lock.release();
                    }
                }
            } else {
                writeSession.beginTransaction();
                try {
                    // preallocation size is 1 - just return the first (and only) element of the allocated vector.
                    Object sequenceValue = sequence.getGeneratedVector(null, writeSession).firstElement();
                    writeSession.commitTransaction();
                    return sequenceValue;
                } catch (RuntimeException ex) {
                    try {
                        // make sure to rollback the transaction we've begun
                        writeSession.rollbackTransaction();
                    } catch (Exception rollbackException) {
                        // ignore rollback exception
                    }

                    // don't eat the original exception
                    throw ex;
                }
            }
        }
    }

    /**
     * Uses preallocation, uses transaction, and acquires an accessor.
     * This is used in a ServerSession with a sequence connection pool.
     * This is typically the default behavior.
     */
    class Preallocation_Transaction_Accessor_State extends State {
        @Override
        public Object getNextValue(Sequence sequence, AbstractSession writeSession) {
            String seqName = sequence.getName();
            if(sequence.getPreallocationSize() > 1) {
                PreallocationHandler handler = getPreallocationHandler(getContext(writeSession));
                Queue<Object> sequencesForName = handler.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.
                ConcurrencyManager lock = 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.
                            handler.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 {
                    lock.release();
                }
                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);
                }
            }
        }
    }

    /**
     * Using preallocation, NoTransaction, NoAccessor.
     * This is used by native sequence objects.
     * No transaction is required as sequence objects are non-transactional.
     */
    class Preallocation_NoTransaction_State extends State {
        @Override
        public Object getNextValue(Sequence sequence, AbstractSession writeSession) {
            String seqName = sequence.getName();
            if(sequence.getPreallocationSize() > 1) {
                PreallocationHandler handler = getPreallocationHandler(getContext(writeSession));
                Queue<Object> sequencesForName = handler.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.
                ConcurrencyManager lock = acquireLock(seqName);
                try {
                    sequenceValue = sequencesForName.poll();
                    if (sequenceValue != null) {
                        return sequenceValue;
                    }
                    Vector<?> sequences = sequence.getGeneratedVector(null, 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.
                    handler.setPreallocated(seqName, sequences);
                    logDebugPreallocation(seqName, sequenceValue, sequences);
                } finally {
                    lock.release();
                }
                return sequenceValue;
            } else {
                // preallocation size is 1 - just return the first (and only) element of the allocated vector.
                return sequence.getGeneratedVector(null, writeSession).firstElement();
            }
        }
    }

    /**
     * Using NoPreallocation, no transaction, no Accessor.
     * This is only used for identity sequencing when preallocation is not possible.
     * The writeSession is always in a transaction, so a transaction is never required.
     * Table or sequence object with preallocation size 1 still goes through the preallocation state.
     */
    class NoPreallocation_State extends State {
        @Override
        public Object getNextValue(Sequence sequence, AbstractSession writeSession) {
            return sequence.getGeneratedValue(null, writeSession);
        }
    }

    @Override
    public void resetSequencing() {
        if (isConnected()) {
            onDisconnect();
            onConnect();
        }
    }

    /**
     * Initialize the sequences on login.
     */
    @Override
    public void onConnect() {
        if (isConnected()) {
            return;
        }

        if (!getOwnerSession().getProject().usesSequencing()) {
            return;
        }

        onConnectInternal(null);
    }

    /**
     * If sequencing is connected initialize the sequences used by descriptors, otherwise connect.
     * @param descriptors
     */
    @Override
    public void onAddDescriptors(Collection<ClassDescriptor> descriptors) {
        if (!isConnected()) {
            onConnect();
            return;
        }

        if (descriptors == null || descriptors.isEmpty()) {
            return;
        }

        onConnectInternal(descriptors);
    }

    /**
     * Initialize the sequences on login.
     * @param descriptors class descriptors for which to initialize sequencing
     */
    protected void onConnectInternal(Collection<ClassDescriptor> descriptors) {
        // This method is called in two distinct cases.
        //
        // Connect case.
        // If descriptors == null then the sequencing has not been connected yet
        // and this method by onConnect method.
        // Nothing is allocated yet (connectedSequences, etc) and
        // therefore nAlreadyConnectedSequences = 0
        //
        // AddDescriptors case.
        // If descriptors is not null then sequencing is already connected and this method
        // is called by onAddDescriptors method.
        // connectedSequences (and the rest of stuff allocated by onConnect) already exists.
        // Typically in this case nAlreadyConnectedSequences > 0
        // (unless none sequences were connected by onConnect.
        int nAlreadyConnectedSequences = 0;
        if (connectedSequences != null) {
            nAlreadyConnectedSequences = connectedSequences.size();
        }

        // These flags saved here to rollback the state of sequencing in case of failure.
        int whenShouldAcquireValueForAllOriginal = whenShouldAcquireValueForAll;
        boolean atLeastOneSequenceShouldUseTransactionOriginal = atLeastOneSequenceShouldUseTransaction;
        boolean atLeastOneSequenceShouldUsePreallocationOriginal = atLeastOneSequenceShouldUsePreallocation;

        onConnectSequences(descriptors);

        if (nAlreadyConnectedSequences == connectedSequences.size()) {
            // no sequences connected by onConnectSequences method - nothing to do
            return;
        }

        boolean onExceptionDisconnectPreallocationHandler = false;
        boolean onExceptionDisconnectConnectionHandler = false;

        boolean hasConnectionHandler = getConnectionHandler() != null;
        boolean hasPreallocationHandler = getPreallocationHandler(null) != null;

        try {
            // In AddDescriptors case the handler may have been already created
            if (!hasConnectionHandler) {
                if (!shouldUseSeparateConnection()) {
                    setConnectionHandler(null);
                } else if (atLeastOneSequenceShouldUseTransaction) {
                    if (getConnectionHandler() == null) {
                        createConnectionHandler();
                    }
                    if (getConnectionHandler() != null) {
                        getConnectionHandler().onConnect();
                        onExceptionDisconnectConnectionHandler = true;
                    }
                }
            }

            // In AddDescriptors case the handler may have been already created
            if (!hasPreallocationHandler) {
                if (atLeastOneSequenceShouldUsePreallocation) {
                    String context = getContext(null);
                    if (getPreallocationHandler(context) == null) {
                        createPreallocationHandler(context);
                    }
                    getPreallocationHandler(context).onConnect();
                    onExceptionDisconnectPreallocationHandler = true;
                }
            }

            initializeStates(nAlreadyConnectedSequences);

        } catch (RuntimeException ex) {
            try {
                onDisconnectSequences(nAlreadyConnectedSequences);
            } catch (Exception ex2) {
                // Ignore
            } finally {
                whenShouldAcquireValueForAll = whenShouldAcquireValueForAllOriginal;
                atLeastOneSequenceShouldUseTransaction = atLeastOneSequenceShouldUseTransactionOriginal;
                atLeastOneSequenceShouldUsePreallocation = atLeastOneSequenceShouldUsePreallocationOriginal;
            }
            if (!hasConnectionHandler && getConnectionHandler() != null) {
                if (onExceptionDisconnectConnectionHandler) {
                    getConnectionHandler().onDisconnect();
                }
                setConnectionHandler(null);
            }
            if (!hasPreallocationHandler && getPreallocationHandler(null) != null) {
                if (onExceptionDisconnectPreallocationHandler) {
                    getPreallocationHandler(null).onDisconnect();
                }
                clearPreallocationHandler(null);
            }
            throw ex;
        }
        // In AddDescriptors case locks may have been already created
        if (atLeastOneSequenceShouldUsePreallocation && getLocks() == null) {
            setLocks(new ConcurrentHashMap<>(20));
        }
        // In AddDescriptors case the factory may have been already created and listeners initialized.
        boolean hasSequencingCallbackFactory = isSequencingCallbackRequired();
        if (!hasSequencingCallbackFactory) {
            createSequencingCallbackFactory();
            if(getOwnerSession().hasExternalTransactionController()) {
                getOwnerSession().getExternalTransactionController().initializeSequencingListeners();
            }
        }
        // In AddDescriptors case sequencing is already set.
        if (descriptors == null) {
            if (getOwnerSession().isServerSession()) {
                setSequencingServer(this);
            }
            setSequencing(this);
        }
        logDebugSequencingConnected(nAlreadyConnectedSequences);
    }

    @Override
    public void onDisconnect() {
        if (!isConnected()) {
            return;
        }

        setSequencing(null);
        setSequencingServer(null);
        setSequencingCallbackFactory(null);
        if(getOwnerSession().hasExternalTransactionController() && !getOwnerSession().hasBroker()) {
            getOwnerSession().getExternalTransactionController().clearSequencingListeners();
        }
        setLocks(null);
        clearStates();

        if (getConnectionHandler() != null) {
            getConnectionHandler().onDisconnect();
            setConnectionHandler(null);
        }
        if (getPreallocationHandler(null) != null) {
            getPreallocationHandler(null).onDisconnect();
            clearPreallocationHandler();
        }
        onDisconnectSequences(0);
        getOwnerSession().log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_disconnected");
    }

    protected PreallocationHandler getPreallocationHandler(String context) {
        if (preallocationHandler != null) {
            if (context == null) {
                return preallocationHandler.get("default");
            } else {
                PreallocationHandler handler = preallocationHandler.get(context);
                if (handler == null && !"default".equals(context)) {
                    handler = new PreallocationHandler();
                    preallocationHandler.put(context, handler);
                    handler.onConnect();
                }
                return handler;
            }
        }
        return null;
    }

    protected void createPreallocationHandler(String context) {
        if (preallocationHandler == null) {
            preallocationHandler = new ConcurrentHashMap<>(5);
        }
        preallocationHandler.put(context, new PreallocationHandler());
    }

    protected void clearPreallocationHandler() {
        preallocationHandler = null;
    }

    protected void clearPreallocationHandler(AbstractSession session) {
        preallocationHandler.remove(getContext(session));
    }

    /*
     * If passed collection is null then connect all sequences used by owner session's descriptors.
     * Otherwise connect sequences used by passed descriptors.
     */
    protected void onConnectSequences(Collection<ClassDescriptor> descriptors) {
        boolean isConnected = isConnected();
        int nAlreadyConnectedSequences = 0;
        if (connectedSequences == null) {
            connectedSequences = new Vector<>();
        } else {
            nAlreadyConnectedSequences = connectedSequences.size();
        }
        boolean shouldUseTransaction = false;
        boolean shouldUsePreallocation = false;
        boolean shouldAcquireValueAfterInsert = false;
        if (descriptors == null) {
            descriptors = getOwnerSession().getDescriptors().values();
        }
        Iterator<ClassDescriptor> itDescriptors = descriptors.iterator();
        while (itDescriptors.hasNext()) {
            ClassDescriptor descriptor = itDescriptors.next();
            // Find root sequence, because inheritance needs to be resolved here.
            // TODO: The way we initialize sequencing needs to be in line with descriptor init.
            ClassDescriptor parentDescriptor = descriptor;
            while (!parentDescriptor.usesSequenceNumbers() && parentDescriptor.isChildDescriptor()) {
                ClassDescriptor newDescriptor = getOwnerSession().getDescriptor(parentDescriptor.getInheritancePolicy().getParentClass());
                // Avoid issue with error cases of self parent, or null parent.
                if ((newDescriptor == null) || (newDescriptor == parentDescriptor)) {
                    break;
                }
                parentDescriptor = newDescriptor;
            }
            if (!parentDescriptor.usesSequenceNumbers()) {
                continue;
            }
            String seqName = parentDescriptor.getSequenceNumberName();
            Sequence sequence = getSequence(seqName);
            if (sequence == null) {
                sequence = new DefaultSequence(seqName);
                getOwnerSession().getDatasourcePlatform().addSequence(sequence, isConnected);
            }
            // PERF: Initialize the sequence, this avoid having to look it up every time.
            descriptor.setSequence(sequence);
            if (connectedSequences.contains(sequence)) {
                continue;
            }
            try {
                if (sequence instanceof DefaultSequence && !connectedSequences.contains(getDefaultSequence())) {
                    getDefaultSequence().onConnect(getOwnerSession().getDatasourcePlatform());
                    connectedSequences.add(nAlreadyConnectedSequences, getDefaultSequence());
                    shouldUseTransaction |= getDefaultSequence().shouldUseTransaction();
                    shouldUsePreallocation |= getDefaultSequence().shouldUsePreallocation();
                    shouldAcquireValueAfterInsert |= getDefaultSequence().shouldAcquireValueAfterInsert();
                }
                sequence.onConnect(getOwnerSession().getDatasourcePlatform());
                connectedSequences.addElement(sequence);
                shouldUseTransaction |= sequence.shouldUseTransaction();
                shouldUsePreallocation |= sequence.shouldUsePreallocation();
                shouldAcquireValueAfterInsert |= sequence.shouldAcquireValueAfterInsert();
            } catch (RuntimeException ex) {
                // defaultSequence has to disconnect the last
                for (int i = connectedSequences.size() - 1; i >= nAlreadyConnectedSequences; i--) {
                    try {
                        Sequence sequenceToDisconnect = connectedSequences.elementAt(i);
                        sequenceToDisconnect.onDisconnect(getOwnerSession().getDatasourcePlatform());
                    } catch (RuntimeException ex2) {
                        //ignore
                    }
                }
                if (nAlreadyConnectedSequences == 0) {
                    connectedSequences = null;
                }
                throw ex;
            }
        }

        if (nAlreadyConnectedSequences == 0) {
            if (shouldAcquireValueAfterInsert && !shouldUsePreallocation) {
                whenShouldAcquireValueForAll = AFTER_INSERT;
            } else if (!shouldAcquireValueAfterInsert && shouldUsePreallocation) {
                whenShouldAcquireValueForAll = BEFORE_INSERT;
            }
        } else {
            if (whenShouldAcquireValueForAll == AFTER_INSERT) {
                if (!shouldAcquireValueAfterInsert || shouldUsePreallocation) {
                    whenShouldAcquireValueForAll = UNDEFINED;
                }
            } else if (whenShouldAcquireValueForAll == BEFORE_INSERT) {
                if (shouldAcquireValueAfterInsert || !shouldUsePreallocation) {
                    whenShouldAcquireValueForAll = UNDEFINED;
                }
            }
        }
        atLeastOneSequenceShouldUseTransaction |= shouldUseTransaction;
        atLeastOneSequenceShouldUsePreallocation |= shouldUsePreallocation;
    }

    /*
     * Keeps the first nAlreadyConnectedSequences sequences connected,
     * disconnects the rest.
     */
    protected void onDisconnectSequences(int nAlreadyConnectedSequences) {
        RuntimeException exception = null;

        // defaultSequence has to disconnect the last
        for (int i = connectedSequences.size() - 1; i >= nAlreadyConnectedSequences; i--) {
            try {
                Sequence sequenceToDisconnect = connectedSequences.elementAt(i);
                sequenceToDisconnect.onDisconnect(getOwnerSession().getDatasourcePlatform());
            } catch (RuntimeException ex) {
                if (exception == null) {
                    exception = ex;
                }
            }
        }
        if (nAlreadyConnectedSequences == 0) {
            connectedSequences = null;
            whenShouldAcquireValueForAll = UNDEFINED;
            atLeastOneSequenceShouldUseTransaction = false;
            atLeastOneSequenceShouldUsePreallocation = false;
        }
        if (exception != null) {
            throw exception;
        }
    }

    protected void initializeStates(int nAlreadyConnectedSequences) {
        if (states == null) {
            states = new State[NUMBER_OF_STATES];
        }

        int nSize = connectedSequences.size();
        for (int i = nAlreadyConnectedSequences; i < nSize; i++) {
            Sequence sequence = connectedSequences.get(i);
            State state = getState(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction());
            if (state == null) {
                createState(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction());
            }
        }
    }

    protected void clearStates() {
        states = null;
    }

    protected int getStateId(boolean shouldUsePreallocation, boolean shouldUseTransaction) {
        if (!shouldUsePreallocation) {
            // Non-Oracle native sequencing uses this state
            return NOPREALLOCATION;
        } else if (!shouldUseTransaction) {
            // Oracle native sequencing uses this state
            return PREALLOCATION_NOTRANSACTION;
        } else if (getConnectionHandler() == null) {
            // TableSequence and UnaryTableSequence in case there is no separate connection(s) available use this state
            return PREALLOCATION_TRANSACTION_NOACCESSOR;
        } else/*if(getConnectionHandler()!=null)*/
         {
            // TableSequence and UnaryTableSequence in case there is separate connection(s) available use this state
            return PREALLOCATION_TRANSACTION_ACCESSOR;
        }
    }

    protected State getState(boolean shouldUsePreallocation, boolean shouldUseTransaction) {
        return states[getStateId(shouldUsePreallocation, shouldUseTransaction)];
    }

    protected void createState(boolean shouldUsePreallocation, boolean shouldUseTransaction) {
        if (!shouldUsePreallocation) {
            // Non-Oracle native sequencing uses this state
            states[NOPREALLOCATION] = new NoPreallocation_State();
        } else if (!shouldUseTransaction) {
            // Oracle native sequencing uses this state
            states[PREALLOCATION_NOTRANSACTION] = new Preallocation_NoTransaction_State();
        } else if (getConnectionHandler() == null) {
            // TableSequence and UnaryTableSequence in case there is no separate connection(s) available use this state
            states[PREALLOCATION_TRANSACTION_NOACCESSOR] = new Preallocation_Transaction_NoAccessor_State();
        } else/*if(getConnectionHandler()!=null)*/
         {
            // TableSequence and UnaryTableSequence in case there is separate connection(s) available use this state
            states[PREALLOCATION_TRANSACTION_ACCESSOR] = new Preallocation_Transaction_Accessor_State();
        }
    }

    protected void createSequencingCallbackFactory() {
        if (states[PREALLOCATION_TRANSACTION_NOACCESSOR] != null) {
            setSequencingCallbackFactory(states[PREALLOCATION_TRANSACTION_NOACCESSOR].getSequencingCallbackFactory());
        } else {
            setSequencingCallbackFactory(null);
        }
    }

    @Override
    public Object getNextValue(AbstractSession writeSession, Class<?> cls) {
        Sequence sequence = getSequence(cls);
        State state = getState(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction());
        return state.getNextValue(sequence, writeSession);
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    protected void logDebugSequencingConnected(int nAlreadyConnectedSequences) {
        Vector<Sequence>[] sequenceVectors = (Vector<Sequence>[]) new Vector[NUMBER_OF_STATES];
        int size = connectedSequences.size();
        for (int i = nAlreadyConnectedSequences; i < size; i++) {
            Sequence sequence = connectedSequences.get(i);
            int stateId = getStateId(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction());
            Vector<Sequence> v = sequenceVectors[stateId];
            if (v == null) {
                v = new Vector<>();
                sequenceVectors[stateId] = v;
            }
            v.addElement(sequence);
        }
        for (int i = 0; i < NUMBER_OF_STATES; i++) {
            Vector<Sequence> v = sequenceVectors[i];
            if (v != null) {
                getOwnerSession().log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_connected", states[i]);
                for (int j = 0; j < v.size(); j++) {
                    Sequence sequence = v.elementAt(j);
                    Object[] args = { sequence.getName(), Integer.toString(sequence.getPreallocationSize()),
                            Integer.toString(sequence.getInitialValue())};
                    getOwnerSession().log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequence_without_state", args);
                }
            }
        }
    }

    public int getPreallocationSize() {
        return getDefaultSequence().getPreallocationSize();
    }

    public int getInitialValue() {
        return getDefaultSequence().getInitialValue();
    }

    @Override
    public int whenShouldAcquireValueForAll() {
        return whenShouldAcquireValueForAll;
    }

    protected Sequence getDefaultSequence() {
        return getOwnerSession().getDatasourcePlatform().getDefaultSequence();
    }

    protected Sequence getSequence(String seqName) {
        return getOwnerSession().getDatasourcePlatform().getSequence(seqName);
    }

    @Override
    public void setConnectionPool(ConnectionPool connectionPool) {
        this.connectionPool = connectionPool;
    }

    private String getContext(AbstractSession writeSession) {
        String context = "default";
        if (writeSession != null) {
            MultitenantPolicy policy = writeSession.getProject().getMultitenantPolicy();
            if (policy != null && policy.isSchemaPerMultitenantPolicy()) {
                SchemaPerMultitenantPolicy tableMtPolicy = (SchemaPerMultitenantPolicy) policy;
                if (tableMtPolicy.isSchemaPerTable()) {
                    String tenantContext = (String) writeSession.getProperty(tableMtPolicy.getContextProperty());
                    if (tenantContext != null) {
                        context = tenantContext;
                    }
                }
            }
        }
        return context;
    }
}
