FileDocCategorySizeDatePackage
SequencingManager.javaAPI DocGlassfish v2 API37737Tue May 22 16:54:42 BST 2007oracle.toplink.essentials.internal.sequencing

SequencingManager

public class SequencingManager extends Object implements SequencingServer, SequencingControl, SequencingHome
SequencingManager is private to TopLink. 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 -> Not connected State. State: Not connected. isConnected() returns false; getSequencingControl() could be used; getSequencing() == getSequencingServer() == getSequencingCallback() == null; Action: onConnect is called -> 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 -> 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;

Fields Summary
private DatabaseSessionImpl
ownerSession
private SequencingConnectionHandler
connectionHandler
private PreallocationHandler
preallocationHandler
private int
whenShouldAcquireValueForAll
private Vector
connectedSequences
boolean
atLeastOneSequenceShouldUseTransaction
boolean
atLeastOneSequenceShouldUsePreallocation
private static final int
NOPREALLOCATION
private static final int
PREALLOCATION_NOTRANSACTION
private static final int
PREALLOCATION_TRANSACTION_NOACCESSOR
private static final int
PREALLOCATION_TRANSACTION_ACCESSOR
private static final int
NUMBER_OF_STATES
private State[]
states
private Hashtable
locks
private SequencingCallback
callback
private SequencingServer
server
private Sequencing
seq
private boolean
shouldUseSeparateConnection
private Login
login
private int
minPoolSize
private int
maxPoolSize
Constructors Summary
public SequencingManager(DatabaseSessionImpl ownerSession)


       
        this.ownerSession = ownerSession;
    
Methods Summary
protected voidacquireLock(java.lang.String seqName)

        ConcurrencyManager manager;
        synchronized (getLocks()) {
            manager = (ConcurrencyManager)getLocks().get(seqName);
            if (manager == null) {
                manager = new ConcurrencyManager();
                getLocks().put(seqName, manager);
            }
        }
        manager.acquire();
    
protected voidclearPreallocationHandler()

        preallocationHandler = null;
    
protected voidclearStates()

        states = null;
    
protected voidcreateConnectionHandler()

        boolean isServerSession = getOwnerSession().isServerSession();

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

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

        if (isServerSession) {
            ConnectionPool pool = null;
            if (getLogin().shouldUseExternalConnectionPooling()) {
                pool = new ExternalConnectionPool("sequencing", getLogin(), (ServerSession)getOwnerSession());
            } else {
                if ((getMinPoolSize() == 0) && (getMaxPoolSize() == 0)) {
                    setMinPoolSize(2);
                    setMaxPoolSize(2);
                }
                pool = new ConnectionPool("sequencing", getLogin(), getMinPoolSize(), getMaxPoolSize(), (ServerSession)getOwnerSession());
            }

            setConnectionHandler(new ServerSessionConnectionHandler(pool));

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

        }
    
protected voidcreatePreallocationHandler()

        preallocationHandler = new PreallocationHandler();
    
protected voidcreateSequencingCallback()

        Vector callbackVector = new Vector();
        for (int i = 0; i < NUMBER_OF_STATES; i++) {
            if (states[i] != null) {
                SequencingCallback callback = states[i].getSequencingCallback();
                if (callback != null) {
                    callbackVector.addElement(callback);
                }
            }
        }
        if (callbackVector.isEmpty()) {
            setSequencingCallback(null);
        } else if (callbackVector.size() == 1) {
            setSequencingCallback((SequencingCallback)callbackVector.firstElement());
        } else {
            setSequencingCallback(new SequencingCallbackContainer(callbackVector));
        }
    
protected voidcreateState(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 oracle.toplink.essentials.internal.sequencing.SequencingConnectionHandlergetConnectionHandler()

        return connectionHandler;
    
protected oracle.toplink.essentials.sequencing.SequencegetDefaultSequence()

        return getOwnerSession().getDatasourcePlatform().getDefaultSequence();
    
public intgetInitialValue()

        return getDefaultSequence().getInitialValue();
    
protected java.util.HashtablegetLocks()

        return locks;
    
public oracle.toplink.essentials.sessions.LogingetLogin()

        return login;
    
public intgetMaxPoolSize()

        return maxPoolSize;
    
public intgetMinPoolSize()

        return minPoolSize;
    
public java.lang.ObjectgetNextValue(java.lang.Class cls)

        return getNextValue(getOwnerSession(), cls);
    
public java.lang.ObjectgetNextValue(oracle.toplink.essentials.internal.sessions.AbstractSession writeSession, java.lang.Class cls)

        Sequence sequence = getSequence(cls);
        State state = getState(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction());
        return state.getNextValue(sequence, writeSession);
    
protected oracle.toplink.essentials.internal.sessions.DatabaseSessionImplgetOwnerSession()

        return ownerSession;
    
protected oracle.toplink.essentials.internal.sequencing.PreallocationHandlergetPreallocationHandler()

        return preallocationHandler;
    
public intgetPreallocationSize()

        return getDefaultSequence().getPreallocationSize();
    
protected oracle.toplink.essentials.sequencing.SequencegetSequence(java.lang.Class cls)

        //** should check here that sequencing is used?
        String seqName = getOwnerSession().getDescriptor(cls).getSequenceNumberName();
        return getSequence(seqName);
    
protected oracle.toplink.essentials.sequencing.SequencegetSequence(java.lang.String seqName)

        return getOwnerSession().getDatasourcePlatform().getSequence(seqName);
    
public oracle.toplink.essentials.internal.sequencing.SequencinggetSequencing()

        return seq;
    
public oracle.toplink.essentials.internal.sequencing.SequencingCallbackgetSequencingCallback()

        return callback;
    
public oracle.toplink.essentials.sequencing.SequencingControlgetSequencingControl()

        return this;
    
public oracle.toplink.essentials.internal.sequencing.SequencingServergetSequencingServer()

        return server;
    
protected oracle.toplink.essentials.internal.sequencing.SequencingManager$StategetState(boolean shouldUsePreallocation, boolean shouldUseTransaction)

        return states[getStateId(shouldUsePreallocation, shouldUseTransaction)];
    
protected intgetStateId(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;
        }
    
public voidinitializePreallocated()

        if (getPreallocationHandler() != null) {
            getPreallocationHandler().initializePreallocated();
        }
    
public voidinitializePreallocated(java.lang.String seqName)

        if (getPreallocationHandler() != null) {
            getPreallocationHandler().initializePreallocated(seqName);
        }
    
protected voidinitializeStates()

        states = new State[NUMBER_OF_STATES];

        Iterator itConnectedSequences = connectedSequences.iterator();
        while (itConnectedSequences.hasNext()) {
            Sequence sequence = (Sequence)itConnectedSequences.next();
            State state = getState(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction());
            if (state == null) {
                createState(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction());
            }
        }
    
public booleanisConnected()

        return states != null;
    
public booleanisConnectedUsingSeparateConnection()

        return isConnected() && (getConnectionHandler() != null);
    
protected voidlogDebugLocalPreallocation(oracle.toplink.essentials.internal.sessions.AbstractSession writeSession, java.lang.String seqName, java.util.Vector sequences, oracle.toplink.essentials.internal.databaseaccess.Accessor accessor)

        if (writeSession.shouldLog(SessionLog.FINEST, SessionLog.SEQUENCING)) {
            Object[] args = { seqName, new Integer(sequences.size()), sequences.firstElement(), sequences.lastElement() };
            writeSession.log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_localPreallocation", args, accessor);
        }
    
protected voidlogDebugPreallocation(java.lang.String seqName, java.util.Vector sequences)

        if (getOwnerSession().shouldLog(SessionLog.FINEST, SessionLog.SEQUENCING)) {
            Object[] args = { seqName, new Integer(sequences.size()), sequences.firstElement(), sequences.lastElement() };
            getOwnerSession().log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_preallocation", args);
        }
    
protected voidlogDebugSequencingConnected()

        Vector[] sequenceVectors = new Vector[NUMBER_OF_STATES];
        Iterator itConnectedSequences = connectedSequences.iterator();
        while (itConnectedSequences.hasNext()) {
            Sequence sequence = (Sequence)itConnectedSequences.next();
            int stateId = getStateId(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction());
            Vector 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 v = sequenceVectors[i];
            if (v != null) {
                getOwnerSession().log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_connected", states[i]);
                for (int j = 1; j < v.size(); j++) {
                    Sequence 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 voidonConnect()

        if (isConnected()) {
            return;
        }

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

        getOwnerSession().getDatasourcePlatform().platformSpecificSequencingInitialization(getOwnerSession()); 

        onConnectAllSequences();

        boolean onExceptionDisconnectPreallocationHandler = false;
        boolean onExceptionDisconnectConnectionHandler = false;

        try {
            if (!shouldUseSeparateConnection()) {
                setConnectionHandler(null);
            } else if (atLeastOneSequenceShouldUseTransaction) {
                if (getConnectionHandler() == null) {
                    createConnectionHandler();
                }
                if (getConnectionHandler() != null) {
                    getConnectionHandler().onConnect();
                    onExceptionDisconnectConnectionHandler = true;
                }
            }

            if (atLeastOneSequenceShouldUsePreallocation) {
                if (getPreallocationHandler() == null) {
                    createPreallocationHandler();
                }
                getPreallocationHandler().onConnect();
                onExceptionDisconnectPreallocationHandler = true;
            }

            initializeStates();

        } catch (RuntimeException ex) {
            onDisconnectAllSequences();
            if (getConnectionHandler() != null) {
                if (onExceptionDisconnectConnectionHandler) {
                    getConnectionHandler().onDisconnect();
                }
                setConnectionHandler(null);
            }
            if (getPreallocationHandler() != null) {
                if (onExceptionDisconnectPreallocationHandler) {
                    getPreallocationHandler().onDisconnect();
                }
                clearPreallocationHandler();
            }
            throw ex;
        }
        if (atLeastOneSequenceShouldUsePreallocation) {
            setLocks(new Hashtable(20));
        }
        createSequencingCallback();
        if (getOwnerSession().isServerSession()) {
            setSequencingServer(this);
        }
        setSequencing(this);
        logDebugSequencingConnected();
    
protected voidonConnectAllSequences()

        connectedSequences = new Vector();
        boolean shouldUseTransaction = false;
        boolean shouldUsePreallocation = false;
        boolean shouldAcquireValueAfterInsert = false;
        Iterator descriptors = getOwnerSession().getDescriptors().values().iterator();
        while (descriptors.hasNext()) {
            ClassDescriptor descriptor = (ClassDescriptor)descriptors.next();
            if (!descriptor.usesSequenceNumbers()) {
                continue;
            }
            String seqName = descriptor.getSequenceNumberName();
            Sequence sequence = getSequence(seqName);
            if (sequence == null) {
                sequence = new DefaultSequence(seqName);
                getOwnerSession().getDatasourcePlatform().addSequence(sequence);
            }
            if (connectedSequences.contains(sequence)) {
                continue;
            }
            try {
                if (sequence instanceof DefaultSequence && !connectedSequences.contains(getDefaultSequence())) {
                    getDefaultSequence().onConnect(getOwnerSession().getDatasourcePlatform());
                    connectedSequences.add(0, 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 >= 0; i--) {
                    try {
                        Sequence sequenceToDisconnect = (Sequence)connectedSequences.elementAt(i);
                        sequenceToDisconnect.onDisconnect(getOwnerSession().getDatasourcePlatform());
                    } catch (RuntimeException ex2) {
                        //ignore
                    }
                }
                connectedSequences = null;
                throw ex;
            }
        }

        if (shouldAcquireValueAfterInsert && !shouldUsePreallocation) {
            whenShouldAcquireValueForAll = AFTER_INSERT;
        } else if (!shouldAcquireValueAfterInsert && shouldUsePreallocation) {
            whenShouldAcquireValueForAll = BEFORE_INSERT;
        }
        atLeastOneSequenceShouldUseTransaction = shouldUseTransaction;
        atLeastOneSequenceShouldUsePreallocation = shouldUsePreallocation;
    
public voidonDisconnect()

        if (!isConnected()) {
            return;
        }

        setSequencing(null);
        setSequencingServer(null);
        setSequencingCallback(null);
        setLocks(null);
        clearStates();

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

        RuntimeException exception = null;

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

        ConcurrencyManager manager = (ConcurrencyManager)locks.get(seqName);
        manager.release();
    
public voidresetSequencing()

        if (isConnected()) {
            onDisconnect();
            onConnect();
        }
    
protected voidsetConnectionHandler(oracle.toplink.essentials.internal.sequencing.SequencingConnectionHandler handler)

        this.connectionHandler = handler;
    
protected voidsetLocks(java.util.Hashtable locks)

        this.locks = locks;
    
public voidsetLogin(oracle.toplink.essentials.sessions.Login login)

        this.login = login;
    
public voidsetMaxPoolSize(int size)

        this.maxPoolSize = size;
    
public voidsetMinPoolSize(int size)

        this.minPoolSize = size;
    
protected voidsetSequencing(oracle.toplink.essentials.internal.sequencing.Sequencing sequencing)

        this.seq = sequencing;
    
protected voidsetSequencingCallback(oracle.toplink.essentials.internal.sequencing.SequencingCallback callback)

        this.callback = callback;
    
protected voidsetSequencingServer(oracle.toplink.essentials.internal.sequencing.SequencingServer server)

        this.server = server;
    
public voidsetShouldUseSeparateConnection(boolean shouldUseSeparateConnection)

        this.shouldUseSeparateConnection = shouldUseSeparateConnection;
    
public booleanshouldAcquireValueAfterInsert(java.lang.Class cls)

        return getSequence(cls).shouldAcquireValueAfterInsert();
    
public booleanshouldOverrideExistingValue(java.lang.Class cls, java.lang.Object existingValue)

        return getSequence(cls).shouldOverrideExistingValue(existingValue);
    
public booleanshouldUseSeparateConnection()

        return shouldUseSeparateConnection;
    
public intwhenShouldAcquireValueForAll()

        return whenShouldAcquireValueForAll;